feat: 添加批量删除功能
This commit is contained in:
@@ -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",
|
||||||
|
|||||||
@@ -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":"すべてテスト",
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
Reference in New Issue
Block a user