后端架构更新

This commit is contained in:
super
2026-04-27 09:18:10 +08:00
parent 0caf62c3d2
commit 995e2ee65a
141 changed files with 6957 additions and 772 deletions

View File

@@ -86,31 +86,33 @@
</div>
</template>
<!-- 国家顺序 -->
<div class="section-title">处理国家顺序</div>
<p class="hint country-pref-hint">
勾选需要处理的站点拖拽调整顺序设置会按当前登录用户保存
</p>
<div class="country-pref-checks">
<label v-for="row in countryCheckboxRows" :key="row.code" class="country-check-row">
<input type="checkbox" class="country-check-input" :checked="isCountrySelected(row.code)"
:disabled="isCountrySelectionLocked(row.code)"
@change="onCountryNativeChange(row.code, $event)" />
<span class="country-check-text">{{ row.label }}{{ row.code }}</span>
</label>
</div>
<div v-if="orderedCountryCodes.length" class="country-order-panel">
<div class="country-order-caption">已选顺序拖拽 调整</div>
<div class="country-order-list">
<div v-for="(code, idx) in orderedCountryCodes" :key="code" class="country-drag-row"
:class="{ dragging: dragCountryIndex === idx }" draggable="true" @dragstart="onCountryDragStart(idx)"
@dragend="onCountryDragEnd" @dragover.prevent @drop.prevent="onCountryDrop(idx)">
<span class="drag-handle" title="拖动排序"></span>
<span class="country-drag-label">{{ countryLabel(code) }}{{ code }}</span>
<template v-if="!asinModeEnabled">
<!-- 国家顺序 -->
<div class="section-title">处理国家与顺序</div>
<p class="hint country-pref-hint">
勾选需要处理的站点拖拽调整顺序设置会按当前登录用户保存
</p>
<div class="country-pref-checks">
<label v-for="row in countryCheckboxRows" :key="row.code" class="country-check-row">
<input type="checkbox" class="country-check-input" :checked="isCountrySelected(row.code)"
:disabled="isCountrySelectionLocked(row.code)"
@change="onCountryNativeChange(row.code, $event)" />
<span class="country-check-text">{{ row.label }}{{ row.code }}</span>
</label>
</div>
<div v-if="orderedCountryCodes.length" class="country-order-panel">
<div class="country-order-caption">已选顺序拖拽 调整</div>
<div class="country-order-list">
<div v-for="(code, idx) in orderedCountryCodes" :key="code" class="country-drag-row"
:class="{ dragging: dragCountryIndex === idx }" draggable="true" @dragstart="onCountryDragStart(idx)"
@dragend="onCountryDragEnd" @dragover.prevent @drop.prevent="onCountryDrop(idx)">
<span class="drag-handle" title="拖动排序"></span>
<span class="country-drag-label">{{ countryLabel(code) }}{{ code }}</span>
</div>
</div>
</div>
</div>
<div v-if="countryPrefSaving" class="country-pref-status">保存中</div>
<div v-if="countryPrefSaving" class="country-pref-status">保存中</div>
</template>
<!-- 状态指示 -->
<div v-if="statusModeEnabled" class="mode-status-bar">
@@ -569,6 +571,10 @@ function resolveAsinRequestPaths() {
return asinFiles.value
}
function resolveCountryCodesForRequest() {
return asinModeEnabled.value ? COUNTRY_OPTIONS.map((item) => item.code) : [...orderedCountryCodes.value]
}
function selectMode(mode: 'status' | 'asin') {
statusModeEnabled.value = mode === 'status'
asinModeEnabled.value = mode === 'asin'
@@ -777,7 +783,7 @@ async function runMatch() {
try {
const res = await matchPriceTrackShops(names, {
asinFiles: asinModeEnabled.value ? resolveAsinRequestPaths() : [],
countryCodes: [...orderedCountryCodes.value],
countryCodes: resolveCountryCodesForRequest(),
})
const batch = res.items || []
matchAsinRowsByCountry.value = res.asinRowsByCountry || {}
@@ -915,7 +921,7 @@ async function pushToPythonQueueLegacy() {
asinMode: asinModeEnabled.value,
items: matchedRows as unknown as Record<string, unknown>[],
asinFiles: resolveAsinRequestPaths(),
countryCodes: [...orderedCountryCodes.value],
countryCodes: resolveCountryCodesForRequest(),
}
const taskVo = await createPriceTrackTask(taskReq)
taskSnapshots.value = {
@@ -940,7 +946,7 @@ async function pushToPythonQueueLegacy() {
task_id: taskVo.taskId,
// 店铺简要信息(用于展示)
shop_names: matchedRows.map((i) => i.shopName).filter(Boolean),
country_codes: [...orderedCountryCodes.value],
country_codes: resolveCountryCodesForRequest(),
skip_asin_delete_policy: buildSkipAsinDeletePolicy(),
delete_skip_asin_when_price_below_minimum: statusModeEnabled.value && !asinModeEnabled.value,
deleteSkipAsinWhenPriceBelowMinimum: statusModeEnabled.value && !asinModeEnabled.value,
@@ -1003,7 +1009,7 @@ function buildQueuePayload(taskVo: PriceTrackCreateTaskVo, row: PriceTrackShopQu
task_status: taskStatus,
loop_run_id: loopRunId,
round_index: roundIndex,
country_codes: [...orderedCountryCodes.value],
country_codes: resolveCountryCodesForRequest(),
mode: statusModeEnabled.value ? 'status' : 'asin',
skip_asins: skipAsinsByCountry,
skip_asins_by_country: skipAsinsByCountry,
@@ -1142,7 +1148,7 @@ async function processMatchedQueue() {
asinMode: asinModeEnabled.value,
items: [row] as unknown as Record<string, unknown>[],
asinFiles: resolveAsinRequestPaths(),
countryCodes: [...orderedCountryCodes.value],
countryCodes: resolveCountryCodesForRequest(),
})
} catch (error) {
const message = (error instanceof Error ? error.message : String(error || '')).toLowerCase()
@@ -1416,7 +1422,7 @@ async function pushToPythonLoopQueue() {
asinMode: asinModeEnabled.value,
items: matchedRows,
asinFiles: resolveAsinRequestPaths(),
countryCodes: [...orderedCountryCodes.value],
countryCodes: resolveCountryCodesForRequest(),
executionMode: executionMode.value,
targetRounds: executionMode.value === 'FINITE' ? Math.max(1, Number(roundCount.value) || 1) : undefined,
})
@@ -1568,7 +1574,7 @@ function statusClass(item: PriceTrackHistoryItem) {
}
function canDownload(item: PriceTrackHistoryItem) {
if (!item.resultId) return false
if (!item.resultId || (!item.fileReady && !item.downloadUrl)) return false
const st = resolvedTaskStatus(item)
return st === 'SUCCESS' || item.success === true
}