From 5c00a7d28626d3737eaa68995ba7428b14946bc2 Mon Sep 17 00:00:00 2001
From: MortalSnow <3352221860@qq.com>
Date: Thu, 11 Jun 2026 10:16:11 +0800
Subject: [PATCH] Simplify trust workbench UX
---
frontend/src/components/TrustCenterView.vue | 70 +++++--
.../src/components/TrustDiagnosticsPanel.vue | 34 +++-
.../src/components/TrustOpenLoopPanel.vue | 11 +-
frontend/src/components/TrustReviewDetail.vue | 90 ++++++---
frontend/src/components/TrustReviewInbox.vue | 35 +++-
frontend/src/styles.css | 190 +++++++++++++++++-
tests/trust_operations_ui.test.ts | 28 +++
7 files changed, 391 insertions(+), 67 deletions(-)
diff --git a/frontend/src/components/TrustCenterView.vue b/frontend/src/components/TrustCenterView.vue
index b8e8a33..561a418 100644
--- a/frontend/src/components/TrustCenterView.vue
+++ b/frontend/src/components/TrustCenterView.vue
@@ -3,18 +3,25 @@
-
-
- {{ metric.label }}
- {{ metric.value }}
- {{ metric.caption }}
-
+
+
+
今日焦点
+
{{ focusHeadline }}
+
{{ focusCaption }}
+
+
+
+ {{ metric.label }}
+ {{ metric.value }}
+ {{ metric.caption }}
+
+
()
-const metrics = computed(() => [
+const urgentReviewCount = computed(() => props.review.summary.critical + props.review.summary.high)
+
+const focusHeadline = computed(() => {
+ if (props.review.summary.critical) {
+ return `先确认 ${props.review.summary.critical} 条 critical 推断`
+ }
+ if (props.review.summary.high) {
+ return `先扫完 ${props.review.summary.high} 条高风险判断`
+ }
+ if (props.openLoops.summary.total) {
+ return `把 ${props.openLoops.summary.total} 个 open loop 变成下一步`
+ }
+ return '当前没有高压审查项'
+})
+
+const focusCaption = computed(() => {
+ if (urgentReviewCount.value) {
+ return '默认只展示最能帮助你做决定的信息;需要证据、历史和诊断时再展开。'
+ }
+ if (props.review.summary.unreviewed) {
+ return '剩余项目风险较低,可以按空间或关键词慢慢清理,不需要一次看完所有细节。'
+ }
+ return '信任边界已经比较干净,后续重点是继续沉淀用户确认过的理由。'
+})
+
+const compactMetrics = computed(() => [
{
- label: 'critical',
- value: props.review.summary.critical,
- caption: '必须先判断的 AI 推断',
+ label: '需判断',
+ value: props.review.summary.unreviewed,
+ caption: `${urgentReviewCount.value} 条高优先级`,
tone: 'tone-critical',
},
{
- label: 'high',
- value: props.review.summary.high,
- caption: '高风险证据或未审查项',
+ label: 'AI 推断',
+ value: props.review.summary.ai_inferred,
+ caption: `${props.review.summary.user_stated} 条用户原话`,
tone: 'tone-high',
},
{
- label: 'open loops',
+ label: 'open loop',
value: props.openLoops.summary.total,
- caption: '还没有闭环的问题',
+ caption: `${props.openLoops.summary.by_state.next || 0} 个下一步`,
tone: 'tone-loop',
},
{
- label: 'history',
+ label: '已审查',
value: props.diagnostics?.history_count || 0,
- caption: '已经写入的审查记录',
+ caption: '可追溯记录',
tone: 'tone-history',
},
])
diff --git a/frontend/src/components/TrustDiagnosticsPanel.vue b/frontend/src/components/TrustDiagnosticsPanel.vue
index 81d9e7a..daad284 100644
--- a/frontend/src/components/TrustDiagnosticsPanel.vue
+++ b/frontend/src/components/TrustDiagnosticsPanel.vue
@@ -8,6 +8,8 @@
{{ diagnostics?.queue_total || 0 }}
+ {{ diagnosticsSummary }}
+
AI 未审查
@@ -27,17 +29,39 @@
-
-
{{ warning }}
-
没有诊断警告。
-
+
+
+ 诊断警告
+ {{ diagnostics?.warnings.length || 0 }} 条
+
+
+
{{ warning }}
+
没有诊断警告。
+
+
diff --git a/frontend/src/components/TrustOpenLoopPanel.vue b/frontend/src/components/TrustOpenLoopPanel.vue
index aaffa0c..315fd06 100644
--- a/frontend/src/components/TrustOpenLoopPanel.vue
+++ b/frontend/src/components/TrustOpenLoopPanel.vue
@@ -16,7 +16,7 @@
-
+
{{ loop.state }}
{{ loop.text }}
@@ -29,16 +29,19 @@
+
+ 还有 {{ overflowCount }} 个 open loop 已收起,先处理上面这些更高价值的问题。
+
当前没有 open-loop。
diff --git a/frontend/src/components/TrustReviewInbox.vue b/frontend/src/components/TrustReviewInbox.vue
index a442450..0ce8c2b 100644
--- a/frontend/src/components/TrustReviewInbox.vue
+++ b/frontend/src/components/TrustReviewInbox.vue
@@ -3,7 +3,7 @@
Review Inbox
-
AI 推断审查队列
+ 待判断
{{ items.length }} 条
@@ -48,13 +48,16 @@
-
-
{{ item.why_saved_status }}
-
{{ item.space_name }}
-
{{ Math.round(item.confidence * 100) }}%
-
{{ item.open_loops.length }} open loop
+
+ {{ actionHint(item) }}
+
+
+ {{ boundaryLabel(item.why_saved_status) }}
+ {{ item.space_name || '未分配空间' }}
+ 可信度 {{ Math.round(item.confidence * 100) }}%
+ {{ item.open_loops.length }} 个 open loop
当前筛选下没有待审查项。
@@ -108,4 +111,22 @@ function riskLabel(level: TrustRiskLevel) {
if (level === 'medium') return 'medium'
return 'low'
}
+
+function compactReason(item: TrustReviewItem) {
+ const text = item.why_saved || item.summary || '这条材料还没有稳定的保存理由。'
+ return text.length > 108 ? `${text.slice(0, 108)}...` : text
+}
+
+function boundaryLabel(status: string) {
+ if (status === 'user-stated') return '用户原话'
+ if (status === 'AI-inferred') return 'AI 推断'
+ return status || '边界未知'
+}
+
+function actionHint(item: TrustReviewItem) {
+ if (item.risk_level === 'critical') return '建议现在处理:确认、改写或拒绝这条推断。'
+ if (item.risk_level === 'high') return '建议优先扫一眼证据,再决定是否确认。'
+ if (item.open_loops.length) return '可以转成下一步,避免问题继续悬空。'
+ return item.recommended_action || '低压力项目,可以稍后批量处理。'
+}
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index 649f8b4..032c0fa 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -7032,6 +7032,11 @@ button:not(:disabled):hover {
padding-bottom: 14px;
}
+.trust-center-header .paper-button {
+ flex: 0 0 auto;
+ white-space: nowrap;
+}
+
.trust-center-header h1 {
margin: 3px 0 5px;
font-family: var(--snap-title);
@@ -7053,6 +7058,57 @@ button:not(:disabled):hover {
gap: 10px;
}
+.trust-focus-strip {
+ display: grid;
+ grid-template-columns: minmax(300px, 1fr) minmax(420px, 1.1fr);
+ gap: 12px;
+ align-items: stretch;
+ border: 1px solid rgba(44, 53, 68, 0.12);
+ border-radius: 8px;
+ background: linear-gradient(135deg, rgba(250, 250, 246, 0.96), rgba(241, 246, 244, 0.9));
+ padding: 12px;
+}
+
+.trust-focus-primary {
+ display: grid;
+ align-content: center;
+ gap: 6px;
+ min-width: 0;
+}
+
+.trust-focus-primary h2 {
+ margin: 0;
+ font-family: var(--snap-title);
+ font-size: clamp(1.18rem, 1.7vw, 1.6rem);
+ font-weight: 560;
+ letter-spacing: 0;
+}
+
+.trust-focus-primary p,
+.trust-diagnostics-summary,
+.trust-loop-overflow-note {
+ margin: 0;
+ color: var(--muted-foreground);
+ line-height: 1.5;
+}
+
+.trust-focus-stats {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: 8px;
+}
+
+.trust-focus-stats article {
+ border: 1px solid rgba(44, 53, 68, 0.1);
+ border-radius: 8px;
+ background: rgba(255, 255, 255, 0.72);
+ padding: 10px;
+ display: grid;
+ gap: 4px;
+ align-content: start;
+ min-width: 0;
+}
+
.trust-summary-grid article {
min-height: 96px;
border: 1px solid var(--line);
@@ -7065,7 +7121,10 @@ button:not(:disabled):hover {
}
.trust-summary-grid span,
+.trust-focus-stats span,
.trust-batch-bar span,
+.trust-detail-brief span,
+.trust-detail-disclosure summary span,
.trust-detail-section > span,
.trust-diagnostics-grid span,
.trust-loop-state-grid span {
@@ -7075,12 +7134,14 @@ button:not(:disabled):hover {
letter-spacing: 0.04em;
}
-.trust-summary-grid strong {
+.trust-summary-grid strong,
+.trust-focus-stats strong {
font-size: 1.55rem;
line-height: 1;
}
-.trust-summary-grid small {
+.trust-summary-grid small,
+.trust-focus-stats small {
color: var(--muted-foreground);
line-height: 1.35;
}
@@ -7130,6 +7191,9 @@ button:not(:disabled):hover {
.trust-filter-row select,
.trust-loop-actions input,
.trust-detail-actions textarea {
+ width: 100%;
+ min-width: 0;
+ box-sizing: border-box;
min-height: 34px;
border: 1px solid var(--line);
border-radius: 8px;
@@ -7242,15 +7306,24 @@ button:not(:disabled):hover {
}
.trust-select-line,
-.trust-review-meta {
+.trust-review-meta,
+.trust-review-compact-meta {
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
}
+.trust-batch-actions > *,
+.trust-detail-button-row > *,
+.trust-loop-actions > *,
+.trust-filter-row > * {
+ min-width: 0;
+}
+
.trust-select-line small,
-.trust-review-meta span {
+.trust-review-meta span,
+.trust-review-compact-meta span {
border: 1px solid var(--line);
border-radius: 999px;
padding: 3px 7px;
@@ -7281,6 +7354,19 @@ button:not(:disabled):hover {
margin: 0;
color: var(--muted-foreground);
line-height: 1.45;
+ overflow-wrap: anywhere;
+}
+
+.trust-review-action-hint {
+ border-left: 3px solid rgba(58, 105, 97, 0.4);
+ color: var(--foreground);
+ font-size: 0.86rem;
+ line-height: 1.4;
+ padding-left: 8px;
+}
+
+.trust-review-compact-meta {
+ gap: 6px;
}
.trust-detail-panel {
@@ -7288,6 +7374,60 @@ button:not(:disabled):hover {
top: 14px;
}
+.trust-detail-brief {
+ display: grid;
+ gap: 8px;
+ border: 1px solid rgba(44, 53, 68, 0.1);
+ border-radius: 8px;
+ background: color-mix(in srgb, #f8faf8 78%, white);
+ padding: 11px;
+}
+
+.trust-detail-brief > div:first-child {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+
+.trust-detail-brief strong {
+ font-size: 0.95rem;
+}
+
+.trust-detail-brief p {
+ margin: 0;
+ color: var(--foreground);
+ line-height: 1.5;
+}
+
+.trust-detail-disclosure {
+ border-top: 1px solid var(--line);
+ margin-top: 10px;
+ padding-top: 8px;
+}
+
+.trust-detail-disclosure summary {
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 10px;
+ list-style-position: inside;
+}
+
+.trust-detail-disclosure summary strong {
+ color: var(--foreground);
+ font-size: 0.84rem;
+}
+
+.trust-detail-disclosure .trust-detail-section,
+.trust-detail-disclosure .trust-warning-list {
+ border-top: 0;
+ margin-top: 8px;
+ padding-top: 0;
+}
+
.trust-detail-section {
border-top: 1px solid var(--line);
padding-top: 10px;
@@ -7310,6 +7450,8 @@ button:not(:disabled):hover {
border-radius: 8px;
background: color-mix(in srgb, var(--background) 86%, white);
padding: 9px;
+ min-width: 0;
+ overflow-wrap: anywhere;
}
.trust-loop-state-grid,
@@ -7333,6 +7475,10 @@ button:not(:disabled):hover {
font-size: 1.12rem;
}
+.trust-diagnostics-summary {
+ margin-bottom: 10px;
+}
+
.trust-open-loop-card {
display: grid;
grid-template-columns: minmax(0, 1fr);
@@ -7344,6 +7490,13 @@ button:not(:disabled):hover {
margin: 4px 0;
}
+.trust-loop-overflow-note {
+ border: 1px dashed rgba(44, 53, 68, 0.18);
+ border-radius: 8px;
+ padding: 9px;
+ background: rgba(250, 250, 246, 0.68);
+}
+
.trust-empty {
color: var(--muted-foreground);
margin: 0;
@@ -7351,6 +7504,7 @@ button:not(:disabled):hover {
@media (max-width: 980px) {
.trust-summary-grid,
+ .trust-focus-strip,
.trust-workbench-grid,
.trust-secondary-grid,
.trust-filter-row,
@@ -7361,6 +7515,34 @@ button:not(:disabled):hover {
.trust-detail-panel {
position: static;
}
+
+ .trust-focus-stats {
+ grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
+ }
+
+ .trust-loop-state-grid,
+ .trust-diagnostics-grid {
+ grid-template-columns: repeat(auto-fit, minmax(68px, 1fr));
+ }
+}
+
+@media (max-width: 560px) {
+ .trust-center-header {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .trust-center-header .paper-button {
+ align-self: flex-start;
+ }
+
+ .trust-batch-actions,
+ .trust-detail-button-row,
+ .trust-loop-actions {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(58px, 1fr));
+ width: 100%;
+ }
}
.recall-result-desk {
diff --git a/tests/trust_operations_ui.test.ts b/tests/trust_operations_ui.test.ts
index 222b83e..30ba720 100644
--- a/tests/trust_operations_ui.test.ts
+++ b/tests/trust_operations_ui.test.ts
@@ -69,3 +69,31 @@ test('Trust Center components expose review operations, evidence, open loops, an
assert.match(styles, /\.trust-filter-row input\s*{[\s\S]*grid-column: 1 \/ -1/)
assert.match(styles, /\.trust-filter-row \.ghost-button\s*{[\s\S]*white-space: nowrap/)
})
+
+test('Trust Center reduces information pressure with compact focus and progressive disclosure', () => {
+ const view = read('frontend/src/components/TrustCenterView.vue')
+ const inbox = read('frontend/src/components/TrustReviewInbox.vue')
+ const detail = read('frontend/src/components/TrustReviewDetail.vue')
+ const diagnostics = read('frontend/src/components/TrustDiagnosticsPanel.vue')
+ const loops = read('frontend/src/components/TrustOpenLoopPanel.vue')
+ const styles = read('frontend/src/styles.css')
+
+ assert.match(view, /trust-focus-strip/)
+ assert.match(view, /trust-focus-primary/)
+ assert.match(view, /focusHeadline/)
+ assert.match(view, /trust-focus-stats/)
+ assert.match(view, /compactMetrics/)
+ assert.match(inbox, /trust-review-compact-meta/)
+ assert.match(inbox, /trust-review-action-hint/)
+ assert.match(detail, /trust-detail-brief/)
+ assert.match(detail, /trust-detail-disclosure/)
+ assert.match(detail, /