feat(assets): migrate asset views and reconcile inventory drilldowns
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
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 XLSX = await import("xlsx");
|
||||
const sheet = XLSX.utils.json_to_sheet(
|
||||
rows.map((row) =>
|
||||
Object.fromEntries(columns.map((col) => [col.label, cellValue(row, col)])),
|
||||
),
|
||||
);
|
||||
const book = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(book, sheet, sheetName);
|
||||
XLSX.writeFile(book, `${filename}.xlsx`);
|
||||
}
|
||||
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user