feat: add A-card operations frontend and backend foundation

This commit is contained in:
郑龙捷
2026-09-02 09:54:03 +08:00
parent 9badd3597f
commit ad71259ba5
106 changed files with 12461 additions and 1796 deletions
+35
View File
@@ -0,0 +1,35 @@
export type ExcelValue = string | number | boolean | Date | null | undefined;
export type ExcelExportOptions = {
fileName: string;
sheetName: string;
headers: string[];
rows: ExcelValue[][];
};
function safeFileName(value: string): string {
return value.replace(/[\\/:*?"<>|]/g, "_").replace(/\.xlsx$/i, "");
}
function safeSheetName(value: string): string {
return value.replace(/[\\/*?:\[\]]/g, "_").slice(0, 31) || "Sheet1";
}
export async function exportRowsToExcel({ fileName, sheetName, headers, rows }: ExcelExportOptions): Promise<void> {
const { default: writeExcelFile } = await import("write-excel-file/browser");
const headerRow = headers.map((value) => ({
value,
fontWeight: "bold" as const,
backgroundColor: "#EDF6FF",
align: "center" as const,
}));
const columns = headers.map((header, index) => {
const maxLength = Math.max(header.length * 2, ...rows.map((row) => String(row[index] ?? "").length));
return { width: Math.min(42, Math.max(12, maxLength + 3)) };
});
await writeExcelFile([headerRow, ...rows], {
sheet: safeSheetName(sheetName),
stickyRowsCount: 1,
columns,
}).toFile(`${safeFileName(fileName)}.xlsx`);
}