紫鸟查询店铺更新
This commit is contained in:
@@ -105,7 +105,7 @@
|
||||
<div class="left split-result-main">
|
||||
<span class="id" :title="item.sourceFilename">{{ item.sourceFilename || '-' }}</span>
|
||||
<div class="files">店铺名:{{ item.shopName || '-' }}</div>
|
||||
<div class="files">匹配结果:{{ item.matched ? `已匹配 ${item.shopId || ''}` : '未匹配到紫鸟店铺' }}</div>
|
||||
<div class="files">匹配结果:{{ formatMatchResult(item) }}</div>
|
||||
<div v-if="item.platform" class="files">平台:{{ item.platform }}</div>
|
||||
<div v-if="getQueueStatus(item)" class="files">队列状态:{{ getQueueStatus(item) }}</div>
|
||||
<div v-if="item.countryCount !== undefined && item.matched" class="files">国家数:{{ item.countryCount
|
||||
@@ -158,7 +158,7 @@
|
||||
<div class="left split-result-main">
|
||||
<span class="id" :title="item.sourceFilename">{{ item.sourceFilename || '-' }}</span>
|
||||
<div class="files">店铺名:{{ item.shopName || '-' }}</div>
|
||||
<div class="files">匹配结果:{{ item.matched ? `已匹配 ${item.shopId || ''}` : '未匹配到紫鸟店铺' }}</div>
|
||||
<div class="files">匹配结果:{{ formatMatchResult(item) }}</div>
|
||||
<div v-if="item.platform" class="files">平台:{{ item.platform }}</div>
|
||||
<div v-if="item.countryCount !== undefined && item.matched" class="files">国家数:{{ item.countryCount
|
||||
}}</div>
|
||||
@@ -281,8 +281,7 @@ function loadSessionTasksFromStorage() {
|
||||
}
|
||||
|
||||
function saveSessionTask(taskId: number, items: DeleteBrandResultItem[], pushResult?: string, payloadText?: string) {
|
||||
// 只将解析成功且匹配成功的任务放入当前队列中,失败的将留在历史记录里
|
||||
const validItems = items.filter(i => i.matched !== false && i.success !== false)
|
||||
const validItems = items.filter(i => i.matchStatus === 'MATCHED' && i.success !== false)
|
||||
if (validItems.length === 0) return
|
||||
|
||||
const newTask: StoredCurrentTask = {
|
||||
@@ -326,6 +325,9 @@ function getTaskStatus(taskId?: number) {
|
||||
|
||||
function getDisplayError(item: DeleteBrandResultItem) {
|
||||
if (item.error) return item.error
|
||||
if (item.matchStatus && item.matchStatus !== 'MATCHED') {
|
||||
return item.matchMessage || ''
|
||||
}
|
||||
const taskId = item.taskId
|
||||
if (!taskId) return ''
|
||||
return taskDetails.value[taskId]?.task?.errorMessage || ''
|
||||
@@ -339,18 +341,37 @@ function shouldShowProgress(item: DeleteBrandResultItem) {
|
||||
|
||||
function normalizeDeleteBrandItems(items: DeleteBrandResultItem[]) {
|
||||
return items.map((item) => {
|
||||
// 只有在既没成功,又显式标记为未匹配时,才做错误兜底
|
||||
if (!item.success && item.matched === false) {
|
||||
return {
|
||||
...item,
|
||||
error: item.error || '未匹配到紫鸟店铺',
|
||||
openStoreUrl: undefined,
|
||||
}
|
||||
if (item.matchStatus === 'MATCHED') {
|
||||
return item
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
matched: false,
|
||||
openStoreUrl: undefined,
|
||||
error: item.error || undefined,
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
|
||||
function formatMatchResult(item: DeleteBrandResultItem) {
|
||||
if (item.matchStatus === 'MATCHED') {
|
||||
return `已匹配 ${item.shopId || ''}`.trim()
|
||||
}
|
||||
if (item.matchMessage) {
|
||||
return item.matchMessage
|
||||
}
|
||||
if (item.matchStatus === 'CONFLICT') {
|
||||
return '存在多个同名店铺,请人工确认'
|
||||
}
|
||||
if (item.matchStatus === 'PENDING' || item.matchStatus === 'INDEX_STALE') {
|
||||
return '店铺索引暂未就绪'
|
||||
}
|
||||
if (item.matchStatus) {
|
||||
return item.matchStatus
|
||||
}
|
||||
return item.matched ? `已匹配 ${item.shopId || ''}`.trim() : '待匹配'
|
||||
}
|
||||
|
||||
function mergeVisibleItems() {
|
||||
resultItems.value = [...currentSectionItems.value, ...historySectionItems.value]
|
||||
}
|
||||
@@ -369,10 +390,6 @@ function updateSummary(items: DeleteBrandResultItem[]) {
|
||||
}
|
||||
}
|
||||
|
||||
function getItemTaskId(item: DeleteBrandResultItem) {
|
||||
return item.taskId || 0
|
||||
}
|
||||
|
||||
function formatProgress(taskId: number) {
|
||||
if (!taskId) return ''
|
||||
const detail = taskDetails.value[taskId]
|
||||
@@ -410,11 +427,6 @@ function formatProgressPercent(taskId: number) {
|
||||
return status === 'SUCCESS' ? 100 : 0
|
||||
}
|
||||
|
||||
function isTaskRunning(taskId: number) {
|
||||
const status = taskDetails.value[taskId]?.task?.status
|
||||
return status === 'RUNNING'
|
||||
}
|
||||
|
||||
function isTaskTerminal(taskId: number) {
|
||||
const status = taskDetails.value[taskId]?.task?.status
|
||||
return status === 'SUCCESS' || status === 'FAILED'
|
||||
@@ -477,18 +489,58 @@ function canDownloadTaskResult(item: DeleteBrandResultItem) {
|
||||
return status === 'SUCCESS'
|
||||
}
|
||||
|
||||
function mergeTaskDetailItemsIntoSession(detail: DeleteBrandTaskDetailVo) {
|
||||
const taskId = detail?.task?.id
|
||||
if (!taskId || !detail?.items?.length) return false
|
||||
const sessionTask = sessionTasks.value.find(t => t.taskId === taskId)
|
||||
if (!sessionTask) return false
|
||||
|
||||
let changed = false
|
||||
const mergedItems = sessionTask.items.map((item) => {
|
||||
const latest = detail.items?.find((candidate) => candidate.resultId === item.resultId || candidate.sourceFilename === item.sourceFilename)
|
||||
if (!latest) return item
|
||||
const merged = {
|
||||
...item,
|
||||
...latest,
|
||||
success: item.success ?? latest.success,
|
||||
}
|
||||
if (JSON.stringify(merged) !== JSON.stringify(item)) {
|
||||
changed = true
|
||||
}
|
||||
return merged
|
||||
})
|
||||
|
||||
const validItems = mergedItems.filter(i => i.matchStatus === 'MATCHED' && i.success !== false)
|
||||
if (JSON.stringify(validItems) !== JSON.stringify(sessionTask.items)) {
|
||||
sessionTask.items = validItems
|
||||
changed = true
|
||||
}
|
||||
|
||||
if (changed && typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(getStorageKey(), JSON.stringify(sessionTasks.value))
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
async function refreshTaskDetails(taskIds?: number[]) {
|
||||
const ids = taskIds || getPollingTaskIds()
|
||||
if (!ids.length) return
|
||||
|
||||
try {
|
||||
const batch = await getDeleteBrandTaskDetails(ids)
|
||||
let changed = false
|
||||
for (const detail of batch.items || []) {
|
||||
const id = detail?.task?.id
|
||||
if (typeof id === 'number' && id > 0) {
|
||||
taskDetails.value[id] = detail
|
||||
if (mergeTaskDetailItemsIntoSession(detail)) {
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
syncResultState()
|
||||
}
|
||||
} catch {
|
||||
// ignore polling failures
|
||||
}
|
||||
@@ -649,7 +701,8 @@ async function submitRun() {
|
||||
})),
|
||||
})
|
||||
const normalizedItems = normalizeDeleteBrandItems(result.items || [])
|
||||
const hasUnmatched = normalizedItems.some((item) => !item.matched)
|
||||
const hasMatchedItems = normalizedItems.some((item) => item.matchStatus === 'MATCHED')
|
||||
const hasPendingItems = normalizedItems.some((item) => item.matchStatus && item.matchStatus !== 'MATCHED')
|
||||
|
||||
queuePushResult.value = '解析完成,等待手动点击打开紫鸟进行单任务处理'
|
||||
queuePayloadText.value = ''
|
||||
@@ -659,10 +712,12 @@ async function submitRun() {
|
||||
}
|
||||
syncResultState()
|
||||
|
||||
if (hasUnmatched) {
|
||||
ElMessage.error('存在未匹配到紫鸟店铺的文件,请检查报错内容。这些文件已自动归档至历史记录。')
|
||||
} else {
|
||||
if (hasPendingItems) {
|
||||
ElMessage.warning('部分文件尚未命中可用店铺索引,已保留状态信息,请等待后台刷新后重试。')
|
||||
} else if (hasMatchedItems) {
|
||||
ElMessage.success('删除品牌解析完成,请手动推送')
|
||||
} else {
|
||||
ElMessage.warning('当前没有可推送的已匹配文件,请先等待店铺索引刷新。')
|
||||
}
|
||||
|
||||
// 更新历史记录,以展示那些未进入队列的失败项
|
||||
@@ -783,10 +838,7 @@ function findNextAutoRunnableItem() {
|
||||
}
|
||||
|
||||
async function runItem(item: DeleteBrandResultItem, options?: { auto?: boolean }) {
|
||||
if (isPythonQueueBusy()) {
|
||||
if (!options?.auto) {
|
||||
ElMessage.warning('当前存在正在处理的任务,请等待其完成后再推送下一条!')
|
||||
}
|
||||
if (options?.auto && isPythonQueueBusy()) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -816,7 +868,7 @@ async function runItem(item: DeleteBrandResultItem, options?: { auto?: boolean }
|
||||
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 = sessionTask.items.find(i => i.resultId === item.resultId || i.sourceFilename === item.sourceFilename)
|
||||
if (sessionItem) {
|
||||
@@ -874,10 +926,6 @@ async function triggerItemRun(item: DeleteBrandResultItem) {
|
||||
}
|
||||
}
|
||||
|
||||
function openShop(url: string) {
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadSessionTasksFromStorage()
|
||||
const taskIds = getPollingTaskIds()
|
||||
|
||||
@@ -211,12 +211,16 @@ export interface DeleteBrandTaskBatchVo {
|
||||
missingTaskIds: number[]
|
||||
}
|
||||
|
||||
export type DeleteBrandMatchStatus = 'MATCHED' | 'PENDING' | 'CONFLICT' | 'INDEX_STALE'
|
||||
|
||||
export interface DeleteBrandResultItem {
|
||||
resultId?: number
|
||||
fileKey?: string
|
||||
sourceFilename: string
|
||||
shopName?: string
|
||||
matched?: boolean
|
||||
matchStatus?: DeleteBrandMatchStatus
|
||||
matchMessage?: string
|
||||
shopId?: string
|
||||
platform?: string
|
||||
openStoreUrl?: string
|
||||
|
||||
Reference in New Issue
Block a user