新增: 批次工作落地(推进链/评估闭环/事件总线/并发/加固) + 技术债清理 + 文档整理
后端: - 工作流推进链(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:
@@ -39,7 +39,7 @@
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useProjectStore } from '@/stores/project'
|
||||
import { formatRelativeZh } from '@/utils/time'
|
||||
import { formatRelative } from '@/utils/time'
|
||||
|
||||
const store = useProjectStore()
|
||||
const { t } = useI18n()
|
||||
@@ -59,9 +59,9 @@ function getProjectTaskCount(projectId: string): number {
|
||||
return store.tasks.filter(t => t.project_id === projectId && t.status === 'in_progress').length
|
||||
}
|
||||
|
||||
// 相对时间复用 utils/time.formatRelativeZh(与 Tasks/AuditLog/MessageList 等同源,根治 NaN)
|
||||
// 相对时间复用 utils/time.formatRelative(与 Tasks/AuditLog/MessageList 等同源,根治 NaN)
|
||||
// 原 formatLastActivity 是其逐行复制,提取为单一来源。
|
||||
const formatLastActivity = formatRelativeZh
|
||||
const formatLastActivity = formatRelative
|
||||
|
||||
const displayProjects = computed(() =>
|
||||
store.projects.map(p => {
|
||||
|
||||
@@ -4,6 +4,24 @@
|
||||
<h2 class="df-panel-title">{{ $t('dashboard.ideaPool') }}</h2>
|
||||
<router-link to="/ideas" class="df-link">{{ $t('dashboard.viewAll') }}</router-link>
|
||||
</div>
|
||||
<div class="ideas-stats">
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">{{ stats.total }}</span>
|
||||
<span class="stat-label">{{ $t('ideas.statsTotal') }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">{{ stats.pending }}</span>
|
||||
<span class="stat-label">{{ $t('ideas.statsPending') }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">{{ stats.promoted }}</span>
|
||||
<span class="stat-label">{{ $t('ideas.statsPromoted') }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-num">{{ stats.avgScore }}</span>
|
||||
<span class="stat-label">{{ $t('ideas.statsAvgScore') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="idea-rows">
|
||||
<div v-for="idea in displayIdeas" :key="idea.id" class="idea-row">
|
||||
<div class="idea-score-ring" :class="'ring-' + idea.tier">
|
||||
@@ -39,6 +57,22 @@ const displayIdeas = computed(() =>
|
||||
}))
|
||||
)
|
||||
|
||||
// 灵感池统计概览 — 4 项关键指标(总数/待审/已晋升/平均分)。
|
||||
// score 可为 null(未评估),avgScore 仅对已评估灵感求均值,无则显示 '—'。
|
||||
const stats = computed(() => {
|
||||
const ideas = store.ideas
|
||||
const scored = ideas.filter(i => i.score != null)
|
||||
const avg = scored.length > 0
|
||||
? Math.round(scored.reduce((sum, i) => sum + (i.score ?? 0), 0) / scored.length)
|
||||
: null
|
||||
return {
|
||||
total: ideas.length,
|
||||
pending: ideas.filter(i => i.status === 'draft' || i.status === 'pending_review').length,
|
||||
promoted: ideas.filter(i => i.status === 'promoted').length,
|
||||
avgScore: avg == null ? '—' : avg,
|
||||
}
|
||||
})
|
||||
|
||||
function ideaStatusLabel(status: string): string {
|
||||
return t('dashboard.ideaStatus.' + status)
|
||||
}
|
||||
@@ -46,6 +80,35 @@ function ideaStatusLabel(status: string): string {
|
||||
|
||||
<style scoped>
|
||||
/* 仅迁入灵感行自身样式;df-panel/df-link 等通用面板类留 Dashboard.vue(多面板共享) */
|
||||
.ideas-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 8px 4px;
|
||||
background: var(--df-bg);
|
||||
border: 0.5px solid var(--df-border);
|
||||
border-radius: var(--df-radius);
|
||||
}
|
||||
.stat-num {
|
||||
font-family: var(--df-font-mono);
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--df-text);
|
||||
line-height: 1.1;
|
||||
}
|
||||
.stat-label {
|
||||
font-size: 10px;
|
||||
color: var(--df-text-dim);
|
||||
margin-top: 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.idea-rows { display: flex; flex-direction: column; }
|
||||
.idea-row {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user