Files
nxxmdata/backend/controllers/systemController.js
2025-09-12 20:08:42 +08:00

671 lines
17 KiB
JavaScript

/**
* 系统管理控制器
* @file systemController.js
* @description 处理系统配置和菜单权限管理相关业务逻辑
*/
const { SystemConfig, MenuPermission, User, Role } = require('../models');
const logger = require('../utils/logger');
const { validationResult } = require('express-validator');
const { Op } = require('sequelize');
/**
* 获取系统配置列表
* @route GET /api/system/configs
*/
const getSystemConfigs = async (req, res) => {
try {
const { category, is_public } = req.query;
const whereClause = {};
if (category) {
whereClause.category = category;
}
if (is_public !== undefined) {
whereClause.is_public = is_public === 'true';
}
const configs = await SystemConfig.findAll({
where: whereClause,
order: [['category', 'ASC'], ['sort_order', 'ASC']],
attributes: { exclude: ['updated_by'] } // 隐藏敏感字段
});
// 解析配置值
const parsedConfigs = configs.map(config => ({
...config.dataValues,
parsed_value: SystemConfig.parseValue(config.config_value, config.config_type)
}));
logger.info(`用户 ${req.user.username} 获取系统配置列表,分类: ${category || '全部'}`);
res.json({
success: true,
data: parsedConfigs,
total: parsedConfigs.length
});
} catch (error) {
logger.error('获取系统配置列表失败:', error);
res.status(500).json({
success: false,
message: '获取系统配置失败',
error: error.message
});
}
};
/**
* 获取公开系统配置(前端使用)
* @route GET /api/system/configs/public
*/
const getPublicConfigs = async (req, res) => {
try {
const configs = await SystemConfig.getPublicConfigs();
res.json({
success: true,
data: configs
});
} catch (error) {
logger.error('获取公开系统配置失败:', error);
res.status(500).json({
success: false,
message: '获取系统配置失败',
error: error.message
});
}
};
/**
* 更新系统配置
* @route PUT /api/system/configs/:id
*/
const updateSystemConfig = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: '参数验证失败',
errors: errors.array()
});
}
const { id } = req.params;
const { config_value, description } = req.body;
const config = await SystemConfig.findByPk(id);
if (!config) {
return res.status(404).json({
success: false,
message: '配置项不存在'
});
}
if (!config.is_editable) {
return res.status(403).json({
success: false,
message: '该配置项不允许编辑'
});
}
await config.update({
config_value: SystemConfig.stringifyValue(config_value),
config_type: SystemConfig.detectType(config_value),
description,
updated_by: req.user.id
});
logger.info(`用户 ${req.user.username} 更新系统配置: ${config.config_key}`);
res.json({
success: true,
message: '配置更新成功',
data: {
...config.dataValues,
parsed_value: SystemConfig.parseValue(config.config_value, config.config_type)
}
});
} catch (error) {
logger.error('更新系统配置失败:', error);
res.status(500).json({
success: false,
message: '更新配置失败',
error: error.message
});
}
};
/**
* 创建系统配置
* @route POST /api/system/configs
*/
const createSystemConfig = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: '参数验证失败',
errors: errors.array()
});
}
const {
config_key,
config_value,
category = 'general',
description,
is_public = false,
is_editable = true,
sort_order = 0
} = req.body;
const config = await SystemConfig.create({
config_key,
config_value: SystemConfig.stringifyValue(config_value),
config_type: SystemConfig.detectType(config_value),
category,
description,
is_public,
is_editable,
sort_order,
updated_by: req.user.id
});
logger.info(`用户 ${req.user.username} 创建系统配置: ${config_key}`);
res.status(201).json({
success: true,
message: '配置创建成功',
data: {
...config.dataValues,
parsed_value: SystemConfig.parseValue(config.config_value, config.config_type)
}
});
} catch (error) {
logger.error('创建系统配置失败:', error);
res.status(500).json({
success: false,
message: '创建配置失败',
error: error.message
});
}
};
/**
* 删除系统配置
* @route DELETE /api/system/configs/:id
*/
const deleteSystemConfig = async (req, res) => {
try {
const { id } = req.params;
const config = await SystemConfig.findByPk(id);
if (!config) {
return res.status(404).json({
success: false,
message: '配置项不存在'
});
}
if (!config.is_editable) {
return res.status(403).json({
success: false,
message: '该配置项不允许删除'
});
}
await config.destroy();
logger.info(`用户 ${req.user.username} 删除系统配置: ${config.config_key}`);
res.json({
success: true,
message: '配置删除成功'
});
} catch (error) {
logger.error('删除系统配置失败:', error);
res.status(500).json({
success: false,
message: '删除配置失败',
error: error.message
});
}
};
/**
* 获取配置分类列表
* @route GET /api/system/configs/categories
*/
const getConfigCategories = async (req, res) => {
try {
const categories = await SystemConfig.findAll({
attributes: ['category'],
group: ['category'],
order: [['category', 'ASC']]
});
const categoryList = categories.map(item => item.category);
res.json({
success: true,
data: categoryList
});
} catch (error) {
logger.error('获取配置分类失败:', error);
res.status(500).json({
success: false,
message: '获取配置分类失败',
error: error.message
});
}
};
/**
* 获取菜单权限列表
* @route GET /api/system/menus
*/
const getMenuPermissions = async (req, res) => {
try {
const menus = await MenuPermission.findAll({
order: [['sort_order', 'ASC']],
include: [
{
model: MenuPermission,
as: 'children',
required: false
},
{
model: MenuPermission,
as: 'parent',
required: false
}
]
});
// 构建菜单树
const menuTree = MenuPermission.buildMenuTree(menus);
logger.info(`用户 ${req.user.username} 获取菜单权限列表`);
res.json({
success: true,
data: menuTree,
total: menus.length
});
} catch (error) {
logger.error('获取菜单权限列表失败:', error);
res.status(500).json({
success: false,
message: '获取菜单权限失败',
error: error.message
});
}
};
/**
* 获取用户菜单(根据权限过滤)
* @route GET /api/system/menus/user
*/
const getUserMenus = async (req, res) => {
try {
const user = await User.findByPk(req.user.id, {
include: [{
model: Role,
as: 'role',
attributes: ['name']
}]
});
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
// 获取用户角色
const userRoles = [user.role?.name || 'user'];
// 获取用户权限菜单
const userMenus = await MenuPermission.getUserMenus(userRoles, []);
res.json({
success: true,
data: userMenus,
userRoles
});
} catch (error) {
logger.error('获取用户菜单失败:', error);
res.status(500).json({
success: false,
message: '获取用户菜单失败',
error: error.message
});
}
};
/**
* 更新菜单权限
* @route PUT /api/system/menus/:id
*/
const updateMenuPermission = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: '参数验证失败',
errors: errors.array()
});
}
const { id } = req.params;
const {
menu_name,
menu_path,
required_roles,
required_permissions,
icon,
sort_order,
is_visible,
is_enabled,
description
} = req.body;
const menu = await MenuPermission.findByPk(id);
if (!menu) {
return res.status(404).json({
success: false,
message: '菜单项不存在'
});
}
await menu.update({
menu_name,
menu_path,
required_roles: required_roles ? JSON.stringify(required_roles) : null,
required_permissions: required_permissions ? JSON.stringify(required_permissions) : null,
icon,
sort_order,
is_visible,
is_enabled,
description
});
logger.info(`用户 ${req.user.username} 更新菜单权限: ${menu.menu_key}`);
res.json({
success: true,
message: '菜单权限更新成功',
data: menu
});
} catch (error) {
logger.error('更新菜单权限失败:', error);
res.status(500).json({
success: false,
message: '更新菜单权限失败',
error: error.message
});
}
};
/**
* 获取系统统计信息
* @route GET /api/system/stats
*/
const getSystemStats = async (req, res) => {
try {
const stats = {
configs: {
total: await SystemConfig.count(),
public: await SystemConfig.count({ where: { is_public: true } }),
editable: await SystemConfig.count({ where: { is_editable: true } })
},
menus: {
total: await MenuPermission.count(),
visible: await MenuPermission.count({ where: { is_visible: true } }),
enabled: await MenuPermission.count({ where: { is_enabled: true } })
},
users: {
total: await User.count(),
active: await User.count({ where: { status: 'active' } })
},
roles: {
total: await Role.count()
}
};
res.json({
success: true,
data: stats
});
} catch (error) {
logger.error('获取系统统计信息失败:', error);
res.status(500).json({
success: false,
message: '获取系统统计失败',
error: error.message
});
}
};
/**
* 初始化系统配置
* @route POST /api/system/init
*/
const initializeSystem = async (req, res) => {
try {
// 初始化默认菜单权限
await MenuPermission.initDefaultMenus();
// 初始化默认系统配置
const defaultConfigs = [
{
config_key: 'system.name',
config_value: '宁夏智慧养殖监管平台',
category: 'general',
description: '系统名称',
is_public: true
},
{
config_key: 'system.version',
config_value: '2.1.0',
category: 'general',
description: '系统版本',
is_public: true,
is_editable: false
},
{
config_key: 'pagination.default_page_size',
config_value: '10',
config_type: 'number',
category: 'ui',
description: '默认分页大小',
is_public: true
},
{
config_key: 'notification.email_enabled',
config_value: 'true',
config_type: 'boolean',
category: 'notification',
description: '启用邮件通知'
},
{
config_key: 'security.session_timeout',
config_value: '3600',
config_type: 'number',
category: 'security',
description: '会话超时时间(秒)'
},
{
config_key: 'monitoring.realtime_enabled',
config_value: 'true',
config_type: 'boolean',
category: 'monitoring',
description: '启用实时监控',
is_public: true
},
{
config_key: 'report.auto_cleanup_days',
config_value: '30',
config_type: 'number',
category: 'report',
description: '报表文件自动清理天数'
}
];
for (const configData of defaultConfigs) {
const existing = await SystemConfig.findOne({
where: { config_key: configData.config_key }
});
if (!existing) {
await SystemConfig.create({
...configData,
updated_by: req.user.id
});
}
}
logger.info(`管理员 ${req.user.username} 初始化系统配置`);
res.json({
success: true,
message: '系统初始化完成'
});
} catch (error) {
logger.error('系统初始化失败:', error);
res.status(500).json({
success: false,
message: '系统初始化失败',
error: error.message
});
}
};
/**
* 批量更新系统配置
* @route PUT /api/system/configs/batch
*/
const batchUpdateConfigs = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: '参数验证失败',
errors: errors.array()
});
}
const { configs } = req.body;
if (!Array.isArray(configs)) {
return res.status(400).json({
success: false,
message: 'configs必须是数组'
});
}
const results = [];
for (const configData of configs) {
try {
const { config_key, config_value } = configData;
const existingConfig = await SystemConfig.findOne({
where: { config_key }
});
if (existingConfig && existingConfig.is_editable) {
await existingConfig.update({
config_value: SystemConfig.stringifyValue(config_value),
config_type: SystemConfig.detectType(config_value),
updated_by: req.user.id
});
results.push({ config_key, success: true });
} else if (!existingConfig) {
results.push({ config_key, success: false, reason: '配置不存在' });
} else {
results.push({ config_key, success: false, reason: '配置不可编辑' });
}
} catch (error) {
results.push({ config_key: configData.config_key, success: false, reason: error.message });
}
}
logger.info(`用户 ${req.user.username} 批量更新系统配置`);
res.json({
success: true,
message: '批量更新完成',
data: results
});
} catch (error) {
logger.error('批量更新系统配置失败:', error);
res.status(500).json({
success: false,
message: '批量更新失败',
error: error.message
});
}
};
/**
* 重置系统配置到默认值
* @route POST /api/system/configs/:id/reset
*/
const resetSystemConfig = async (req, res) => {
try {
const { id } = req.params;
const config = await SystemConfig.findByPk(id);
if (!config) {
return res.status(404).json({
success: false,
message: '配置项不存在'
});
}
if (!config.is_editable) {
return res.status(403).json({
success: false,
message: '该配置项不允许重置'
});
}
// 这里可以根据需要实现默认值重置逻辑
// 暂时返回成功消息
logger.info(`用户 ${req.user.username} 重置系统配置: ${config.config_key}`);
res.json({
success: true,
message: '配置重置成功'
});
} catch (error) {
logger.error('重置系统配置失败:', error);
res.status(500).json({
success: false,
message: '重置配置失败',
error: error.message
});
}
};
module.exports = {
getSystemConfigs,
getPublicConfigs,
updateSystemConfig,
createSystemConfig,
deleteSystemConfig,
getConfigCategories,
getMenuPermissions,
getUserMenus,
updateMenuPermission,
getSystemStats,
initializeSystem,
batchUpdateConfigs,
resetSystemConfig
};