671 lines
17 KiB
JavaScript
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
|
|
};
|