diff --git a/server_admin/src/views/DatasetDetail.vue b/server_admin/src/views/DatasetDetail.vue index 43f8447..9428c35 100644 --- a/server_admin/src/views/DatasetDetail.vue +++ b/server_admin/src/views/DatasetDetail.vue @@ -10,6 +10,36 @@ const router = useRouter() const datasetId = computed(() => Number(route.params.id)) const dataset = ref(null) +// 顶部状态汇总:各档位训练状态依次拼(双档 2026-09-03:s 高识别 / n 高性能 各一条最新记录); +// running 带进度,queued 提示排队;无训练记录回退数据集状态 +const variantLabel = { s: 's高识别', n: 'n高性能' } +const trainBanner = computed(() => { + const d = dataset.value + if (!d) return { text: '', type: 'info' } + const trs = d.trains || [] + if (!trs.length) { + const fallback = { building: ['建设中', 'info'], labeled: ['已标注', 'success'], synced: ['已同步', 'primary'] } + const [text, type] = fallback[d.status] || ['', 'info'] + return { text, type } + } + const parts = [] + for (const t of trs) { + const lab = variantLabel[t.variant] || t.variant + if (t.status === 'running') parts.push(`${lab} 训练中 ${t.currentEpoch || 0}/${t.totalEpochs || '-'} 轮`) + else if (t.status === 'queued') parts.push(`${lab} 排队中`) + else if (t.status === 'success') parts.push(`${lab} ${t.published ? '已训练·已发布' : '已训练'}`) + else if (t.status === 'failed') parts.push(`${lab} 训练失败`) + } + const type = trs.some((t) => t.status === 'running') + ? 'primary' + : trs.some((t) => t.status === 'queued') + ? 'warning' + : trs.some((t) => t.status === 'failed') + ? 'danger' + : 'success' + return { text: parts.join(' / ') || '—', type } +}) + // ---------- 数据 ---------- const detail = ref(null) // 工作台数据:images[{filename,url,width,height,boxes,labeled}] const imageMeta = ref({}) // filename -> {id, source, cleanExcluded}(来自 /datasets/images,行内展示用) @@ -910,13 +940,7 @@ onBeforeUnmount(() => {
← 返回数据集 {{ dataset?.name || '数据训练' }} - - {{ dataset.trainingStatus === 'running' ? `训练中 ${dataset.trainingCurrentEpoch || 0}/${dataset.trainingTotalEpochs || '-'}` : (dataset.trainingStatus === 'success' ? '训练完成' : (dataset.trainingStatus === 'failed' ? '训练失败' : (dataset.status === 'labeled' ? '已标注' : '建设中'))) }} - + {{ trainBanner.text }}
- - 发布模型 - - -
- - + + + {{ t.status === 'queued' ? '取消排队' : '终止' }} + +
@@ -449,6 +510,28 @@ onBeforeUnmount(() => { /> + + +
数据集:{{ startRow?.name }}
+
+
+ s 高识别 + yolov8s @1280 · 精度优先,默认档 +
+
+ n 高性能 + yolov8n @704 · 速度优先 +
+
+

+ 训练机 GPU 独占:已有任务时本次训练自动排队(queued),按发起顺序逐个执行;该档位已有进行中任务时会提示错误。排队的任务可在卡片上取消。 +

+ +
+ @@ -605,11 +688,17 @@ onBeforeUnmount(() => { } .ds-train { display: flex; - align-items: center; - gap: 10px; + flex-direction: column; + gap: 6px; padding: 8px 12px 12px; border-top: 1px dashed #ebeef5; } +.ds-train-line { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; +} .ds-train-bar { flex: 1; } @@ -618,6 +707,43 @@ onBeforeUnmount(() => { color: #606266; white-space: nowrap; } +.ds-pub { + margin-left: auto; +} +.ds-cancel { + margin-left: auto; +} +.start-dataset { + font-size: 14px; + font-weight: 600; + margin-bottom: 12px; +} +.start-opts { + display: flex; + flex-direction: column; + gap: 10px; +} +.start-opt { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 10px; + border: 1px solid #ebeef5; + border-radius: 6px; +} +.start-opt.is-act { + background: #f5f7fa; +} +.start-tip { + font-size: 12px; + color: #909399; +} +.start-note { + font-size: 12px; + color: #909399; + line-height: 1.6; + margin: 12px 0 0; +} .ds-body { padding: 10px 12px 6px; }