feat(M08-B): 补联调风险清单导出

This commit is contained in:
Codex
2026-07-07 09:26:27 +08:00
parent 654f41fa40
commit dc27897ea4
6 changed files with 61 additions and 9 deletions
@@ -53,6 +53,7 @@
<el-button :icon="FileDown" @click="exportSnapshot">快照</el-button>
<el-button :icon="FileUp" @click="openSnapshotImport">导入</el-button>
<el-button :icon="Download" @click="exportChecklist">导出</el-button>
<el-button :icon="FileDown" :disabled="riskItems.length === 0" @click="exportRiskRegister">风险</el-button>
<el-button :icon="Copy" @click="copyHandoffReport">复制报告</el-button>
<el-button :icon="FileDown" @click="exportHandoffReport">报告</el-button>
<el-button :icon="RotateCcw" @click="resetDraft">重置</el-button>
@@ -375,6 +376,12 @@ const evidenceMissingItems = computed(() => checklist.filter((item) => (
)));
const evidenceMissingCount = computed(() => evidenceMissingItems.value.length);
const blockedItems = computed(() => checklist.filter((item) => draft[item.id].status === 'BLOCKED'));
const riskItems = computed(() => checklist.filter((item) => {
const itemDraft = draft[item.id];
return itemDraft.status === 'BLOCKED'
|| itemDraft.status === 'PENDING'
|| (itemDraft.status !== 'SKIP' && !itemDraft.evidenceRef.trim());
}));
const checklistIds = new Set(checklist.map((item) => item.id));
const handoffReady = computed(() => pendingCount.value === 0 && blockedCount.value === 0);
const missingCloseoutFields = computed(() => {
@@ -683,6 +690,38 @@ function exportChecklist() {
]);
}
function exportRiskRegister() {
downloadCsv(`cleaning-field-risk-register-${Date.now()}.csv`, [
['类别', '字段', '值', '', '', '', '', '', ''],
['session', '联调批次', sessionMeta.batchNo, '', '', '', '', '', ''],
['session', '现场/门店', sessionMeta.site, '', '', '', '', '', ''],
['session', '负责人', sessionMeta.coordinator, '', '', '', '', '', ''],
['session', '执行时间', sessionMeta.executedAt, '', '', '', '', '', ''],
['session', '最后更新', sessionMeta.updatedAt, '', '', '', '', '', ''],
['session', '风险项数量', String(riskItems.value.length), '', '', '', '', '', ''],
['ID', '类别', '检查项', '状态', '负责人', '风险/缺口', '应留证据', '证据记录', '下一步'],
...riskItems.value.map((item) => {
const itemDraft = draft[item.id];
const gaps = [
itemDraft.status === 'PENDING' ? '待处理' : '',
itemDraft.status === 'BLOCKED' ? '阻断' : '',
itemDraft.status !== 'SKIP' && !itemDraft.evidenceRef.trim() ? '缺证据' : ''
].filter(Boolean).join(' / ');
return [
item.id,
item.category,
item.title,
statusText(itemDraft.status),
itemDraft.owner,
gaps,
item.evidence,
itemDraft.evidenceRef,
itemDraft.note || item.expected
];
})
]);
}
function exportSnapshot() {
const payload = {
schema: 'qipai.cleaning.field-handoff.snapshot.v1',