@@ -120,12 +127,12 @@
-
-
{{ shorten(item.source_path, 42) }}
-
输出文件:{{ item.output_path }}
+
{{ item.source_path || '-' }}
+
结果下载地址已生成
错误信息:{{ item.error }}
@@ -137,9 +144,17 @@
v-if="item.success && item.output_path"
type="button"
class="download"
- @click="openConvertResult(item)"
+ @click="downloadConvertResult(item)"
>
- 打开文件
+ 下载文件
+
+
@@ -175,7 +190,6 @@ function shorten(value: string, maxLength: number) {
}
function resetConvertResults() {
- convertResultItems.value = []
convertSummary.value = { total: 0, success_count: 0, failed_count: 0 }
convertOutputDir.value = ''
}
@@ -217,6 +231,26 @@ async function importConvertTemplate() {
ElMessage.success('模板导入成功')
}
+async function deleteConvertTemplate(templateId: string) {
+ const api = getPywebviewApi()
+ if (!api?.delete_txt_template) {
+ ElMessage.warning('当前环境不支持删除模板')
+ return
+ }
+
+ const result = await api.delete_txt_template(templateId)
+ if (!result.success) {
+ ElMessage.error(result.error || '删除模板失败')
+ return
+ }
+
+ if (convertTemplateId.value === templateId) {
+ convertTemplateId.value = ''
+ }
+ await loadConvertTemplates()
+ ElMessage.success('模板已删除')
+}
+
async function setConvertDefaultTemplate() {
const api = getPywebviewApi()
if (!api?.set_default_txt_template || !convertTemplateId.value) {
@@ -279,7 +313,7 @@ async function selectConvertFolder() {
async function submitConvertRun() {
const api = getPywebviewApi()
- if (!api?.convert_excel_to_uk_txt || !api?.select_folder) {
+ if (!api?.convert_excel_to_uk_txt) {
ElMessage.warning('当前环境不支持格式转换,请在桌面端打开')
return
}
@@ -289,13 +323,9 @@ async function submitConvertRun() {
}
try {
- const outputDir = await api.select_folder()
- if (!outputDir) return
-
convertRunning.value = true
const result = await api.convert_excel_to_uk_txt({
paths: convertSelectedPaths.value,
- output_dir: outputDir,
template_id: convertTemplateId.value,
})
@@ -304,13 +334,13 @@ async function submitConvertRun() {
return
}
- convertOutputDir.value = result.summary?.output_dir || outputDir
+ convertOutputDir.value = ''
convertSummary.value = {
total: result.summary?.total || 0,
success_count: result.summary?.success_count || 0,
failed_count: result.summary?.failed_count || 0,
}
- convertResultItems.value = result.items || []
+ await loadConvertHistory()
ElMessage.success('格式转换完成')
} catch (error) {
ElMessage.error(error instanceof Error ? error.message : '格式转换失败')
@@ -319,34 +349,68 @@ async function submitConvertRun() {
}
}
-async function openConvertOutputDir() {
+async function deleteConvertHistory(resultId: number) {
const api = getPywebviewApi()
- if (!api?.open_path || !convertOutputDir.value) {
- ElMessage.warning('当前环境不支持打开输出目录')
+ if (!api?.delete_history_item) {
+ ElMessage.warning('当前环境不支持删除历史')
return
}
- const result = await api.open_path(convertOutputDir.value)
+ const result = await api.delete_history_item('convert', resultId)
if (!result.success) {
- ElMessage.error(result.error || '打开目录失败')
+ ElMessage.error(result.error || '删除失败')
+ return
}
+ await loadConvertHistory()
+ ElMessage.success('已删除')
}
-async function openConvertResult(item: ConvertTxtResultItem) {
+async function downloadConvertResult(item: ConvertTxtResultItem) {
const api = getPywebviewApi()
- if (!api?.open_path || !item.output_path) {
- ElMessage.warning('当前环境不支持打开结果文件')
+ if (!item.output_path) {
+ ElMessage.warning('当前结果没有下载地址')
return
}
- const result = await api.open_path(item.output_path)
- if (!result.success) {
- ElMessage.error(result.error || '打开文件失败')
+ const today = new Date()
+ const yyyy = String(today.getFullYear())
+ const mm = String(today.getMonth() + 1).padStart(2, '0')
+ const dd = String(today.getDate()).padStart(2, '0')
+ const filename = `${yyyy}${mm}${dd}.txt`
+ if (api?.save_file_from_url) {
+ const result = await api.save_file_from_url(item.output_path, filename)
+ if (result.success) {
+ ElMessage.success(`已保存:${result.path || filename}`)
+ } else if (result.error && result.error !== '用户取消') {
+ ElMessage.error(result.error)
+ }
+ return
+ }
+
+ window.open(item.output_path, '_blank')
+}
+
+async function loadConvertHistory() {
+ const api = getPywebviewApi()
+ if (!api?.get_convert_history) return
+
+ try {
+ const response = await api.get_convert_history()
+ if (!response.success || !response.items) return
+ convertResultItems.value = response.items
+ convertSummary.value = {
+ total: response.items.length,
+ success_count: response.items.filter((item) => item.success).length,
+ failed_count: response.items.filter((item) => !item.success).length,
+ }
+ } catch {
+ // ignore history load errors
}
}
onMounted(() => {
loadConvertTemplates().catch(() => undefined)
+ loadConvertHistory().catch(() => undefined)
})
@@ -374,7 +438,10 @@ onMounted(() => {
.template-tag { margin-left: 8px; padding: 2px 8px; border-radius: 999px; font-size: 11px; color: #8fd0ff; background: rgba(52, 152, 219, 0.14); }
.template-tag.muted { color: #b8b8b8; background: rgba(255, 255, 255, 0.08); }
.compact-row { margin-top: 4px; }
-.radio-item { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; padding: 10px 12px; border-radius: 8px; background: #252525; border: 1px solid #2a2a2a; margin-bottom: 8px; transition: all 0.2s ease; }
+ .radio-item { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; padding: 10px 12px; border-radius: 8px; background: #252525; border: 1px solid #2a2a2a; margin-bottom: 8px; transition: all 0.2s ease; }
+.template-item-content { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; }
+.template-delete-btn { padding: 6px 10px; border: 1px solid #5c2f2f; border-radius: 6px; background: rgba(231, 76, 60, 0.12); color: #ff8f8f; font-size: 12px; cursor: pointer; }
+.template-delete-btn:hover { background: rgba(231, 76, 60, 0.2); }
.radio-item:hover, .radio-item.active { background: #2a2a2a; border-color: #3a3a3a; }
.radio-item input { margin-top: 3px; }
.label { font-weight: 500; color: #e0e0e0; font-size: 13px; }
diff --git a/frontend-vue/src/pages/brand/components/BrandDedupeTab.vue b/frontend-vue/src/pages/brand/components/BrandDedupeTab.vue
index 5c35ef3..a6d83c8 100644
--- a/frontend-vue/src/pages/brand/components/BrandDedupeTab.vue
+++ b/frontend-vue/src/pages/brand/components/BrandDedupeTab.vue
@@ -79,7 +79,7 @@
{{ cleanRunning ? '清洗中...' : '开始清洗' }}
- {{ cleanRunning ? '正在处理文件,请稍候…' : '选择文件、列和 ID 规则后即可执行本地清洗' }}
+ {{ cleanRunning ? '正在处理文件并上传结果,请稍候…' : '选择文件、列和 ID 规则后即可执行清洗,结果会显示在右侧供下载' }}
@@ -106,9 +106,6 @@
@@ -118,8 +115,8 @@
-
-
{{ shorten(item.source_path, 42) }}
-
输出文件:{{ item.output_path }}
+
{{ item.source_path || '-' }}
+
结果下载地址已生成
错误信息:{{ item.error }}
@@ -131,9 +128,17 @@
v-if="item.success && item.output_path"
type="button"
class="download"
- @click="openCleanResult(item)"
+ @click="downloadCleanResult(item)"
>
- 打开文件
+ 下载文件
+
+
@@ -145,7 +150,7 @@
diff --git a/frontend-vue/src/pages/brand/components/BrandSplitTab.vue b/frontend-vue/src/pages/brand/components/BrandSplitTab.vue
index 93c3382..b1debca 100644
--- a/frontend-vue/src/pages/brand/components/BrandSplitTab.vue
+++ b/frontend-vue/src/pages/brand/components/BrandSplitTab.vue
@@ -90,7 +90,7 @@
{{ splitRunning ? '拆分中...' : '开始拆分' }}
- {{ splitRunning ? '正在拆分文件,请稍候…' : '选择文件、保留列和拆分规则后即可执行本地拆分' }}
+ {{ splitRunning ? '正在拆分并上传结果,请稍候…' : '选择文件、保留列和拆分规则后即可执行拆分,结果会显示在右侧供下载' }}
@@ -116,9 +116,6 @@
@@ -128,8 +125,8 @@
-
-
{{ shorten(item.source_path, 42) }}
-
输出文件:{{ item.output_path }}
+
{{ item.source_path || '-' }}
+
结果下载地址已生成
包含 {{ item.row_count }} 条数据
错误信息:{{ item.error }}
@@ -142,9 +139,17 @@
v-if="item.success && item.output_path"
type="button"
class="download"
- @click="openSplitResult(item)"
+ @click="downloadSplitResult(item)"
>
- 打开文件
+ 下载文件
+
+
@@ -156,7 +161,7 @@
diff --git a/frontend-vue/src/pages/brand/index.vue b/frontend-vue/src/pages/brand/index.vue
index aa23520..3e3f025 100644
--- a/frontend-vue/src/pages/brand/index.vue
+++ b/frontend-vue/src/pages/brand/index.vue
@@ -3,42 +3,26 @@
- 南日AI-亚马逊
+ 数富AI-亚马逊
返回首页
-
@@ -55,13 +39,8 @@
选择文件夹
-
+
@@ -117,12 +96,7 @@
{{ runMode === 'immediate' ? '立即运行' : '添加任务' }}
生成中,请稍候…
-
+
取消生成
@@ -137,8 +111,10 @@
@@ -151,9 +127,12 @@
@@ -180,10 +159,7 @@
-
+
@@ -196,21 +172,13 @@
{{ getStatusLabel(task.status) }}
-
+
取消
-
+
下载结果
@@ -560,7 +528,7 @@ async function downloadTaskResult(task: BrandTaskItem) {
}
onMounted(() => {
- document.title = '亚马逊 - 南日AI'
+ document.title = '亚马逊 - 数富AI'
loadTasks().catch(() => undefined)
taskRefreshTimer = window.setInterval(() => {
loadTasks().catch(() => undefined)
diff --git a/frontend-vue/src/pages/home/index.vue b/frontend-vue/src/pages/home/index.vue
index edba641..2dafe26 100644
--- a/frontend-vue/src/pages/home/index.vue
+++ b/frontend-vue/src/pages/home/index.vue
@@ -2,7 +2,7 @@