76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
|
|
/**
|
|||
|
|
* 导出列选择弹窗 —— 勾选要写进 CSV 的列。
|
|||
|
|
*
|
|||
|
|
* 列清单由后端 /audit/options 下发(value=后端列 key,label=中文表头),
|
|||
|
|
* 前端不硬编码表头:否则两端各维护一份,迟早出现「导出的列和页面对不上」。
|
|||
|
|
*
|
|||
|
|
* 默认全选 —— 大多数人只是想"全部导出来",不该逼他们先勾一遍。
|
|||
|
|
*/
|
|||
|
|
import { useEffect, useState } from "react";
|
|||
|
|
import { Modal, Checkbox, Button } from "antd";
|
|||
|
|
import type { AuditOption } from "../../services/auditApi";
|
|||
|
|
|
|||
|
|
export default function ExportColumnsModal({
|
|||
|
|
open,
|
|||
|
|
columns,
|
|||
|
|
submitting,
|
|||
|
|
onCancel,
|
|||
|
|
onConfirm,
|
|||
|
|
}: {
|
|||
|
|
open: boolean;
|
|||
|
|
columns: AuditOption[];
|
|||
|
|
submitting?: boolean;
|
|||
|
|
onCancel: () => void;
|
|||
|
|
/** 传出当前勾选的列 key(顺序 = 后端下发顺序,保证表头稳定) */
|
|||
|
|
onConfirm: (keys: string[]) => void;
|
|||
|
|
}) {
|
|||
|
|
const [checked, setChecked] = useState<string[]>([]);
|
|||
|
|
|
|||
|
|
// 每次打开都重置为全选:上一次的勾选残留会让用户莫名少导几列
|
|||
|
|
useEffect(() => {
|
|||
|
|
if (open) setChecked(columns.map((c) => c.value));
|
|||
|
|
}, [open, columns]);
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<Modal
|
|||
|
|
open={open}
|
|||
|
|
title="选择导出列"
|
|||
|
|
onCancel={onCancel}
|
|||
|
|
width={520}
|
|||
|
|
footer={
|
|||
|
|
<div className="flex items-center justify-between">
|
|||
|
|
<div className="flex gap-2">
|
|||
|
|
<Button size="small" onClick={() => setChecked(columns.map((c) => c.value))}>
|
|||
|
|
全选
|
|||
|
|
</Button>
|
|||
|
|
<Button size="small" onClick={() => setChecked([])}>
|
|||
|
|
全不选
|
|||
|
|
</Button>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex gap-2">
|
|||
|
|
<Button onClick={onCancel}>取消</Button>
|
|||
|
|
<Button
|
|||
|
|
type="primary"
|
|||
|
|
loading={submitting}
|
|||
|
|
disabled={checked.length === 0}
|
|||
|
|
onClick={() => onConfirm(checked)}
|
|||
|
|
>
|
|||
|
|
导出 ({checked.length} 列)
|
|||
|
|
</Button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
}
|
|||
|
|
>
|
|||
|
|
{checked.length === 0 && (
|
|||
|
|
<p className="mb-2 text-xs text-amber-600">至少勾选一列才能导出。</p>
|
|||
|
|
)}
|
|||
|
|
<Checkbox.Group
|
|||
|
|
value={checked}
|
|||
|
|
onChange={(v) => setChecked(v as string[])}
|
|||
|
|
className="grid grid-cols-3 gap-y-2"
|
|||
|
|
options={columns.map((c) => ({ value: c.value, label: c.label }))}
|
|||
|
|
/>
|
|||
|
|
</Modal>
|
|||
|
|
);
|
|||
|
|
}
|