修复: CR-27 Dashboard refresh 健壮性+stage 颜色修正+删死代码
M1 refresh 包 try/catch+console.error(原 Promise.all 无兜底 unhandledrejection);M3 getProjectStage planning→planning(蓝)/cancelled→cancelled(灰) 颜色与 label 语义一致(原 planning 归 coding 紫/cancelled 归 testing 橙颜色撒谎)+CSS 新增;L4 决策/批注 panel 死代码删(模板+CSS,功能未实现)。批8,vue-tsc 0
This commit is contained in:
@@ -98,26 +98,6 @@
|
|||||||
<div v-if="displayIdeas.length === 0" class="empty-hint">{{ $t('dashboard.empty.noIdeas') }}</div>
|
<div v-if="displayIdeas.length === 0" class="empty-hint">{{ $t('dashboard.empty.noIdeas') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Decisions -->
|
|
||||||
<section class="df-panel" style="animation-delay: 320ms">
|
|
||||||
<div class="df-panel-head">
|
|
||||||
<h2 class="df-panel-title">{{ $t('dashboard.recentDecisions') }}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="empty-hint" style="padding:12px 0;text-align:center;color:var(--df-text-dim);font-size:12px">
|
|
||||||
{{ $t('dashboard.empty.noData') }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Annotations -->
|
|
||||||
<section class="df-panel" style="animation-delay: 360ms">
|
|
||||||
<div class="df-panel-head">
|
|
||||||
<h2 class="df-panel-title">{{ $t('dashboard.openAnnotations') }}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="empty-hint" style="padding:12px 0;text-align:center;color:var(--df-text-dim);font-size:12px">
|
|
||||||
{{ $t('dashboard.empty.noData') }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -146,12 +126,14 @@ const stats = computed(() => [
|
|||||||
])
|
])
|
||||||
|
|
||||||
function getProjectStage(status: string): { stage: string; stageLabelKey: string; progress: number } {
|
function getProjectStage(status: string): { stage: string; stageLabelKey: string; progress: number } {
|
||||||
|
// stage(颜色档)与 stageLabelKey(文案)语义必须一致:
|
||||||
|
// planning/cancelled 不再借用 coding/testing 颜色(否则颜色撒谎),改用专属颜色档。
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'planning': return { stage: 'coding', stageLabelKey: 'planning', progress: 20 }
|
case 'planning': return { stage: 'planning', stageLabelKey: 'planning', progress: 20 }
|
||||||
case 'in_progress': return { stage: 'coding', stageLabelKey: 'coding', progress: 55 }
|
case 'in_progress': return { stage: 'coding', stageLabelKey: 'coding', progress: 55 }
|
||||||
case 'paused': return { stage: 'testing', stageLabelKey: 'paused', progress: 40 }
|
case 'paused': return { stage: 'testing', stageLabelKey: 'paused', progress: 40 }
|
||||||
case 'completed': return { stage: 'release', stageLabelKey: 'done', progress: 100 }
|
case 'completed': return { stage: 'release', stageLabelKey: 'done', progress: 100 }
|
||||||
case 'cancelled': return { stage: 'testing', stageLabelKey: 'cancelled', progress: 0 }
|
case 'cancelled': return { stage: 'cancelled', stageLabelKey: 'cancelled', progress: 0 }
|
||||||
default: return { stage: 'coding', stageLabelKey: 'coding', progress: 30 }
|
default: return { stage: 'coding', stageLabelKey: 'coding', progress: 30 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +182,11 @@ function ideaStatusLabel(status: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
|
try {
|
||||||
await Promise.all([store.loadProjects(), store.loadTasks(), store.loadIdeas()])
|
await Promise.all([store.loadProjects(), store.loadTasks(), store.loadIdeas()])
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Dashboard refresh failed:', e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function quickCapture() {
|
function quickCapture() {
|
||||||
@@ -403,6 +389,8 @@ onMounted(async () => {
|
|||||||
.dot-coding { background: var(--df-accent); }
|
.dot-coding { background: var(--df-accent); }
|
||||||
.dot-testing { background: var(--df-warning); }
|
.dot-testing { background: var(--df-warning); }
|
||||||
.dot-release { background: var(--df-success); }
|
.dot-release { background: var(--df-success); }
|
||||||
|
.dot-planning { background: var(--df-info); }
|
||||||
|
.dot-cancelled { background: var(--df-text-dim); }
|
||||||
|
|
||||||
.project-name {
|
.project-name {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -422,6 +410,8 @@ onMounted(async () => {
|
|||||||
.chip-coding { background: rgba(123,111,240,0.12); color: var(--df-accent); }
|
.chip-coding { background: rgba(123,111,240,0.12); color: var(--df-accent); }
|
||||||
.chip-testing { background: rgba(240,199,94,0.12); color: var(--df-warning); }
|
.chip-testing { background: rgba(240,199,94,0.12); color: var(--df-warning); }
|
||||||
.chip-release { background: rgba(61,219,160,0.12); color: var(--df-success); }
|
.chip-release { background: rgba(61,219,160,0.12); color: var(--df-success); }
|
||||||
|
.chip-planning { background: rgba(94,175,240,0.12); color: var(--df-info); }
|
||||||
|
.chip-cancelled { background: rgba(255,255,255,0.06); color: var(--df-text-dim); }
|
||||||
|
|
||||||
.project-bar-wrap { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
|
.project-bar-wrap { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
|
||||||
.project-bar {
|
.project-bar {
|
||||||
@@ -439,6 +429,8 @@ onMounted(async () => {
|
|||||||
.fill-coding { background: var(--df-accent); }
|
.fill-coding { background: var(--df-accent); }
|
||||||
.fill-testing { background: var(--df-warning); }
|
.fill-testing { background: var(--df-warning); }
|
||||||
.fill-release { background: var(--df-success); }
|
.fill-release { background: var(--df-success); }
|
||||||
|
.fill-planning { background: var(--df-info); }
|
||||||
|
.fill-cancelled { background: var(--df-text-dim); }
|
||||||
|
|
||||||
.project-pct {
|
.project-pct {
|
||||||
font-family: var(--df-font-mono);
|
font-family: var(--df-font-mono);
|
||||||
@@ -501,76 +493,6 @@ onMounted(async () => {
|
|||||||
.idea-name { font-size: 12px; font-weight: 500; color: var(--df-text); display: block; }
|
.idea-name { font-size: 12px; font-weight: 500; color: var(--df-text); display: block; }
|
||||||
.idea-status { font-size: 10px; color: var(--df-text-dim); margin-top: 1px; display: block; }
|
.idea-status { font-size: 10px; color: var(--df-text-dim); margin-top: 1px; display: block; }
|
||||||
|
|
||||||
/* ═══ Decision Rows ═══ */
|
|
||||||
.decision-rows { display: flex; flex-direction: column; }
|
|
||||||
.decision-row {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 7px 0;
|
|
||||||
border-bottom: 0.5px solid var(--df-border);
|
|
||||||
}
|
|
||||||
.decision-row:last-child { border-bottom: none; }
|
|
||||||
|
|
||||||
.decision-marker {
|
|
||||||
width: 20px; height: 20px;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
font-size: 9px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
border-radius: var(--df-radius-sm);
|
|
||||||
}
|
|
||||||
.marker-ai { background: rgba(94,175,240,0.12); color: var(--df-info); }
|
|
||||||
.marker-human { background: rgba(123,111,240,0.12); color: var(--df-accent); }
|
|
||||||
|
|
||||||
.decision-q { font-size: 11px; color: var(--df-text-secondary); display: block; margin-bottom: 2px; }
|
|
||||||
.decision-a {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--df-accent);
|
|
||||||
display: block;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
.decision-time {
|
|
||||||
font-family: var(--df-font-mono);
|
|
||||||
font-size: 9px;
|
|
||||||
color: var(--df-text-dim);
|
|
||||||
margin-top: 3px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ═══ Annotation Rows ═══ */
|
|
||||||
.anno-rows { display: flex; flex-direction: column; }
|
|
||||||
.anno-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 5px 0;
|
|
||||||
border-bottom: 0.5px solid var(--df-border);
|
|
||||||
}
|
|
||||||
.anno-row:last-child { border-bottom: none; }
|
|
||||||
|
|
||||||
.anno-tag {
|
|
||||||
font-family: var(--df-font-mono);
|
|
||||||
font-size: 9px;
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 2px 7px;
|
|
||||||
border-radius: var(--df-radius-sm);
|
|
||||||
min-width: 54px;
|
|
||||||
text-align: center;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
.tag-fixme { background: rgba(240,101,101,0.14); color: var(--df-danger); }
|
|
||||||
.tag-todo { background: rgba(94,175,240,0.12); color: var(--df-info); }
|
|
||||||
.tag-risk { background: rgba(240,199,94,0.12); color: #f0a830; }
|
|
||||||
.tag-question { background: rgba(94,175,240,0.10); color: var(--df-info); }
|
|
||||||
|
|
||||||
.anno-text {
|
|
||||||
font-family: var(--df-font-mono);
|
|
||||||
font-size: 10px;
|
|
||||||
color: var(--df-text-secondary);
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ═══ Responsive ═══ */
|
/* ═══ Responsive ═══ */
|
||||||
|
|
||||||
/* 窄窗口:单栏 */
|
/* 窄窗口:单栏 */
|
||||||
|
|||||||
Reference in New Issue
Block a user