style(frontend): 全站背景图 webp 化(bg.jpg 4MB→251KB 压缩 + bg.webp)+品牌工具页默认策略调优(品牌检测默认改精确匹配 Simple、Terms 后置)+任务面板/登录页/亚马逊控制台观感微调
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<aside class="left-panel left-panel--with-template">
|
||||
<div class="section-title">选择文件</div>
|
||||
<div class="upload-zone">
|
||||
<div class="hint">上传删除品牌 Excel;无论是直接上传文件还是上传文件夹批量导入,都会按每个 Excel 文件名作为店铺名。</div>
|
||||
<div class="hint">上传删除品牌 Excel;直接上传文件或上传文件夹批量导入都可以,每个 Excel 文件名会作为店铺名。</div>
|
||||
<div class="btns">
|
||||
<button type="button" class="opt-btn" @click="selectFiles">选择 Excel 文件</button>
|
||||
<button type="button" class="opt-btn" @click="selectFolder">选择文件夹</button>
|
||||
@@ -299,7 +299,7 @@ const historySectionItems = computed(() =>
|
||||
),
|
||||
);
|
||||
const queueRunnableItems = computed(() =>
|
||||
currentSectionItems.value.filter((item) => canPushToQueue(item) && getQueueStatus(item) === '未入队'),
|
||||
currentSectionItems.value.filter((item) => canPushToQueue(item) && getQueueStatus(item) === '未启动'),
|
||||
)
|
||||
|
||||
const deleteBrandCards = computed<TaskStatCard[]>(() => {
|
||||
@@ -477,7 +477,7 @@ function shouldShowProgress(item: DeleteBrandResultItem) {
|
||||
const isProgressTarget = Boolean(progress?.has_progress && progress?.info?.file_name === item.sourceFilename)
|
||||
|
||||
// 多文件任务下,展示规则更宽松:
|
||||
// 1) 当前活跃文件;2) 后端进度指向的文件;3) 已推送文件;4) 已完成文件(任务未终态时保留)。
|
||||
// 1) 当前活跃文件;2) 后端进度指向的文件;3) 已启动文件;4) 已完成文件(任务未终态时保留)。
|
||||
if (isActiveItem || isProgressTarget || sessionItem?._pushed) {
|
||||
return true
|
||||
}
|
||||
@@ -497,7 +497,7 @@ function shouldShowProgress(item: DeleteBrandResultItem) {
|
||||
return true
|
||||
}
|
||||
|
||||
return qs === '已入队' || qs === '处理中'
|
||||
return qs === '已提交' || qs === '处理中'
|
||||
}
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ function formatDateTime(value?: string) {
|
||||
|
||||
function formatMatchResult(item: DeleteBrandResultItem) {
|
||||
if (item.matchStatus === 'INDEX_STALE' && isUsableMatchedItem(item)) {
|
||||
return `已匹配 ${item.shopId || ''}(索引过期,可继续推送)`.trim()
|
||||
return `已匹配 ${item.shopId || ''}(匹配信息已过期,可继续启动)`.trim()
|
||||
}
|
||||
if (item.matchStatus === 'MATCHED' || item.matched) {
|
||||
return `已匹配 ${item.shopId || ''}`.trim()
|
||||
@@ -562,7 +562,7 @@ function formatMatchResult(item: DeleteBrandResultItem) {
|
||||
return '存在多个同名店铺,请人工确认'
|
||||
}
|
||||
if (item.matchStatus === 'PENDING') {
|
||||
return '店铺索引暂未就绪'
|
||||
return '店铺尚未匹配完成'
|
||||
}
|
||||
if (item.matchStatus) {
|
||||
return item.matchStatus
|
||||
@@ -774,9 +774,9 @@ function getQueueStatus(item: DeleteBrandResultItem) {
|
||||
return '处理中'
|
||||
}
|
||||
|
||||
// 多文件:未推送且未完成,才视为未入队。
|
||||
// 多文件:未推送且未完成,才视为未启动。
|
||||
if (multiFileTask && !sessionItem?._pushed && !sessionItem?._completed) {
|
||||
return '未入队'
|
||||
return '未启动'
|
||||
}
|
||||
|
||||
if (multiFileTask && status === 'SUCCESS') {
|
||||
@@ -794,10 +794,10 @@ function getQueueStatus(item: DeleteBrandResultItem) {
|
||||
}
|
||||
|
||||
if (sessionItem?._pushed) {
|
||||
return '已入队'
|
||||
return '已提交'
|
||||
}
|
||||
|
||||
return '未入队'
|
||||
return '未启动'
|
||||
}
|
||||
|
||||
function canDownloadTaskResult(item: DeleteBrandResultItem) {
|
||||
@@ -902,7 +902,7 @@ async function refreshTaskDetails(taskIds?: number[]) {
|
||||
try {
|
||||
const batch = await getDeleteBrandTaskProgress(ids)
|
||||
if (waitingForBackendRecovery.value && chainStarted.value) {
|
||||
queuePushResult.value = '后端已恢复,继续执行当前任务并自动衔接后续任务...'
|
||||
queuePushResult.value = '服务已恢复,继续执行当前任务并自动衔接后续任务...'
|
||||
}
|
||||
waitingForBackendRecovery.value = false
|
||||
let changed = false
|
||||
@@ -923,10 +923,10 @@ async function refreshTaskDetails(taskIds?: number[]) {
|
||||
}
|
||||
} catch (error) {
|
||||
const message = (error instanceof Error ? error.message : String(error || '')).toLowerCase()
|
||||
const transient = ['无法连接到后端服务', 'bad gateway', 'gateway timeout', 'network error', 'timeout', '502', '503', '504'].some((pattern) => message.includes(pattern.toLowerCase()))
|
||||
const transient = ['无法连接到服务', 'bad gateway', 'gateway timeout', 'network error', 'timeout', '502', '503', '504'].some((pattern) => message.includes(pattern.toLowerCase()))
|
||||
if (transient && chainStarted.value) {
|
||||
waitingForBackendRecovery.value = true
|
||||
queuePushResult.value = '当前任务运行中,正在等待后端服务恢复...'
|
||||
queuePushResult.value = '当前任务运行中,正在等待服务恢复...'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1123,8 +1123,8 @@ async function submitRun() {
|
||||
const hasBlockedItems = normalizedItems.some((item) => !isUsableMatchedItem(item))
|
||||
|
||||
queuePushResult.value = hasRunnableItems
|
||||
? '解析完成,可在左侧点击“启动任务”开始串行处理'
|
||||
: '解析完成,当前没有可推送的文件'
|
||||
? '解析完成,可在左侧点击“启动任务”开始依次处理'
|
||||
: '解析完成,当前没有可启动的文件'
|
||||
queuePayloadText.value = ''
|
||||
|
||||
if (normalizedItems.length && normalizedItems[0].taskId) {
|
||||
@@ -1133,13 +1133,13 @@ async function submitRun() {
|
||||
syncResultState()
|
||||
|
||||
if (hasBlockedItems) {
|
||||
ElMessage.warning('部分文件尚未命中可用店铺索引,已保留状态信息,请等待后台刷新后重试。')
|
||||
ElMessage.warning('部分文件尚未匹配到店铺,已保留状态信息,请稍后重试。')
|
||||
} else if (hasStaleMatchedItems) {
|
||||
ElMessage.warning('部分文件命中的是过期索引,仍可启动任务;后台刷新后会自动重新匹配。')
|
||||
ElMessage.warning('部分文件匹配到的店铺信息已过期,仍可启动任务;后台会自动重新匹配。')
|
||||
} else if (hasRunnableItems) {
|
||||
ElMessage.success('删除品牌解析完成,请在左侧启动任务')
|
||||
} else {
|
||||
ElMessage.warning('当前没有可推送的文件,请先等待店铺索引刷新。')
|
||||
ElMessage.warning('当前没有可启动的文件,请先等待店铺匹配完成。')
|
||||
}
|
||||
|
||||
// 更新历史记录,以展示那些未进入队列的失败项
|
||||
@@ -1183,7 +1183,7 @@ async function loadHistory() {
|
||||
ensurePolling(true)
|
||||
} catch (err) {
|
||||
const message = (err instanceof Error ? err.message : String(err || '')).toLowerCase()
|
||||
const transient = ['无法连接到后端服务', 'bad gateway', 'gateway timeout', 'network error', 'timeout', '502', '503', '504'].some((pattern) => message.includes(pattern.toLowerCase()))
|
||||
const transient = ['无法连接到服务', 'bad gateway', 'gateway timeout', 'network error', 'timeout', '502', '503', '504'].some((pattern) => message.includes(pattern.toLowerCase()))
|
||||
if (!transient) {
|
||||
console.error('loadHistory error:', err)
|
||||
}
|
||||
@@ -1263,7 +1263,7 @@ function isPythonQueueBusy() {
|
||||
for (const task of sessionTasks.value) {
|
||||
for (const item of task.items) {
|
||||
const qs = getQueueStatus(item)
|
||||
if (qs === '已入队' || qs === '处理中') {
|
||||
if (qs === '已提交' || qs === '处理中') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1302,7 +1302,7 @@ function findNextAutoRunnableItem() {
|
||||
if (getItemKey(item) === activeItemKey.value) return false
|
||||
const sessionItem = findSessionItem(item.taskId, item)
|
||||
if (sessionItem?._completed) return false
|
||||
return getQueueStatus(item) === '未入队'
|
||||
return getQueueStatus(item) === '未启动'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1325,7 +1325,7 @@ async function runItem(item: DeleteBrandResultItem, options?: { auto?: boolean }
|
||||
if (!sessionTask) return { success: false, retryable: false }
|
||||
|
||||
if (!api?.enqueue_json) {
|
||||
ElMessage.error('当前环境未启用 pywebview enqueue_json(浏览器环境不会推送)')
|
||||
ElMessage.error('当前环境未启用任务队列能力(浏览器预览环境不会启动)')
|
||||
return { success: false, retryable: false }
|
||||
}
|
||||
|
||||
@@ -1346,14 +1346,14 @@ async function runItem(item: DeleteBrandResultItem, options?: { auto?: boolean }
|
||||
nonEmptyArrayKeys: ['items'],
|
||||
})
|
||||
if (!(await passGuard(guard))) {
|
||||
queuePushResult.value = `文件 ${item.sourceFilename || taskId} 数据校验未通过,已阻止推送`
|
||||
queuePushResult.value = `文件 ${item.sourceFilename || taskId} 数据校验未通过,已阻止启动`
|
||||
saveSessionTask(taskId, sessionTask.items, queuePushResult.value, queuePayloadText.value)
|
||||
return { success: false, retryable: false }
|
||||
}
|
||||
const pushResult = await api.enqueue_json(payload)
|
||||
let qpr = ''
|
||||
if (pushResult?.success) {
|
||||
qpr = `已推送文件 ${item.sourceFilename},当前队列长度:${pushResult.queue_size ?? '-'}`
|
||||
qpr = `已启动文件 ${item.sourceFilename},排队中的任务数:${pushResult.queue_size ?? '-'}`
|
||||
|
||||
const sessionItem = findSessionItem(taskId, item)
|
||||
if (sessionItem) {
|
||||
@@ -1381,7 +1381,7 @@ async function runItem(item: DeleteBrandResultItem, options?: { auto?: boolean }
|
||||
async function pushToPythonQueue() {
|
||||
const nextItem = findNextAutoRunnableItem()
|
||||
if (!nextItem) {
|
||||
ElMessage.warning('当前没有可推送的文件')
|
||||
ElMessage.warning('当前没有可启动的文件')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1426,7 +1426,7 @@ async function maybeAutoAdvance() {
|
||||
})
|
||||
}
|
||||
const status = getQueueStatus(currentItem)
|
||||
if (status === '已入队' || status === '处理中') {
|
||||
if (status === '已提交' || status === '处理中') {
|
||||
debugAutoAdvance('skip: current item still running', {
|
||||
currentKey,
|
||||
status,
|
||||
@@ -1581,7 +1581,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
|
||||
.module-page {
|
||||
min-height: 100vh;
|
||||
background: #151a25;
|
||||
background: #242424;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@@ -1592,7 +1592,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
|
||||
.left-panel {
|
||||
width: 380px;
|
||||
background: #1c2333;
|
||||
background: #242424;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
border-right: 1px solid #2e3a52;
|
||||
@@ -1603,7 +1603,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
background: #151a25;
|
||||
background: #242424;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@@ -1617,14 +1617,14 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
border-radius: 10px;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
background: #2e3a52;
|
||||
background: #242424;
|
||||
margin-bottom: 20px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.upload-zone:hover {
|
||||
border-color: #3498db;
|
||||
background: #2e3a52;
|
||||
background: #242424;
|
||||
}
|
||||
|
||||
.hint {
|
||||
@@ -1654,7 +1654,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
color: #c8d2e2;
|
||||
background: #2e3a52;
|
||||
background: #242424;
|
||||
border: 1px solid #3e4a62;
|
||||
border-radius: 6px;
|
||||
}
|
||||
@@ -1701,7 +1701,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
cursor: pointer;
|
||||
padding: 10px 12px;
|
||||
border-radius: 8px;
|
||||
background: #2e3a52;
|
||||
background: #242424;
|
||||
border: 1px solid #2e3a52;
|
||||
margin-bottom: 8px;
|
||||
transition: all 0.2s ease;
|
||||
@@ -1709,7 +1709,7 @@ async function batchDeleteHistory(views: TaskItemView[]) {
|
||||
|
||||
.radio-item:hover,
|
||||
.radio-item.active {
|
||||
background: #2e3a52;
|
||||
background: #242424;
|
||||
border-color: #3e4a62;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user