feat: 添加设备位置冲突检查功能并优化操作日志
feat(api): 在设备API中添加checkPosition接口用于检查U位冲突 feat(frontend): 在设备表单和空闲设备管理中实现U位冲突检查 refactor(backend): 重构操作日志功能,添加设备描述生成和元数据构建工具 fix(backend): 修复批量导入机柜时的ID验证规则 feat(backend): 为机柜导入添加创建和跳过机柜的详细返回信息 fix(backend): 修复设备删除时未检查关联接线的问题 feat(backend): 添加机柜导入模板生成脚本 perf(frontend): 优化机柜管理页面的导入结果展示 fix(frontend): 修复设备端口删除时的关联接线检查
This commit is contained in:
@@ -4,7 +4,7 @@ const { Op } = require('sequelize');
|
||||
const Device = require('../models/Device');
|
||||
const Rack = require('../models/Rack');
|
||||
const Room = require('../models/Room');
|
||||
const { logDeviceOperation } = require('../utils/operationLogger');
|
||||
const { logDeviceOperation, generateDeviceDescription, buildDeviceMetadata } = require('../utils/operationLogger');
|
||||
|
||||
async function generateIdleDeviceId() {
|
||||
const devices = await Device.findAll({
|
||||
@@ -148,12 +148,19 @@ router.post('/', async (req, res) => {
|
||||
description: description || ''
|
||||
});
|
||||
|
||||
await logDeviceOperation('create', `新增空闲设备【${device.name || deviceId}】`, {
|
||||
await logDeviceOperation('create', generateDeviceDescription('新增空闲设备', {
|
||||
deviceId: device.deviceId,
|
||||
name: device.name || deviceId,
|
||||
type: device.type,
|
||||
model: device.model,
|
||||
serialNumber: device.serialNumber,
|
||||
ipAddress: device.ipAddress
|
||||
}, { includeRack: false }), {
|
||||
targetId: device.deviceId,
|
||||
targetName: device.name,
|
||||
targetName: device.name || deviceId,
|
||||
afterState: device.toJSON(),
|
||||
req,
|
||||
metadata: { sourceType: device.sourceType, type: 'idle_device_create' }
|
||||
metadata: buildDeviceMetadata(device.toJSON(), { sourceType: device.sourceType, type: 'idle_device_create' })
|
||||
});
|
||||
|
||||
res.status(201).json(device);
|
||||
@@ -189,13 +196,14 @@ router.post('/from-device/:deviceId', async (req, res) => {
|
||||
|
||||
await t.commit();
|
||||
|
||||
await logDeviceOperation('to_idle', `设备【${device.name}】转入空闲设备`, {
|
||||
const deviceData = device.toJSON();
|
||||
await logDeviceOperation('to_idle', generateDeviceDescription('设备转入空闲设备', deviceData), {
|
||||
targetId: device.deviceId,
|
||||
targetName: device.name,
|
||||
beforeState: { ...device.toJSON(), isIdle: false },
|
||||
afterState: { ...device.toJSON(), isIdle: true },
|
||||
beforeState: { ...deviceData, isIdle: false },
|
||||
afterState: { ...deviceData, isIdle: true },
|
||||
req,
|
||||
metadata: { idleReason, type: 'device_to_idle' }
|
||||
metadata: buildDeviceMetadata(deviceData, { idleReason, type: 'device_to_idle' })
|
||||
});
|
||||
|
||||
res.json({
|
||||
@@ -244,11 +252,16 @@ router.post('/batch-from-devices', async (req, res) => {
|
||||
|
||||
await t.commit();
|
||||
|
||||
await logDeviceOperation('batch_to_idle', `批量将 ${notIdleDevices.length} 台设备转入空闲设备`, {
|
||||
const deviceDetails = notIdleDevices.map(d => d.toJSON());
|
||||
const deviceSummary = deviceDetails.map(d =>
|
||||
`${d.name}(编号:${d.deviceId}${d.type ? `,类型:${d.type}` : ''}${d.serialNumber ? `,序列号:${d.serialNumber}` : ''})`
|
||||
).join('、');
|
||||
|
||||
await logDeviceOperation('batch_to_idle', `批量将 ${notIdleDevices.length} 台设备转入空闲设备:${deviceSummary}`, {
|
||||
targetId: deviceIds.join(','),
|
||||
targetName: `${notIdleDevices.length}台设备`,
|
||||
req,
|
||||
metadata: { idleReason, type: 'batch_device_to_idle' }
|
||||
metadata: { idleReason, type: 'batch_device_to_idle', devices: deviceDetails }
|
||||
});
|
||||
|
||||
res.json({
|
||||
@@ -391,11 +404,16 @@ router.put('/batch-restore', async (req, res) => {
|
||||
const failedCount = results.filter(r => r.status === 'failed').length;
|
||||
const skippedCount = results.filter(r => r.status === 'skipped').length;
|
||||
|
||||
await logDeviceOperation('batch_restore', `批量上架 ${successCount} 台空闲设备`, {
|
||||
const successDevices = idleDevices.filter(d => results.some(r => r.deviceId === d.deviceId && r.status === 'success'));
|
||||
const deviceSummary = successDevices.map(d =>
|
||||
`${d.name}(编号:${d.deviceId}${d.type ? `,类型:${d.type}` : ''}${d.ipAddress ? `,IP:${d.ipAddress}` : ''})`
|
||||
).join('、');
|
||||
|
||||
await logDeviceOperation('batch_restore', `批量上架 ${successCount} 台空闲设备:${deviceSummary}`, {
|
||||
targetId: deviceIds.join(','),
|
||||
targetName: `${successCount}台设备`,
|
||||
req,
|
||||
metadata: { results, type: 'batch_idle_device_restore' }
|
||||
metadata: { results, type: 'batch_idle_device_restore', devices: successDevices.map(d => d.toJSON()) }
|
||||
});
|
||||
|
||||
res.json({
|
||||
@@ -479,13 +497,19 @@ router.put('/:deviceId/shelve', async (req, res) => {
|
||||
]
|
||||
});
|
||||
|
||||
await logDeviceOperation('shelve', `空闲设备【${device.name}】上架到机柜【${targetRack.name}】U${position}`, {
|
||||
const deviceData = {
|
||||
...updatedDevice.toJSON(),
|
||||
rackName: targetRack.name,
|
||||
roomName: updatedDevice.Rack?.Room?.name
|
||||
};
|
||||
|
||||
await logDeviceOperation('shelve', generateDeviceDescription('空闲设备上架', deviceData, { includePosition: false }) + `到机柜【${targetRack.name}】U${position}`, {
|
||||
targetId: device.deviceId,
|
||||
targetName: device.name,
|
||||
beforeState: { ...beforeState, isIdle: true },
|
||||
afterState: updatedDevice.toJSON(),
|
||||
afterState: deviceData,
|
||||
req,
|
||||
metadata: { rackId, position, type: 'idle_device_shelve' }
|
||||
metadata: buildDeviceMetadata(deviceData, { rackId, position, type: 'idle_device_shelve' })
|
||||
});
|
||||
|
||||
res.json({
|
||||
@@ -542,13 +566,13 @@ router.put('/:deviceId', async (req, res) => {
|
||||
|
||||
await device.save();
|
||||
|
||||
await logDeviceOperation('update', `更新空闲设备【${device.name}】`, {
|
||||
await logDeviceOperation('update', generateDeviceDescription('更新空闲设备', device.toJSON(), { includeRack: false }), {
|
||||
targetId: device.deviceId,
|
||||
targetName: device.name,
|
||||
beforeState,
|
||||
afterState: device.toJSON(),
|
||||
req,
|
||||
metadata: { type: 'idle_device_update' }
|
||||
metadata: buildDeviceMetadata(device.toJSON(), { type: 'idle_device_update' })
|
||||
});
|
||||
|
||||
res.json(device);
|
||||
@@ -613,13 +637,19 @@ router.put('/:deviceId/restore', async (req, res) => {
|
||||
]
|
||||
});
|
||||
|
||||
await logDeviceOperation('restore', `空闲设备【${device.name}】恢复到机柜【${targetRack.name}】U${targetPosition}`, {
|
||||
const deviceData = {
|
||||
...updatedDevice.toJSON(),
|
||||
rackName: targetRack.name,
|
||||
roomName: updatedDevice.Rack?.Room?.name
|
||||
};
|
||||
|
||||
await logDeviceOperation('restore', generateDeviceDescription('空闲设备恢复', deviceData, { includePosition: false }) + `到机柜【${targetRack.name}】U${targetPosition}`, {
|
||||
targetId: device.deviceId,
|
||||
targetName: device.name,
|
||||
beforeState: { ...device.toJSON(), isIdle: true },
|
||||
afterState: updatedDevice.toJSON(),
|
||||
afterState: deviceData,
|
||||
req,
|
||||
metadata: { targetRackId, targetPosition, type: 'idle_device_restore' }
|
||||
metadata: buildDeviceMetadata(deviceData, { targetRackId, targetPosition, type: 'idle_device_restore' })
|
||||
});
|
||||
|
||||
res.json({
|
||||
@@ -761,11 +791,16 @@ router.put('/batch-restore', async (req, res) => {
|
||||
const failedCount = results.filter(r => r.status === 'failed').length;
|
||||
const skippedCount = results.filter(r => r.status === 'skipped').length;
|
||||
|
||||
await logDeviceOperation('batch_restore', `批量上架 ${successCount} 台空闲设备`, {
|
||||
const successDevices = idleDevices.filter(d => results.some(r => r.deviceId === d.deviceId && r.status === 'success'));
|
||||
const deviceSummary = successDevices.map(d =>
|
||||
`${d.name}(编号:${d.deviceId}${d.type ? `,类型:${d.type}` : ''}${d.ipAddress ? `,IP:${d.ipAddress}` : ''})`
|
||||
).join('、');
|
||||
|
||||
await logDeviceOperation('batch_restore', `批量上架 ${successCount} 台空闲设备:${deviceSummary}`, {
|
||||
targetId: deviceIds.join(','),
|
||||
targetName: `${successCount}台设备`,
|
||||
req,
|
||||
metadata: { results, type: 'batch_idle_device_restore' }
|
||||
metadata: { results, type: 'batch_idle_device_restore', devices: successDevices.map(d => d.toJSON()) }
|
||||
});
|
||||
|
||||
res.json({
|
||||
@@ -802,12 +837,15 @@ router.delete('/:deviceId', async (req, res) => {
|
||||
|
||||
await t.commit();
|
||||
|
||||
await logDeviceOperation('delete', `删除空闲设备【${device.name || device.deviceId}】`, {
|
||||
await logDeviceOperation('delete', generateDeviceDescription('删除空闲设备', {
|
||||
...device.toJSON(),
|
||||
name: device.name || device.deviceId
|
||||
}, { includeRack: false }), {
|
||||
targetId: device.deviceId,
|
||||
targetName: device.name,
|
||||
beforeState,
|
||||
req,
|
||||
metadata: { type: 'idle_device_delete' }
|
||||
metadata: buildDeviceMetadata(device.toJSON(), { type: 'idle_device_delete' })
|
||||
});
|
||||
|
||||
res.json({ message: '空闲设备删除成功' });
|
||||
|
||||
Reference in New Issue
Block a user