diff --git a/dashboard/src/components/shared/ItemCard.vue b/dashboard/src/components/shared/ItemCard.vue index 6152c531f..14453ae7a 100644 --- a/dashboard/src/components/shared/ItemCard.vue +++ b/dashboard/src/components/shared/ItemCard.vue @@ -4,28 +4,28 @@ {{ getItemTitle() }} {{ getItemEnabled() ? t('core.common.itemCard.enabled') : t('core.common.itemCard.disabled') }} - + - + {{ t('core.common.itemCard.edit') }} + + {{ t('core.common.itemCard.copy') }} + @@ -83,9 +92,13 @@ export default { loading: { type: Boolean, default: false + }, + showCopyButton: { + type: Boolean, + default: false } }, - emits: ['toggle-enabled', 'delete', 'edit'], + emits: ['toggle-enabled', 'delete', 'edit', 'copy'], methods: { getItemTitle() { return this.item[this.titleField]; diff --git a/dashboard/src/i18n/locales/zh-CN/core/common.json b/dashboard/src/i18n/locales/zh-CN/core/common.json index 5405c15f6..9a7f5eeaf 100644 --- a/dashboard/src/i18n/locales/zh-CN/core/common.json +++ b/dashboard/src/i18n/locales/zh-CN/core/common.json @@ -73,6 +73,7 @@ "disabled": "已禁用", "delete": "删除", "edit": "编辑", + "copy": "复制", "noData": "暂无数据" } -} \ No newline at end of file +} \ No newline at end of file diff --git a/dashboard/src/views/ProviderPage.vue b/dashboard/src/views/ProviderPage.vue index 9915f0112..b36c0db21 100644 --- a/dashboard/src/views/ProviderPage.vue +++ b/dashboard/src/views/ProviderPage.vue @@ -56,14 +56,16 @@ - + @delete="deleteProvider" + @edit="configExistingProvider" + @copy="copyProvider" + :show-copy-button="true"> @@ -95,7 +97,7 @@ {{ tm('availability.noData') }} - + @@ -113,7 +115,7 @@ > {{ status.id }} - + {{ getStatusText(status.status) }} @@ -348,10 +350,10 @@ export default { save_message_success: "success", showConsole: false, - + // 显示状态部分 showStatus: false, - + // 供应商状态相关 providerStatuses: [], loadingStatus: false, @@ -437,7 +439,7 @@ export default { } }; }, - + // 根据选择的标签过滤提供商列表 filteredProviders() { if (!this.config_data.provider || this.activeProviderTypeTab === 'all') { @@ -449,7 +451,7 @@ export default { if (provider.provider_type) { return provider.provider_type === this.activeProviderTypeTab; } - + // 否则使用映射关系 const mappedType = this.oldVersionProviderTypeMapping[provider.type]; return mappedType === this.activeProviderTypeTab; @@ -657,6 +659,40 @@ export default { } }, + async copyProvider(providerToCopy) { + console.log('copyProvider triggered for:', providerToCopy); + // 1. 创建深拷贝 + const newProviderConfig = JSON.parse(JSON.stringify(providerToCopy)); + + // 2. 生成唯一的 ID + const generateUniqueId = (baseId) => { + let newId = `${baseId}_copy`; + let counter = 1; + const existingIds = this.config_data.provider.map(p => p.id); + while (existingIds.includes(newId)) { + newId = `${baseId}_copy_${counter}`; + counter++; + } + return newId; + }; + newProviderConfig.id = generateUniqueId(providerToCopy.id); + + // 3. 设置为禁用状态,等待用户手动开启 + newProviderConfig.enable = false; + + this.loading = true; + try { + // 4. 调用后端接口创建 + const res = await axios.post('/api/config/provider/new', newProviderConfig); + this.showSuccess(res.data.message || `成功复制并创建了 ${newProviderConfig.id}`); + this.getConfig(); // 5. 刷新列表 + } catch (err) { + this.showError(err.response?.data?.message || err.message); + } finally { + this.loading = false; + } + }, + deleteProvider(provider) { if (confirm(this.tm('messages.confirm.delete', { id: provider.id }))) { axios.post('/api/config/provider/delete', { id: provider.id }).then((res) => { @@ -694,14 +730,14 @@ export default { this.save_message_success = "error"; this.save_message_snack = true; }, - + // 获取供应商状态 async fetchProviderStatus() { if (this.loadingStatus) return; this.loadingStatus = true; this.showStatus = true; // 自动展开状态部分 - + // 1. 立即初始化UI为pending状态 this.providerStatuses = this.config_data.provider.map(p => ({ id: p.id,