refactor(字段管理): 优化字段选项编辑界面,使用可视化编辑器 refactor(工单字段管理): 重构选项编辑组件,提升用户体验 chore: 移除不再使用的设备字段选项迁移脚本
131 lines
3.5 KiB
React
131 lines
3.5 KiB
React
import React, { useState } from 'react';
|
||
import { Modal, Form, Select, Button } from 'antd';
|
||
import { ExportOutlined } from '@ant-design/icons';
|
||
import { designTokens } from '../../config/theme';
|
||
|
||
const { Option } = Select;
|
||
|
||
const modalHeaderStyle = {
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
gap: '8px',
|
||
fontSize: '18px',
|
||
fontWeight: 600,
|
||
};
|
||
|
||
const ExportModal = ({
|
||
visible,
|
||
selectedDevices,
|
||
currentPageDevices,
|
||
allDevices,
|
||
onExport,
|
||
onCancel,
|
||
}) => {
|
||
const [exportFormat, setExportFormat] = useState('csv');
|
||
const [exportScope, setExportScope] = useState('selected');
|
||
const [exportLoading, setExportLoading] = useState(false);
|
||
|
||
const handleExport = async () => {
|
||
setExportLoading(true);
|
||
try {
|
||
await onExport({
|
||
format: exportFormat,
|
||
scope: exportScope,
|
||
});
|
||
onCancel();
|
||
} finally {
|
||
setExportLoading(false);
|
||
}
|
||
};
|
||
|
||
const getScopeLabel = () => {
|
||
switch (exportScope) {
|
||
case 'selected':
|
||
return `选择的行 (${selectedDevices.length} 个)`;
|
||
case 'currentPage':
|
||
return `当前页 (${currentPageDevices.length} 个)`;
|
||
case 'all':
|
||
return `全部设备 (${allDevices.length} 个)`;
|
||
default:
|
||
return '';
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
title={
|
||
<div style={{ ...modalHeaderStyle, paddingRight: '32px' }}>
|
||
<ExportOutlined style={{ color: '#fa8c16' }} />
|
||
导出设备数据
|
||
</div>
|
||
}
|
||
open={visible}
|
||
onCancel={onCancel}
|
||
footer={[
|
||
<Button
|
||
key="cancel"
|
||
onClick={onCancel}
|
||
style={{
|
||
height: '40px',
|
||
borderRadius: designTokens.borderRadius.small,
|
||
border: `1px solid ${designTokens.colors.border.light}`,
|
||
}}
|
||
>
|
||
取消
|
||
</Button>,
|
||
<Button
|
||
key="submit"
|
||
type="primary"
|
||
loading={exportLoading}
|
||
onClick={handleExport}
|
||
style={{
|
||
height: '40px',
|
||
borderRadius: designTokens.borderRadius.small,
|
||
background: designTokens.colors.primary.gradient,
|
||
border: 'none',
|
||
color: '#ffffff',
|
||
boxShadow: designTokens.shadows.small,
|
||
fontWeight: '500',
|
||
display: 'inline-flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
}}
|
||
>
|
||
导出
|
||
</Button>,
|
||
]}
|
||
destroyOnHidden
|
||
styles={{
|
||
header: {
|
||
borderBottom: '1px solid #f0f0f0',
|
||
padding: '16px 24px',
|
||
position: 'relative',
|
||
},
|
||
body: { padding: '24px' },
|
||
}}
|
||
width={500}
|
||
>
|
||
<Form layout="vertical">
|
||
<Form.Item label="导出格式">
|
||
<Select value={exportFormat} onChange={setExportFormat} style={{ width: '100%' }}>
|
||
<Option value="csv">CSV 格式</Option>
|
||
<Option value="json">JSON 格式</Option>
|
||
</Select>
|
||
</Form.Item>
|
||
<Form.Item label="导出范围">
|
||
<Select value={exportScope} onChange={setExportScope} style={{ width: '100%' }}>
|
||
<Option value="selected">{getScopeLabel()}</Option>
|
||
<Option value="currentPage">当前页 ({currentPageDevices.length} 个)</Option>
|
||
<Option value="all">全部设备 ({allDevices.length} 个)</Option>
|
||
</Select>
|
||
</Form.Item>
|
||
<div style={{ color: '#666', fontSize: '13px' }}>
|
||
将导出设备的所有字段(包括自定义字段)
|
||
</div>
|
||
</Form>
|
||
</Modal>
|
||
);
|
||
};
|
||
|
||
export default React.memo(ExportModal);
|