feat: 更新后端平台模块、前端组件及构建产物,新增工作计划文档
- 更新 backend 平台 API endpoints 及 platform_store - 更新前端 ComputeNodesView、DataProcessCreateView、FineTuneCreateView 等组件 - 更新前端 API 模块(compute、fineTune) - 重构 frontend/dist 构建产物(新 hash) - 新增 docs/2026-07-24-work-plan.md 工作计划文档 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import TrainingTaskOverview from './training-log/TrainingTaskOverview.vue'
|
||||
import { usePolling } from '@/composables/usePolling'
|
||||
import '@/plugins/echarts-training-log'
|
||||
import { useModelsStore } from '@/stores/models'
|
||||
import { getFineTune, getFineTuneLogs } from '@/api/modules/fineTune'
|
||||
import { getFineTune, getFineTuneDiagnostics, getFineTuneLogs, type TrainingDiagnostic } from '@/api/modules/fineTune'
|
||||
import { getTrainingLogFiles, getTrainingLogContent } from '@/api/modules/log'
|
||||
import { getDataset } from '@/api/modules/dataset'
|
||||
import { getSystemInfo } from '@/api/modules/system'
|
||||
@@ -35,6 +35,7 @@ const logContent = ref('')
|
||||
const gpuPool = ref<GpuInfo[]>([])
|
||||
const gpuUpdatedAt = ref<Date | null>(null)
|
||||
const gpuLoadError = ref('')
|
||||
const diagnostics = ref<TrainingDiagnostic[]>([])
|
||||
|
||||
/** 初始加载状态:首次数据返回前显示 loading,避免空白闪烁 */
|
||||
const loading = ref(true)
|
||||
@@ -247,6 +248,19 @@ async function loadLog(currentTask: FineTuneTask) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDiagnostics(currentTask: FineTuneTask) {
|
||||
if (currentTask.status !== 'failed') {
|
||||
diagnostics.value = []
|
||||
return
|
||||
}
|
||||
try {
|
||||
const result = await getFineTuneDiagnostics(currentTask.id)
|
||||
diagnostics.value = result.diagnostics || []
|
||||
} catch {
|
||||
diagnostics.value = []
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshAll() {
|
||||
if (refreshInFlight) return
|
||||
refreshInFlight = true
|
||||
@@ -262,7 +276,7 @@ async function refreshAll() {
|
||||
const datasetPromise = currentTask.train_dataset_id
|
||||
? loadDataset(currentTask.train_dataset_id)
|
||||
: Promise.resolve()
|
||||
await Promise.all([datasetPromise, loadLog(currentTask), loadGpuStatus()])
|
||||
await Promise.all([datasetPromise, loadLog(currentTask), loadGpuStatus(), loadDiagnostics(currentTask)])
|
||||
} finally {
|
||||
loading.value = false
|
||||
refreshInFlight = false
|
||||
@@ -535,6 +549,15 @@ onMounted(async () => {
|
||||
</div>
|
||||
</PageCard>
|
||||
|
||||
<PageCard v-if="diagnostics.length" class="diagnostics-card" title="失败诊断" subtitle="根据训练日志和失败原因生成的排查建议">
|
||||
<div class="diagnostics-list">
|
||||
<article v-for="item in diagnostics" :key="item.title" class="diagnostics-item">
|
||||
<strong>{{ item.title }}</strong>
|
||||
<p>{{ item.suggestion }}</p>
|
||||
</article>
|
||||
</div>
|
||||
</PageCard>
|
||||
|
||||
<!-- 原始日志 -->
|
||||
<PageCard class="log-card" title="训练日志" subtitle="查看训练任务的原始运行输出">
|
||||
<template #extra><span class="log-meta">{{ logLineCount }} 行 · 每 5 秒刷新</span></template>
|
||||
@@ -634,6 +657,7 @@ onMounted(async () => {
|
||||
.summary-card,
|
||||
.parameters-card,
|
||||
.metrics-panel,
|
||||
.diagnostics-card,
|
||||
.log-card {
|
||||
margin-bottom: 0;
|
||||
border: 1px solid #e4e7ed !important;
|
||||
@@ -641,6 +665,28 @@ onMounted(async () => {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.diagnostics-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.diagnostics-item {
|
||||
border: 1px solid #fecaca;
|
||||
border-radius: 8px;
|
||||
padding: 12px 14px;
|
||||
background: #fef2f2;
|
||||
|
||||
strong {
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 6px 0 0;
|
||||
color: #374151;
|
||||
line-height: 1.7;
|
||||
}
|
||||
}
|
||||
|
||||
.overview-card-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
Reference in New Issue
Block a user