diff --git a/frontend/package.json b/frontend/package.json index 92a6362..07913b5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,9 +11,11 @@ "test:default-dashboard": "node scripts/regression-default-dashboard.mjs", "test:dashboard": "node scripts/regression-dashboard.mjs", "test:data-process-list": "node scripts/regression-data-process-list.mjs", + "test:data-process-detail": "node scripts/regression-data-process-detail.mjs", "test:data-process-wizard": "node scripts/regression-data-process-wizard.mjs", "test:dataset-task-tab": "node scripts/regression-dataset-task-tab.mjs", "test:dataset-preview": "node scripts/regression-dataset-preview.mjs", + "test:data-convert": "node scripts/regression-data-convert.mjs", "test:eval-create": "node scripts/regression-eval-create-wizard.mjs", "test:eval-detail": "node scripts/regression-eval-detail.mjs", "test:model-manage": "node scripts/regression-model-manage.mjs", diff --git a/frontend/scripts/regression-data-process-detail.mjs b/frontend/scripts/regression-data-process-detail.mjs new file mode 100644 index 0000000..cbd34d6 --- /dev/null +++ b/frontend/scripts/regression-data-process-detail.mjs @@ -0,0 +1,55 @@ +import assert from 'node:assert/strict' +import { readFile } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' +import path from 'node:path' +import { parse as parseSfc } from '@vue/compiler-sfc' + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)) +const sourceRoot = path.resolve(scriptDir, '../src') +const [detailSource, listSource, routerSource] = await Promise.all([ + readFile(path.join(sourceRoot, 'views/data-process/DataProcessDetailView.vue'), 'utf8'), + readFile(path.join(sourceRoot, 'views/data-process/DataProcessListView.vue'), 'utf8'), + readFile(path.join(sourceRoot, 'router/index.ts'), 'utf8'), +]) + +const { descriptor, errors } = parseSfc(detailSource, { filename: 'DataProcessDetailView.vue' }) +assert.equal(errors.length, 0, `数据处理详情页无法解析:${errors[0]}`) +assert.ok(descriptor.template?.content.trim(), '数据处理详情页缺少可渲染模板') + +assert.match(routerSource, /path:\s*['"]data-process\/:id['"]/, '缺少数据处理详情动态路由') +assert.match(routerSource, /name:\s*['"]data-process-detail['"]/, '数据处理详情路由缺少名称') +assert.match(routerSource, /DataProcessDetailView\.vue/, '数据处理详情路由未加载详情页面') +assert.match(routerSource, /title:\s*['"]数据处理详情['"]/, '数据处理详情路由标题不正确') + +assert.match(listSource, /name:\s*['"]data-process-detail['"]/, '列表详情按钮未使用详情命名路由') +assert.match(listSource, /params:\s*\{\s*id:\s*taskId\s*\}/, '列表详情按钮未传递任务 ID') +assert.doesNotMatch(listSource, /查看详情功能开发中/, '详情按钮仍保留开发中提示') + +for (const requiredCopy of [ + '处理耗时', + '开始时间', + '完成时间', + '输入数据', + '输出结果', + '处理统计', + '处理配置', + '结果明细', +]) { + assert.match(detailSource, new RegExp(requiredCopy), `详情页缺少必要信息:${requiredCopy}`) +} + +for (const status of ['completed', 'running', 'pending', 'failed']) { + assert.match(detailSource, new RegExp(`status:\\s*['"]${status}['"]`), `详情 Mock 缺少 ${status} 状态`) +} + +assert.match(detailSource, /const completedResults:\s*ResultRow\[\]/, '完成任务缺少结果明细 Mock') +assert.match(detailSource, /:data="paginatedResults"/, '结果表格未绑定分页后的处理结果') +assert.match(detailSource, /v-model="keyword"/, '结果明细缺少搜索能力') +assert.match(detailSource, /v-model="statusFilter"/, '结果明细缺少状态筛选') +assert.match(detailSource, /router\.push\(`\/dataset\/\$\{detail\.outputDatasetId\}\/preview`\)/, '输出数据集未接入预览入口') +assert.match(detailSource, /未找到数据处理任务/, '未知任务 ID 缺少明确空状态') +assert.match(detailSource, /width:\s*100%/, '详情页没有铺满内容区域') +assert.doesNotMatch(detailSource, /^\s*max-width:\s*\d+px/m, '详情页不应使用固定最大宽度') +assert.doesNotMatch(detailSource, /\b(?:password|secret|token)\b/i, '详情页不得展示敏感凭据字段') + +console.log('数据处理任务详情 UI 回归检查通过') diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 7f74203..15f1cbb 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -133,6 +133,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/data-process/DataProcessCreateView.vue'), meta: { title: '新建数据处理任务', pageSurface: 'self' }, }, + { + path: 'data-process/:id', + name: 'data-process-detail', + component: () => import('@/views/data-process/DataProcessDetailView.vue'), + meta: { title: '数据处理详情' }, + }, // 数据集管理 { path: 'dataset', diff --git a/frontend/src/views/data-process/DataProcessDetailView.vue b/frontend/src/views/data-process/DataProcessDetailView.vue new file mode 100644 index 0000000..088605e --- /dev/null +++ b/frontend/src/views/data-process/DataProcessDetailView.vue @@ -0,0 +1,428 @@ + + + + + diff --git a/frontend/src/views/data-process/DataProcessListView.vue b/frontend/src/views/data-process/DataProcessListView.vue index ff78bcb..3e011d4 100644 --- a/frontend/src/views/data-process/DataProcessListView.vue +++ b/frontend/src/views/data-process/DataProcessListView.vue @@ -60,13 +60,14 @@ function handleCreate() { router.push('/data-process/create') } -/** 查看任务详情(功能开发中) */ -function viewDetail(_row: DataProcessTask) { - ElMessage.info('查看详情功能开发中...') +/** 查看任务详情 */ +function viewDetail(row: unknown) { + const taskId = (row as { id: string | number }).id + router.push({ name: 'data-process-detail', params: { id: taskId } }) } /** 删除任务(功能开发中) */ -function handleDelete(_row: DataProcessTask) { +function handleDelete(_row: unknown) { ElMessage.info('删除功能开发中...') }