import React, { useState, useEffect } from 'react'; import { Modal, Form, Input, Select, InputNumber, DatePicker, Switch, Row, Col, Button, Space, Alert, } from 'antd'; import { PlusOutlined, EditOutlined, DatabaseOutlined, ExclamationCircleOutlined, } from '@ant-design/icons'; import dayjs from 'dayjs'; import { designTokens } from '../../config/theme'; import { getFormInitialValues, prepareDeviceFormData } from '../../utils/deviceUtils.jsx'; import { deviceAPI } from '../../api'; const { Option } = Select; const modalHeaderStyle = { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '18px', fontWeight: 600, }; const inputStyle = { borderRadius: '8px', transition: 'all 0.3s ease', }; const DeviceFormModal = ({ visible, editingDevice, deviceFields, racks, rooms, onCancel, onSubmit, }) => { const [form] = Form.useForm(); const [selectedRoomId, setSelectedRoomId] = useState(null); const [selectedRackId, setSelectedRackId] = useState(null); const [positionConflict, setPositionConflict] = useState(null); const [checkingPosition, setCheckingPosition] = useState(false); useEffect(() => { if (visible) { if (editingDevice) { const initialValues = getFormInitialValues(editingDevice, racks); if (initialValues.purchaseDate) { initialValues.purchaseDate = dayjs(initialValues.purchaseDate); } if (initialValues.warrantyExpiry) { initialValues.warrantyExpiry = dayjs(initialValues.warrantyExpiry); } form.setFieldsValue(initialValues); if (editingDevice.rackId) { const rack = racks.find(r => r.rackId === editingDevice.rackId); if (rack) { setSelectedRoomId(rack.roomId); setSelectedRackId(editingDevice.rackId); } } if (editingDevice.position) { checkPositionConflict( editingDevice.rackId, editingDevice.position, editingDevice.height, editingDevice.deviceId ); } } else { form.resetFields(); setSelectedRoomId(null); setSelectedRackId(null); setPositionConflict(null); } } }, [visible, editingDevice, racks, form]); const checkPositionConflict = async (rackId, position, height, deviceId = null) => { if (!rackId || !position) { setPositionConflict(null); return; } setCheckingPosition(true); try { const params = { position, height: height || 1, }; if (deviceId) { params.excludeDeviceId = deviceId; } const result = await deviceAPI.checkPosition(rackId, params); if (!result.available) { setPositionConflict(result.reason); } else { setPositionConflict(null); } } catch (error) { console.error('检查U位冲突失败:', error); setPositionConflict(null); } finally { setCheckingPosition(false); } }; const handleRackChange = value => { setSelectedRackId(value); const position = form.getFieldValue('position'); const height = form.getFieldValue('height'); if (position) { checkPositionConflict(value, position, height, editingDevice?.deviceId); } else { setPositionConflict(null); } }; const handlePositionChange = value => { const height = form.getFieldValue('height'); if (selectedRackId && value) { checkPositionConflict(selectedRackId, value, height, editingDevice?.deviceId); } else { setPositionConflict(null); } }; const handleHeightChange = value => { const position = form.getFieldValue('position'); if (selectedRackId && position) { checkPositionConflict(selectedRackId, position, value, editingDevice?.deviceId); } else { setPositionConflict(null); } }; const handleSubmit = values => { if (positionConflict) { return; } const deviceData = prepareDeviceFormData(values, !!editingDevice); onSubmit(deviceData); }; const handleRoomChange = value => { setSelectedRoomId(value); setSelectedRackId(null); setPositionConflict(null); form.setFieldValue('rackId', undefined); }; const renderFieldControl = field => { switch (field.fieldType) { case 'number': return ( ); case 'boolean': return ; case 'date': return ( ); case 'textarea': return ( ); case 'select': return ( ); default: return ( ); } }; const filteredFields = deviceFields.filter( field => field.fieldName !== 'deviceId' && field.fieldName !== 'rackId' && field.fieldName !== 'position' && field.fieldName !== 'height' ); const formItems = []; filteredFields.forEach(field => { if (field.fieldName === 'serialNumber') { formItems.push( {field.displayName} {field.required && *} } rules={ field.required ? [{ required: true, message: `请输入${field.displayName}` }] : [] } > {renderFieldControl(field)}
设备位置选择
机房 * } rules={[{ required: true, message: '请选择机房' }]} style={{ marginBottom: '0' }} > 机柜 * } rules={[{ required: true, message: '请选择机柜' }]} style={{ marginBottom: '0' }} > 安装位置 (U位) * } rules={[{ required: true, message: '请输入U位' }]} style={{ marginBottom: '0' }} > 设备高度 (U) * } rules={[{ required: true, message: '请输入设备高度' }]} initialValue={1} style={{ marginBottom: '0' }} > {positionConflict && (
} />
)}
); } else if (field.fieldType === 'textarea') { formItems.push( {field.displayName} {field.required && *} } rules={ field.required ? [{ required: true, message: `请输入${field.displayName}` }] : [] } > {renderFieldControl(field)} ); } else { formItems.push( {field.displayName} {field.required && *} } rules={ field.required ? [{ required: true, message: `请输入${field.displayName}` }] : [] } > {renderFieldControl(field)} ); } }); return ( {editingDevice ? ( ) : ( )} {editingDevice ? '编辑设备' : '添加设备'} } open={visible} onCancel={onCancel} footer={null} width={700} style={{ borderRadius: '16px' }} styles={{ header: { borderBottom: '1px solid #f0f0f0', padding: '16px 24px', position: 'relative', }, body: { padding: '24px' }, }} className="device-modal" >
{formItems}
); }; export default React.memo(DeviceFormModal);