feat: 添加操作日志、危险操作确认和业务关联功能

1. 新增操作日志记录功能,记录关键操作
2. 实现危险操作确认对话框,防止误删
3. 添加业务和库房管理模块
4. 支持设备标记为空闲状态
5. 完善API文档和健康检查
6. 优化前端删除操作的确认流程
7. 添加Swagger API文档支持
8. 实现设备与业务的关联功能
9. 改进设备模型,添加空闲相关字段
10. 优化用户、角色管理操作日志
This commit is contained in:
zhang1106
2026-03-20 17:15:14 +08:00
parent c392df9ce3
commit 73cbe4ac1b
52 changed files with 11149 additions and 1756 deletions
+74
View File
@@ -4,6 +4,7 @@ const Permission = require('../models/Permission');
const UserRole = require('../models/UserRole');
const User = require('../models/User');
const { authMiddleware } = require('../middleware/auth');
const { logRoleOperation } = require('../utils/operationLogger');
const router = express.Router();
@@ -134,6 +135,18 @@ router.post('/', authMiddleware, async (req, res) => {
sort: sort || 0
});
const permissionNames = permissions && permissions.length > 0
? permissions.join('、')
: '无';
await logRoleOperation('create', `创建角色【${roleName}】(编码:${roleCode},权限:${permissionNames}`, {
targetId: role.roleId,
targetName: roleName,
afterState: role.toJSON(),
req,
metadata: { roleCode, permissions, permissionNames }
});
res.status(201).json({
success: true,
message: '创建成功',
@@ -160,6 +173,8 @@ router.put('/:roleId', authMiddleware, async (req, res) => {
});
}
const beforeState = role.toJSON();
if (roleName !== undefined) role.roleName = roleName;
if (description !== undefined) role.description = description;
if (permissions !== undefined) role.permissions = permissions;
@@ -168,6 +183,53 @@ router.put('/:roleId', authMiddleware, async (req, res) => {
await role.save();
const afterState = role.toJSON();
const changedFields = {};
if (roleName !== undefined && beforeState.roleName !== roleName) {
changedFields.roleName = { from: beforeState.roleName, to: roleName };
}
if (description !== undefined && beforeState.description !== description) {
changedFields.description = { from: beforeState.description, to: description };
}
if (permissions !== undefined) {
const oldPerms = (beforeState.permissions || []).sort().join(',');
const newPerms = (permissions || []).sort().join(',');
if (oldPerms !== newPerms) {
changedFields.permissions = { from: beforeState.permissions, to: permissions };
}
}
if (status !== undefined && beforeState.status !== status) {
const statusText = { active: '启用', inactive: '禁用' };
changedFields.status = { from: beforeState.status, to: status, fromText: statusText[beforeState.status], toText: statusText[status] };
}
const changeDetails = Object.entries(changedFields).map(([field, values]) => {
const fieldNames = { roleName: '角色名称', description: '描述', permissions: '权限', status: '状态' };
const displayName = fieldNames[field] || field;
if (field === 'permissions') {
return `权限: ${(values.from || []).join('、') || '无'}${(values.to || []).join('、') || '无'}`;
}
if (field === 'status') {
return `状态: ${values.fromText}${values.toText}`;
}
return `${displayName}: ${values.from ?? '空'}${values.to ?? '空'}`;
}).join('');
const updateDesc = changeDetails
? `更新角色【${role.roleName}】:${changeDetails}`
: `更新角色【${role.roleName}`;
await logRoleOperation('update', updateDesc, {
targetId: role.roleId,
targetName: role.roleName,
beforeState,
afterState,
req,
metadata: { changedFields, oldRoleName: beforeState.roleName, oldPermissions: beforeState.permissions }
});
res.json({
success: true,
message: '更新成功',
@@ -208,8 +270,20 @@ router.delete('/:roleId', authMiddleware, async (req, res) => {
});
}
const roleName = role.roleName;
const roleCode = role.roleCode;
const beforeState = role.toJSON();
await role.destroy();
await logRoleOperation('delete', `删除角色【${roleName}】(编码:${roleCode},权限:${(role.permissions || []).join('、') || '无'}`, {
targetId: req.params.roleId,
targetName: roleName,
beforeState,
req,
metadata: { roleCode, userCount, permissions: role.permissions }
});
res.json({
success: true,
message: '删除成功'