重构: 前端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:
lxy
2026-07-03 00:18:21 +08:00
parent 249b3b9ea8
commit 3d8b755229
22 changed files with 163 additions and 124 deletions
+6 -11
View File
@@ -12,10 +12,10 @@
* 注:带 seq 竞态守卫的场景调用方需在 fn 内部判断,不在本工具职责范围。
*/
import type { Ref } from 'vue'
// (Ref import 已移除,_Unused 类型已删除)
/** 带 error 字段的 store state 形状(仅约束 error,其他字段任意)。 */
export interface ErrorSink {
/** 带 error 字段的 store state 形状(仅约束 error,其他字段任意)。仅本模块内部使用。 */
interface ErrorSink {
error: string | null
}
@@ -40,12 +40,8 @@ export async function runWithCatch<T>(
}
}
/**
* 把 unknown 错误转为可读字符串(无则返 undefined,由调用方兜底 i18n)。
*
* Tauri invoke 抛出的通常是 string 或 Error 实例。
*/
export function stringifyError(e: unknown): string | undefined {
// stringifyError 仅本模块内部使用(runWithCatch/runWithCatchGuarded 调用),不导出。
function stringifyError(e: unknown): string | undefined {
if (typeof e === 'string') return e
if (e instanceof Error) return e.message || e.toString()
if (e && typeof e === 'object' && 'toString' in e) {
@@ -81,5 +77,4 @@ export async function runWithCatchGuarded<T>(
}
}
// 显式标记 Ref 未使用(避免未来用上时改导入)
export type _Unused = Ref<unknown>
// _Unused 类型从未被外部 import,已删除(同时移除上方 Ref import)。