重构: 前端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:
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* HTML 转义 — 消除 useMarkdown / FilePreview 两处重复实现。
|
||||
*/
|
||||
|
||||
/** 转义 &, <, > 三个核心 HTML 特殊字符 */
|
||||
export function escapeHtml(s: string): string {
|
||||
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* JSON 字符串数组解析 — 消除 parseStack / parseTags / ModuleNode 内联 3 处重复。
|
||||
*
|
||||
* 后端将 string[] 以 JSON.stringify 形式存于 stack/tags 等字段;
|
||||
* 解析失败或非数组时返回空数组,避免渲染崩溃。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 安全解析 JSON 字符串数组。
|
||||
* null / 空 / 非法 JSON / 非数组 → 返回 fallback(默认 [])。
|
||||
*/
|
||||
export function parseJsonArray<T = string>(
|
||||
raw: string | null | undefined,
|
||||
fallback: T[] = [],
|
||||
): T[] {
|
||||
if (!raw) return fallback
|
||||
try {
|
||||
const arr = JSON.parse(raw)
|
||||
return Array.isArray(arr) ? arr : fallback
|
||||
} catch {
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
//! parseStack 此前在 Projects.vue 与 ProjectDetail.vue 各有一份重复实现,
|
||||
//! 现抽到此处统一维护。
|
||||
|
||||
import { parseJsonArray } from './json'
|
||||
|
||||
/**
|
||||
* 解析技术栈 JSON 数组字符串(防崩)。
|
||||
*
|
||||
@@ -10,11 +12,5 @@
|
||||
* 解析失败或非数组时返回空数组,避免渲染崩溃。
|
||||
*/
|
||||
export function parseStack(stack: string | null | undefined): string[] {
|
||||
if (!stack) return []
|
||||
try {
|
||||
const arr = JSON.parse(stack)
|
||||
return Array.isArray(arr) ? arr : []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
return parseJsonArray(stack)
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@ import { t, currentLocale } from '@/i18n/i18n-helpers'
|
||||
// CR-260615-08(P1-10):相对时间走 i18n(原硬编码中文,en locale 时间恒中文)。
|
||||
// 类型安全访问经 i18n-helpers 收口(规避 vue-i18n TS2589)。
|
||||
|
||||
/** 解析任意时间值为毫秒时间戳;无效或空返回 null */
|
||||
export function parseTs(v: string | number | null | undefined): number | null {
|
||||
/** 解析任意时间值为毫秒时间戳;无效或空返回 null(仅本模块内部使用) */
|
||||
function parseTs(v: string | number | null | undefined): number | null {
|
||||
if (v == null) return null
|
||||
if (typeof v === 'number') {
|
||||
if (!Number.isFinite(v)) return null
|
||||
|
||||
Reference in New Issue
Block a user