export type ExportColumnDef = { key: string; header: string; value: (row: T) => string | number; }; /** 按请求的列 key 过滤导出列;未传则导出全部 */ export function pickExportColumns( defs: ExportColumnDef[], requestedKeys?: string[], ): ExportColumnDef[] { if (!requestedKeys?.length) return defs; const byKey = new Map(defs.map((d) => [d.key, d])); return requestedKeys.map((k) => byKey.get(k)).filter((d): d is ExportColumnDef => !!d); } export function parseExportColumnKeys(raw?: string): string[] | undefined { if (!raw?.trim()) return undefined; const keys = raw .split(',') .map((k) => k.trim()) .filter(Boolean); return keys.length ? keys : undefined; } export function buildCsvFromColumns( defs: ExportColumnDef[], rows: T[], requestedKeys?: string[], ): { csv: string; count: number } { const active = pickExportColumns(defs, requestedKeys); if (!active.length) { return { csv: '\uFEFF', count: 0 }; } const header = active.map((d) => d.header).join(','); const body = rows.map((row) => active .map((d) => { const v = d.value(row); const s = v == null ? '' : String(v); return s.includes(',') || s.includes('"') || s.includes('\n') ? `"${s.replace(/"/g, '""')}"` : s; }) .join(','), ); return { csv: `\uFEFF${[header, ...body].join('\n')}`, count: rows.length }; }