feat: 添加批量删除功能

This commit is contained in:
Baobhan Sith
2025-05-16 22:37:01 +08:00
parent 890bcf64a1
commit 084cc570f4
5 changed files with 106 additions and 3 deletions
+6 -1
View File
@@ -140,7 +140,12 @@
"title": "Batch Edit Connections", "title": "Batch Edit Connections",
"editSelected": "Edit Selected", "editSelected": "Edit Selected",
"noChange":"No change", "noChange":"No change",
"selectedItems":"{count} items selected" "selectedItems":"{count} items selected",
"deleteSelectedButton": "Delete Selected",
"deleteSelectedTooltip": "Delete selected connections",
"confirmMessage": "Are you sure you want to delete the selected {count} connections? This action cannot be undone.",
"successMessage": "Selected connections have been successfully deleted.",
"errorMessage": "Batch delete connections failed: {error}"
}, },
"actions": { "actions": {
"testAllFiltered":"Test All", "testAllFiltered":"Test All",
+6 -1
View File
@@ -118,7 +118,12 @@
"title": "接続の一括編集", "title": "接続の一括編集",
"editSelected": "選択した項目を編集", "editSelected": "選択した項目を編集",
"noChange": "変更なし", "noChange": "変更なし",
"selectedItems": "{count} 件選択済み" "selectedItems": "{count} 件選択済み",
"deleteSelectedButton": "選択した項目を削除",
"deleteSelectedTooltip": "選択した接続を削除します",
"confirmMessage": "選択した {count} 件の接続を本当に削除しますか?この操作は元に戻せません。",
"successMessage": "選択した接続は正常に削除されました。",
"errorMessage": "接続の一括削除に失敗しました: {error}"
}, },
"actions": { "actions": {
"testAllFiltered":"すべてテスト", "testAllFiltered":"すべてテスト",
+5 -1
View File
@@ -140,7 +140,11 @@
"title": "批量编辑连接", "title": "批量编辑连接",
"selectedItems": "已选项目", "selectedItems": "已选项目",
"noChange": "保持不变", "noChange": "保持不变",
"tagsPlaceholder": "输入标签 (替换现有)" "deleteSelectedButton": "删除选中",
"deleteSelectedTooltip": "删除选中的连接",
"confirmMessage": "您确定要删除选中的 {count} 个连接吗?此操作无法撤销。",
"successMessage": "选中的连接已成功删除。",
"errorMessage": "批量删除连接失败: {error}"
}, },
"actions": { "actions": {
"testAllFiltered":"测试全部", "testAllFiltered":"测试全部",
@@ -190,6 +190,51 @@ export const useConnectionsStore = defineStore('connections', {
} }
}, },
// 批量删除连接
async deleteBatchConnections(connectionIds: number[]): Promise<boolean> {
if (!connectionIds || connectionIds.length === 0) {
console.warn('[ConnectionsStore] deleteBatchConnections called with no IDs.');
return true; // 没有要删除的,视为成功
}
this.isLoading = true; // 标记整个批量删除操作正在进行
this.error = null;
let allSucceeded = true;
const individualErrors: string[] = [];
for (const id of connectionIds) {
try {
// 调用现有的 deleteConnection 方法
const success = await this.deleteConnection(id);
if (!success) {
allSucceeded = false;
if (this.error) {
individualErrors.push(`删除连接 ID ${id} 失败: ${this.error}`);
} else {
individualErrors.push(`删除连接 ID ${id} 失败 (未知原因)`);
}
this.error = null;
}
} catch (e: any) {
// 捕获 deleteConnection 调用本身可能抛出的意外错误
allSucceeded = false;
const errorMessage = e.message || '未知错误';
individualErrors.push(`调用删除连接 ID ${id} 时发生意外错误: ${errorMessage}`);
console.error(`[ConnectionsStore] Unexpected error calling deleteConnection for ID ${id}`, e);
}
}
if (!allSucceeded) {
this.error = `批量删除操作中部分连接未能成功删除。详情: ${individualErrors.join('; ')}`;
console.error('[ConnectionsStore] Batch delete operation completed with one or more failures.');
} else {
// 如果所有操作都成功,确保 this.error 为 null
this.error = null;
}
this.isLoading = false;
return allSucceeded;
},
// 测试连接 Action // 测试连接 Action
async testConnection(connectionId: number): Promise<{ success: boolean; message?: string; latency?: number }> { async testConnection(connectionId: number): Promise<{ success: boolean; message?: string; latency?: number }> {
// 注意:这里不改变 isLoading 状态,或者可以引入单独的 testing 状态 // 注意:这里不改变 isLoading 状态,或者可以引入单独的 testing 状态
@@ -45,6 +45,7 @@ const connectionToEdit = ref<ConnectionInfo | null>(null);
const isBatchEditMode = ref(false); const isBatchEditMode = ref(false);
const selectedConnectionIdsForBatch = ref<Set<number>>(new Set()); const selectedConnectionIdsForBatch = ref<Set<number>>(new Set());
const showBatchEditForm = ref(false); const showBatchEditForm = ref(false);
const isDeletingSelectedConnections = ref(false);
const sortOptions: { value: SortField; labelKey: string }[] = [ const sortOptions: { value: SortField; labelKey: string }[] = [
{ value: 'last_connected_at', labelKey: 'dashboard.sortOptions.lastConnected' }, { value: 'last_connected_at', labelKey: 'dashboard.sortOptions.lastConnected' },
@@ -269,6 +270,39 @@ const handleBatchEditFormClose = () => {
showBatchEditForm.value = false; showBatchEditForm.value = false;
}; };
// --- 批量删除 ---
const handleBatchDeleteConnections = async () => {
if (selectedConnectionIdsForBatch.value.size === 0 || isDeletingSelectedConnections.value) {
return;
}
const confirmMessage = t(
'connections.batchEdit.confirmMessage',
{ count: selectedConnectionIdsForBatch.value.size },
`您确定要删除选中的 ${selectedConnectionIdsForBatch.value.size} 个连接吗?此操作无法撤销。`
);
if (window.confirm(confirmMessage)) {
isDeletingSelectedConnections.value = true;
try {
const idsToDelete = Array.from(selectedConnectionIdsForBatch.value);
await connectionsStore.deleteBatchConnections(idsToDelete);
alert(t('connections.batchEdit.successMessage', '选中的连接已成功删除。'));
selectedConnectionIdsForBatch.value.clear();
await connectionsStore.fetchConnections();
} catch (error: any) {
console.error("Batch delete connections error:", error);
alert(t('connections.batchEdit.errorMessage', `批量删除连接失败: ${error.message || '未知错误'}`));
} finally {
isDeletingSelectedConnections.value = false;
}
}
};
// --- Test Connection Logic --- // --- Test Connection Logic ---
interface ConnectionTestState { interface ConnectionTestState {
status: 'idle' | 'testing' | 'success' | 'error'; status: 'idle' | 'testing' | 'success' | 'error';
@@ -570,6 +604,16 @@ const handleConnectAllFilteredConnections = async () => {
<i class="fas fa-edit mr-1"></i> <i class="fas fa-edit mr-1"></i>
{{ t('connections.batchEdit.editSelected', '编辑选中') }} {{ t('connections.batchEdit.editSelected', '编辑选中') }}
</button> </button>
<button
@click="handleBatchDeleteConnections"
:disabled="selectedConnectionIdsForBatch.size === 0 || isDeletingSelectedConnections"
class="px-4 py-1.5 text-sm bg-red-600 text-white rounded-md shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed flex items-center"
:title="t('connections.batchEdit.deleteSelectedTooltip', '删除选中的连接')"
>
<i v-if="isDeletingSelectedConnections" class="fas fa-spinner fa-spin mr-1.5"></i>
<i v-else class="fas fa-trash-alt mr-1.5"></i>
<span>{{ t('connections.batchEdit.deleteSelectedButton', '删除选中') }}</span>
</button>
</div> </div>
<div class="p-4"> <div class="p-4">