- refactor(web): PatientDetail.tsx 拆分为 4 个子组件(737→334行) - refactor(web): 提取 usePaginatedData hook 消除重复分页状态 - feat(db): patient.id_number varchar(20)→varchar(255) 容纳加密值 - test(health): 添加预约模块集成测试(创建/列表/租户隔离) - test(plugin): 添加 6 个 SQL 注入 sanitize 测试 - fix(miniprogram): 7 个 service 文件 URL 构建规范化(params 对象) - fix(miniprogram): 跨平台字段名对齐(birth_date/start_time/end_time)
47 lines
1.1 KiB
TypeScript
47 lines
1.1 KiB
TypeScript
import { Button, message } from 'antd';
|
|
import { DownloadOutlined } from '@ant-design/icons';
|
|
import client from '../../../api/client';
|
|
|
|
interface Props {
|
|
fetchUrl: string;
|
|
params?: Record<string, string>;
|
|
filename?: string;
|
|
label?: string;
|
|
}
|
|
|
|
export function ExportButton({
|
|
fetchUrl,
|
|
params,
|
|
filename,
|
|
label = '导出',
|
|
}: Props) {
|
|
const handleExport = async () => {
|
|
try {
|
|
const query = params
|
|
? '?' + new URLSearchParams(params).toString()
|
|
: '';
|
|
const resp = await client.get(fetchUrl + query, {
|
|
responseType: 'blob',
|
|
});
|
|
const blob = resp.data instanceof Blob
|
|
? resp.data
|
|
: new Blob([resp.data]);
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = filename ?? `export_${Date.now()}.csv`;
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
message.success('导出成功');
|
|
} catch {
|
|
message.error('导出失败');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Button icon={<DownloadOutlined />} onClick={handleExport}>
|
|
{label}
|
|
</Button>
|
|
);
|
|
}
|