style(frontend): 全站背景图 webp 化(bg.jpg 4MB→251KB 压缩 + bg.webp)+品牌工具页默认策略调优(品牌检测默认改精确匹配 Simple、Terms 后置)+任务面板/登录页/亚马逊控制台观感微调
This commit is contained in:
@@ -361,7 +361,7 @@ const progressLoop = useTaskProgressLoop<PublishTaskDetailVo>({
|
||||
await Promise.all([loadDashboard(), loadHistory()])
|
||||
},
|
||||
onError: () => {
|
||||
if (hasQueueWork.value) queueMessage.value = '任务仍在执行,正在等待后端状态恢复...'
|
||||
if (hasQueueWork.value) queueMessage.value = '任务仍在执行,正在等待服务恢复...'
|
||||
},
|
||||
})
|
||||
|
||||
@@ -453,10 +453,10 @@ function toPublishTaskView(detail: PublishTaskDetailVo): TaskItemView {
|
||||
}
|
||||
|
||||
const operationHint = computed(() => {
|
||||
if (uploading.value) return '正在逐个上传文件到后端...'
|
||||
if (parsing.value) return '正在解析 Excel、匹配店铺并创建批次...'
|
||||
if (queueWorkerRunning.value) return '当前文件完成后会自动派发下一个文件。'
|
||||
return '创建批次后会按文件严格串行处理。'
|
||||
if (uploading.value) return '正在逐个上传文件,请稍候...'
|
||||
if (parsing.value) return '正在解析 Excel、匹配店铺并准备上架...'
|
||||
if (queueWorkerRunning.value) return '当前文件上架完成后,会自动开始下一个文件。'
|
||||
return '提交后会按文件逐个依次上架。'
|
||||
})
|
||||
|
||||
watch(publishCountry, (code, previousCode) => {
|
||||
@@ -618,7 +618,7 @@ async function submitRun() {
|
||||
|
||||
await Promise.all([loadDashboard(), loadHistory()])
|
||||
if (!batch.pendingFileIds.length) {
|
||||
queueMessage.value = '解析完成,当前没有匹配成功且可执行的文件。'
|
||||
queueMessage.value = '解析完成,当前没有匹配成功且可上架的文件。'
|
||||
ElMessage.warning(queueMessage.value)
|
||||
return
|
||||
}
|
||||
@@ -627,7 +627,7 @@ async function submitRun() {
|
||||
if (shouldWait) {
|
||||
queuedBatches.value.push(batch)
|
||||
saveQueueState()
|
||||
queueMessage.value = `批次 ${parsed.taskNo || parsed.taskId} 已加入等待队列,前面还有 ${queuedBatches.value.length} 个批次`
|
||||
queueMessage.value = `任务 ${parsed.taskNo || parsed.taskId} 已加入等待队列,前面还有 ${queuedBatches.value.length} 个批次`
|
||||
ElMessage.success(queueMessage.value)
|
||||
if (!queueWorkerRunning.value) void processQueue()
|
||||
return
|
||||
@@ -635,7 +635,7 @@ async function submitRun() {
|
||||
|
||||
setActiveBatch(batch)
|
||||
saveQueueState()
|
||||
queueMessage.value = `批次 ${parsed.taskNo || parsed.taskId} 已创建,开始串行处理 ${batch.pendingFileIds.length} 个文件。`
|
||||
queueMessage.value = `任务 ${parsed.taskNo || parsed.taskId} 已创建,开始依次上架 ${batch.pendingFileIds.length} 个文件。`
|
||||
ElMessage.success(queueMessage.value)
|
||||
void processQueue()
|
||||
} catch (error) {
|
||||
@@ -909,13 +909,13 @@ async function processQueue() {
|
||||
positiveNumberKeys: ['totalRows', 'totalPages'],
|
||||
})
|
||||
if (!(await passGuard(guard))) {
|
||||
throw new Error(`文件 ${file.sourceFilename || nextFileId} 数据校验未通过,已阻止推送`)
|
||||
throw new Error(`文件 ${file.sourceFilename || nextFileId} 数据校验未通过,已阻止启动`)
|
||||
}
|
||||
const result = await api.enqueue_json(payload)
|
||||
if (!result?.success) throw new Error(result?.error || '任务队列拒绝接收任务')
|
||||
queueMessage.value = pendingFileIds.value.length
|
||||
? `文件 ${file.sourceFilename || nextFileId} 已入队,完成后继续剩余 ${pendingFileIds.value.length} 个文件。`
|
||||
: `文件 ${file.sourceFilename || nextFileId} 已入队,等待执行完成。`
|
||||
? `文件 ${file.sourceFilename || nextFileId} 已提交,完成后继续剩余 ${pendingFileIds.value.length} 个文件。`
|
||||
: `文件 ${file.sourceFilename || nextFileId} 已提交,等待执行完成。`
|
||||
const finalStatus = await waitForFileTerminal(taskId, nextFileId)
|
||||
if (finalStatus === 'STOPPED') return
|
||||
queueMessage.value = `文件 ${file.sourceFilename || nextFileId} ${['SUCCESS', 'COMPLETED'].includes(finalStatus) ? '已完成' : '执行失败'},继续下一个文件。`
|
||||
@@ -927,11 +927,11 @@ async function processQueue() {
|
||||
await submitDispatchFailure(taskId, file, reason)
|
||||
} catch (compensationError) {
|
||||
const message = compensationError instanceof Error ? compensationError.message : '失败状态提交失败'
|
||||
queueMessage.value = `文件 ${file.sourceFilename || nextFileId} 派发失败,后端未确认失败状态:${message}。串行队列已暂停。`
|
||||
queueMessage.value = `文件 ${file.sourceFilename || nextFileId} 启动失败,后端未确认失败状态:${message}。上架已暂停。`
|
||||
saveQueueState()
|
||||
throw new Error(queueMessage.value)
|
||||
}
|
||||
queueMessage.value = `文件 ${file.sourceFilename || nextFileId} 派发失败,已记录并继续下一个文件。`
|
||||
queueMessage.value = `文件 ${file.sourceFilename || nextFileId} 启动失败,已记录并继续下一个文件。`
|
||||
activeFileId.value = null
|
||||
saveQueueState()
|
||||
}
|
||||
@@ -941,16 +941,16 @@ async function processQueue() {
|
||||
await progressLoop.refreshOnce()
|
||||
await Promise.all([loadDashboard(), loadHistory()])
|
||||
if (queuedBatches.value.length) {
|
||||
queueMessage.value = `当前批次已完成派发,继续处理后续 ${queuedBatches.value.length} 个等待批次。`
|
||||
queueMessage.value = `当前批次已完成,继续处理后续 ${queuedBatches.value.length} 个等待批次。`
|
||||
continue
|
||||
}
|
||||
queueMessage.value = '所有上架批次已按顺序派发完成,正在生成结果文件。'
|
||||
ElMessage.success('上架等待队列已完成派发')
|
||||
queueMessage.value = '所有上架批次已按顺序完成,正在生成结果文件。'
|
||||
ElMessage.success('上架等待队列已完成')
|
||||
break
|
||||
}
|
||||
} catch (error) {
|
||||
if (disposed) return
|
||||
const message = error instanceof Error ? error.message : '串行队列执行失败'
|
||||
const message = error instanceof Error ? error.message : '任务执行失败'
|
||||
queueMessage.value = message
|
||||
ElMessage.error(message)
|
||||
} finally {
|
||||
@@ -1033,7 +1033,7 @@ function reconcileStoredQueue() {
|
||||
const activeId = active.activeFileId
|
||||
const activeStatus = normalizeStatus(active.files.find((file) => file.fileId === activeId)?.status)
|
||||
if (!activeStatus || activeStatus === 'PENDING') {
|
||||
queueMessage.value = `文件 ${activeId} 尚未激活,已恢复到待派发队列。`
|
||||
queueMessage.value = `文件 ${activeId} 尚未开始,已恢复到等待队列。`
|
||||
}
|
||||
}
|
||||
saveQueueState()
|
||||
@@ -1179,7 +1179,7 @@ onMounted(async () => {
|
||||
if (hasQueueWork.value) {
|
||||
queueMessage.value = activeFileId.value != null
|
||||
? `检测到未完成文件 ${activeFileId.value},继续等待完成后衔接后续文件。`
|
||||
: `检测到未完成队列,继续处理当前文件及后续 ${queuedBatches.value.length} 个批次。`
|
||||
: `检测到未完成的任务,继续处理当前文件及后续 ${queuedBatches.value.length} 个批次。`
|
||||
void processQueue()
|
||||
}
|
||||
})
|
||||
@@ -1211,23 +1211,23 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.module-page { min-height: 100vh; background: #151a25; }
|
||||
.module-page { min-height: 100vh; background: #242424; }
|
||||
.main-content { display: flex; min-height: calc(100vh - 88px); height: calc(100vh - 88px); }
|
||||
.left-panel { width: 400px; background: #1c2333; padding: 20px; overflow-y: auto; border-right: 1px solid #2e3a52; }
|
||||
.right-panel { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #151a25; }
|
||||
.left-panel { width: 400px; background: #242424; padding: 20px; overflow-y: auto; border-right: 1px solid #2e3a52; }
|
||||
.right-panel { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #242424; }
|
||||
.section-title { margin-bottom: 10px; color: #a0acbe; font-size: 13px; }
|
||||
.upload-zone { margin-bottom: 20px; padding: 20px; border: 1px dashed #3e4a62; border-radius: 8px; background: #2e3a52; text-align: center; }
|
||||
.upload-zone { margin-bottom: 20px; padding: 20px; border: 1px dashed #3e4a62; border-radius: 8px; background: #242424; text-align: center; }
|
||||
.hint, .loading-msg { color: #5e6878; font-size: 12px; line-height: 1.5; }
|
||||
.btns, .run-row { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
|
||||
.btns { justify-content: center; }
|
||||
.opt-btn, .btn-run, .download, .btn-delete { border: 0; border-radius: 6px; cursor: pointer; transition: background-color .15s ease, color .15s ease, opacity .15s ease; }
|
||||
.opt-btn { padding: 8px 16px; border: 1px solid #3e4a62; background: #2e3a52; color: #c8d2e2; font-size: 13px; }
|
||||
.opt-btn { padding: 8px 16px; border: 1px solid #3e4a62; background: #242424; color: #c8d2e2; font-size: 13px; }
|
||||
.opt-btn:hover:not(:disabled) { border-color: #3498db; color: #67b7ef; }
|
||||
.opt-btn:disabled, .btn-run:disabled { opacity: .55; cursor: not-allowed; }
|
||||
.selected-files { max-height: 120px; min-height: 72px; margin-top: 14px; overflow-y: auto; color: #5e6878; font-size: 12px; text-align: left; }
|
||||
.selected-files span { display: block; margin: 4px 0; word-break: break-all; }
|
||||
.more-line { color: #a0acbe; }
|
||||
.country-group { margin-bottom: 12px; padding: 14px; border: 1px solid #323e58; border-radius: 8px; background: #2e3a52; }
|
||||
.country-group { margin-bottom: 12px; padding: 14px; border: 1px solid #323e58; border-radius: 8px; background: #242424; }
|
||||
.country-group-title { margin-bottom: 10px; color: #a0acbe; font-size: 12px; }
|
||||
.country-checks { display: flex; flex-wrap: wrap; gap: 10px 16px; }
|
||||
.country-check-row { display: inline-flex; align-items: center; gap: 8px; color: #c8d2e2; cursor: pointer; font-size: 12px; user-select: none; }
|
||||
@@ -1238,7 +1238,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
.run-row { margin-top: 16px; }
|
||||
.btn-run { min-height: 38px; padding: 9px 20px; background: #3498db; color: #f5f8fc; font-size: 14px; }
|
||||
.btn-run:hover:not(:disabled) { background: #2980b9; }
|
||||
.queue-status { margin-top: 16px; padding: 12px; border-left: 3px solid #409eff; background: #2e3a52; color: #b8d8ef; font-size: 12px; line-height: 1.6; }
|
||||
.queue-status { margin-top: 16px; padding: 12px; border-left: 3px solid #409eff; background: #242424; color: #b8d8ef; font-size: 12px; line-height: 1.6; }
|
||||
.queue-status-title { margin-bottom: 4px; }
|
||||
.download { padding: 7px 12px; background: #2d6b46; color: #dff7e8; font-size: 12px; white-space: nowrap; }
|
||||
.download:hover { background: #367d54; }
|
||||
|
||||
Reference in New Issue
Block a user