|
@@ -0,0 +1,73 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * 角色→权限映射表
|
|
|
|
|
+ * 每个角色映射一组权限标识,支持通配符 '*' 和前缀通配 'prefix:*'
|
|
|
|
|
+ */
|
|
|
|
|
+const ROLE_PERMISSIONS = {
|
|
|
|
|
+ admin: ['*'],
|
|
|
|
|
+ teacher: ['dashboard', 'service:*', 'growth:*', 'biz:*', 'assessment:*', 'messages'],
|
|
|
|
|
+ nutritionist: ['dashboard', 'service:family', 'health:*', 'assessment:dan', 'energy'],
|
|
|
|
|
+ article_manager: ['dashboard', 'articles:*'],
|
|
|
|
|
+ activity_manager: ['dashboard', 'activity:*'],
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取用户有效权限列表
|
|
|
|
|
+ * @param {string[]} roles - 用户拥有的角色列表
|
|
|
|
|
+ * @returns {string[]} - 去重后的权限标识列表
|
|
|
|
|
+ */
|
|
|
|
|
+export function getEffectivePermissions(roles) {
|
|
|
|
|
+ if (!roles || roles.length === 0) return []
|
|
|
|
|
+ const permSet = new Set()
|
|
|
|
|
+ for (const role of roles) {
|
|
|
|
|
+ const perms = ROLE_PERMISSIONS[role]
|
|
|
|
|
+ if (perms) {
|
|
|
|
|
+ for (const p of perms) {
|
|
|
|
|
+ permSet.add(p)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return Array.from(permSet)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 判断是否拥有指定权限
|
|
|
|
|
+ * @param {string[]} userPerms - 用户的有效权限列表
|
|
|
|
|
+ * @param {string} required - 需要的权限标识(支持 'prefix:*' 通配匹配)
|
|
|
|
|
+ * @returns {boolean}
|
|
|
|
|
+ *
|
|
|
|
|
+ * 匹配规则:
|
|
|
|
|
+ * - 如果 userPerms 包含 '*' → 返回 true
|
|
|
|
|
+ * - 如果 required 是 'prefix:sub' 且 userPerms 包含 'prefix:*' → 返回 true
|
|
|
|
|
+ * - 如果 userPerms 包含 required → 返回 true
|
|
|
|
|
+ * - 否则返回 false
|
|
|
|
|
+ */
|
|
|
|
|
+export function hasPermission(userPerms, required) {
|
|
|
|
|
+ if (!userPerms || !required) return false
|
|
|
|
|
+ if (userPerms.includes('*')) return true
|
|
|
|
|
+
|
|
|
|
|
+ // 精确匹配
|
|
|
|
|
+ if (userPerms.includes(required)) return true
|
|
|
|
|
+
|
|
|
|
|
+ // 前缀通配匹配: required = 'articles:manage', 检查 'articles:*' 是否在 userPerms 中
|
|
|
|
|
+ const colonIndex = required.indexOf(':')
|
|
|
|
|
+ if (colonIndex > 0) {
|
|
|
|
|
+ const prefix = required.substring(0, colonIndex) + ':*'
|
|
|
|
|
+ if (userPerms.includes(prefix)) return true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return false
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取角色中文名
|
|
|
|
|
+ */
|
|
|
|
|
+export function getRoleLabel(role) {
|
|
|
|
|
+ const labels = {
|
|
|
|
|
+ admin: '管理员',
|
|
|
|
|
+ teacher: '成长规划师',
|
|
|
|
|
+ nutritionist: '营养师',
|
|
|
|
|
+ article_manager: '文章管理员',
|
|
|
|
|
+ activity_manager: '活动管理员',
|
|
|
|
|
+ }
|
|
|
|
|
+ return labels[role] || role
|
|
|
|
|
+}
|