重构: 前端DRY收口+后端测试类型对齐

- 新增 useToast composable: 消除 AiChat/Settings/Projects 4处 toast 重复
  统一默认3000ms(Projects原4000ms为操作类提示保留参数覆盖)
- 新增 utils/json.ts parseJsonArray: 消除 parseStack/parseTags/ModuleNode
  3处JSON字符串数组解析重复
- 新增 utils/html.ts escapeHtml: 消除 useMarkdown/FilePreview 2处重复
- ProjectDetail score-bar 内联三元改用 scoreTier(消除最后一处阈值硬编码)
- ConversationSidebar 删除 formatTime 透传包装(直接用 formatRelative)
- 清理死代码: parseTs/stringifyError/ErrorSink/_Unused 改私有或删除
  wrapNakedDiff 改私有(无外部 import)
- ModuleNode shortPath 改名 truncatedPath(与 useToolCard.shortPath 语义不同)
This commit is contained in:
2026-07-03 00:18:21 +08:00
parent 249b3b9ea8
commit 3d8b755229
22 changed files with 163 additions and 124 deletions

View File

@@ -189,6 +189,7 @@ mod tests {
status: ProjectStatus::InProgress,
description: "AI-native dev tool".into(),
path: Some(SanitizedPath::new("E:/wk-lab/devflow")),
extra: vec![],
};
let seg = build_augmentation_segment(&[aug], "zh");
assert!(seg.starts_with("--- 以下是用户选择的上下文参考"), "头部应隔离标注, got: {}", seg);
@@ -206,6 +207,7 @@ mod tests {
status: TaskStatus::Todo,
description: "do X".into(),
project_name: Some("devflow".into()),
extra: vec![],
};
let seg = build_augmentation_segment(&[aug], "zh");
assert!(seg.contains("【任务】Implement X"));
@@ -234,6 +236,7 @@ mod tests {
title: "Idea1".into(),
status: IdeaStatus::Approved,
description: String::new(),
extra: vec![],
},
Augmentation::Project {
id: "p1".into(),
@@ -241,6 +244,7 @@ mod tests {
status: ProjectStatus::Planning,
description: String::new(),
path: None,
extra: vec![],
},
];
let seg = build_augmentation_segment(&augs, "zh");
@@ -258,6 +262,7 @@ mod tests {
title: "Idea1".into(),
status: IdeaStatus::Approved,
description: String::new(),
extra: vec![],
};
let seg = build_augmentation_segment(&[aug], "en");
assert!(seg.starts_with("--- The following is the context"), "en 头部: {}", seg);
@@ -271,6 +276,7 @@ mod tests {
title: "Idea1".into(),
status: IdeaStatus::Approved,
description: String::new(),
extra: vec![],
};
let seg = build_augmentation_segment(&[aug], "fr");
assert!(seg.starts_with("--- 以下是用户选择的上下文参考"), "未知 lang 应按 zh 兜底");
@@ -284,6 +290,7 @@ mod tests {
status: ProjectStatus::Planning,
description: String::new(),
path: None,
extra: vec![],
};
let seg = build_augmentation_segment(&[aug], "zh");
assert!(!seg.contains("目录:"), "无 path 不应渲染目录行: {}", seg);