refactor(ui): single-source intelligent-eval label maps in status.ts
All checks were successful
CI / test (push) Successful in 3m13s
All checks were successful
CI / test (push) Successful in 3m13s
架构审查候选⑤:消除标签双轨,状态/决策类型映射单一出口。 - status.ts 新增 DECISION_TYPE_META(12 类型与后端 decision_type 字面量 对齐)+ decisionTypeOf() 兜底:后端新增类型时前端不再静默显示裸字符串, 未识别类型显式标注"未识别·xxx" - DecisionProcess / ExecutionProcess 删除各自手写的 DECISION_TYPE_LABELS (后者是审查报告之外的第三处双轨),统一走 decisionTypeOf - IntelligentEvals 的 STAT_CHIPS 标签从 EVAL_STATUS 派生,不再平行维护 tsc --noEmit 通过,前端 20 tests 全过,标签文本零变化。
This commit is contained in:
parent
2a0bcdd185
commit
d87aad5aed
@ -5,25 +5,11 @@ import {
|
||||
import type { ColumnsType } from 'antd/es/table'
|
||||
import { DownloadOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import SectionHeader from '../SectionHeader'
|
||||
import { decisionTypeOf } from './status'
|
||||
import { intelligentEvalsApi, type DecisionLog } from '../../api'
|
||||
import { colors } from '../../tokens'
|
||||
import { formatDateTime } from '../../utils/date'
|
||||
|
||||
const DECISION_TYPE_LABELS: Record<string, { label: string; color: string }> = {
|
||||
execute_session: { label: '执行会话', color: 'blue' },
|
||||
wait: { label: '等待', color: 'default' },
|
||||
start_analysis: { label: '开始分析', color: 'green' },
|
||||
task_abandoned: { label: '任务放弃', color: 'red' },
|
||||
session_expired: { label: '会话过期', color: 'orange' },
|
||||
planner_trigger: { label: '规划触发', color: 'purple' },
|
||||
planning_gate_failed: { label: '规划超闸判败', color: 'red' },
|
||||
analyst_nudge: { label: '催促汇总', color: 'purple' },
|
||||
executing_timeout: { label: '执行超窗判败', color: 'red' },
|
||||
trigger_failed: { label: '触发失败', color: 'orange' },
|
||||
trigger_failure_gate: { label: '触发失败判死', color: 'red' },
|
||||
worker_trigger: { label: '执行触发', color: 'purple' },
|
||||
}
|
||||
|
||||
interface DecisionProcessProps {
|
||||
evalId: string
|
||||
/** 独立页内作为子视图 tab 使用时可不传(tab 切换代替返回)。 */
|
||||
@ -85,7 +71,7 @@ export default function DecisionProcess({ evalId, onBack }: DecisionProcessProps
|
||||
key: 'decision_type',
|
||||
width: 120,
|
||||
render: (val: string) => {
|
||||
const info = DECISION_TYPE_LABELS[val] ?? { label: val, color: 'default' }
|
||||
const info = decisionTypeOf(val)
|
||||
return <Tag color={info.color}>{info.label}</Tag>
|
||||
},
|
||||
},
|
||||
@ -150,8 +136,8 @@ export default function DecisionProcess({ evalId, onBack }: DecisionProcessProps
|
||||
children: (
|
||||
<div>
|
||||
<div style={{ marginBottom: 4 }}>
|
||||
<Tag color={DECISION_TYPE_LABELS[log.decision_type]?.color ?? 'default'}>
|
||||
{DECISION_TYPE_LABELS[log.decision_type]?.label ?? log.decision_type}
|
||||
<Tag color={decisionTypeOf(log.decision_type).color}>
|
||||
{decisionTypeOf(log.decision_type).label}
|
||||
</Tag>
|
||||
<span style={{ fontSize: 12, color: colors.textSecondary }}>
|
||||
{formatDateTime(log.created_at)}
|
||||
|
||||
@ -14,7 +14,7 @@ import {
|
||||
type IntelligentEval,
|
||||
type TaskQueueItem,
|
||||
} from '../../api'
|
||||
import { SESSION_STATUS } from './status'
|
||||
import { SESSION_STATUS, decisionTypeOf } from './status'
|
||||
import { colors, statusColors } from '../../tokens'
|
||||
import { formatDateTime } from '../../utils/date'
|
||||
import { usePolling } from '../../hooks/usePolling'
|
||||
@ -28,12 +28,6 @@ const STAGE_CONFIG = [
|
||||
{ key: 'done', title: '完成', icon: CheckCircleOutlined },
|
||||
]
|
||||
|
||||
const DECISION_TYPE_LABELS: Record<string, string> = {
|
||||
execute_session: '执行会话',
|
||||
wait: '等待',
|
||||
start_analysis: '开始分析',
|
||||
}
|
||||
|
||||
interface ActivityEvent {
|
||||
time: string
|
||||
color: string
|
||||
@ -93,7 +87,7 @@ function decisionEvents(logs: DecisionLog[]): ActivityEvent[] {
|
||||
.map((log) => ({
|
||||
time: log.created_at as string,
|
||||
color: log.decision_type === 'start_analysis' ? 'green' : log.decision_type === 'wait' ? 'gray' : 'blue',
|
||||
text: `决策·${DECISION_TYPE_LABELS[log.decision_type] ?? log.decision_type}:${log.reason}`,
|
||||
text: `决策·${decisionTypeOf(log.decision_type).label}:${log.reason}`,
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@ -26,3 +26,24 @@ export const SEVERITY_META: Record<string, { label: string; color: string; order
|
||||
export function severityOf(severity: string) {
|
||||
return SEVERITY_META[severity?.toLowerCase()] ?? { label: severity, color: 'default', order: 99 }
|
||||
}
|
||||
|
||||
// 决策日志类型的标签/颜色单一出口,与后端 decision_type 字面量一一对应。
|
||||
// 后端新增类型时前端在此补一行;未识别类型由 decisionTypeOf 显式兜底。
|
||||
export const DECISION_TYPE_META: Record<string, { label: string; color: string }> = {
|
||||
execute_session: { label: '执行会话', color: 'blue' },
|
||||
wait: { label: '等待', color: 'default' },
|
||||
start_analysis: { label: '开始分析', color: 'green' },
|
||||
task_abandoned: { label: '任务放弃', color: 'red' },
|
||||
session_expired: { label: '会话过期', color: 'orange' },
|
||||
planner_trigger: { label: '规划触发', color: 'purple' },
|
||||
planning_gate_failed: { label: '规划超闸判败', color: 'red' },
|
||||
analyst_nudge: { label: '催促汇总', color: 'purple' },
|
||||
executing_timeout: { label: '执行超窗判败', color: 'red' },
|
||||
trigger_failed: { label: '触发失败', color: 'orange' },
|
||||
trigger_failure_gate: { label: '触发失败判死', color: 'red' },
|
||||
worker_trigger: { label: '执行触发', color: 'purple' },
|
||||
}
|
||||
|
||||
export function decisionTypeOf(decisionType: string) {
|
||||
return DECISION_TYPE_META[decisionType] ?? { label: `未识别·${decisionType}`, color: 'default' }
|
||||
}
|
||||
|
||||
@ -43,14 +43,14 @@ const TASKS_TAB: TabItem = {
|
||||
}
|
||||
|
||||
// 状态统计条:全部 + 各状态(含 cancelled,保证 全部 = 各状态之和;draft 为 0 不单列)
|
||||
// 标签从 EVAL_STATUS 单一出口派生,不与 status.ts 平行维护
|
||||
const STAT_CHIPS: { key: string; label: string; color?: string }[] = [
|
||||
{ key: 'all', label: '全部评估' },
|
||||
{ key: 'planning', label: '规划中' },
|
||||
{ key: 'pending_approval', label: '待审批' },
|
||||
{ key: 'executing', label: '执行中' },
|
||||
{ key: 'completed', label: '已完成', color: statusColors.completed },
|
||||
{ key: 'cancelled', label: '已取消' },
|
||||
{ key: 'failed', label: '失败', color: statusColors.failed },
|
||||
...(['planning', 'pending_approval', 'executing', 'completed', 'cancelled', 'failed'] as const).map((s) => ({
|
||||
key: s,
|
||||
label: EVAL_STATUS[s].label,
|
||||
color: s === 'completed' ? statusColors.completed : s === 'failed' ? statusColors.failed : undefined,
|
||||
})),
|
||||
]
|
||||
|
||||
export default function IntelligentEvalsPage() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user