重构: 前端DRY(style全局沉淀 + ts/js公共沉淀)

style-dry:
- 新增 src/styles/components.css: .info-item*/.panel/.panel-header/.tech-tag/.card-tags 全局
- main.ts 注册 import
- 删重复: ProjectDetail/TaskDetail/TaskOutputCard/ProjectCard/Projects(scoped删重复, 全局对子组件生效)
- 未使用清理: Projects .card-progress dead(1处保守核对)

tsjs-dry:
- aiShared.ts: resolveAiLang(合并useAiSend.resolveLang + useAiContext.resolveLanguage)
- stores/knowledge.ts: kindText/kindLabel/kindIcon/knowledgeStatusLabel/knowledgeConfidenceLabel(5公共)
- 删重复: useAiSend/useAiContext(resolveLang) + Knowledge/KnowledgeDetail(4+5 helper) + ActiveProjectsPanel(formatLastActivity→formatRelativeZh复用)

strategy: DRY收口, 公共沉淀(utils/store/shared); relativeTime非纯重复保留; .btn/.empty-hint局部override WATCH未动
This commit is contained in:
2026-06-19 12:11:19 +08:00
parent 64ece1d3a0
commit 7748e3ecbc
14 changed files with 177 additions and 212 deletions

View File

@@ -87,27 +87,9 @@ const reviewSuggestions = computed<string[]>(() => {
<style scoped>
/* ===== F-AiNodeSelfReview: output_json 区块(产出 + 自审结论卡) ===== */
/* 基础布局 .info-item / .info-block / .label / .value:Vue scoped 不穿透子组件后代 DOM,
父级 TaskDetail.vue 的 .info-item .label 等后代选择器不会作用到本子组件内部元素,
此处复制等价基础布局(与 TaskDetail.vue L559-577 一致),保持视觉零变化。 */
.info-item {
display: flex;
flex-direction: row;
align-items: baseline;
gap: 12px;
}
.info-item.info-block {
flex-direction: column;
}
.info-item .label {
font-size: 12px;
color: var(--df-text-dim);
text-transform: uppercase;
letter-spacing: 0.5px;
min-width: 88px;
flex-shrink: 0;
}
.info-item .value { font-size: 14px; color: var(--df-text); flex: 1; min-width: 0; }
/* 基础布局 .info-item / .info-block / .label / .value 已收敛至全局 components.css
(DRY 收口 B-260619)。全局类对子组件内部 DOM 生效(全局非 scoped 无渗透限制),
本子组件无需复制等价基础布局,仅保留本组件特有的 output/review 样式。 */
.output-block .output-body {
display: flex;