iter(g88): 数据表支持导出 CSV
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { h } from '@ui-arch/frame';
|
||||
import type { RowModel } from '@ui-arch/table-core';
|
||||
import { button } from './button.js';
|
||||
import type { TableColumn } from './types.js';
|
||||
|
||||
/*** 单元格转义:含逗号 / 引号 / 换行时整体加引号,内部引号翻倍 ***/
|
||||
function cell(v: unknown): string {
|
||||
const s = v == null ? '' : String(v);
|
||||
return /[",\r\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
||||
}
|
||||
|
||||
/*** 导出 CSV:前置 BOM + CRLF 换行,Excel 打开中文不乱码 ***/
|
||||
export function downloadCsv(name: string, header: string[], rows: unknown[][]): void {
|
||||
const text = '\ufeff' + [header, ...rows].map((r) => r.map(cell).join(',')).join('\r\n') + '\r\n';
|
||||
const url = URL.createObjectURL(new Blob([text], { type: 'text/csv;charset=utf-8' }));
|
||||
const a = h('a', { href: url, download: name }) as HTMLAnchorElement;
|
||||
document.body.appendChild(a); // 挂进文档再点击:Safari 对游离锚点不触发下载
|
||||
a.click();
|
||||
a.remove(); // 立即摘除,不留残留节点
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
/*** 导出按钮:取筛选 + 排序后的全量行(不分页),列序与表头一致、单元格走 format ***/
|
||||
export function exportButton<T>(
|
||||
table: { getAllRows(): RowModel<T>; getCellValue(row: T, key: string): unknown },
|
||||
columns: TableColumn<T>[],
|
||||
name: string,
|
||||
): HTMLElement {
|
||||
const run = (): void => {
|
||||
const rows = table.getAllRows().rows;
|
||||
const header = columns.map((c) => String(c.header ?? c.key));
|
||||
const body = rows.map((row) => columns.map((c) => {
|
||||
const raw = table.getCellValue(row, c.key);
|
||||
return c.format ? c.format(raw, row) : raw; // 与单元格显示同源,导出内容与看到的一致
|
||||
}));
|
||||
downloadCsv(name, header, body);
|
||||
};
|
||||
return button({ label: '导出 CSV', variant: 'ghost', onClick: run });
|
||||
}
|
||||
Reference in New Issue
Block a user