修改多文件
This commit is contained in:
@@ -224,9 +224,14 @@ import {
|
|||||||
} from '@/shared/api/java-modules'
|
} from '@/shared/api/java-modules'
|
||||||
import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview'
|
import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview'
|
||||||
|
|
||||||
|
interface SessionDeleteBrandItem extends DeleteBrandResultItem {
|
||||||
|
_pushed?: boolean
|
||||||
|
_completed?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
interface StoredCurrentTask {
|
interface StoredCurrentTask {
|
||||||
taskId: number
|
taskId: number
|
||||||
items: DeleteBrandResultItem[]
|
items: SessionDeleteBrandItem[]
|
||||||
createdAt: number
|
createdAt: number
|
||||||
queuePushResult?: string
|
queuePushResult?: string
|
||||||
queuePayloadText?: string
|
queuePayloadText?: string
|
||||||
@@ -318,6 +323,84 @@ const historySectionItems = computed(() =>
|
|||||||
);
|
);
|
||||||
const hasVisibleItems = computed(() => currentSectionItems.value.length > 0 || historySectionItems.value.length > 0)
|
const hasVisibleItems = computed(() => currentSectionItems.value.length > 0 || historySectionItems.value.length > 0)
|
||||||
|
|
||||||
|
function persistSessionTasks() {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.localStorage.setItem(getStorageKey(), JSON.stringify(sessionTasks.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMultiFileTask(taskId?: number) {
|
||||||
|
if (!taskId) return false
|
||||||
|
const sessionTask = sessionTasks.value.find(t => t.taskId === taskId)
|
||||||
|
return (sessionTask?.items.length || 0) > 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSessionTask(taskId?: number) {
|
||||||
|
if (!taskId) return null
|
||||||
|
return sessionTasks.value.find(t => t.taskId === taskId) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSameDeleteBrandItem(left: Pick<DeleteBrandResultItem, 'resultId' | 'fileKey' | 'sourceFilename'> | null | undefined,
|
||||||
|
right: Pick<DeleteBrandResultItem, 'resultId' | 'fileKey' | 'sourceFilename'> | null | undefined) {
|
||||||
|
if (!left || !right) return false
|
||||||
|
if (left.resultId != null && right.resultId != null) {
|
||||||
|
return left.resultId === right.resultId
|
||||||
|
}
|
||||||
|
if (left.fileKey && right.fileKey) {
|
||||||
|
return left.fileKey === right.fileKey
|
||||||
|
}
|
||||||
|
return left.sourceFilename === right.sourceFilename
|
||||||
|
}
|
||||||
|
|
||||||
|
function findSessionItem(taskId: number | undefined, item: DeleteBrandResultItem) {
|
||||||
|
const sessionTask = findSessionTask(taskId)
|
||||||
|
if (!sessionTask) return null
|
||||||
|
return sessionTask.items.find(i => isSameDeleteBrandItem(i, item)) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCompletedItemsFromProgress(taskId: number | undefined) {
|
||||||
|
if (!taskId) return false
|
||||||
|
|
||||||
|
const sessionTask = findSessionTask(taskId)
|
||||||
|
if (!sessionTask) return false
|
||||||
|
|
||||||
|
let changed = false
|
||||||
|
const info = taskDetails.value[taskId]?.line_progress?.info
|
||||||
|
|
||||||
|
// 多文件任务优先依据后端 finished_files 同步已完成文件数量。
|
||||||
|
// 规则:按 sessionTask.items 的顺序,标记「已推送」中的前 N 个为 completed。
|
||||||
|
if (isMultiFileTask(taskId) && info?.finished_files != null && info.finished_files >= 0) {
|
||||||
|
const pushedItems = sessionTask.items.filter(i => i._pushed)
|
||||||
|
const shouldCompleted = Math.max(0, Math.min(info.finished_files, pushedItems.length))
|
||||||
|
|
||||||
|
for (let i = 0; i < shouldCompleted; i += 1) {
|
||||||
|
if (!pushedItems[i]._completed) {
|
||||||
|
pushedItems[i]._completed = true
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容单文件/兜底:当当前文件行进度到达末行时,标记活动文件完成。
|
||||||
|
if (info?.file_name && info.current_line != null && info.total_lines != null && info.total_lines > 0) {
|
||||||
|
if (info.current_line >= info.total_lines) {
|
||||||
|
const activeItem = currentSectionItems.value.find(item => getItemKey(item) === activeItemKey.value)
|
||||||
|
const sessionItem = activeItem && activeItem.taskId === taskId
|
||||||
|
? findSessionItem(taskId, activeItem)
|
||||||
|
: sessionTask.items.find(i => i.sourceFilename === info.file_name)
|
||||||
|
if (sessionItem && !sessionItem._completed) {
|
||||||
|
sessionItem._completed = true
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
persistSessionTasks()
|
||||||
|
}
|
||||||
|
return changed
|
||||||
|
}
|
||||||
|
|
||||||
function getTaskStatus(taskId?: number) {
|
function getTaskStatus(taskId?: number) {
|
||||||
if (!taskId) return ''
|
if (!taskId) return ''
|
||||||
return taskDetails.value[taskId]?.task?.status || ''
|
return taskDetails.value[taskId]?.task?.status || ''
|
||||||
@@ -342,14 +425,20 @@ function shouldShowProgress(item: DeleteBrandResultItem) {
|
|||||||
function normalizeDeleteBrandItems(items: DeleteBrandResultItem[]) {
|
function normalizeDeleteBrandItems(items: DeleteBrandResultItem[]) {
|
||||||
return items.map((item) => {
|
return items.map((item) => {
|
||||||
if (item.matchStatus === 'MATCHED') {
|
if (item.matchStatus === 'MATCHED') {
|
||||||
return item
|
return {
|
||||||
|
...item,
|
||||||
|
_pushed: false,
|
||||||
|
_completed: false,
|
||||||
|
} as SessionDeleteBrandItem
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
matched: false,
|
matched: false,
|
||||||
openStoreUrl: undefined,
|
openStoreUrl: undefined,
|
||||||
error: item.error || undefined,
|
error: item.error || undefined,
|
||||||
}
|
_pushed: false,
|
||||||
|
_completed: false,
|
||||||
|
} as SessionDeleteBrandItem
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,11 +493,14 @@ function formatProgress(taskId: number) {
|
|||||||
if (info.file_index && info.file_total) parts.push(`文件:${info.file_index}/${info.file_total}`)
|
if (info.file_index && info.file_total) parts.push(`文件:${info.file_index}/${info.file_total}`)
|
||||||
if (info.file_name) parts.push(`当前文件:${info.file_name}`)
|
if (info.file_name) parts.push(`当前文件:${info.file_name}`)
|
||||||
if (info.current_line != null && info.total_lines != null) {
|
if (info.current_line != null && info.total_lines != null) {
|
||||||
parts.push(`进度:${info.current_line}/${info.total_lines}`)
|
parts.push(`${isMultiFileTask(taskId) ? '当前文件进度' : '进度'}:${info.current_line}/${info.total_lines}`)
|
||||||
}
|
}
|
||||||
if (info.current_country) parts.push(`国家:${info.current_country}`)
|
if (info.current_country) parts.push(`国家:${info.current_country}`)
|
||||||
if (info.current_asin) parts.push(`ASIN:${info.current_asin}`)
|
if (info.current_asin) parts.push(`ASIN:${info.current_asin}`)
|
||||||
if (info.finished_files != null) parts.push(`已完成文件:${info.finished_files}`)
|
if (info.finished_files != null) {
|
||||||
|
const total = info.file_total && info.file_total > 0 ? `/${info.file_total}` : ''
|
||||||
|
parts.push(`已完成文件:${info.finished_files}${total}`)
|
||||||
|
}
|
||||||
return parts.join('|')
|
return parts.join('|')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,34 +538,41 @@ function getPollingTaskIds() {
|
|||||||
function getQueueStatus(item: DeleteBrandResultItem) {
|
function getQueueStatus(item: DeleteBrandResultItem) {
|
||||||
const taskId = item.taskId
|
const taskId = item.taskId
|
||||||
if (!taskId) return ''
|
if (!taskId) return ''
|
||||||
const sessionTask = sessionTasks.value.find(t => t.taskId === taskId)
|
const sessionTask = findSessionTask(taskId)
|
||||||
if (!sessionTask) return ''
|
if (!sessionTask) return ''
|
||||||
|
|
||||||
|
const sessionItem = findSessionItem(taskId, item)
|
||||||
const status = getTaskStatus(taskId)
|
const status = getTaskStatus(taskId)
|
||||||
if (status === 'SUCCESS' || status === 'FAILED' || item.taskStatus === 'SUCCESS' || item.taskStatus === 'FAILED') {
|
const info = taskDetails.value[taskId]?.line_progress
|
||||||
|
const multiFileTask = isMultiFileTask(taskId)
|
||||||
|
|
||||||
|
if (!multiFileTask && (status === 'SUCCESS' || status === 'FAILED' || item.taskStatus === 'SUCCESS' || item.taskStatus === 'FAILED')) {
|
||||||
return '已被全局判定为终态'
|
return '已被全局判定为终态'
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionItem = sessionTask.items.find(i => i.resultId === item.resultId || i.sourceFilename === item.sourceFilename)
|
|
||||||
|
|
||||||
const info = taskDetails.value[taskId]?.line_progress
|
|
||||||
|
|
||||||
// 此时这个特定文件是否正好被后端报了进度名
|
|
||||||
if (status === 'RUNNING' && info?.has_progress && info?.info?.file_name === item.sourceFilename) {
|
if (status === 'RUNNING' && info?.has_progress && info?.info?.file_name === item.sourceFilename) {
|
||||||
return '处理中'
|
return '处理中'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查查是否已经完结了这个特定文件
|
if (sessionItem?._completed) {
|
||||||
const detail = taskDetails.value[taskId]
|
return '本文件解析完毕'
|
||||||
if (detail?.items) {
|
}
|
||||||
// 后端返回的 items 是 `resultJson` 解析来的,里面只含有已经做完的!
|
|
||||||
const finished = detail.items.find((i: DeleteBrandResultItem) => i.sourceFilename === item.sourceFilename)
|
if (multiFileTask && status === 'SUCCESS') {
|
||||||
if (finished) {
|
return '本文件解析完毕'
|
||||||
return '本文件解析完毕'
|
}
|
||||||
|
|
||||||
|
if (!multiFileTask) {
|
||||||
|
const detail = taskDetails.value[taskId]
|
||||||
|
if (detail?.items) {
|
||||||
|
const finished = detail.items.find((i: DeleteBrandResultItem) => isSameDeleteBrandItem(i, item))
|
||||||
|
if (finished && status === 'SUCCESS') {
|
||||||
|
return '本文件解析完毕'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionItem && (sessionItem as any)._pushed) {
|
if (sessionItem?._pushed) {
|
||||||
return '已入队'
|
return '已入队'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,12 +596,14 @@ function mergeTaskDetailItemsIntoSession(detail: DeleteBrandTaskDetailVo) {
|
|||||||
|
|
||||||
let changed = false
|
let changed = false
|
||||||
const mergedItems = sessionTask.items.map((item) => {
|
const mergedItems = sessionTask.items.map((item) => {
|
||||||
const latest = detail.items?.find((candidate) => candidate.resultId === item.resultId || candidate.sourceFilename === item.sourceFilename)
|
const latest = detail.items?.find((candidate) => isSameDeleteBrandItem(candidate, item))
|
||||||
if (!latest) return item
|
if (!latest) return item
|
||||||
const merged = {
|
const merged = {
|
||||||
...item,
|
...item,
|
||||||
...latest,
|
...latest,
|
||||||
success: item.success ?? latest.success,
|
success: item.success ?? latest.success,
|
||||||
|
_pushed: item._pushed,
|
||||||
|
_completed: item._completed,
|
||||||
}
|
}
|
||||||
if (JSON.stringify(merged) !== JSON.stringify(item)) {
|
if (JSON.stringify(merged) !== JSON.stringify(item)) {
|
||||||
changed = true
|
changed = true
|
||||||
@@ -516,8 +617,8 @@ function mergeTaskDetailItemsIntoSession(detail: DeleteBrandTaskDetailVo) {
|
|||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed && typeof window !== 'undefined') {
|
if (changed) {
|
||||||
window.localStorage.setItem(getStorageKey(), JSON.stringify(sessionTasks.value))
|
persistSessionTasks()
|
||||||
}
|
}
|
||||||
return changed
|
return changed
|
||||||
}
|
}
|
||||||
@@ -536,6 +637,9 @@ async function refreshTaskDetails(taskIds?: number[]) {
|
|||||||
if (mergeTaskDetailItemsIntoSession(detail)) {
|
if (mergeTaskDetailItemsIntoSession(detail)) {
|
||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
|
if (updateCompletedItemsFromProgress(id)) {
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
@@ -833,6 +937,8 @@ function findNextAutoRunnableItem() {
|
|||||||
return currentSectionItems.value.find((item) => {
|
return currentSectionItems.value.find((item) => {
|
||||||
if (!item.openStoreUrl) return false
|
if (!item.openStoreUrl) return false
|
||||||
if (getItemKey(item) === activeItemKey.value) return false
|
if (getItemKey(item) === activeItemKey.value) return false
|
||||||
|
const sessionItem = findSessionItem(item.taskId, item)
|
||||||
|
if (sessionItem?._completed) return false
|
||||||
return getQueueStatus(item) === '未入队'
|
return getQueueStatus(item) === '未入队'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -870,9 +976,10 @@ async function runItem(item: DeleteBrandResultItem, options?: { auto?: boolean }
|
|||||||
if (pushResult?.success) {
|
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)
|
const sessionItem = findSessionItem(taskId, item)
|
||||||
if (sessionItem) {
|
if (sessionItem) {
|
||||||
(sessionItem as any)._pushed = true
|
sessionItem._pushed = true
|
||||||
|
sessionItem._completed = false
|
||||||
}
|
}
|
||||||
activeItemKey.value = getItemKey(item)
|
activeItemKey.value = getItemKey(item)
|
||||||
saveSessionTask(taskId, sessionTask.items, qpr, queuePayloadText.value)
|
saveSessionTask(taskId, sessionTask.items, qpr, queuePayloadText.value)
|
||||||
@@ -892,10 +999,21 @@ async function maybeAutoAdvance() {
|
|||||||
if (currentKey) {
|
if (currentKey) {
|
||||||
const currentItem = currentSectionItems.value.find(item => getItemKey(item) === currentKey)
|
const currentItem = currentSectionItems.value.find(item => getItemKey(item) === currentKey)
|
||||||
if (currentItem) {
|
if (currentItem) {
|
||||||
|
const taskId = currentItem.taskId
|
||||||
|
const multiFileTask = isMultiFileTask(taskId)
|
||||||
|
if (multiFileTask) {
|
||||||
|
updateCompletedItemsFromProgress(taskId)
|
||||||
|
}
|
||||||
const status = getQueueStatus(currentItem)
|
const status = getQueueStatus(currentItem)
|
||||||
if (status === '已入队' || status === '处理中') {
|
if (status === '已入队' || status === '处理中') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (multiFileTask) {
|
||||||
|
const sessionItem = findSessionItem(taskId, currentItem)
|
||||||
|
if (sessionItem && !sessionItem._completed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user