// REQ-USR-003: 前端零依赖 CSV 导出(UTF-8 BOM + Blob + ,D-PLAN-1)
import type { UserVO } from '../../../api/types';
/** 导出列定义:中文表头 + 从 UserVO 取值(与列定义语义一致,作废 0/1→否/是;不含序号列) */
const EXPORT_COLUMNS: { header: string; pick: (row: UserVO) => string }[] = [
{ header: '用户名', pick: (r) => r.sUserName ?? '' },
{ header: '员工名', pick: (r) => r.employeeName ?? '' },
{ header: '用户号', pick: (r) => r.sUserNo ?? '' },
{ header: '部门', pick: (r) => r.departmentName ?? '' },
{ header: '用户类型', pick: (r) => r.sUserType ?? '' },
{ header: '语言', pick: (r) => r.sLanguage ?? '' },
{ header: '作废', pick: (r) => (r.iIsVoid === 1 ? '是' : '否') },
{ header: '登录日期', pick: (r) => r.tLastLoginDate ?? '' },
{ header: '制单人', pick: (r) => r.sCreator ?? '' },
{ header: '制单日期', pick: (r) => r.tCreateDate ?? '' },
];
/** CSV 单元转义:含逗号 / 引号 / 换行时用双引号包裹并转义内部引号 */
function escapeCell(value: string): string {
if (/[",\n\r]/.test(value)) {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
}
/** 按列定义顺序与中文表头生成 CSV 文本(含表头行;空值→空串;作废 0/1→否/是) */
export function buildUserCsv(rows: UserVO[]): string {
const header = EXPORT_COLUMNS.map((c) => escapeCell(c.header)).join(',');
const body = rows.map((row) =>
EXPORT_COLUMNS.map((c) => escapeCell(c.pick(row))).join(','),
);
return [header, ...body].join('\n');
}
/** 前置 UTF-8 BOM → Blob → createObjectURL → 触发 下载 */
export function downloadCsv(filename: string, csv: string): void {
const BOM = '';
const blob = new Blob([BOM + csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}