Merge feature/asset-statistics into main and release v1.2.1
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
shishengliang
2026-09-23 14:28:26 +08:00
116 changed files with 18694 additions and 4137 deletions
+52
View File
@@ -0,0 +1,52 @@
import { Download } from "lucide-react";
import { Button } from "@/components/ui/button";
import type { Column } from "./DataGrid";
function cellValue<T extends object>(row: T, col: Column<T>): string | number {
const raw = row[col.key];
if (col.format) return col.format(raw, row);
return (raw as string | number) ?? "";
}
/** 按表格列定义导出 xlsx;xlsx 按需加载,避免进入首屏包。 */
export async function exportToXlsx<T extends object>(
rows: T[],
columns: Column<T>[],
filename: string,
sheetName = "明细",
): Promise<void> {
const { buildJsonSheet, writeWorkbook } = await import("../../../shared/xlsx");
const sheet = buildJsonSheet(
rows.map((row) =>
Object.fromEntries(columns.map((col) => [col.label, cellValue(row, col)])),
),
);
writeWorkbook([{ name: sheetName, sheet }], filename);
}
export function ExportButton<T extends object>({
rows,
columns,
filename,
sheetName,
label = "导出",
}: {
rows: T[];
columns: Column<T>[];
filename: string;
sheetName?: string;
label?: string;
}) {
return (
<Button
variant="outline"
size="sm"
className="min-h-9 w-fit md:min-h-7"
disabled={!rows.length}
onClick={() => void exportToXlsx(rows, columns, filename, sheetName)}
>
<Download data-icon="inline-start" />
{label}
</Button>
);
}