// middleware/permissions.js —— 接口权限 + 数据范围 + 合同类型校验 /** * 检查当前用户是否拥有指定权限 * @param {string} resource - 资源名,如 'customer' * @param {string} action - 操作名,如 'read' */ function checkPermission(resource, action) { return (req, res, next) => { const permName = `${resource}:${action}` if (!req.user || !req.user.permissions || !req.user.permissions.includes(permName)) { return res.status(403).json({ code: 403, message: '权限不足' }) } next() } } /** * 根据用户部门计算数据范围,挂到 req.scope * @param {string} resource - 资源名:customers / contracts / after_sales / employees */ function dataScope(resource) { return (req, res, next) => { const deptName = req.user.departmentName // 如 'franchise_manager' // 信息技术部和总经理办公室:全量数据 if (deptName === 'admin' || deptName === 'general_manager') { return next() } let sql = null, params = [] switch (resource) { case 'customers': // 过渡期:招商部和运营部也能看全量加盟商 break case 'contracts': if (deptName === 'franchise_manager') { sql = 'AND type = ?' params = ['franchise'] } else if (deptName === 'procurement_manager') { sql = 'AND type = ?' params = ['supply'] } // finance 全量看;operations_manager 无合同权限(checkPermission 已拦截) break case 'after_sales': // 过渡期:运营部看全量售后 break case 'employees': if (['franchise_manager', 'operations_manager', 'procurement_manager'].includes(deptName)) { sql = 'AND department = ?' params = [req.user.departmentDesc] // 如 '招商部' } // finance 全量看员工 break } if (sql) { req.scope = { sql, params } } next() } } /** * 合同创建/修改时校验类型是否匹配部门 * 招商部只能操作加盟合同,采购部只能操作采购合同 */ function validateContractType(req, res, next) { const deptName = req.user.departmentName const type = req.body.type // 未传 type 则跳过(路由会默认 'franchise') if (type === undefined) return next() // 管理员/总经理/财务不限制 if (['admin', 'general_manager', 'finance'].includes(deptName)) return next() // 采购部只能操作采购合同 if (deptName === 'procurement_manager' && type !== 'supply') { return res.status(403).json({ code: 403, message: '采购部只能操作采购合同' }) } // 招商部只能操作加盟合同 if (deptName === 'franchise_manager' && type !== 'franchise') { return res.status(403).json({ code: 403, message: '招商部只能操作加盟合同' }) } next() } module.exports = { checkPermission, dataScope, validateContractType }