diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java index ff996ddb..713d55dc 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/deletebrand/service/DeleteBrandRunService.java @@ -379,39 +379,6 @@ public class DeleteBrandRunService { FileTaskEntity taskEntity = taskById.get(entity.getTaskId()); item.setCreatedAt(fmt(taskEntity == null ? null : taskEntity.getCreatedAt())); item.setFinishedAt(fmt(taskEntity == null ? null : taskEntity.getFinishedAt())); - List taskItems = null; - if (taskItems != null && entity.getSourceFilename() != null && !entity.getSourceFilename().isBlank()) { - for (DeleteBrandResultItemVo candidate : taskItems) { - if (candidate == null) { - continue; - } - if (entity.getSourceFilename().equals(candidate.getSourceFilename())) { - item.setMatched(candidate.isMatched()); - item.setMatchStatus(candidate.getMatchStatus()); - item.setMatchMessage(candidate.getMatchMessage()); - // 如果物理结果已经成功,说明已经处理过,强制标记为匹配成功 - if (item.isSuccess() && candidate.getShopId() != null && !candidate.getShopId().isBlank()) { - item.setMatched(true); - item.setMatchStatus(ZiniaoShopIndexService.MATCH_STATUS_MATCHED); - item.setMatchMessage(null); - } - - item.setShopId(candidate.getShopId()); - item.setCompanyName(candidate.getCompanyName()); - item.setPlatform(candidate.getPlatform()); - item.setOpenStoreUrl(candidate.getOpenStoreUrl()); - - // 历史表里可能只有通用 errorMessage,优先返回任务当时的真实 error - // 但如果物理结果已成功,就不应该再显示所谓“未匹配”的报错 - if (item.isSuccess()) { - item.setError(null); - } else if ((item.getError() == null || item.getError().isBlank()) && candidate.getError() != null && !candidate.getError().isBlank()) { - item.setError(candidate.getError()); - } - break; - } - } - } } return item; }).toList()); diff --git a/frontend-vue/src/pages/brand/components/BrandAppearancePatentTab.vue b/frontend-vue/src/pages/brand/components/BrandAppearancePatentTab.vue index c0a856cd..e9923113 100644 --- a/frontend-vue/src/pages/brand/components/BrandAppearancePatentTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandAppearancePatentTab.vue @@ -258,24 +258,6 @@ function effectivePatentToken() { return getStoredApiSecret('appearance-patent-token').trim() } -function maskSecret(secret: string) { - if (!secret) return '' - if (secret.length <= 10) return '***' - return `${secret.slice(0, 6)}***${secret.slice(-4)}` -} - -function payloadForDisplay }>(payload: T) { - return { - ...payload, - data: payload.data - ? { - ...payload.data, - api_key: maskSecret(String(payload.data.api_key || '')), - patent_token: maskSecret(String(payload.data.patent_token || '')), - } - : payload.data, - } -} function uidForStorage() { return typeof window !== 'undefined' ? window.localStorage.getItem('uid') || '0' : '0' diff --git a/frontend-vue/src/pages/brand/components/BrandBrandTab.vue b/frontend-vue/src/pages/brand/components/BrandBrandTab.vue index 2041db04..085e4b5f 100644 --- a/frontend-vue/src/pages/brand/components/BrandBrandTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandBrandTab.vue @@ -159,9 +159,6 @@ function baseName(path: string) { let pollTimer: number | null = null -function hasRunning() { - return tasks.value.some((item) => isRunning(item)) -} function isRunning(item: BrandTaskItem) { return (item.status || '').toLowerCase() === 'running' @@ -452,19 +449,6 @@ async function downloadTemplate(kind: 'xlsx' | 'zip') { } } -function schedulePoll() { - if (pollTimer) { - window.clearTimeout(pollTimer) - pollTimer = null - } - pollTimer = window.setTimeout(async () => { - await loadTasks() - if (hasRunning()) { - schedulePoll() - } - }, 3000) -} - onMounted(() => { void loadTasks() }) diff --git a/frontend-vue/src/pages/brand/components/BrandCollectDataTab.vue b/frontend-vue/src/pages/brand/components/BrandCollectDataTab.vue index 2667632c..71693ec6 100644 --- a/frontend-vue/src/pages/brand/components/BrandCollectDataTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandCollectDataTab.vue @@ -264,11 +264,6 @@ const progressLoop = useTaskProgressLoop({ const displayFileNames = computed(() => selectedFileNames.value.slice(0, 8)) -function countryLabel(code: string) { - const row = COUNTRY_OPTIONS.find((o) => o.code === code) - return row?.label ?? code -} - function selectCountry(code: string) { if (!COUNTRY_OPTIONS.some((row) => row.code === code)) return if (selectedCountryCode.value === code) return diff --git a/frontend-vue/src/pages/brand/components/BrandConvertTab.vue b/frontend-vue/src/pages/brand/components/BrandConvertTab.vue index 2edfbab9..3792555d 100644 --- a/frontend-vue/src/pages/brand/components/BrandConvertTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandConvertTab.vue @@ -154,17 +154,14 @@ import { ElMessage } from 'element-plus' import AmazonToolPageShell from '@/pages/amazon/components/AmazonToolPageShell.vue'; import TaskCenterPanel from '@/shared/components/tasks/TaskCenterPanel.vue' import type { TaskItemView, TaskStatCard } from '@/shared/components/tasks/types' -import { expandBrandFolderRecursive, getBrandTemplateXlsxUrl, getBrandTemplateZipUrl } from '@/shared/api/brand' +import { expandBrandFolderRecursive } from '@/shared/api/brand' import type { BrandExpandFolderItem } from '@/shared/api/brand' import { deleteConvertHistory, - deleteConvertTemplate, getConvertHistory, getConvertResultDownloadUrl, getConvertTemplates, - importConvertTemplate, runConvert, - setDefaultConvertTemplate, type ConvertResultItem, type ConvertTemplateVo, } from '@/shared/api/java-modules' @@ -180,18 +177,11 @@ const convertRunning = ref(false) const convertResultItems = ref([]) const convertTemplates = ref([]) const convertTemplateId = ref('') -const templateUploading = ref(false) -const templateSavingDefault = ref(false) -const templateDeleting = ref(false) -const templateInputRef = ref() const convertDisplayPaths = computed(() => convertSelectedPaths.value.slice(0, 8)) const currentConvertTemplate = computed( () => convertTemplates.value.find((item) => item.id === convertTemplateId.value) || null, ) -const canDeleteCurrentTemplate = computed( - () => Boolean(currentConvertTemplate.value && !currentConvertTemplate.value.builtIn), -) // ---- 右侧任务面板统一视图(TaskCenterPanel)---- const convertCards = computed(() => [ @@ -362,127 +352,6 @@ async function selectConvertFolder() { } } -function openTemplatePicker() { - templateInputRef.value?.click() -} - -async function handleTemplateFileChange(event: Event) { - const input = event.target as HTMLInputElement - const file = input.files?.[0] - input.value = '' - - if (!file) { - return - } - - // 浏览器侧直接读内容的唯一入口:扩展名与内容都在这里拦,空模板传上去后 - // 转换阶段每个文件都会失败,不如在上传时就说清楚。 - if (!(await passGuard(checkSelectedFiles([file.name], { allowedExtensions: ['.txt'] })))) { - return - } - - try { - templateUploading.value = true - const templateContent = await file.text() - if (!templateContent.trim()) { - await passGuard( - guardBlocked( - '模板内容为空', - `${file.name} 里没有任何内容。\n空模板无法用于格式转换,请填好列映射后重新上传。`, - 'convert.empty-template', - ), - ) - return - } - const templateName = file.name.replace(/\.[^.]+$/, '') || file.name - - const template = await importConvertTemplate({ - templateName, - templateContent, - }) - - await loadConvertTemplates(template.id) - ElMessage.success(`模板已上传:${template.templateName}`) - } catch (error) { - ElMessage.error(error instanceof Error ? error.message : '模板上传失败') - } finally { - templateUploading.value = false - } -} - -async function saveCurrentTemplateAsDefault() { - if (!currentConvertTemplate.value) { - ElMessage.warning('请先选择模板') - return - } - - try { - templateSavingDefault.value = true - await setDefaultConvertTemplate(currentConvertTemplate.value.templateCode || currentConvertTemplate.value.id) - await loadConvertTemplates(currentConvertTemplate.value.id) - ElMessage.success('默认模板已更新') - } catch (error) { - ElMessage.error(error instanceof Error ? error.message : '设置默认模板失败') - } finally { - templateSavingDefault.value = false - } -} - -async function removeCurrentTemplate() { - if (!currentConvertTemplate.value) { - ElMessage.warning('请先选择模板') - return - } - if (currentConvertTemplate.value.builtIn) { - ElMessage.warning('内置模板不允许删除') - return - } - - try { - templateDeleting.value = true - await deleteConvertTemplate(currentConvertTemplate.value.templateCode || currentConvertTemplate.value.id) - const deletedTemplateId = currentConvertTemplate.value.id - await loadConvertTemplates() - if (convertTemplateId.value === deletedTemplateId) { - convertTemplateId.value = convertTemplates.value[0]?.id || '' - } - ElMessage.success('模板已删除') - } catch (error) { - ElMessage.error(error instanceof Error ? error.message : '删除模板失败') - } finally { - templateDeleting.value = false - } -} - -async function saveTemplateFromUrl(url: string, fallbackFilename: string, bridgeMethod?: 'save_template_xlsx' | 'save_template_zip') { - const api = getPywebviewApi() - - if (bridgeMethod && api?.[bridgeMethod]) { - const result = await api[bridgeMethod]!() - if (result.success) { - ElMessage.success(`已保存:${result.path || fallbackFilename}`) - } else if (result.error && result.error !== '用户取消') { - ElMessage.error(result.error) - } - return - } - - const result = await saveUrlWithProgress(url, fallbackFilename) - if (result.success) { - ElMessage.success(`已保存:${result.path || fallbackFilename}`) - } else if (result.error && result.error !== '用户取消') { - ElMessage.error(result.error) - } -} - -async function downloadTemplateXlsx() { - await saveTemplateFromUrl(getBrandTemplateXlsxUrl(), '品牌文档格式_模板.xlsx', 'save_template_xlsx') -} - -async function downloadTemplateZip() { - await saveTemplateFromUrl(getBrandTemplateZipUrl(), '模板2-以文件夹方式上传.zip', 'save_template_zip') -} - async function submitConvertRun() { if (!convertUploadedFiles.value.length) { ElMessage.warning('请先选择待转换 Excel 文件或文件夹') diff --git a/frontend-vue/src/pages/brand/components/BrandDeleteBrandTab.vue b/frontend-vue/src/pages/brand/components/BrandDeleteBrandTab.vue index 9ebf46f5..819495ca 100644 --- a/frontend-vue/src/pages/brand/components/BrandDeleteBrandTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandDeleteBrandTab.vue @@ -119,7 +119,6 @@ import { deleteDeleteBrandHistory, getDeleteBrandHistory, getDeleteBrandResultDownloadUrl, - getDeleteBrandTaskDetails, getDeleteBrandTaskProgress, getDeleteBrandTaskDownloadUrl, runDeleteBrand, diff --git a/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue b/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue index ce32813d..6030796d 100644 --- a/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue @@ -213,7 +213,6 @@ import ModuleTemplateDownload from '@/shared/components/ModuleTemplateDownload.v import ZiniaoVersionSetting from '@/shared/components/ZiniaoVersionSetting.vue' import TaskCenterPanel from '@/shared/components/tasks/TaskCenterPanel.vue' import type { TaskItemView, TaskStatCard } from '@/shared/components/tasks/types' -import { LISTING_FILTER_OPTIONS, type ListingFilterValue } from '@/pages/brand/components/listingFilters' import { expandBrandFolderRecursive } from '@/shared/api/brand' import { getPywebviewApi, type PywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview' import { getTaskPollIntervalMs } from '@/shared/task-progress-config' @@ -242,7 +241,6 @@ import { getPriceTrackLoopRun, getPriceTrackResultDownloadUrl, getPriceTrackTaskProgressBatch, - getPriceTrackTasksBatch, getTaskSkipPriceAsinsPaginated, listPriceTrackCandidates, matchPriceTrackShops, @@ -942,88 +940,6 @@ async function removeMatchedRow(row: PriceTrackShopQueueItem) { } } -async function pushToPythonQueueLegacy() { - if (!hasValidMode.value) { - ElMessage.warning('请至少选择一个跟价模式') - return - } - if (asinModeEnabled.value && !asinFiles.value.length) { - ElMessage.warning('请先选择 ASIN 文件') - return - } - const api = getPywebviewApi() - if (!api?.enqueue_json) { - ElMessage.error('当前环境未启用 pywebview enqueue_json') - return - } - const matchedRows = matchedItems.value.filter((i) => i.matched) - if (!matchedRows.length) { - ElMessage.warning('无可用匹配店铺') - return - } - pushing.value = true - queuePayloadText.value = '' - try { - // 1. 先调用 Java API 创建任务(落库,含 skip ASIN) - const taskReq = { - userId: 0, // 会被 java-modules 自动填充 - statusMode: statusModeEnabled.value, - asinMode: asinModeEnabled.value, - items: matchedRows as unknown as Record[], - asinFiles: resolveAsinRequestPaths(), - countryCodes: resolveCountryCodesForRequest(), - } - const taskVo = await createPriceTrackTask(taskReq) - taskSnapshots.value = { - ...taskSnapshots.value, - [taskVo.taskId]: { - task: { id: taskVo.taskId, status: 'RUNNING' }, - items: taskVo.items, - }, - } - taskDetails.value = { - ...taskDetails.value, - [taskVo.taskId]: 'RUNNING', - } - saveTaskSnapshotsToStorage() - saveTaskDetailsToStorage() - - const firstRow = matchedRows[0] - const asinRowsByCountry = await loadAsinRowsForAppClient(taskVo) - const minimumPriceByCountryAndAsin = buildMinimumPriceMapForAppClient(taskVo, asinRowsByCountry) - - // 2. 推送 app_client 当前消费的字段 - const queuePayload = { - type: 'price-track-run', - ts: Date.now(), - data: { - task_id: taskVo.taskId, - ziniao_version: ziniaoVersion.value, - shop_name: (firstRow.shopName || '').trim(), - shopName: (firstRow.shopName || '').trim(), - companyName: firstRow.companyName || '', - shopMallName: firstRow.shopMallName || '', - country_codes: resolveCountryCodesForRequest(), - mode: priceTrackModeForAppClient(), - asin_rows_by_country: asinRowsByCountry, - minimum_price_by_country_and_asin: minimumPriceByCountryAndAsin, - }, - } - queuePayloadText.value = JSON.stringify(queuePayload, null, 2) - - await enqueueCreatedTask(api, taskVo.taskId, queuePayload) - queuePushResult.value = `任务 ${taskVo.taskId} 已入队,等待执行完成...` - addPollingTask(taskVo.taskId) - scheduleNextPoll(true) - ElMessage.success('已启动任务') - } catch (e) { - queuePushResult.value = e instanceof Error ? e.message : '推送异常' - ElMessage.error(queuePushResult.value) - } finally { - pushing.value = false - } -} - // ========== 任务状态轮询 ========== async function buildQueuePayload(taskVo: PriceTrackCreateTaskVo, row: PriceTrackShopQueueItem) { const shopName = (row.shopName || '').trim() @@ -1155,11 +1071,6 @@ async function waitForTaskTerminal(taskId: number) { } } -async function pushToPythonQueue() { - autoQueueEnabled.value = true - await processMatchedQueue() -} - function nextMatchedQueueItem() { return matchedItems.value.find((item) => item.matched) } diff --git a/frontend-vue/src/pages/brand/components/BrandProductRiskTab.vue b/frontend-vue/src/pages/brand/components/BrandProductRiskTab.vue index 5efa2f15..3cad1be5 100644 --- a/frontend-vue/src/pages/brand/components/BrandProductRiskTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandProductRiskTab.vue @@ -159,7 +159,6 @@ import { getProductRiskHistory, getProductRiskResultDownloadUrl, getProductRiskTaskProgressBatch, - getProductRiskTasksBatch, listProductRiskCandidates, matchProductRiskShops, putProductRiskCountryPreference, diff --git a/frontend-vue/src/pages/brand/components/BrandPublishTab.vue b/frontend-vue/src/pages/brand/components/BrandPublishTab.vue index ae80f9a7..43af298d 100644 --- a/frontend-vue/src/pages/brand/components/BrandPublishTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandPublishTab.vue @@ -452,18 +452,6 @@ function toPublishTaskView(detail: PublishTaskDetailVo): TaskItemView { } } -const summary = computed(() => { - const files = visibleTasks.value.flatMap((detail) => detail.files || []) - const successCount = files.filter((file) => ['SUCCESS', 'COMPLETED'].includes(normalizeStatus(file.status))).length - const failedCount = files.filter((file) => ['FAILED', 'CANCELLED'].includes(normalizeStatus(file.status))).length - return { - total: files.length, - completed: successCount + failedCount, - successCount, - failedCount, - } -}) - const operationHint = computed(() => { if (uploading.value) return '正在逐个上传文件到后端...' if (parsing.value) return '正在解析 Excel、匹配店铺并创建批次...' diff --git a/frontend-vue/src/pages/brand/components/BrandQueryAsinTab.vue b/frontend-vue/src/pages/brand/components/BrandQueryAsinTab.vue index ae33068c..8bb15a03 100644 --- a/frontend-vue/src/pages/brand/components/BrandQueryAsinTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandQueryAsinTab.vue @@ -618,13 +618,6 @@ function isRecordMissingError(error: unknown) { return /记录不存在|任务不存在|不存在|已删除|not\s*found|404/i.test(message); } -function removeMatchedRowLocally(row: QueryAsinShopQueueItem) { - matchedItems.value = matchedItems.value.filter( - (item) => rowKeyForMatch(item) !== rowKeyForMatch(row), - ); - saveMatchedItems(); -} - function removeHistoryItemLocally(item: QueryAsinHistoryItem) { historyItems.value = historyItems.value.filter((row) => { if (item.resultId != null && row.resultId === item.resultId) return false; diff --git a/frontend-vue/src/pages/brand/components/BrandShopMatchTab.vue b/frontend-vue/src/pages/brand/components/BrandShopMatchTab.vue index 692a7ae9..4e79bc88 100644 --- a/frontend-vue/src/pages/brand/components/BrandShopMatchTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandShopMatchTab.vue @@ -115,7 +115,7 @@ import TaskCenterPanel from '@/shared/components/tasks/TaskCenterPanel.vue' import type { TaskItemView, TaskStatCard } from '@/shared/components/tasks/types' import ZiniaoVersionSetting from '@/shared/components/ZiniaoVersionSetting.vue' import { LISTING_FILTER_OPTIONS, type ListingFilterValue } from '@/pages/brand/components/listingFilters' -import { activateShopMatchTask, addShopMatchCandidate, createShopMatchTask, deleteShopMatchCandidate, deleteShopMatchHistory, deleteShopMatchTask, getShopMatchCountryPreference, getShopMatchDashboard, getShopMatchHistory, getShopMatchResultDownloadUrl, getShopMatchTaskProgressBatch, getShopMatchTasksBatch, listShopMatchCandidates, matchShopMatchShops, putShopMatchCountryPreference, type ShopMatchCandidateVo, type ShopMatchCreateTaskItem, type ShopMatchDashboardVo, type ShopMatchHistoryItem, type ShopMatchShopQueueItem, type ShopMatchTaskDetailVo } from '@/shared/api/java-modules' +import { activateShopMatchTask, addShopMatchCandidate, createShopMatchTask, deleteShopMatchCandidate, deleteShopMatchHistory, deleteShopMatchTask, getShopMatchCountryPreference, getShopMatchDashboard, getShopMatchHistory, getShopMatchResultDownloadUrl, getShopMatchTaskProgressBatch, listShopMatchCandidates, matchShopMatchShops, putShopMatchCountryPreference, type ShopMatchCandidateVo, type ShopMatchCreateTaskItem, type ShopMatchDashboardVo, type ShopMatchHistoryItem, type ShopMatchShopQueueItem, type ShopMatchTaskDetailVo } from '@/shared/api/java-modules' import { getPywebviewApi } from '@/shared/bridges/pywebview' import { getTaskPollIntervalMs } from '@/shared/task-progress-config' import { createCategorizedTimers } from '@/shared/utils/categorized-timers' diff --git a/frontend-vue/src/pages/brand/components/BrandSimilarAsinTab.vue b/frontend-vue/src/pages/brand/components/BrandSimilarAsinTab.vue index 624da140..91224eaa 100644 --- a/frontend-vue/src/pages/brand/components/BrandSimilarAsinTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandSimilarAsinTab.vue @@ -134,7 +134,6 @@ import { type SimilarAsinParseVo, type UploadedFileRef, type UploadFileVo, - uploadTempFileToJava, } from '@/shared/api/java-modules' import { expandBrandFolderRecursive, type BrandExpandFolderItem } from '@/shared/api/brand' import { getPywebviewApi, type ProxyMode } from '@/shared/bridges/pywebview' diff --git a/frontend-vue/src/pages/brand/components/BrandVariantTab.vue b/frontend-vue/src/pages/brand/components/BrandVariantTab.vue index 50ed920b..461dded1 100644 --- a/frontend-vue/src/pages/brand/components/BrandVariantTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandVariantTab.vue @@ -288,15 +288,6 @@ function statusText(status?: number | string) { return String(status ?? '未知') } -function statusClass(status?: number | string) { - const numeric = Number(status) - if (numeric === 1 || String(status).toLowerCase() === 'running') return 'running' - if (numeric === 2 || ['success', 'completed', 'done'].includes(String(status).toLowerCase())) return 'success' - if (numeric === 3 || ['failed', 'error'].includes(String(status).toLowerCase())) return 'failed' - if (['cancelled', 'stopped'].includes(String(status).toLowerCase())) return 'cancelled' - return 'pending' -} - function isBusy(status?: number | string) { const numeric = Number(status) return numeric === 0 || numeric === 1 || String(status).toLowerCase() === 'pending' || String(status).toLowerCase() === 'running' @@ -320,10 +311,6 @@ function latestMessage(item: VariantEntry) { return (raw || '').trim() || '等待后台处理…' } -function taskMeta(item: VariantEntry) { - return { source: item.meta?.source || '' } -} - function resultFiles(item?: VariantEntry) { return toArray(item?.file_url) } diff --git a/frontend-vue/src/pages/brand/components/BrandWithdrawTab.vue b/frontend-vue/src/pages/brand/components/BrandWithdrawTab.vue index 61dc442f..a058c515 100644 --- a/frontend-vue/src/pages/brand/components/BrandWithdrawTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandWithdrawTab.vue @@ -762,13 +762,6 @@ function isRecordMissingError(error: unknown) { return /记录不存在|任务不存在|不存在|已删除|not\s*found|404/i.test(message); } -function removeMatchedRowLocally(row: WithdrawShopQueueItem) { - matchedItems.value = matchedItems.value.filter( - (item) => rowKeyForMatch(item) !== rowKeyForMatch(row), - ); - saveMatchedItems(); -} - function removeHistoryItemLocally(item: WithdrawHistoryItem) { historyItems.value = historyItems.value.filter((row) => { if (item.resultId != null && row.resultId === item.resultId) return false; diff --git a/frontend-vue/src/pages/home/DesktopHomePage.vue b/frontend-vue/src/pages/home/DesktopHomePage.vue index 5ae5fa16..f7ce2cbd 100644 --- a/frontend-vue/src/pages/home/DesktopHomePage.vue +++ b/frontend-vue/src/pages/home/DesktopHomePage.vue @@ -164,13 +164,6 @@ function toggleUpdatePanel() { updatePanel.value = !updatePanel.value } -function showTip(message: string) { - toastText.value = message - window.setTimeout(() => { - if (toastText.value === message) toastText.value = '' - }, 2600) -} - async function fetchVersion() { try { const resp = await window.fetch('/api/version', { credentials: 'same-origin' }) diff --git a/frontend-vue/src/pages/image-video/components/DeliveryVideoWorkspace.vue b/frontend-vue/src/pages/image-video/components/DeliveryVideoWorkspace.vue index 3758f792..b7c476e5 100644 --- a/frontend-vue/src/pages/image-video/components/DeliveryVideoWorkspace.vue +++ b/frontend-vue/src/pages/image-video/components/DeliveryVideoWorkspace.vue @@ -91,7 +91,7 @@ :source-url="currentWorkspace.sceneAsset.sourceUrl" :loading="currentWorkspace.sceneAsset.uploading" allow-url compact action-label="上传场景图" selected-label="场景图" url-label="场景图链接" url-placeholder="也可以粘贴场景图链接" @select="(file) => setAsset(activeTab, 'sceneAsset', file)" - @url-change="(url) => setAssetUrl(activeTab, 'sceneAsset', url, 'image/*')" preview-clickable + @url-change="(url) => setAssetUrl(activeTab, 'sceneAsset', url)" preview-clickable @preview="openImagePreview" @clear="clearAsset(activeTab, 'sceneAsset')" /> @@ -190,7 +190,7 @@ :source-url="currentWorkspace.modelAsset.sourceUrl" :loading="currentWorkspace.modelAsset.uploading" allow-url compact preview-clickable action-label="上传模特图" selected-label="模特图" url-label="模特图链接" url-placeholder="也可以粘贴模特图链接" @select="(file) => setAsset(activeTab, 'modelAsset', file)" - @url-change="(url) => setAssetUrl(activeTab, 'modelAsset', url, 'image/*')" @preview="openImagePreview" + @url-change="(url) => setAssetUrl(activeTab, 'modelAsset', url)" @preview="openImagePreview" @clear="clearAsset(activeTab, 'modelAsset')" /> @@ -277,7 +277,7 @@ :source-url="currentWorkspace.speechAsset.sourceUrl" :loading="currentWorkspace.speechAsset.uploading" allow-url compact action-label="上传背景音乐" selected-label="背景音乐" url-label="背景音乐链接" @select="(file) => setAsset(activeTab, 'speechAsset', file)" - @url-change="(url) => setAssetUrl(activeTab, 'speechAsset', url, 'audio/*')" + @url-change="(url) => setAssetUrl(activeTab, 'speechAsset', url)" @clear="clearAsset(activeTab, 'speechAsset')" /> @@ -786,7 +786,7 @@ function resolvePreviewKindFromMediaType(mediaType: string): PreviewKind { return 'file' } -function resolveMediaTypeFromUrl(url: string, accept = ''): MediaType { +function resolveMediaTypeFromUrl(url: string): MediaType { const cleanUrl = url.split('?')[0]?.toLowerCase() || '' if (/\.(png|jpe?g|webp|gif|bmp|svg)$/.test(cleanUrl)) return 'image' if (/\.(mp4|mov|webm|m4v|ogg|avi|mkv)$/.test(cleanUrl)) return 'video' @@ -794,10 +794,10 @@ function resolveMediaTypeFromUrl(url: string, accept = ''): MediaType { return 'file' } -function setAssetUrl(tab: WorkspaceTab, assetKey: AssetKey, url: string, accept = '') { +function setAssetUrl(tab: WorkspaceTab, assetKey: AssetKey, url: string) { const target = workspaces[tab][assetKey] const normalizedUrl = (url || '').trim() - const mediaType = resolveMediaTypeFromUrl(normalizedUrl, accept) + const mediaType = resolveMediaTypeFromUrl(normalizedUrl) target.sourceUrl = normalizedUrl target.previewUrl = normalizedUrl target.fileName = normalizedUrl ? '在线素材' : '' @@ -855,7 +855,7 @@ function setProductAssetUrl(tab: WorkspaceTab, index: number, url: string) { target.sourceUrl = normalizedUrl target.previewUrl = normalizedUrl target.fileName = normalizedUrl ? '在线素材' : '' - target.mediaType = resolveMediaTypeFromUrl(normalizedUrl, 'image/*') + target.mediaType = resolveMediaTypeFromUrl(normalizedUrl) target.previewKind = resolvePreviewKindFromMediaType(target.mediaType) scheduleDeliveryGridLayout() } @@ -1517,26 +1517,6 @@ function findMediaFileUrl(value: unknown) { ]) || findUrlMatching(value, isMediaFileUrl) } -function resolveWorkflowStatus(value: unknown) { - return (findTextByKeys(value, [ - 'execute_status', - 'executeStatus', - 'workflow_status', - 'workflowStatus', - 'status', - ]) || '').toUpperCase() -} - -function isTerminalWorkflowStatus(status: string) { - const normalized = (status || '').toUpperCase() - return ['SUCCESS', 'SUCCEEDED', 'COMPLETED', 'DONE', 'FINISHED', 'FAILED', 'FAIL', 'ERROR', 'CANCELED', 'CANCELLED'].includes(normalized) -} - -function isFailedWorkflowStatus(status: string) { - const normalized = (status || '').toUpperCase() - return ['FAILED', 'FAIL', 'ERROR', 'CANCELED', 'CANCELLED'].includes(normalized) -} - function findTextByKeys(value: unknown, keys: string[]): string { if (!value) return '' const normalizedKeys = keys.map((key) => key.toLowerCase()) @@ -1751,7 +1731,7 @@ async function synthesizeVoice() { const result = await waitForImageVideoTask(ticket) const audioUrl = findMediaFileUrl(result) if (audioUrl) { - setAssetUrl(activeTab.value, 'speechAsset', audioUrl, 'audio/*') + setAssetUrl(activeTab.value, 'speechAsset', audioUrl) setVoiceStatus('语音合成完成,已写入最终配音文件', 'success') ElMessage.success('语音合成完成,已写入口播音频链接') } else { @@ -1794,7 +1774,7 @@ async function setVoiceCloneAsset(file: File) { function setVoiceCloneUrl(url: string) { const normalizedUrl = (url || '').trim() - const mediaType = resolveMediaTypeFromUrl(normalizedUrl, 'audio/*,video/*') + const mediaType = resolveMediaTypeFromUrl(normalizedUrl) voiceCloneAsset.sourceUrl = normalizedUrl voiceCloneAsset.previewUrl = normalizedUrl voiceCloneAsset.fileName = normalizedUrl ? '在线克隆素材' : '' diff --git a/frontend-vue/src/pages/image/ImageWorkbenchPage.vue b/frontend-vue/src/pages/image/ImageWorkbenchPage.vue index d479ffb3..a31e16e2 100644 --- a/frontend-vue/src/pages/image/ImageWorkbenchPage.vue +++ b/frontend-vue/src/pages/image/ImageWorkbenchPage.vue @@ -659,10 +659,6 @@ function refreshModalFooter() { modalShow.workspaceRegenerate = src === 'workspace' } -function imageModalVisible(img: string) { - return img.startsWith('data:') || img.startsWith('http') -} - function openImageModal(images: string[], index: number, opts?: ModalSourceOpts) { const o = opts || {} imageModalImages.value = (Array.isArray(images) ? images : [images]).map(String) @@ -765,10 +761,6 @@ function triggerBlobDownload(blob: Blob, filename: string) { URL.revokeObjectURL(blobUrl) } -async function modalDownloadCurrent() { - const src = imageModalImages.value[imageModalIndex.value] - await downloadImage(src, `原图_${imageModalIndex.value + 1}.png`) -} async function modalBatchDownload() { for (let i = 0; i < imageModalImages.value.length; i++) { await downloadImage(imageModalImages.value[i], `image_${i + 1}.png`) diff --git a/frontend-vue/src/router/index.ts b/frontend-vue/src/router/index.ts index 2bfbd2f9..41084d1d 100644 --- a/frontend-vue/src/router/index.ts +++ b/frontend-vue/src/router/index.ts @@ -128,7 +128,7 @@ const routes = [ const router = createRouter({ history: createWebHistory(), routes, - scrollBehavior(to, _from, savedPosition) { + scrollBehavior(_to, _from, savedPosition) { // 返回工具台的 #group-xxx 锚点由组件 onMounted 处理;普通滚动回顶部 if (savedPosition) return savedPosition return { top: 0 } diff --git a/frontend-vue/src/shared/api/types/modules/collect-data.ts b/frontend-vue/src/shared/api/types/modules/collect-data.ts index 1e0b3b71..43e7ef2d 100644 --- a/frontend-vue/src/shared/api/types/modules/collect-data.ts +++ b/frontend-vue/src/shared/api/types/modules/collect-data.ts @@ -1,5 +1,5 @@ import { get, post, put, del, type JavaApiResponse, unwrapJavaResponse } from '../../http.ts' -import { buildJavaUrl, JAVA_API_PREFIX } from '../../url.ts' +import { JAVA_API_PREFIX } from '../../url.ts' import { getCurrentUserId } from '../../user.ts' import { getTaskProgressCacheTtlMs, getTaskProgressTimeoutMs } from '../../../task-progress-config.ts' import { createTaskProgressRequestCache } from '../../../task-progress-request-cache.ts' diff --git a/frontend-vue/src/shared/api/types/modules/image-video.ts b/frontend-vue/src/shared/api/types/modules/image-video.ts index 7fb756b6..f61ac61a 100644 --- a/frontend-vue/src/shared/api/types/modules/image-video.ts +++ b/frontend-vue/src/shared/api/types/modules/image-video.ts @@ -1,5 +1,5 @@ import { get, post, put, type JavaApiResponse, unwrapJavaResponse } from '../../http.ts' -import { buildJavaUrl, JAVA_API_PREFIX } from '../../url.ts' +import { JAVA_API_PREFIX } from '../../url.ts' import { getCurrentUserId } from '../../user.ts' export interface ImageVideoDouyinCopyVo { diff --git a/frontend-vue/src/shared/api/types/modules/price-track.ts b/frontend-vue/src/shared/api/types/modules/price-track.ts index 67da99e4..7ceff2e9 100644 --- a/frontend-vue/src/shared/api/types/modules/price-track.ts +++ b/frontend-vue/src/shared/api/types/modules/price-track.ts @@ -1,5 +1,5 @@ import { get, post, put, del, type JavaApiResponse, unwrapJavaResponse } from '../../http.ts' -import { buildJavaUrl, JAVA_API_PREFIX } from '../../url.ts' +import { JAVA_API_PREFIX } from '../../url.ts' import { getCurrentUserId } from '../../user.ts' import { getJavaDownloadUrl } from '../../download-url.ts' import { getTaskProgressCacheTtlMs, getTaskProgressTimeoutMs } from '../../../task-progress-config.ts' diff --git a/frontend-vue/src/shared/api/types/modules/query-asin.ts b/frontend-vue/src/shared/api/types/modules/query-asin.ts index 780d8f5d..ca080d90 100644 --- a/frontend-vue/src/shared/api/types/modules/query-asin.ts +++ b/frontend-vue/src/shared/api/types/modules/query-asin.ts @@ -1,5 +1,5 @@ import { get, post, put, del, type JavaApiResponse, unwrapJavaResponse } from '../../http.ts' -import { buildJavaUrl, JAVA_API_PREFIX } from '../../url.ts' +import { JAVA_API_PREFIX } from '../../url.ts' import { getCurrentUserId } from '../../user.ts' import { getJavaDownloadUrl } from '../../download-url.ts' import { getTaskProgressCacheTtlMs, getTaskProgressTimeoutMs } from '../../../task-progress-config.ts' diff --git a/frontend-vue/src/shared/api/types/modules/shop-match.ts b/frontend-vue/src/shared/api/types/modules/shop-match.ts index 43bf1e27..d1fca1f0 100644 --- a/frontend-vue/src/shared/api/types/modules/shop-match.ts +++ b/frontend-vue/src/shared/api/types/modules/shop-match.ts @@ -1,10 +1,9 @@ import { get, post, put, del, type JavaApiResponse, unwrapJavaResponse } from '../../http.ts' -import { buildJavaUrl, JAVA_API_PREFIX } from '../../url.ts' +import { JAVA_API_PREFIX } from '../../url.ts' import { getCurrentUserId } from '../../user.ts' import { getJavaDownloadUrl } from '../../download-url.ts' import { getTaskProgressCacheTtlMs, getTaskProgressTimeoutMs } from '../../../task-progress-config.ts' import { createTaskProgressRequestCache } from '../../../task-progress-request-cache.ts' -import { API_ENDPOINTS } from '../../endpoints.ts' import type { QueryAsinCountryAsins } from './query-asin.ts' /** 商品风险处理:备选店铺与匹配相关数据结构。 */ diff --git a/frontend-vue/src/shared/api/types/modules/withdraw.ts b/frontend-vue/src/shared/api/types/modules/withdraw.ts index 7f108c7f..334c4c4b 100644 --- a/frontend-vue/src/shared/api/types/modules/withdraw.ts +++ b/frontend-vue/src/shared/api/types/modules/withdraw.ts @@ -1,5 +1,5 @@ import { get, post, del, type JavaApiResponse, unwrapJavaResponse } from '../../http.ts' -import { buildJavaUrl, JAVA_API_PREFIX } from '../../url.ts' +import { JAVA_API_PREFIX } from '../../url.ts' import { getCurrentUserId } from '../../user.ts' import { getJavaDownloadUrl } from '../../download-url.ts' import { getTaskProgressCacheTtlMs, getTaskProgressTimeoutMs } from '../../../task-progress-config.ts' diff --git a/frontend-vue/src/shared/composables/useTaskProgressLoop.ts b/frontend-vue/src/shared/composables/useTaskProgressLoop.ts index 3a4a71d5..7d8f85d4 100644 --- a/frontend-vue/src/shared/composables/useTaskProgressLoop.ts +++ b/frontend-vue/src/shared/composables/useTaskProgressLoop.ts @@ -6,18 +6,9 @@ import { getTaskForegroundRefreshDelayMs, } from '../task-progress-config.ts' import { createCategorizedTimers } from '../utils/categorized-timers.ts' -import { - createTaskPollingBaseline, - type TaskPollingBaseline, -} from '../task-polling-baseline.ts' -import { - createProgressResponseCache, - type ProgressResponseCache, -} from '../progress-response-cache.ts' -import { - createTaskPollingCoordinator, - type TaskPollingCoordinator, -} from '../task-polling-coordinator.ts' +import { createTaskPollingBaseline, type TaskPollingBaseline } from '../task-polling-baseline.ts' +import type { ProgressResponseCache } from '../progress-response-cache.ts' +import type { TaskPollingCoordinator } from '../task-polling-coordinator.ts' /** * 通用任务进度轮询组合式函数。 @@ -86,7 +77,7 @@ export interface TaskProgressLoopOptions { coordinator?: TaskPollingCoordinator } -export interface TaskProgressLoopHandle { +export interface TaskProgressLoopHandle { taskIds: Ref taskStatuses: Ref> inFlight: Ref @@ -135,7 +126,7 @@ function writeIdsToStorage(key: string | undefined, ids: number[]) { export function useTaskProgressLoop( options: TaskProgressLoopOptions, -): TaskProgressLoopHandle { +): TaskProgressLoopHandle { const timers = createCategorizedTimers(`task-progress-loop:${options.scope}`) const isTerminal = options.isTerminal ?? DEFAULT_TERMINAL const intervalMs = options.getIntervalMs ?? getTaskPollIntervalMs diff --git a/frontend-vue/src/shared/page-prefix.ts b/frontend-vue/src/shared/page-prefix.ts index 8081201d..71611708 100644 --- a/frontend-vue/src/shared/page-prefix.ts +++ b/frontend-vue/src/shared/page-prefix.ts @@ -12,7 +12,3 @@ export function resolvePageHref(rawHref?: string): string { return rawHref.replace(/^\/new_web_source\/(.+)\.html$/, '/$1') } -/** 兼容旧引用:SPA 下生产/开发路径一致,恒为 false(页面不再按路径区分桌面/Web) */ -export function isDesktopClientPage(): boolean { - return false -} diff --git a/frontend-vue/src/shared/progress-response-cache.ts b/frontend-vue/src/shared/progress-response-cache.ts index b7a53cbc..929fe468 100644 --- a/frontend-vue/src/shared/progress-response-cache.ts +++ b/frontend-vue/src/shared/progress-response-cache.ts @@ -57,7 +57,7 @@ export function createProgressResponseCache(options: ProgressResponseCacheOpt return removed } - function evictIfNeeded(at: number) { + function evictIfNeeded(_at: number) { while (map.size > maxEntries) { const oldest = map.keys().next().value as number | undefined if (oldest == null) break diff --git a/frontend-vue/src/shared/task-progress-request-cache.ts b/frontend-vue/src/shared/task-progress-request-cache.ts index af483ad6..615b403c 100644 --- a/frontend-vue/src/shared/task-progress-request-cache.ts +++ b/frontend-vue/src/shared/task-progress-request-cache.ts @@ -48,7 +48,6 @@ export interface TaskProgressRequestCache { export function createTaskProgressRequestCache(options: TaskProgressRequestCacheOptions) { const ttl = options.ttlMs - const ttlValue = typeof ttl === 'number' ? ttl : 0 if (typeof ttl === 'number') { if (!(ttl > 0)) { throw new Error('ttlMs 必须为正数: ' + ttl)