Add dark theme, richer Markdown and readable plugin results. Improve Android input evidence, response integrity and diagnostics. Unify lifecycle, guidance receipts and evidence sources across clients. Keep direct action dispatch without an added AI quota approval layer. Align version metadata at 2.2.0 and bundle Helper 1.2.2. Validation: 3063 backend tests before the version bump; 44 after. Frontend: 317 tests and production build passed.
53 lines
2.9 KiB
TypeScript
53 lines
2.9 KiB
TypeScript
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
|
|
|
interface SourceReference { step_id?: string; step_number?: number; call_id?: string; source_id?: string; }
|
|
interface RecordedSource {
|
|
id: string; kind: string; label: string; target_id: string; plugin_id: string;
|
|
category: 'interface' | 'auxiliary'; references: SourceReference[]; reference_count: number;
|
|
}
|
|
interface SourceSummary {
|
|
sources: RecordedSource[]; total_sources: number; sources_omitted: number;
|
|
unattributed_step_count: number; note: string;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-evidence-sources', standalone: true,
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
template: `@if (value(); as summary) {
|
|
<details class="sources" aria-label="证据来源与验收边界">
|
|
<summary>证据来源 · {{ summary.total_sources ? summary.total_sources + ' 个' : '未记录' }}</summary>
|
|
<p>{{ summary.note }}</p>
|
|
@for (source of summary.sources; track source.id) {
|
|
<article>
|
|
<strong>{{ source.category === 'interface' ? '界面来源' : '辅助来源' }} · {{ kind(source.kind) }}</strong>
|
|
<div>{{ source.label || source.target_id }}</div>
|
|
<small>目标 {{ source.target_id }}@if(source.plugin_id) { · 插件 {{ source.plugin_id }} }</small>
|
|
<ul>
|
|
@for (ref of source.references; track $index) {
|
|
<li>步骤 {{ ref.step_number ?? '未记录' }}@if(ref.step_id) { · <code>{{ ref.step_id }}</code> }@if(ref.call_id) { · 调用 <code>{{ ref.call_id }}</code> }</li>
|
|
}
|
|
</ul>
|
|
@if(source.reference_count > source.references.length) { <small>另 {{ source.reference_count - source.references.length }} 条引用见步骤记录。</small> }
|
|
</article>
|
|
}
|
|
@if(summary.sources_omitted) { <p>另 {{ summary.sources_omitted }} 个来源见原始步骤记录。</p> }
|
|
@if(summary.unattributed_step_count) { <p>来源未完整记录的步骤:{{ summary.unattributed_step_count }};不据此推断执行平台。</p> }
|
|
</details>
|
|
}`,
|
|
styles: [`
|
|
:host { display:block; margin:10px 0; }
|
|
.sources { border:1px solid var(--app-border-control,#cbd5e1); border-radius:8px; padding:10px 12px; background:var(--app-surface,#fff); color:var(--app-text-control,#1e293b); font-size:12px; line-height:1.7; overflow-wrap:anywhere; }
|
|
summary { cursor:pointer; font-weight:600; }
|
|
article { border-top:1px solid var(--app-border-control,#cbd5e1); margin-top:8px; padding-top:8px; }
|
|
p,small { color:var(--app-text-secondary,#475569); }
|
|
ul { padding-left:20px; margin:4px 0; }
|
|
code { font-size:11px; }
|
|
`]
|
|
})
|
|
export class EvidenceSourcesComponent {
|
|
value = input<SourceSummary | null>(null);
|
|
kind(kind: string): string {
|
|
return ({android:'安卓界面', computer:'电脑界面', api:'接口数据', terminal:'终端', file:'文件', other:'其他'} as Record<string,string>)[kind] || '来源类型未记录';
|
|
}
|
|
}
|