新增: 批次工作落地(推进链/评估闭环/事件总线/并发/加固) + 技术债清理 + 文档整理

后端:
- 工作流推进链(D-03):advance_task/状态机/闸门走 df-nodes Node trait,conditions 条件引擎扩展
- 想法评估闭环:启发式评分+对抗评估,df-ideas/scoring + df-storage/idea_eval_repo + idea 前端打通
- 全局事件数据总线:df-ai/context+context_helpers+augmentation 跨模块解耦
- AI planner/plan_hint/intent:aichat B 路线并行多轮基础
- patch_file 加固(TD-03/04):读改写整体锁防 lost update,expected_hash 合约闭环
- 压缩超时兜底(F-15 卡死根治)
- F-09 多会话并发:LlmConcurrency per-conv + streamingGuard 前端守护 + verify 脚本
- 知识注入 DRY/skills/audit 扩展

清理:
- aichat 技术债(误报 allow/死导入/过时注释 30 项)
- URGENT.md 删除(11 项加急全解决/迁 todo)
- 文档整理(todo/待决策/待审查/ARCHITECTURE/INDEX + 总线/技术债审查新文档)
This commit is contained in:
2026-06-21 20:51:26 +08:00
parent 330bb7f505
commit bd6a41fe6e
111 changed files with 11932 additions and 1034 deletions

67
src/utils/ideaEval.ts Normal file
View File

@@ -0,0 +1,67 @@
/**
* 灵感评估(assessment 三件套)共用纯函数 + 类型。
*
* 抽自 ProjectDetail.vue / IdeaDetail.vue 两处完全相同的定义
* (ScoreDimension interface + parseScores + assessmentClass + assessmentLabel),
* 消除 DRY 重复。本模块无响应式依赖,可被任意 <script setup> import 复用。
*/
import type { ComposerTranslation } from 'vue-i18n'
/** 传统评分维度:name + 分数 */
export interface ScoreDimension {
name: string
score: number
}
/**
* 解析 idea.scores(JSON 对象 {dim: score})为维度数组。
* null / 空 / 非法 / 非对象 → []。非数值分维度记 0。
* @param scoresJson idea.scores 原始字符串(可能为 null)
*/
export function parseScores(scoresJson: string | null | undefined): ScoreDimension[] {
if (!scoresJson) return []
try {
const parsed = JSON.parse(scoresJson)
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
return Object.entries(parsed).map(([name, score]) => ({
name,
score: typeof score === 'number' ? score : 0,
}))
}
return []
} catch {
return []
}
}
/** recommendation → CSS badge 颜色类映射(对应 .immediate/.soon/.conditional/.revised/.defer/.cancel) */
const ASSESSMENT_CLASS_MAP: Record<string, string> = {
'immediate action': 'immediate',
'soon': 'soon',
'with resources': 'conditional',
'research more': 'revised',
'monitor': 'defer',
'cancel': 'cancel',
}
/**
* recommendation 字符串 → CSS badge 类。
* 未知值回退到 'conditional'(中性,对齐原两处实现)。
*/
export function assessmentClass(recommendation: string): string {
return ASSESSMENT_CLASS_MAP[recommendation.toLowerCase()] ?? 'conditional'
}
/**
* recommendation 字符串 → i18n 本地化标签。
* 命中 ideas.assessment.{recommendation} 则返回译文,否则回退到原始 recommendation。
* @param t vue-i18n 的 t 函数(useI18n().t),由调用方注入避免本模块耦合 i18n 实例
*/
export function assessmentLabel(
t: ComposerTranslation,
recommendation: string,
): string {
const key = `ideas.assessment.${recommendation}`
const translated = t(key)
return translated === key ? recommendation : translated
}

View File

@@ -44,8 +44,8 @@ export function formatDate(v: string | number | null | undefined): string {
return d.toLocaleDateString(locale) + ' ' + d.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' })
}
/** 中文相对时间 '刚刚 / X 分钟前 / X 小时前 / X 天前';无效返回 '—' */
export function formatRelativeZh(v: string | number | null | undefined): string {
/** 相对时间(走 i18n:justNow/minutesAgo/hoursAgo/dayAgoen/zh 双语);无效返回 '—' */
export function formatRelative(v: string | number | null | undefined): string {
const ms = parseTs(v)
if (ms == null) return '—'
const diffMin = Math.floor((Date.now() - ms) / 60000)