266 lines
6.3 KiB
JavaScript
266 lines
6.3 KiB
JavaScript
const Joi = require('joi');
|
|
const DeviceField = require('../models/DeviceField');
|
|
|
|
const DEVICE_TYPES = ['server', 'switch', 'router', 'storage', 'other'];
|
|
const DEVICE_STATUS = ['running', 'maintenance', 'offline', 'fault'];
|
|
|
|
const baseFieldSchemas = {
|
|
deviceId: Joi.string()
|
|
.max(50)
|
|
.pattern(/^[a-zA-Z0-9_-]+$/)
|
|
.allow('', null)
|
|
.messages({
|
|
'string.max': '设备ID不能超过50个字符',
|
|
'string.pattern.base': '设备ID只能包含字母、数字、下划线和横线'
|
|
}),
|
|
|
|
name: Joi.string()
|
|
.max(100)
|
|
.messages({
|
|
'string.empty': '设备名称不能为空',
|
|
'string.max': '设备名称不能超过100个字符'
|
|
}),
|
|
|
|
type: Joi.string()
|
|
.valid(...DEVICE_TYPES)
|
|
.messages({
|
|
'string.empty': '设备类型不能为空',
|
|
'any.only': `设备类型必须是以下之一: ${DEVICE_TYPES.join(', ')}`
|
|
}),
|
|
|
|
model: Joi.string()
|
|
.max(100)
|
|
.allow('', null)
|
|
.messages({
|
|
'string.max': '型号不能超过100个字符'
|
|
}),
|
|
|
|
serialNumber: Joi.string()
|
|
.max(100)
|
|
.messages({
|
|
'string.empty': '序列号不能为空',
|
|
'string.max': '序列号不能超过100个字符'
|
|
}),
|
|
|
|
rackId: Joi.string()
|
|
.max(50)
|
|
.messages({
|
|
'string.empty': '机柜ID不能为空',
|
|
'string.max': '机柜ID不能超过50个字符'
|
|
}),
|
|
|
|
position: Joi.number()
|
|
.integer()
|
|
.min(1)
|
|
.max(100)
|
|
.messages({
|
|
'number.base': '位置必须是数字',
|
|
'number.integer': '位置必须是整数',
|
|
'number.min': '位置不能小于1',
|
|
'number.max': '位置不能大于100'
|
|
}),
|
|
|
|
height: Joi.number()
|
|
.integer()
|
|
.min(1)
|
|
.max(50)
|
|
.messages({
|
|
'number.base': '高度必须是数字',
|
|
'number.integer': '高度必须是整数',
|
|
'number.min': '高度不能小于1',
|
|
'number.max': '高度不能大于50'
|
|
}),
|
|
|
|
powerConsumption: Joi.number()
|
|
.min(0)
|
|
.max(100000)
|
|
.messages({
|
|
'number.base': '功率必须是数字',
|
|
'number.min': '功率不能小于0',
|
|
'number.max': '功率不能超过100000'
|
|
}),
|
|
|
|
ipAddress: Joi.string()
|
|
.ip({ version: ['ipv4', 'ipv6'] })
|
|
.allow('', null)
|
|
.messages({
|
|
'string.ip': 'IP地址格式无效'
|
|
}),
|
|
|
|
status: Joi.string()
|
|
.valid(...DEVICE_STATUS)
|
|
.default('offline')
|
|
.messages({
|
|
'any.only': `状态必须是以下之一: ${DEVICE_STATUS.join(', ')}`
|
|
}),
|
|
|
|
purchaseDate: Joi.date()
|
|
.allow(null)
|
|
.messages({
|
|
'date.base': '购买日期格式无效'
|
|
}),
|
|
|
|
warrantyExpiry: Joi.date()
|
|
.allow(null)
|
|
.messages({
|
|
'date.base': '保修到期日期格式无效'
|
|
}),
|
|
|
|
description: Joi.string()
|
|
.max(500)
|
|
.allow('', null)
|
|
.messages({
|
|
'string.max': '描述不能超过500个字符'
|
|
}),
|
|
|
|
customFields: Joi.object().allow(null)
|
|
};
|
|
|
|
async function buildDynamicSchema(isCreate = true) {
|
|
const fields = await DeviceField.findAll({
|
|
where: { isSystem: true },
|
|
order: [['order', 'ASC']]
|
|
});
|
|
|
|
const schemaObj = {};
|
|
|
|
fields.forEach(field => {
|
|
const baseSchema = baseFieldSchemas[field.fieldName];
|
|
if (baseSchema) {
|
|
let fieldSchema = baseSchema.clone();
|
|
|
|
if (field.required && isCreate) {
|
|
fieldSchema = fieldSchema.required();
|
|
}
|
|
|
|
schemaObj[field.fieldName] = fieldSchema;
|
|
}
|
|
});
|
|
|
|
schemaObj.customFields = baseFieldSchemas.customFields;
|
|
|
|
return Joi.object(schemaObj).custom((value, helpers) => {
|
|
if (value.purchaseDate && value.warrantyExpiry) {
|
|
const purchase = new Date(value.purchaseDate);
|
|
const warranty = new Date(value.warrantyExpiry);
|
|
if (warranty <= purchase) {
|
|
return helpers.error('date.warrantyAfterPurchase');
|
|
}
|
|
}
|
|
return value;
|
|
}).messages({
|
|
'date.warrantyAfterPurchase': '保修到期日期必须晚于购买日期'
|
|
});
|
|
}
|
|
|
|
async function getCreateDeviceSchema() {
|
|
return buildDynamicSchema(true);
|
|
}
|
|
|
|
async function getUpdateDeviceSchema() {
|
|
const schema = await buildDynamicSchema(false);
|
|
return schema.min(1).messages({
|
|
'object.min': '至少需要提供一个字段进行更新'
|
|
});
|
|
}
|
|
|
|
const batchDeviceIdsSchema = Joi.object({
|
|
deviceIds: Joi.array()
|
|
.items(Joi.string().required())
|
|
.min(1)
|
|
.required()
|
|
.messages({
|
|
'array.base': '设备ID列表必须是数组',
|
|
'array.min': '至少需要提供一个设备ID',
|
|
'any.required': '设备ID列表是必填字段'
|
|
})
|
|
});
|
|
|
|
const batchStatusSchema = Joi.object({
|
|
deviceIds: Joi.array()
|
|
.items(Joi.string().required())
|
|
.min(1)
|
|
.required()
|
|
.messages({
|
|
'array.base': '设备ID列表必须是数组',
|
|
'array.min': '至少需要提供一个设备ID',
|
|
'any.required': '设备ID列表是必填字段'
|
|
}),
|
|
status: Joi.string()
|
|
.valid(...DEVICE_STATUS)
|
|
.required()
|
|
.messages({
|
|
'any.only': `状态必须是以下之一: ${DEVICE_STATUS.join(', ')}`,
|
|
'any.required': '状态是必填字段'
|
|
})
|
|
});
|
|
|
|
const batchMoveSchema = Joi.object({
|
|
deviceIds: Joi.array()
|
|
.items(Joi.string().required())
|
|
.min(1)
|
|
.required(),
|
|
targetRackId: Joi.string()
|
|
.required()
|
|
.max(50)
|
|
.messages({
|
|
'string.empty': '目标机柜ID不能为空',
|
|
'any.required': '目标机柜ID是必填字段'
|
|
}),
|
|
startPosition: Joi.number()
|
|
.integer()
|
|
.min(1)
|
|
.allow(null)
|
|
});
|
|
|
|
const queryDeviceSchema = Joi.object({
|
|
keyword: Joi.string()
|
|
.max(100)
|
|
.allow(''),
|
|
status: Joi.string()
|
|
.valid(...DEVICE_STATUS, 'all')
|
|
.allow(''),
|
|
type: Joi.string()
|
|
.valid(...DEVICE_TYPES, 'all')
|
|
.allow(''),
|
|
rackId: Joi.string()
|
|
.max(50)
|
|
.allow(''),
|
|
page: Joi.number()
|
|
.integer()
|
|
.min(1)
|
|
.default(1),
|
|
pageSize: Joi.number()
|
|
.integer()
|
|
.min(1)
|
|
.max(100)
|
|
.default(10)
|
|
});
|
|
|
|
const createDeviceSchema = {
|
|
validate: async (data, options = {}) => {
|
|
const schema = await getCreateDeviceSchema();
|
|
return schema.validate(data, options);
|
|
}
|
|
};
|
|
|
|
const updateDeviceSchema = {
|
|
validate: async (data, options = {}) => {
|
|
const schema = await getUpdateDeviceSchema();
|
|
return schema.validate(data, options);
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
createDeviceSchema,
|
|
updateDeviceSchema,
|
|
batchDeviceIdsSchema,
|
|
batchStatusSchema,
|
|
batchMoveSchema,
|
|
queryDeviceSchema,
|
|
DEVICE_TYPES,
|
|
DEVICE_STATUS,
|
|
getCreateDeviceSchema,
|
|
getUpdateDeviceSchema
|
|
};
|