diff --git a/backend/routes/devices.js b/backend/routes/devices.js index 4d70859..db99dad 100644 --- a/backend/routes/devices.js +++ b/backend/routes/devices.js @@ -88,16 +88,50 @@ router.get('/', validateQuery(queryDeviceSchema), async (req, res) => { } }); +// 生成设备ID的辅助函数 +async function generateDeviceId() { + // 获取当前最大的设备ID序号 + const devices = await Device.findAll({ + where: { + deviceId: { + [require('sequelize').Op.like]: 'DEV%' + } + } + }); + + let maxNumber = 0; + devices.forEach(device => { + const match = device.deviceId.match(/^DEV(\d+)$/); + if (match) { + const num = parseInt(match[1], 10); + if (num > maxNumber) { + maxNumber = num; + } + } + }); + + // 生成新的设备ID,序号+1,至少3位数字 + const newNumber = maxNumber + 1; + return `DEV${String(newNumber).padStart(3, '0')}`; +} + // 创建设备 router.post('/', validateBody(createDeviceSchema), async (req, res) => { try { - const device = await Device.create(req.body); + const deviceData = { ...req.body }; + + // 如果没有提供deviceId或为空,则自动生成 + if (!deviceData.deviceId || deviceData.deviceId.trim() === '') { + deviceData.deviceId = await generateDeviceId(); + } + + const device = await Device.create(deviceData); // 更新机柜当前功率 - const rack = await Rack.findByPk(req.body.rackId); + const rack = await Rack.findByPk(deviceData.rackId); if (rack) { await rack.update({ - currentPower: rack.currentPower + req.body.powerConsumption + currentPower: rack.currentPower + deviceData.powerConsumption }); } @@ -513,16 +547,38 @@ router.post('/import', async (req, res) => { throw new Error(`设备类型无效,有效值为:${validTypes.join('、')},当前值:${deviceType}`); } - // 验证设备ID是否已存在 - const deviceId = getFieldValue('deviceId'); - if (!deviceId) { - throw new Error('设备ID不能为空'); - } - const existingDeviceById = await Device.findOne({ - where: { deviceId: deviceId } - }); - if (existingDeviceById) { - throw new Error(`设备ID已存在:${deviceId}`); + // 处理设备ID:如果为空则自动生成 + let deviceId = getFieldValue('deviceId'); + if (!deviceId || deviceId.trim() === '') { + // 自动生成设备ID + const allDevices = await Device.findAll({ + where: { + deviceId: { + [require('sequelize').Op.like]: 'DEV%' + } + } + }); + + let maxNumber = 0; + allDevices.forEach(device => { + const match = device.deviceId.match(/^DEV(\d+)$/); + if (match) { + const num = parseInt(match[1], 10); + if (num > maxNumber) { + maxNumber = num; + } + } + }); + + deviceId = `DEV${String(maxNumber + 1).padStart(3, '0')}`; + } else { + // 验证设备ID是否已存在 + const existingDeviceById = await Device.findOne({ + where: { deviceId: deviceId } + }); + if (existingDeviceById) { + throw new Error(`设备ID已存在:${deviceId}`); + } } // 验证序列号是否已存在 diff --git a/backend/validation/deviceSchema.js b/backend/validation/deviceSchema.js index 28ba6ea..4f3ad30 100644 --- a/backend/validation/deviceSchema.js +++ b/backend/validation/deviceSchema.js @@ -9,14 +9,12 @@ const DEVICE_STATUS = ['running', 'maintenance', 'offline', 'fault']; // 创建设备验证Schema const createDeviceSchema = Joi.object({ deviceId: Joi.string() - .required() .max(50) .pattern(/^[a-zA-Z0-9_-]+$/) + .allow('', null) .messages({ - 'string.empty': '设备ID不能为空', 'string.max': '设备ID不能超过50个字符', - 'string.pattern.base': '设备ID只能包含字母、数字、下划线和横线', - 'any.required': '设备ID是必填字段' + 'string.pattern.base': '设备ID只能包含字母、数字、下划线和横线' }), name: Joi.string() diff --git a/frontend/src/pages/DeviceManagement.jsx b/frontend/src/pages/DeviceManagement.jsx index 19f0ddf..f4d6665 100644 --- a/frontend/src/pages/DeviceManagement.jsx +++ b/frontend/src/pages/DeviceManagement.jsx @@ -167,7 +167,7 @@ const formatDate = (date, fieldName) => { // 默认设备字段配置 const defaultDeviceFields = [ - { fieldName: 'deviceId', displayName: '设备ID', fieldType: 'string', required: true, order: 1, visible: true }, + { fieldName: 'deviceId', displayName: '设备ID', fieldType: 'string', required: false, order: 1, visible: false }, { fieldName: 'name', displayName: '设备名称', fieldType: 'string', required: true, order: 2, visible: true }, { fieldName: 'type', displayName: '设备类型', fieldType: 'select', required: true, order: 3, visible: true, options: [{ value: 'server', label: '服务器' }, { value: 'switch', label: '交换机' }, { value: 'router', label: '路由器' }, { value: 'storage', label: '存储设备' }, { value: 'other', label: '其他设备' }] }, @@ -1770,7 +1770,7 @@ function DeviceManagement() { layout="vertical" onFinish={handleSubmit} > - {deviceFields.map(field => { + {deviceFields.filter(field => field.fieldName !== 'deviceId').map(field => { let control = null; switch (field.fieldType) { @@ -1822,7 +1822,7 @@ function DeviceManagement() { key={field.fieldName} name={field.fieldName} label={field.displayName} - rules={field.required ? [{ required: true, message: `请输入${field.displayName}` }] : []} + rules={field.required && field.fieldName !== 'deviceId' ? [{ required: true, message: `请输入${field.displayName}` }] : []} > {control} @@ -1861,7 +1861,7 @@ function DeviceManagement() { >
- {deviceFields.map(field => ( + {deviceFields.filter(field => field.fieldName !== 'deviceId').map(field => (