feat(M08-B): 补联调证据记录
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
<span>通过 <strong>{{ passedCount }}</strong></span>
|
||||
<span>阻断 <strong>{{ blockedCount }}</strong></span>
|
||||
<span>待处理 <strong>{{ pendingCount }}</strong></span>
|
||||
<span>证据 <strong>{{ evidenceRecordedCount }}</strong></span>
|
||||
<span>更新 <strong>{{ sessionMeta.updatedAt || '未记录' }}</strong></span>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
@@ -188,7 +189,17 @@
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="evidence" label="证据" min-width="210" />
|
||||
<el-table-column prop="evidence" label="应留证据" min-width="210" />
|
||||
<el-table-column label="证据记录" min-width="230">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
v-model="draft[row.id].evidenceRef"
|
||||
size="small"
|
||||
placeholder="截图编号、流水号、回包或文件链接"
|
||||
@change="persistDraft"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</section>
|
||||
@@ -213,6 +224,7 @@ interface HandoffDraft {
|
||||
status: FieldStatus;
|
||||
owner: string;
|
||||
note: string;
|
||||
evidenceRef: string;
|
||||
}
|
||||
|
||||
interface SessionMeta {
|
||||
@@ -303,6 +315,7 @@ const filteredChecklist = computed(() => checklist.filter((item) => {
|
||||
const passedCount = computed(() => checklist.filter((item) => draft[item.id].status === 'PASS').length);
|
||||
const blockedCount = computed(() => checklist.filter((item) => draft[item.id].status === 'BLOCKED').length);
|
||||
const pendingCount = computed(() => checklist.filter((item) => draft[item.id].status === 'PENDING').length);
|
||||
const evidenceRecordedCount = computed(() => checklist.filter((item) => draft[item.id].evidenceRef.trim()).length);
|
||||
const blockedItems = computed(() => checklist.filter((item) => draft[item.id].status === 'BLOCKED'));
|
||||
const checklistIds = new Set(checklist.map((item) => item.id));
|
||||
const handoffReady = computed(() => pendingCount.value === 0 && blockedCount.value === 0);
|
||||
@@ -329,7 +342,7 @@ function createInitialDraft() {
|
||||
const saved = readSavedDraft();
|
||||
return Object.fromEntries(checklist.map((item) => [
|
||||
item.id,
|
||||
saved[item.id] || { status: 'PENDING', owner: '', note: '' }
|
||||
normalizeDraft(saved[item.id])
|
||||
])) as Record<string, HandoffDraft>;
|
||||
}
|
||||
|
||||
@@ -373,7 +386,7 @@ function touchSessionMeta() {
|
||||
|
||||
function resetDraft() {
|
||||
for (const item of checklist) {
|
||||
draft[item.id] = { status: 'PENDING', owner: '', note: '' };
|
||||
draft[item.id] = normalizeDraft();
|
||||
}
|
||||
touchSessionMeta();
|
||||
persistDraft();
|
||||
@@ -398,7 +411,8 @@ async function copyBlockedSummary() {
|
||||
].join('\n');
|
||||
const content = blockedItems.value.map((item) => {
|
||||
const itemDraft = draft[item.id];
|
||||
return `[${item.category}] ${item.title} - ${itemDraft.owner || '未分派'} - ${itemDraft.note || item.expected}`;
|
||||
const evidence = itemDraft.evidenceRef ? ` - 证据:${itemDraft.evidenceRef}` : '';
|
||||
return `[${item.category}] ${item.title} - ${itemDraft.owner || '未分派'} - ${itemDraft.note || item.expected}${evidence}`;
|
||||
}).join('\n');
|
||||
try {
|
||||
await navigator.clipboard.writeText(`${header}\n\n${content}`);
|
||||
@@ -416,7 +430,7 @@ async function copyVerdict() {
|
||||
`执行时间:${sessionMeta.executedAt || '未填写'}`,
|
||||
`最后更新:${sessionMeta.updatedAt || '未记录'}`,
|
||||
`结论:${handoffReady.value ? '可进入现场验收收口' : '仍不可收口'}`,
|
||||
`统计:通过 ${passedCount.value},阻断 ${blockedCount.value},待处理 ${pendingCount.value}`
|
||||
`统计:通过 ${passedCount.value},阻断 ${blockedCount.value},待处理 ${pendingCount.value},证据 ${evidenceRecordedCount.value}/${checklist.length}`
|
||||
].join('\n');
|
||||
try {
|
||||
await navigator.clipboard.writeText(verdict);
|
||||
@@ -428,13 +442,14 @@ async function copyVerdict() {
|
||||
|
||||
function exportChecklist() {
|
||||
downloadCsv(`cleaning-field-handoff-${Date.now()}.csv`, [
|
||||
['类别', '字段', '值', '', '', '', '', ''],
|
||||
['session', '联调批次', sessionMeta.batchNo, '', '', '', '', ''],
|
||||
['session', '现场/门店', sessionMeta.site, '', '', '', '', ''],
|
||||
['session', '负责人', sessionMeta.coordinator, '', '', '', '', ''],
|
||||
['session', '执行时间', sessionMeta.executedAt, '', '', '', '', ''],
|
||||
['session', '最后更新', sessionMeta.updatedAt, '', '', '', '', ''],
|
||||
['ID', '类别', '检查项', '期望', '状态', '负责人', '结果记录', '证据'],
|
||||
['类别', '字段', '值', '', '', '', '', '', ''],
|
||||
['session', '联调批次', sessionMeta.batchNo, '', '', '', '', '', ''],
|
||||
['session', '现场/门店', sessionMeta.site, '', '', '', '', '', ''],
|
||||
['session', '负责人', sessionMeta.coordinator, '', '', '', '', '', ''],
|
||||
['session', '执行时间', sessionMeta.executedAt, '', '', '', '', '', ''],
|
||||
['session', '最后更新', sessionMeta.updatedAt, '', '', '', '', '', ''],
|
||||
['session', '证据记录数', `${evidenceRecordedCount.value}/${checklist.length}`, '', '', '', '', '', ''],
|
||||
['ID', '类别', '检查项', '期望', '状态', '负责人', '结果记录', '应留证据', '证据记录'],
|
||||
...checklist.map((item) => [
|
||||
item.id,
|
||||
item.category,
|
||||
@@ -443,7 +458,8 @@ function exportChecklist() {
|
||||
draft[item.id].status,
|
||||
draft[item.id].owner,
|
||||
draft[item.id].note,
|
||||
item.evidence
|
||||
item.evidence,
|
||||
draft[item.id].evidenceRef
|
||||
])
|
||||
]);
|
||||
}
|
||||
@@ -493,7 +509,8 @@ async function importSnapshot(event: Event) {
|
||||
draft[id] = {
|
||||
status,
|
||||
owner: value.owner || '',
|
||||
note: value.note || ''
|
||||
note: value.note || '',
|
||||
evidenceRef: value.evidenceRef || ''
|
||||
};
|
||||
}
|
||||
touchSessionMeta();
|
||||
@@ -509,6 +526,15 @@ function isFieldStatus(value: unknown): value is FieldStatus {
|
||||
return value === 'PENDING' || value === 'PASS' || value === 'BLOCKED' || value === 'SKIP';
|
||||
}
|
||||
|
||||
function normalizeDraft(value?: Partial<HandoffDraft>): HandoffDraft {
|
||||
return {
|
||||
status: isFieldStatus(value?.status) ? value.status : 'PENDING',
|
||||
owner: value?.owner || '',
|
||||
note: value?.note || '',
|
||||
evidenceRef: value?.evidenceRef || ''
|
||||
};
|
||||
}
|
||||
|
||||
function downloadCsv(filename: string, rows: string[][]) {
|
||||
const content = rows.map((row) => row.map(csvCell).join(',')).join('\r\n');
|
||||
downloadText(filename, `\uFEFF${content}`, 'text/csv;charset=utf-8');
|
||||
|
||||
Reference in New Issue
Block a user