后台店铺数据记录页新增 Tab 切换与重复 ASIN 分析;task-169/170 HTTP 客户端配置接入;dedupe/brand 相关改造
Build Backend JAR / build (push) Has been cancelled
Build Backend JAR / build (push) Has been cancelled
- 管理后台:店铺数据记录改为列表分页展示(去任务号/文件列/累计标题,'最新'改'更新时间'),新增'重复 ASIN' Tab 按跨店聚合展示 ASIN/店铺/分组/国家/日期/价格;修复失败/进行中任务被过滤不显示的问题 - task-169: BrandCheckHttpConfigResolver 从 aiimage.http-client.* 读取品牌检查超时/重试(默认同现状、钳制),附 8 条测试 - task-170: surefire 内存调整为 1536m - dedupe: DedupeRunService 重构(事务边界/进度)、新增 DedupeRunProgressVo、Controller 与结果 VO 调整,PermissionMenuService 相应适配 - brand/dedupe 前端:BrandDedupeTab/BrandPatrolDeleteTab 改造、新增 CountrySelector 组件与 country-options、类型与接口端对齐、测试更新 - 移除无引用文件:backend/static/logo.jpg、prompts/
This commit is contained in:
@@ -79,7 +79,7 @@
|
||||
{{ cleanRunning ? '清洗中...' : '开始清洗' }}
|
||||
</button>
|
||||
<span class="loading-msg">
|
||||
{{ cleanRunning ? '正在处理文件并上传结果,请稍候…' : '选择文件、列和 ID 规则后即可执行清洗,结果会显示在右侧供下载' }}
|
||||
{{ cleanRunning ? `正在处理文件并上传结果,已处理 ${cleanProgressProcessed}/${cleanSummary.total || 0} 个文件…` : '选择文件、列和 ID 规则后即可执行清洗,结果会显示在右侧供下载' }}
|
||||
</span>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -148,7 +148,7 @@ import { computed, onMounted, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import BrandTopBar from './BrandTopBar.vue'
|
||||
import { expandBrandFolderRecursive, type BrandExpandFolderItem } from '@/shared/api/brand'
|
||||
import { deleteDedupeHistory, getDedupeHistory, getDedupeResultDownloadUrl, getExcelInfo, runDedupe, type DedupeResultItem, type DedupeRunVo } from '@/shared/api/java-modules'
|
||||
import { deleteDedupeHistory, getDedupeHistory, getDedupeResultDownloadUrl, getDedupeRunProgress, getExcelInfo, runDedupe, type DedupeResultItem, type DedupeRunProgressVo, type DedupeRunVo } from '@/shared/api/java-modules'
|
||||
import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview'
|
||||
import { saveUrlWithProgress } from '@/shared/utils/download-progress'
|
||||
import { EXCEL_EXTENSIONS, checkSelectedFiles, guardBlocked } from '@/shared/dispatch-guard'
|
||||
@@ -163,6 +163,7 @@ const cleanKeepIntegerIds = ref(false)
|
||||
const cleanKeepUnderscoreIds = ref(true)
|
||||
const cleanKeepIntegerMainIdsWhenNoSubIds = ref(true)
|
||||
const cleanRunning = ref(false)
|
||||
const cleanProgressProcessed = ref(0)
|
||||
const cleanResultItems = ref<DedupeResultItem[]>([])
|
||||
const cleanSummary = ref<DedupeRunVo>({ total: 0, successCount: 0, failedCount: 0, items: [] })
|
||||
const cleanDisplayPaths = computed(() => cleanSelectedPaths.value.slice(0, 8))
|
||||
@@ -290,7 +291,7 @@ async function submitCleanRun() {
|
||||
|
||||
try {
|
||||
cleanRunning.value = true
|
||||
const result = await runDedupe({
|
||||
const progress = await runDedupe({
|
||||
files: cleanUploadedFiles.value.map((item) => ({ fileKey: item.fileKey, originalFilename: item.originalFilename, relativePath: item.relativePath })),
|
||||
selectedColumns: cleanSelectedColumns.value,
|
||||
keepIntegerIds: cleanKeepIntegerIds.value,
|
||||
@@ -301,6 +302,15 @@ async function submitCleanRun() {
|
||||
? cleanArchiveName.value
|
||||
: undefined,
|
||||
})
|
||||
const result = await pollDedupeRunProgress(progress.runId, (latest) => {
|
||||
cleanProgressProcessed.value = latest.processedCount
|
||||
cleanSummary.value = {
|
||||
total: latest.total,
|
||||
successCount: latest.successCount,
|
||||
failedCount: latest.failedCount,
|
||||
items: cleanResultItems.value,
|
||||
}
|
||||
})
|
||||
cleanSummary.value = result
|
||||
cleanResultItems.value = result.items || []
|
||||
await loadCleanHistory()
|
||||
@@ -325,6 +335,36 @@ async function submitCleanRun() {
|
||||
}
|
||||
}
|
||||
|
||||
// 去重任务进度轮询:2 秒一次,10 分钟超时(超时任务由后端继续执行,结果可在历史列表中查看)
|
||||
const DEDUPE_POLL_INTERVAL_MS = 2000
|
||||
const DEDUPE_POLL_TIMEOUT_MS = 10 * 60 * 1000
|
||||
|
||||
async function pollDedupeRunProgress(runId: string, onProgress?: (progress: DedupeRunProgressVo) => void): Promise<DedupeRunVo> {
|
||||
const deadline = Date.now() + DEDUPE_POLL_TIMEOUT_MS
|
||||
while (true) {
|
||||
const progress = await getDedupeRunProgress(runId)
|
||||
if (progress.status === 'not_found') {
|
||||
throw new Error('去重任务不存在或已过期')
|
||||
}
|
||||
if (progress.status !== 'running') {
|
||||
if (progress.status === 'failed') {
|
||||
throw new Error(progress.error || '去重任务执行失败')
|
||||
}
|
||||
if (!progress.result) {
|
||||
throw new Error(progress.error || '去重任务未返回结果')
|
||||
}
|
||||
return progress.result
|
||||
}
|
||||
onProgress?.(progress)
|
||||
if (Date.now() > deadline) {
|
||||
throw new Error(
|
||||
`去重任务仍在处理中(已处理 ${progress.processedCount}/${progress.total} 个文件),请稍后在历史列表中查看结果`,
|
||||
)
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, DEDUPE_POLL_INTERVAL_MS))
|
||||
}
|
||||
}
|
||||
|
||||
async function loadCleanHistory() {
|
||||
try {
|
||||
const response = await getDedupeHistory()
|
||||
|
||||
Reference in New Issue
Block a user