fix(frontend): 对齐数据任务详情状态
This commit is contained in:
13
frontend/src/utils/dataProcessStatus.d.ts
vendored
Normal file
13
frontend/src/utils/dataProcessStatus.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { DataProcessStatus } from '@/types/dataProcess'
|
||||
|
||||
export type DataProcessStatusTagType = 'primary' | 'success' | 'warning' | 'danger' | 'info'
|
||||
|
||||
export interface DataProcessStatusLike {
|
||||
status?: DataProcessStatus
|
||||
output_dataset_id?: string | number | null
|
||||
}
|
||||
|
||||
export function dataProcessDisplayStatus(task: DataProcessStatusLike): {
|
||||
label: string
|
||||
type: DataProcessStatusTagType
|
||||
}
|
||||
18
frontend/src/utils/dataProcessStatus.js
Normal file
18
frontend/src/utils/dataProcessStatus.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 将数据处理任务的执行状态与当前轮发布指针合并为用户可理解的状态。
|
||||
* 上一轮保留的 output_datasets 不参与判断,避免将尚未重新发布的当前轮误标为已发布。
|
||||
*
|
||||
* @param {{ status?: string, output_dataset_id?: string | number | null }} task
|
||||
* @returns {{ label: string, type: 'primary' | 'success' | 'warning' | 'danger' | 'info' }}
|
||||
*/
|
||||
export function dataProcessDisplayStatus(task) {
|
||||
if (task.status === 'running') return { label: '生成中', type: 'primary' }
|
||||
if (task.status === 'completed') {
|
||||
return task.output_dataset_id
|
||||
? { label: '已发布', type: 'success' }
|
||||
: { label: '已生成', type: 'warning' }
|
||||
}
|
||||
if (task.status === 'failed') return { label: '生成失败', type: 'danger' }
|
||||
if (task.status === 'stopped') return { label: '已停止', type: 'info' }
|
||||
return { label: '待生成', type: 'info' }
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import PageCard from '@/components/PageCard.vue'
|
||||
import ModelStatusTag from '@/components/ModelStatusTag.vue'
|
||||
import { usePolling } from '@/composables/usePolling'
|
||||
import {
|
||||
getDataProcessProgress,
|
||||
@@ -21,6 +20,7 @@ import type {
|
||||
DataProcessTask,
|
||||
DataProcessType,
|
||||
} from '@/types/dataProcess'
|
||||
import { dataProcessDisplayStatus } from '@/utils/dataProcessStatus.js'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -155,20 +155,41 @@ const sourceDatasetName = computed(() => (
|
||||
|| '源文件上传'
|
||||
))
|
||||
const outputDatasets = computed(() => {
|
||||
const items = detail.value?.output_datasets || []
|
||||
if (items.length) return items
|
||||
if (!detail.value?.output_dataset_id) return []
|
||||
return [{
|
||||
id: detail.value.output_dataset_id,
|
||||
name: detail.value.output_dataset_name || detail.value.output_dataset || '训练集',
|
||||
type: 'train',
|
||||
}]
|
||||
return detail.value?.output_datasets || []
|
||||
})
|
||||
const outputDatasetName = computed(() => (
|
||||
outputDatasets.value.map((item) => item.name).join('、')
|
||||
))
|
||||
const outputDatasetId = computed(() => detail.value?.output_dataset_id || null)
|
||||
const hasPublishedOutputs = computed(() => outputDatasets.value.length > 0)
|
||||
const hasCurrentPublishedDataset = computed(() => (
|
||||
Boolean(outputDatasetId.value)
|
||||
&& outputDatasets.value.some((dataset) => String(dataset.id) === String(outputDatasetId.value))
|
||||
))
|
||||
const displayStatus = computed(() => dataProcessDisplayStatus({
|
||||
status: detail.value?.status || 'pending',
|
||||
output_dataset_id: hasCurrentPublishedDataset.value ? outputDatasetId.value : null,
|
||||
}))
|
||||
const inputMetricUnit = computed(() => isUnstructured.value ? '个' : '条')
|
||||
const outputSummary = computed(() => {
|
||||
if (hasCurrentPublishedDataset.value) return outputDatasetName.value || '当前轮已发布'
|
||||
if (outputDatasetId.value) return '已发布数据集不可用,请重新发布'
|
||||
if (hasPublishedOutputs.value) {
|
||||
return `当前轮尚未发布;上次已发布 ${outputDatasets.value.length} 个数据集,仍可正常使用`
|
||||
}
|
||||
return detail.value?.status === 'completed' ? '当前轮尚未发布' : '尚未发布为数据集'
|
||||
})
|
||||
const resultEmptyTitle = computed(() => {
|
||||
if (detail.value?.status === 'completed') return '没有符合条件的结果'
|
||||
if (detail.value?.status === 'failed') return '任务生成失败,未生成结果明细'
|
||||
if (detail.value?.status === 'stopped') return '任务已停止,暂无生成结果'
|
||||
return '处理完成后将在这里展示结果明细'
|
||||
})
|
||||
const resultEmptyDescription = computed(() => (
|
||||
detail.value?.status === 'completed'
|
||||
? '请调整搜索或筛选条件'
|
||||
: `当前任务状态:${displayStatus.value.label}`
|
||||
))
|
||||
const canRegenerate = computed(() => {
|
||||
const status = detail.value?.status
|
||||
return status === 'pending'
|
||||
@@ -479,9 +500,11 @@ onBeforeUnmount(() => {
|
||||
<div class="detail-heading">
|
||||
<div class="heading-row">
|
||||
<h1>{{ detail.name }}</h1>
|
||||
<ModelStatusTag :status="detail.status" />
|
||||
<el-tag :type="displayStatus.type" size="small" effect="light">
|
||||
{{ displayStatus.label }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
v-if="detail.status === 'completed' && !outputDatasetId"
|
||||
v-if="detail.status === 'completed' && !hasCurrentPublishedDataset"
|
||||
class="publish-button"
|
||||
type="primary"
|
||||
@click="openPublishDialog"
|
||||
@@ -525,13 +548,13 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<span>{{ inputMetricLabel }}</span>
|
||||
<strong>{{ inputMetricCount.toLocaleString() }}</strong>
|
||||
<strong>{{ inputMetricCount.toLocaleString() }} {{ inputMetricUnit }}</strong>
|
||||
<small>{{ sourceFileCount ? `源文件 ${sourceFileCount} 个:` : '来源:' }}{{ sourceDatasetName }}</small>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<span>输出结果</span>
|
||||
<strong>{{ numeric(detail.output_count).toLocaleString() }}</strong>
|
||||
<small>{{ outputDatasetName || '尚未发布为数据集' }}</small>
|
||||
<strong>{{ numeric(detail.output_count).toLocaleString() }} 条</strong>
|
||||
<small>{{ outputSummary }}</small>
|
||||
</div>
|
||||
<div class="metric-card is-primary">
|
||||
<span>结果保留率</span>
|
||||
@@ -560,9 +583,9 @@ onBeforeUnmount(() => {
|
||||
<dt>输出数据集</dt>
|
||||
<dd class="output-dataset-cell">
|
||||
<p
|
||||
v-if="hasPublishedOutputs && !outputDatasetId"
|
||||
v-if="hasPublishedOutputs && !hasCurrentPublishedDataset"
|
||||
class="output-dataset-hint"
|
||||
>当前生成结果尚未重新发布,以下为上次已发布数据集,仍可正常使用</p>
|
||||
>当前轮尚未发布,以下为上次已发布数据集,仍可正常使用</p>
|
||||
<div v-if="outputDatasets.length" class="output-dataset-links">
|
||||
<el-button
|
||||
v-for="dataset in outputDatasets"
|
||||
@@ -572,6 +595,7 @@ onBeforeUnmount(() => {
|
||||
@click="router.push(`/dataset/${dataset.id}/preview`)"
|
||||
>{{ dataset.name }}({{ dataset.count || 0 }} 条)<i class="fa fa-external-link" /></el-button>
|
||||
</div>
|
||||
<span v-else-if="outputDatasetId">已发布数据集不可用,请重新发布</span>
|
||||
<span v-else>尚未发布为数据集</span>
|
||||
</dd>
|
||||
</div>
|
||||
@@ -583,12 +607,12 @@ onBeforeUnmount(() => {
|
||||
<div><h2 id="statistics-title">处理统计</h2><p>查看数据清洗、过滤和输出情况</p></div>
|
||||
</div>
|
||||
<div class="statistics-grid">
|
||||
<div><span>源文件</span><strong>{{ sourceFileCount.toLocaleString() }}</strong></div>
|
||||
<div><span>{{ inputMetricLabel }}</span><strong>{{ inputMetricCount.toLocaleString() }}</strong></div>
|
||||
<div><span>成功输出</span><strong>{{ numeric(detail.output_count).toLocaleString() }}</strong></div>
|
||||
<div><span>过滤数据</span><strong>{{ numeric(detail.filtered_count).toLocaleString() }}</strong></div>
|
||||
<div><span>重复数据</span><strong>{{ numeric(detail.duplicate_count).toLocaleString() }}</strong></div>
|
||||
<div><span>异常数据</span><strong>{{ numeric(detail.error_count).toLocaleString() }}</strong></div>
|
||||
<div><span>源文件</span><strong>{{ sourceFileCount.toLocaleString() }} 个</strong></div>
|
||||
<div><span>{{ inputMetricLabel }}</span><strong>{{ inputMetricCount.toLocaleString() }} {{ inputMetricUnit }}</strong></div>
|
||||
<div><span>生成结果</span><strong>{{ numeric(detail.output_count).toLocaleString() }} 条</strong></div>
|
||||
<div><span>过滤数据</span><strong>{{ numeric(detail.filtered_count).toLocaleString() }} 条</strong></div>
|
||||
<div><span>重复数据</span><strong>{{ numeric(detail.duplicate_count).toLocaleString() }} 条</strong></div>
|
||||
<div><span>异常数据</span><strong>{{ numeric(detail.error_count).toLocaleString() }} 条</strong></div>
|
||||
<div><span>执行进度</span><strong>{{ progressPercentage }}%</strong></div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -687,8 +711,8 @@ onBeforeUnmount(() => {
|
||||
|
||||
<div v-else class="result-empty">
|
||||
<i class="fa" :class="resultError || detail.status === 'failed' ? 'fa-exclamation-circle' : 'fa-hourglass-half'" aria-hidden="true" />
|
||||
<strong>{{ resultError || (detail.status === 'completed' ? '没有符合条件的结果' : detail.status === 'failed' ? '任务失败,未生成结果明细' : '处理完成后将在这里展示结果明细') }}</strong>
|
||||
<span v-if="!resultError">{{ detail.status === 'completed' ? '请调整搜索或筛选条件' : `当前任务状态:${detail.status === 'running' ? '运行中' : '等待中'}` }}</span>
|
||||
<strong>{{ resultError || resultEmptyTitle }}</strong>
|
||||
<span v-if="!resultError">{{ resultEmptyDescription }}</span>
|
||||
<el-button v-else type="primary" link @click="loadResults">重新加载</el-button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import DataTablePage from '@/components/DataTablePage.vue'
|
||||
import { deleteDataProcessTask, getDataProcessTasks } from '@/api/modules/dataProcess'
|
||||
import type { DataProcessTask, DataProcessType } from '@/types/dataProcess'
|
||||
|
||||
type TaskStatusTagType = 'success' | 'warning' | 'info' | 'danger' | 'primary'
|
||||
import { dataProcessDisplayStatus } from '@/utils/dataProcessStatus.js'
|
||||
|
||||
const processTypeMap: Record<DataProcessType, string> = {
|
||||
structured: '结构化数据',
|
||||
@@ -87,19 +86,6 @@ function generatedCountLabel(task: DataProcessTask) {
|
||||
return `${safeCount(task.output_count)} 条`
|
||||
}
|
||||
|
||||
/** 将当前轮生成状态与发布指针合并为用户可理解的列表状态。 */
|
||||
function taskDisplayStatus(task: DataProcessTask): { label: string; type: TaskStatusTagType } {
|
||||
if (task.status === 'running') return { label: '生成中', type: 'primary' }
|
||||
if (task.status === 'completed') {
|
||||
return task.output_dataset_id
|
||||
? { label: '已发布', type: 'success' }
|
||||
: { label: '已生成', type: 'warning' }
|
||||
}
|
||||
if (task.status === 'failed') return { label: '生成失败', type: 'danger' }
|
||||
if (task.status === 'stopped') return { label: '已停止', type: 'info' }
|
||||
return { label: '待生成', type: 'info' }
|
||||
}
|
||||
|
||||
onMounted(loadData)
|
||||
</script>
|
||||
|
||||
@@ -123,10 +109,10 @@ onMounted(loadData)
|
||||
<el-table-column label="任务状态" align="center" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="taskDisplayStatus(row as DataProcessTask).type"
|
||||
:type="dataProcessDisplayStatus(row as DataProcessTask).type"
|
||||
size="small"
|
||||
effect="light"
|
||||
>{{ taskDisplayStatus(row as DataProcessTask).label }}</el-tag>
|
||||
>{{ dataProcessDisplayStatus(row as DataProcessTask).label }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="处理类型" align="center" width="140">
|
||||
|
||||
Reference in New Issue
Block a user