提交新增内容

This commit is contained in:
super
2026-03-19 23:07:10 +08:00
parent 1e63ab291b
commit 43d508f527
9 changed files with 2138 additions and 57 deletions

View File

@@ -9,12 +9,43 @@
<div class="nav-tabs">
<div class="nav-tab-group">
<button type="button" class="nav-tab active">品牌检测</button>
<button
type="button"
class="nav-tab"
:class="{ active: activeTab === 'brand' }"
@click="activeTab = 'brand'"
>
品牌检测
</button>
<button
type="button"
class="nav-tab"
:class="{ active: activeTab === 'dedupe' }"
@click="activeTab = 'dedupe'"
>
数据去重
</button>
<button
type="button"
class="nav-tab"
:class="{ active: activeTab === 'convert' }"
@click="activeTab = 'convert'"
>
格式转换
</button>
<button
type="button"
class="nav-tab"
:class="{ active: activeTab === 'split' }"
@click="activeTab = 'split'"
>
数据拆分
</button>
</div>
</div>
</header>
<div class="main-content">
<div v-if="activeTab === 'brand'" class="main-content">
<aside class="left-panel">
<div class="section-title">选择文件</div>
<div class="upload-zone">
@@ -106,26 +137,9 @@
<button type="button" class="template-download-row" @click="downloadTemplateXlsx">
<span class="template-download-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none">
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z"
stroke="rgba(255,255,255,0.92)"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M14 2v6h6"
stroke="rgba(255,255,255,0.92)"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M8 13h8M8 17h5"
stroke="rgba(255,255,255,0.86)"
stroke-width="1.5"
stroke-linecap="round"
/>
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z" stroke="rgba(255,255,255,0.92)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
<path d="M14 2v6h6" stroke="rgba(255,255,255,0.92)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
<path d="M8 13h8M8 17h5" stroke="rgba(255,255,255,0.86)" stroke-width="1.5" stroke-linecap="round" />
</svg>
</span>
<span class="template-download-text">
@@ -137,26 +151,9 @@
<button type="button" class="template-download-row" @click="downloadTemplateZip">
<span class="template-download-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none">
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z"
stroke="rgba(255,255,255,0.92)"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M14 2v6h6"
stroke="rgba(255,255,255,0.92)"
stroke-width="1.8"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M4 8h16M7 12h10M7 16h7"
stroke="rgba(255,255,255,0.86)"
stroke-width="1.5"
stroke-linecap="round"
/>
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z" stroke="rgba(255,255,255,0.92)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
<path d="M14 2v6h6" stroke="rgba(255,255,255,0.92)" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
<path d="M4 8h16M7 12h10M7 16h7" stroke="rgba(255,255,255,0.86)" stroke-width="1.5" stroke-linecap="round" />
</svg>
</span>
<span class="template-download-text">
@@ -188,10 +185,7 @@
class="inline-progress"
>
<div class="progress-bar-bg small">
<div
class="progress-bar-fill"
:style="{ width: `${getTaskProgressPercent(task)}%` }"
></div>
<div class="progress-bar-fill" :style="{ width: `${getTaskProgressPercent(task)}%` }"></div>
</div>
<span class="inline-progress-text">
{{ task.progress_current || 0 }} / {{ task.progress_total || 0 }}
@@ -227,6 +221,10 @@
</div>
</section>
</div>
<BrandDedupeTab v-else-if="activeTab === 'dedupe'" />
<BrandConvertTab v-else-if="activeTab === 'convert'" />
<BrandSplitTab v-else-if="activeTab === 'split'" />
</div>
</PageShell>
</template>
@@ -249,8 +247,12 @@ import {
type BrandTaskItem,
} from '@/shared/api/brand'
import { getPywebviewApi, hasPywebview } from '@/shared/bridges/pywebview'
import BrandDedupeTab from '@/pages/brand/components/BrandDedupeTab.vue'
import BrandConvertTab from '@/pages/brand/components/BrandConvertTab.vue'
import BrandSplitTab from '@/pages/brand/components/BrandSplitTab.vue'
const hasPywebviewSupport = hasPywebview()
const activeTab = ref<'brand' | 'dedupe' | 'convert' | 'split'>('brand')
const selectedPaths = ref<string[]>([])
const runMode = ref<'immediate' | 'task'>('immediate')
const matchStrategy = ref<'Terms' | 'Simple'>('Terms')
@@ -267,10 +269,7 @@ let taskRefreshTimer: number | null = null
const displayPaths = computed(() => selectedPaths.value.slice(0, 8))
const progressPercent = computed(() => {
if (!progressTotal.value) {
return progressStatus.value === 'running' ? 12 : 100
}
if (!progressTotal.value) return progressStatus.value === 'running' ? 12 : 100
return Math.min(100, Math.round((progressCurrent.value / progressTotal.value) * 100))
})
@@ -298,7 +297,6 @@ function getStatusLabel(status?: string) {
failed: '失败',
cancelled: '已取消',
}
return statusMap[(status || '').toLowerCase()] || (status || '-')
}
@@ -311,12 +309,10 @@ function getTaskProgressPercent(task: BrandTaskItem) {
function stopTaskMonitor() {
activeTaskId.value = null
running.value = false
if (taskEvents) {
taskEvents.close()
taskEvents = null
}
if (pollTimer !== null) {
window.clearInterval(pollTimer)
pollTimer = null
@@ -345,7 +341,6 @@ async function refreshMonitoredTask(taskId: string | number) {
progressStatus.value = status as typeof progressStatus.value
stopTaskMonitor()
await loadTasks()
if (status === 'success') ElMessage.success('生成完成,可下载结果')
if (status === 'failed') ElMessage.error('生成失败')
if (status === 'cancelled') ElMessage.info('已取消')
@@ -640,12 +635,22 @@ onBeforeUnmount(() => {
.nav-tab {
padding: 8px 14px;
font-size: 13px;
color: #3498db;
background: rgba(52, 152, 219, 0.2);
color: #9fb9d3;
background: transparent;
border: none;
border-radius: 6px;
}
.nav-tab:hover {
color: #d8ecff;
background: rgba(52, 152, 219, 0.12);
}
.nav-tab.active {
color: #3498db;
background: rgba(52, 152, 219, 0.2);
}
.main-content {
display: flex;
height: calc(100vh - 56px);
@@ -1093,4 +1098,4 @@ onBeforeUnmount(() => {
width: 100%;
}
}
</style>
</style>