将 src/read 从单一消费者扩展为通用资源接缝;drawer 标签页与 useCampaignReport / useFiles 统一消费;导出仪式下沉至工具函数。 - 新增 readResource.ts:ReadSlot<T> 相位机(idle/loading/ refreshing/ready/error)、requestId 竞态守卫、静默刷新、 可注入 adapter;SelectedReadSlot<T> 支持 list→detail 的 stale-response rejection。配套 characterization 测试。 - evalActivity.ts / useIntelligentEvalRead.ts 退化为 readResource 的特化;既有测试保持通过。 - DecisionProcess / ConfigSnapshots / TaskQueueMonitor 删除手写 fetch 样板(useState + try/catch + useEffect 三件套),改走 资源接缝;ExecutionProcess 的 5 个 fetch 槽同步收敛。 - 决策日志新鲜度归一:三种策略(父级 5s 详情轮询 + ExecutionProcess 独立 5s 轮询 + DecisionProcess 挂载取一次) 收敛为父级 evalActivity 单一供给,子组件消费同一份数据。 - useCampaignReport 删除私有 ReadPhase / ReadSlot 定义,改 import 自 readResource。 - ACTIVE_STATUSES 合并至 read/intelligentEval.ts 单一出口。 - 新增 utils/download.ts:downloadBlob / downloadJson 取代 api.ts 与 useFiles 中三处重复的 Blob 导出仪式(含 DOM 副作用迁出 接口定义出口)。
18 lines
602 B
TypeScript
18 lines
602 B
TypeScript
/**
|
|
* Blob 下载仪式单一出口:创建对象 URL → 触发锚点点击 → 回收。
|
|
* api.ts 的响应式下载与各组件的 JSON 导出都走这里,不再各自手写 DOM 副作用。
|
|
*/
|
|
|
|
export function downloadBlob(blob: Blob, filename: string): void {
|
|
const url = URL.createObjectURL(blob)
|
|
const a = document.createElement('a')
|
|
a.href = url
|
|
a.download = filename
|
|
a.click()
|
|
URL.revokeObjectURL(url)
|
|
}
|
|
|
|
export function downloadJson(data: unknown, filename: string): void {
|
|
downloadBlob(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }), filename)
|
|
}
|