| | |
| | | useNotify, |
| | | downloadCSV |
| | | } from 'react-admin'; |
| | | import { Box, Button, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material'; |
| | | import { Box, Button, Dialog, DialogTitle, DialogContent, DialogActions , Typography} from '@mui/material'; |
| | | import { styled } from '@mui/material/styles'; |
| | | import CodeCreate from "./CodeCreate"; |
| | | import CodePanel from "./CodePanel"; |
| | |
| | | // ===================== 自定义导出按钮 ===================== |
| | | const CustomExportButton = () => { |
| | | const [open, setOpen] = useState(false); |
| | | const [loading, setLoading] = useState(false); |
| | | const notify = useNotify(); |
| | | const translate = useTranslate(); |
| | | |
| | | // 直接从浏览器地址栏解析 filter 参数 |
| | | const getFilterFromUrl = () => { |
| | | const hash = window.location.hash; // 例如 "#/code?filter=%7B%22corner%22%3A%220%22%7D" |
| | | const hash = window.location.hash; |
| | | const match = hash.match(/[?&]filter=([^&]+)/); |
| | | if (match) { |
| | | try { |
| | |
| | | }; |
| | | |
| | | const handleExport = async (useCurrentFilter) => { |
| | | setLoading(true); |
| | | try { |
| | | let filter = {}; |
| | | if (useCurrentFilter) { |
| | |
| | | console.log('最终导出使用的 filter:', filter); |
| | | |
| | | const token = localStorage.getItem('Authorization'); |
| | | // 将 filter 转换为查询字符串,例如 corner=0 |
| | | const queryParams = new URLSearchParams(filter).toString(); |
| | | const url = `/api/code/export${queryParams ? '?' + queryParams : ''}`; |
| | | console.log('请求 URL:', url); |
| | | |
| | | const response = await fetch(url, { |
| | | method: 'POST', // 改回 POST(因为之前 POST 能返回 Excel) |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': `Bearer ${token}`, |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | // 尝试同时将 filter 以 JSON 格式放在 body 中(看后端是否读取) |
| | | body: JSON.stringify(filter), |
| | | }); |
| | | |
| | | if (!response.ok) throw new Error(`导出失败 ${response.status}`); |
| | | |
| | | // 检查响应类型,如果是 JSON 说明后端报错了 |
| | | const contentType = response.headers.get('content-type'); |
| | | if (contentType && contentType.includes('application/json')) { |
| | | const errorJson = await response.json(); |
| | |
| | | } catch (error) { |
| | | console.error(error); |
| | | notify('导出失败', { type: 'error' }); |
| | | } finally { |
| | | setLoading(false); |
| | | setOpen(false); |
| | | } |
| | | setOpen(false); |
| | | }; |
| | | |
| | | return ( |
| | | <> |
| | | return ( |
| | | <> |
| | | <Button |
| | | color="primary" |
| | | onClick={() => setOpen(true)} |
| | | startIcon={<DownloadIcon />} // 添加向下箭头图标 |
| | | size="small" // 与 ImportButton 保持一致的小尺寸 |
| | | sx={{ textTransform: 'none' }} // 可选:正常大小写,匹配导入按钮 |
| | | startIcon={<DownloadIcon />} |
| | | size="small" |
| | | sx={{ textTransform: 'none' }} |
| | | > |
| | | {translate('ra.action.export') || '导出'} |
| | | </Button> |
| | | <Dialog open={open} onClose={() => setOpen(false)}> |
| | | <DialogTitle>{translate('code.export.title',{_: '选择导出范围'})}</DialogTitle> |
| | | <DialogContent>{translate('code.export.message',{_: '请选择要导出的数据范围'}) }</DialogContent> |
| | | <DialogActions> |
| | | <Button onClick={() => handleExport(true)}> |
| | | {translate('code.export.current',{_: '导出当前筛选结果'}) } |
| | | </Button> |
| | | <Button onClick={() => handleExport(false)}> |
| | | {translate('code.export.all',{_: '导出全部数据' } )} |
| | | </Button> |
| | | <Button onClick={() => setOpen(false)}> |
| | | {translate('ra.action.cancel') || '取消'} |
| | | </Button> |
| | | </DialogActions> |
| | | </Dialog> |
| | | </> |
| | | ); |
| | | }; |
| | | |
| | | <Dialog |
| | | open={open} |
| | | onClose={() => setOpen(false)} |
| | | fullWidth |
| | | maxWidth="sm" |
| | | PaperProps={{ |
| | | sx: { |
| | | borderRadius: 3, |
| | | boxShadow: 24, |
| | | p: 1, |
| | | } |
| | | }} |
| | | > |
| | | <DialogTitle sx={{ pb: 1, fontWeight: 'bold', fontSize: '1.25rem' }}> |
| | | {translate('code.export.title', { _: '选择导出范围' })} |
| | | </DialogTitle> |
| | | <DialogContent sx={{ pt: 0 }}> |
| | | <Typography variant="body2" color="text.secondary"> |
| | | {translate('code.export.message', { _: '请选择要导出的数据范围' })} |
| | | </Typography> |
| | | </DialogContent> |
| | | <DialogActions sx={{ px: 3, pb: 2, gap: 1 }}> |
| | | <Button |
| | | onClick={() => handleExport(true)} |
| | | disabled={loading} |
| | | size="medium" |
| | | sx={{ |
| | | backgroundColor: '#fff', |
| | | color: '#1e293b', |
| | | border: '1px solid #cbd5e1', |
| | | '&:hover': { |
| | | backgroundColor: '#1976d2', |
| | | borderColor: '#1976d2', |
| | | color: '#fff', |
| | | }, |
| | | '&:disabled': { |
| | | backgroundColor: '#f1f5f9', |
| | | color: '#94a3b8', |
| | | borderColor: '#e2e8f0', |
| | | } |
| | | }} |
| | | > |
| | | {translate('code.export.current', { _: '导出当前筛选结果' })} |
| | | </Button> |
| | | <Button |
| | | onClick={() => handleExport(false)} |
| | | disabled={loading} |
| | | size="medium" |
| | | sx={{ |
| | | backgroundColor: '#fff', |
| | | color: '#1e293b', |
| | | border: '1px solid #cbd5e1', |
| | | '&:hover': { |
| | | backgroundColor: '#1976d2', |
| | | borderColor: '#1976d2', |
| | | color: '#fff', |
| | | }, |
| | | '&:disabled': { |
| | | backgroundColor: '#f1f5f9', |
| | | color: '#94a3b8', |
| | | borderColor: '#e2e8f0', |
| | | } |
| | | }} |
| | | > |
| | | {translate('code.export.all', { _: '导出全部数据' })} |
| | | </Button> |
| | | <Button |
| | | onClick={() => setOpen(false)} |
| | | disabled={loading} |
| | | size="medium" |
| | | sx={{ |
| | | backgroundColor: '#fff', |
| | | color: '#1e293b', |
| | | border: '1px solid #cbd5e1', |
| | | '&:hover': { |
| | | backgroundColor: '#1976d2', |
| | | borderColor: '#1976d2', |
| | | color: '#fff', |
| | | }, |
| | | '&:disabled': { |
| | | backgroundColor: '#f1f5f9', |
| | | color: '#94a3b8', |
| | | borderColor: '#e2e8f0', |
| | | } |
| | | }} |
| | | > |
| | | {translate('ra.action.cancel') || '取消'} |
| | | </Button> |
| | | </DialogActions> |
| | | </Dialog> |
| | | </> |
| | | ); |
| | | }; |
| | | // ======================================================= |
| | | // ======================================================= |
| | | const CodeList = () => { |
| | | const translate = useTranslate(); |