diff --git a/packages/frontend/src/locales/en-US.json b/packages/frontend/src/locales/en-US.json index b135814..6c0879d 100644 --- a/packages/frontend/src/locales/en-US.json +++ b/packages/frontend/src/locales/en-US.json @@ -140,7 +140,12 @@ "title": "Batch Edit Connections", "editSelected": "Edit Selected", "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": { "testAllFiltered":"Test All", diff --git a/packages/frontend/src/locales/ja-JP.json b/packages/frontend/src/locales/ja-JP.json index ed51cd1..d75a663 100644 --- a/packages/frontend/src/locales/ja-JP.json +++ b/packages/frontend/src/locales/ja-JP.json @@ -118,7 +118,12 @@ "title": "接続の一括編集", "editSelected": "選択した項目を編集", "noChange": "変更なし", - "selectedItems": "{count} 件選択済み" + "selectedItems": "{count} 件選択済み", + "deleteSelectedButton": "選択した項目を削除", + "deleteSelectedTooltip": "選択した接続を削除します", + "confirmMessage": "選択した {count} 件の接続を本当に削除しますか?この操作は元に戻せません。", + "successMessage": "選択した接続は正常に削除されました。", + "errorMessage": "接続の一括削除に失敗しました: {error}" }, "actions": { "testAllFiltered":"すべてテスト", diff --git a/packages/frontend/src/locales/zh-CN.json b/packages/frontend/src/locales/zh-CN.json index 8418c6f..7c715e7 100644 --- a/packages/frontend/src/locales/zh-CN.json +++ b/packages/frontend/src/locales/zh-CN.json @@ -140,7 +140,11 @@ "title": "批量编辑连接", "selectedItems": "已选项目", "noChange": "保持不变", - "tagsPlaceholder": "输入标签 (替换现有)" + "deleteSelectedButton": "删除选中", + "deleteSelectedTooltip": "删除选中的连接", + "confirmMessage": "您确定要删除选中的 {count} 个连接吗?此操作无法撤销。", + "successMessage": "选中的连接已成功删除。", + "errorMessage": "批量删除连接失败: {error}" }, "actions": { "testAllFiltered":"测试全部", diff --git a/packages/frontend/src/stores/connections.store.ts b/packages/frontend/src/stores/connections.store.ts index 28f5d6d..7296639 100644 --- a/packages/frontend/src/stores/connections.store.ts +++ b/packages/frontend/src/stores/connections.store.ts @@ -190,6 +190,51 @@ export const useConnectionsStore = defineStore('connections', { } }, + // 批量删除连接 + async deleteBatchConnections(connectionIds: number[]): Promise { + 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 async testConnection(connectionId: number): Promise<{ success: boolean; message?: string; latency?: number }> { // 注意:这里不改变 isLoading 状态,或者可以引入单独的 testing 状态 diff --git a/packages/frontend/src/views/ConnectionsView.vue b/packages/frontend/src/views/ConnectionsView.vue index 45bb5ca..dec0692 100644 --- a/packages/frontend/src/views/ConnectionsView.vue +++ b/packages/frontend/src/views/ConnectionsView.vue @@ -45,6 +45,7 @@ const connectionToEdit = ref(null); const isBatchEditMode = ref(false); const selectedConnectionIdsForBatch = ref>(new Set()); const showBatchEditForm = ref(false); +const isDeletingSelectedConnections = ref(false); const sortOptions: { value: SortField; labelKey: string }[] = [ { value: 'last_connected_at', labelKey: 'dashboard.sortOptions.lastConnected' }, @@ -269,6 +270,39 @@ const handleBatchEditFormClose = () => { 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 --- interface ConnectionTestState { status: 'idle' | 'testing' | 'success' | 'error'; @@ -570,6 +604,16 @@ const handleConnectAllFilteredConnections = async () => { {{ t('connections.batchEdit.editSelected', '编辑选中') }} +