Add Excel export feature for full production data
Add "导出全部" button that exports all contract production data to an .xlsx file via a new API endpoint using exceljs, with formatted headers, date columns, auto-width, and frozen header row. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
Checkbox,
|
||||
AutoComplete,
|
||||
} from "antd";
|
||||
import { SearchOutlined, SettingOutlined, HolderOutlined, ClockCircleOutlined } from "@ant-design/icons";
|
||||
import { SearchOutlined, SettingOutlined, HolderOutlined, ClockCircleOutlined, DownloadOutlined } from "@ant-design/icons";
|
||||
import type { ColumnsType } from "antd/es/table";
|
||||
import {
|
||||
DndContext,
|
||||
@@ -333,6 +333,8 @@ function SearchBar({
|
||||
onSearch,
|
||||
onClear,
|
||||
onOpenColumnSettings,
|
||||
exporting,
|
||||
onExport,
|
||||
}: {
|
||||
loading: boolean;
|
||||
resultCount: number;
|
||||
@@ -340,6 +342,8 @@ function SearchBar({
|
||||
onSearch: (workshopNo: string) => Promise<void>;
|
||||
onClear: () => void;
|
||||
onOpenColumnSettings: () => void;
|
||||
exporting: boolean;
|
||||
onExport: () => void;
|
||||
}) {
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [history, setHistory] = useState<string[]>(() => loadHistory());
|
||||
@@ -418,6 +422,13 @@ function SearchBar({
|
||||
<Button icon={<SettingOutlined />} onClick={onOpenColumnSettings}>
|
||||
列设置
|
||||
</Button>
|
||||
<Button
|
||||
icon={<DownloadOutlined />}
|
||||
onClick={onExport}
|
||||
loading={exporting}
|
||||
>
|
||||
导出全部
|
||||
</Button>
|
||||
</Space>
|
||||
{searched && !loading && (
|
||||
<Text type="secondary" style={{ marginLeft: 16 }}>
|
||||
@@ -438,6 +449,7 @@ export default function Home() {
|
||||
const [searched, setSearched] = useState(false);
|
||||
const [columnConfig, setColumnConfig] = useState<ColumnConfig[]>(loadConfig);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [exporting, setExporting] = useState(false);
|
||||
|
||||
// Persist config
|
||||
useEffect(() => {
|
||||
@@ -473,6 +485,31 @@ export default function Home() {
|
||||
setError(null);
|
||||
}, []);
|
||||
|
||||
const handleExport = useCallback(async () => {
|
||||
setExporting(true);
|
||||
try {
|
||||
const res = await fetch("/api/export-excel");
|
||||
if (!res.ok) {
|
||||
const json = await res.json().catch(() => null);
|
||||
setError(json?.error || "导出失败");
|
||||
return;
|
||||
}
|
||||
const blob = await res.blob();
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "压力表合同生产数据.xlsx";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
} catch {
|
||||
setError("导出请求失败");
|
||||
} finally {
|
||||
setExporting(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleApplyConfig = useCallback((newConfig: ColumnConfig[]) => {
|
||||
setColumnConfig(newConfig);
|
||||
setModalOpen(false);
|
||||
@@ -500,6 +537,8 @@ export default function Home() {
|
||||
onSearch={handleSearch}
|
||||
onClear={handleClear}
|
||||
onOpenColumnSettings={() => setModalOpen(true)}
|
||||
exporting={exporting}
|
||||
onExport={handleExport}
|
||||
/>
|
||||
|
||||
<div style={{ flex: 1, minHeight: 0 }}>
|
||||
|
||||
Reference in New Issue
Block a user