新增: 灵感软删除回收站+雷达图正名(父⑤)

- IDEA-FIX-01: ideas 软删除(对标 tasks V14)— V28 迁移 deleted_at(幂等 ALTER) + IdeaRepo soft_delete/restore/list_deleted + list_by_query 恒带 deleted_at IS NULL(防回收站泄漏) + delete_idea 改软删 + restore_idea/list_deleted_ideas IPC + IdeaRecord 不加字段(纯 SQL WHERE 过滤)
- IDEA-FIX-14: 雷达图 CSS class radar→score-bar(IdeaDetail/ProjectDetail 2 文件 template+style+注释,纯正名零行为变更)
- 6 新测试(soft_delete 标记+过滤/幂等/missing, restore 还原/仅已删, list_deleted 排序);df-storage 73 测试过
This commit is contained in:
2026-06-26 20:42:48 +08:00
parent 308775cf4d
commit 005079f762
7 changed files with 230 additions and 37 deletions

View File

@@ -162,16 +162,16 @@
</template>
</div>
<!-- 传统评分雷达图 -->
<!-- 传统评分(score-bar) -->
<div class="detail-section">
<h3>{{ $t('ideas.multiScoreTitle') }}</h3>
<div class="radar-chart" v-if="parseScores(idea.scores).length > 0">
<div class="radar-row" v-for="dim in parseScores(idea.scores)" :key="dim.name">
<span class="radar-label">{{ dim.name }}</span>
<div class="radar-bar-track">
<div class="radar-bar-fill" :style="{ width: dim.score + '%' }" :class="dim.score >= 80 ? 'fill-high' : dim.score >= 60 ? 'fill-mid' : 'fill-low'"></div>
<div class="score-bar-chart" v-if="parseScores(idea.scores).length > 0">
<div class="score-bar-row" v-for="dim in parseScores(idea.scores)" :key="dim.name">
<span class="score-bar-label">{{ dim.name }}</span>
<div class="score-bar-track">
<div class="score-bar-fill" :style="{ width: dim.score + '%' }" :class="dim.score >= 80 ? 'fill-high' : dim.score >= 60 ? 'fill-mid' : 'fill-low'"></div>
</div>
<span class="radar-value">{{ dim.score }}</span>
<span class="score-bar-value">{{ dim.score }}</span>
</div>
</div>
<div v-else class="eval-report" style="opacity:0.5">{{ $t('ideas.noEval') }}</div>
@@ -774,31 +774,31 @@ watch(() => props.idea.id, loadHistory)
margin: 6px 0 0;
}
/* ===== 雷达图div 模拟) ===== */
.radar-chart {
/* ===== 多维评分条div 模拟) ===== */
.score-bar-chart {
display: flex;
flex-direction: column;
gap: 10px;
}
.radar-row {
.score-bar-row {
display: flex;
align-items: center;
gap: 12px;
}
.radar-label {
.score-bar-label {
font-size: 12px;
color: var(--df-text-secondary);
min-width: 72px;
text-align: right;
}
.radar-bar-track {
.score-bar-track {
flex: 1;
height: 8px;
background: var(--df-border);
border-radius: var(--df-radius-xs);
overflow: hidden;
}
.radar-bar-fill {
.score-bar-fill {
height: 100%;
border-radius: var(--df-radius-xs);
transition: width 0.4s;
@@ -806,7 +806,7 @@ watch(() => props.idea.id, loadHistory)
.fill-high { background: var(--df-success); }
.fill-mid { background: var(--df-warning); }
.fill-low { background: var(--df-danger); }
.radar-value {
.score-bar-value {
font-size: 12px;
font-weight: 500;
min-width: 28px;

View File

@@ -154,16 +154,16 @@
<p v-if="sourceAiAnalysis.summary" class="source-summary">{{ sourceAiAnalysis.summary }}</p>
<!-- 多维评分条(借鉴 IdeaDetail parseScores 渲染) -->
<div v-if="sourceScores.length" class="source-scores">
<div class="radar-row" v-for="dim in sourceScores" :key="dim.name">
<span class="radar-label">{{ dim.name }}</span>
<div class="radar-bar-track">
<div class="score-bar-row" v-for="dim in sourceScores" :key="dim.name">
<span class="score-bar-label">{{ dim.name }}</span>
<div class="score-bar-track">
<div
class="radar-bar-fill"
class="score-bar-fill"
:class="dim.score >= 80 ? 'fill-high' : dim.score >= 60 ? 'fill-mid' : 'fill-low'"
:style="{ width: dim.score + '%' }"
></div>
</div>
<span class="radar-value">{{ dim.score }}</span>
<span class="score-bar-value">{{ dim.score }}</span>
</div>
</div>
</template>
@@ -634,24 +634,24 @@ onUnmounted(() => {
.assessment-badge.defer { background: var(--df-danger-bg); color: var(--df-danger); }
.assessment-badge.cancel { background: var(--df-danger-bg); color: var(--df-danger); }
/* 多维评分条(复用 IdeaDetail radar-* 样式定义) */
/* 多维评分条(复用 IdeaDetail score-bar-* 样式定义) */
.source-scores {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 8px;
}
.radar-row { display: flex; align-items: center; gap: 10px; }
.radar-label { font-size: 12px; color: var(--df-text-secondary); min-width: 64px; text-align: right; }
.radar-bar-track {
.score-bar-row { display: flex; align-items: center; gap: 10px; }
.score-bar-label { font-size: 12px; color: var(--df-text-secondary); min-width: 64px; text-align: right; }
.score-bar-track {
flex: 1; height: 8px; background: var(--df-border);
border-radius: var(--df-radius-xs); overflow: hidden;
}
.radar-bar-fill { height: 100%; border-radius: var(--df-radius-xs); transition: width 0.4s; }
.score-bar-fill { height: 100%; border-radius: var(--df-radius-xs); transition: width 0.4s; }
.fill-high { background: var(--df-success); }
.fill-mid { background: var(--df-warning); }
.fill-low { background: var(--df-danger); }
.radar-value { font-size: 12px; font-weight: 500; min-width: 28px; text-align: right; color: var(--df-text); }
.score-bar-value { font-size: 12px; font-weight: 500; min-width: 28px; text-align: right; color: var(--df-text); }
</style>