|
@@ -2,6 +2,7 @@ import Vue from 'vue'
|
|
|
import VueRouter from 'vue-router'
|
|
import VueRouter from 'vue-router'
|
|
|
import Layout from '@/views/Layout.vue'
|
|
import Layout from '@/views/Layout.vue'
|
|
|
import axios from 'axios'
|
|
import axios from 'axios'
|
|
|
|
|
+import { getEffectivePermissions, hasPermission } from '@/utils/permissions'
|
|
|
|
|
|
|
|
Vue.use(VueRouter)
|
|
Vue.use(VueRouter)
|
|
|
|
|
|
|
@@ -11,6 +12,12 @@ const routes = [
|
|
|
name: 'Login',
|
|
name: 'Login',
|
|
|
component: () => import('@/views/Login.vue')
|
|
component: () => import('@/views/Login.vue')
|
|
|
},
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ path: '/403',
|
|
|
|
|
+ name: 'Forbidden',
|
|
|
|
|
+ component: { template: '<div style="text-align:center;padding:100px"><h1>403</h1><p>权限不足</p><router-link to="/">返回首页</router-link></div>' },
|
|
|
|
|
+ meta: { title: '权限不足' }
|
|
|
|
|
+ },
|
|
|
{
|
|
{
|
|
|
path: '/',
|
|
path: '/',
|
|
|
component: Layout,
|
|
component: Layout,
|
|
@@ -20,282 +27,327 @@ const routes = [
|
|
|
path: 'dashboard',
|
|
path: 'dashboard',
|
|
|
name: 'Dashboard',
|
|
name: 'Dashboard',
|
|
|
component: () => import('@/views/Dashboard.vue'),
|
|
component: () => import('@/views/Dashboard.vue'),
|
|
|
- meta: { title: '首页' }
|
|
|
|
|
|
|
+ meta: { title: '首页', perm: 'dashboard' }
|
|
|
},
|
|
},
|
|
|
// 家庭管理
|
|
// 家庭管理
|
|
|
{
|
|
{
|
|
|
path: 'families',
|
|
path: 'families',
|
|
|
name: 'Families',
|
|
name: 'Families',
|
|
|
component: () => import('@/views/Families.vue'),
|
|
component: () => import('@/views/Families.vue'),
|
|
|
- meta: { title: '家庭列表' }
|
|
|
|
|
|
|
+ meta: { title: '家庭列表', perm: 'family:list' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'children',
|
|
path: 'children',
|
|
|
name: 'Children',
|
|
name: 'Children',
|
|
|
component: () => import('@/views/Children.vue'),
|
|
component: () => import('@/views/Children.vue'),
|
|
|
- meta: { title: '孩子管理' }
|
|
|
|
|
|
|
+ meta: { title: '孩子管理', perm: 'family:children' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'points',
|
|
path: 'points',
|
|
|
name: 'Points',
|
|
name: 'Points',
|
|
|
component: () => import('@/views/Points.vue'),
|
|
component: () => import('@/views/Points.vue'),
|
|
|
- meta: { title: '积分管理' }
|
|
|
|
|
|
|
+ meta: { title: '积分管理', perm: 'family:points' }
|
|
|
},
|
|
},
|
|
|
// 任务管理
|
|
// 任务管理
|
|
|
{
|
|
{
|
|
|
path: 'tasks',
|
|
path: 'tasks',
|
|
|
name: 'Tasks',
|
|
name: 'Tasks',
|
|
|
component: () => import('@/views/Tasks.vue'),
|
|
component: () => import('@/views/Tasks.vue'),
|
|
|
- meta: { title: '任务列表' }
|
|
|
|
|
|
|
+ meta: { title: '任务列表', perm: 'task:list' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'task-templates',
|
|
path: 'task-templates',
|
|
|
name: 'TaskTemplates',
|
|
name: 'TaskTemplates',
|
|
|
component: () => import('@/views/TaskTemplates.vue'),
|
|
component: () => import('@/views/TaskTemplates.vue'),
|
|
|
- meta: { title: '任务模板' }
|
|
|
|
|
|
|
+ meta: { title: '任务模板', perm: 'task:templates' }
|
|
|
},
|
|
},
|
|
|
// 奖励管理
|
|
// 奖励管理
|
|
|
{
|
|
{
|
|
|
path: 'rewards',
|
|
path: 'rewards',
|
|
|
name: 'Rewards',
|
|
name: 'Rewards',
|
|
|
component: () => import('@/views/Rewards.vue'),
|
|
component: () => import('@/views/Rewards.vue'),
|
|
|
- meta: { title: '奖励列表' }
|
|
|
|
|
|
|
+ meta: { title: '奖励列表', perm: 'reward:list' }
|
|
|
},
|
|
},
|
|
|
// 成长规划师管理
|
|
// 成长规划师管理
|
|
|
{
|
|
{
|
|
|
path: 'guide-packages',
|
|
path: 'guide-packages',
|
|
|
name: 'GuidePackages',
|
|
name: 'GuidePackages',
|
|
|
component: () => import('@/views/GuidePackages.vue'),
|
|
component: () => import('@/views/GuidePackages.vue'),
|
|
|
- meta: { title: '成长规划师套餐', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '成长规划师套餐', requiresTeacher: true, perm: 'biz:packages' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'guide-family-task',
|
|
path: 'guide-family-task',
|
|
|
name: 'GuideFamilyTask',
|
|
name: 'GuideFamilyTask',
|
|
|
component: () => import('@/views/GuideFamilyTask.vue'),
|
|
component: () => import('@/views/GuideFamilyTask.vue'),
|
|
|
- meta: { title: '家庭任务管理', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '家庭任务管理', requiresTeacher: true, perm: 'service:families' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-consult',
|
|
path: 'teacher-consult',
|
|
|
name: 'TeacherConsult',
|
|
name: 'TeacherConsult',
|
|
|
component: () => import('@/views/TeacherConsult.vue'),
|
|
component: () => import('@/views/TeacherConsult.vue'),
|
|
|
- meta: { title: '家长咨询', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '家长咨询', requiresTeacher: true, perm: 'assessment:consult' }
|
|
|
},
|
|
},
|
|
|
// 新增成长规划师模块
|
|
// 新增成长规划师模块
|
|
|
{
|
|
{
|
|
|
path: 'teacher-dashboard',
|
|
path: 'teacher-dashboard',
|
|
|
name: 'TeacherDashboard',
|
|
name: 'TeacherDashboard',
|
|
|
component: () => import('@/views/teacher/TeacherDashboard.vue'),
|
|
component: () => import('@/views/teacher/TeacherDashboard.vue'),
|
|
|
- meta: { title: '成长规划师工作台', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '成长规划师工作台', requiresTeacher: true, perm: 'dashboard' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-families',
|
|
path: 'teacher-families',
|
|
|
name: 'TeacherFamilies',
|
|
name: 'TeacherFamilies',
|
|
|
component: () => import('@/views/teacher/TeacherFamilies.vue'),
|
|
component: () => import('@/views/teacher/TeacherFamilies.vue'),
|
|
|
- meta: { title: '我的家庭', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '我的家庭', requiresTeacher: true, perm: 'service:families' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-team',
|
|
path: 'teacher-team',
|
|
|
name: 'TeacherTeam',
|
|
name: 'TeacherTeam',
|
|
|
component: () => import('@/views/teacher/TeacherTeam.vue'),
|
|
component: () => import('@/views/teacher/TeacherTeam.vue'),
|
|
|
- meta: { title: '我的团队', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '我的团队', requiresTeacher: true, perm: 'service:team' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-packages',
|
|
path: 'teacher-packages',
|
|
|
name: 'TeacherPackages',
|
|
name: 'TeacherPackages',
|
|
|
component: () => import('@/views/teacher/TeacherPackages.vue'),
|
|
component: () => import('@/views/teacher/TeacherPackages.vue'),
|
|
|
- meta: { title: '套餐管理', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '套餐管理', requiresTeacher: true, perm: 'biz:packages' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-orders',
|
|
path: 'teacher-orders',
|
|
|
name: 'TeacherOrders',
|
|
name: 'TeacherOrders',
|
|
|
component: () => import('@/views/teacher/TeacherOrders.vue'),
|
|
component: () => import('@/views/teacher/TeacherOrders.vue'),
|
|
|
- meta: { title: '订单与佣金', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '订单与佣金', requiresTeacher: true, perm: 'biz:orders' }
|
|
|
},
|
|
},
|
|
|
// 系统管理
|
|
// 系统管理
|
|
|
{
|
|
{
|
|
|
path: 'users',
|
|
path: 'users',
|
|
|
name: 'Users',
|
|
name: 'Users',
|
|
|
component: () => import('@/views/Users.vue'),
|
|
component: () => import('@/views/Users.vue'),
|
|
|
- meta: { title: '用户管理' }
|
|
|
|
|
|
|
+ meta: { title: '用户管理', perm: 'system:users' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'package-audit',
|
|
path: 'package-audit',
|
|
|
name: 'PackageAudit',
|
|
name: 'PackageAudit',
|
|
|
component: () => import('@/views/PackageAudit.vue'),
|
|
component: () => import('@/views/PackageAudit.vue'),
|
|
|
- meta: { title: '套餐审核' }
|
|
|
|
|
|
|
+ meta: { title: '套餐审核', perm: 'system:audit' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'guide-audit',
|
|
path: 'guide-audit',
|
|
|
name: 'GuideAudit',
|
|
name: 'GuideAudit',
|
|
|
component: () => import('@/views/GuideAudit.vue'),
|
|
component: () => import('@/views/GuideAudit.vue'),
|
|
|
- meta: { title: '成长规划师审核' }
|
|
|
|
|
|
|
+ meta: { title: '成长规划师审核', perm: 'system:audit' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'operation-logs',
|
|
path: 'operation-logs',
|
|
|
name: 'OperationLogs',
|
|
name: 'OperationLogs',
|
|
|
component: () => import('@/views/OperationLogs.vue'),
|
|
component: () => import('@/views/OperationLogs.vue'),
|
|
|
- meta: { title: '操作日志' }
|
|
|
|
|
|
|
+ meta: { title: '操作日志', perm: 'system:logs' }
|
|
|
},
|
|
},
|
|
|
// 服务管理(管理员)
|
|
// 服务管理(管理员)
|
|
|
{
|
|
{
|
|
|
path: 'service-types',
|
|
path: 'service-types',
|
|
|
name: 'ServiceTypes',
|
|
name: 'ServiceTypes',
|
|
|
component: () => import('@/views/admin/ServiceTypes.vue'),
|
|
component: () => import('@/views/admin/ServiceTypes.vue'),
|
|
|
- meta: { title: '服务类型管理' }
|
|
|
|
|
|
|
+ meta: { title: '服务类型管理', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'service-contents',
|
|
path: 'service-contents',
|
|
|
name: 'ServiceContents',
|
|
name: 'ServiceContents',
|
|
|
component: () => import('@/views/admin/ServiceContents.vue'),
|
|
component: () => import('@/views/admin/ServiceContents.vue'),
|
|
|
- meta: { title: '服务内容管理' }
|
|
|
|
|
|
|
+ meta: { title: '服务内容管理', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'package-templates',
|
|
path: 'package-templates',
|
|
|
name: 'PackageTemplates',
|
|
name: 'PackageTemplates',
|
|
|
component: () => import('@/views/admin/PackageTemplates.vue'),
|
|
component: () => import('@/views/admin/PackageTemplates.vue'),
|
|
|
- meta: { title: '套餐模板管理' }
|
|
|
|
|
|
|
+ meta: { title: '套餐模板管理', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-messages',
|
|
path: 'teacher-messages',
|
|
|
name: 'TeacherMessages',
|
|
name: 'TeacherMessages',
|
|
|
component: () => import('@/views/teacher/TeacherMessages.vue'),
|
|
component: () => import('@/views/teacher/TeacherMessages.vue'),
|
|
|
- meta: { title: '消息中心', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: '消息中心', requiresTeacher: true, perm: 'messages' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'teacher-assessment',
|
|
path: 'teacher-assessment',
|
|
|
name: 'TeacherAssessment',
|
|
name: 'TeacherAssessment',
|
|
|
component: () => import('@/views/teacher/TeacherAssessment.vue'),
|
|
component: () => import('@/views/teacher/TeacherAssessment.vue'),
|
|
|
- meta: { title: 'DAN测评管理', requiresTeacher: true }
|
|
|
|
|
|
|
+ meta: { title: 'DAN测评管理', requiresTeacher: true, perm: 'assessment:dan' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'assessment-admin',
|
|
path: 'assessment-admin',
|
|
|
name: 'AssessmentAdmin',
|
|
name: 'AssessmentAdmin',
|
|
|
component: () => import('@/views/admin/Assessment.vue'),
|
|
component: () => import('@/views/admin/Assessment.vue'),
|
|
|
- meta: { title: '测评管理' }
|
|
|
|
|
|
|
+ meta: { title: '测评管理', perm: 'assessment:dan' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'vendor-review',
|
|
path: 'vendor-review',
|
|
|
name: 'VendorReview',
|
|
name: 'VendorReview',
|
|
|
component: () => import('@/views/admin/VendorReview.vue'),
|
|
component: () => import('@/views/admin/VendorReview.vue'),
|
|
|
- meta: { title: '服务商审核' }
|
|
|
|
|
|
|
+ meta: { title: '服务商审核', perm: 'system:audit' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'product-manage',
|
|
path: 'product-manage',
|
|
|
name: 'ProductManage',
|
|
name: 'ProductManage',
|
|
|
component: () => import('@/views/admin/ProductManage.vue'),
|
|
component: () => import('@/views/admin/ProductManage.vue'),
|
|
|
- meta: { title: '商品管理' }
|
|
|
|
|
|
|
+ meta: { title: '商品管理', perm: 'system:products' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'order-manage',
|
|
path: 'order-manage',
|
|
|
name: 'OrderManage',
|
|
name: 'OrderManage',
|
|
|
component: () => import('@/views/admin/OrderManage.vue'),
|
|
component: () => import('@/views/admin/OrderManage.vue'),
|
|
|
- meta: { title: '订单管理' }
|
|
|
|
|
|
|
+ meta: { title: '订单管理', perm: 'system:orders' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'sys-config',
|
|
path: 'sys-config',
|
|
|
name: 'SysConfig',
|
|
name: 'SysConfig',
|
|
|
component: () => import('@/views/admin/SysConfig.vue'),
|
|
component: () => import('@/views/admin/SysConfig.vue'),
|
|
|
- meta: { title: '系统配置' }
|
|
|
|
|
|
|
+ meta: { title: '系统配置', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'energy-sandbox',
|
|
path: 'energy-sandbox',
|
|
|
name: 'EnergySandbox',
|
|
name: 'EnergySandbox',
|
|
|
component: () => import('@/views/admin/EnergySandbox.vue'),
|
|
component: () => import('@/views/admin/EnergySandbox.vue'),
|
|
|
- meta: { title: '五维能量' }
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ meta: { title: '五维能量', perm: 'system:energy' }
|
|
|
|
|
+ },
|
|
|
// ========== 文章管理 ==========
|
|
// ========== 文章管理 ==========
|
|
|
{
|
|
{
|
|
|
path: 'article-categories',
|
|
path: 'article-categories',
|
|
|
name: 'ArticleCategory',
|
|
name: 'ArticleCategory',
|
|
|
component: () => import('@/views/admin/ArticleCategory.vue'),
|
|
component: () => import('@/views/admin/ArticleCategory.vue'),
|
|
|
- meta: { title: '文章分类' }
|
|
|
|
|
|
|
+ meta: { title: '文章分类', perm: 'articles:categories' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'article-manage',
|
|
path: 'article-manage',
|
|
|
name: 'ArticleManage',
|
|
name: 'ArticleManage',
|
|
|
component: () => import('@/views/admin/ArticleManage.vue'),
|
|
component: () => import('@/views/admin/ArticleManage.vue'),
|
|
|
- meta: { title: '文章管理' }
|
|
|
|
|
|
|
+ meta: { title: '文章管理', perm: 'articles:manage' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'article-edit',
|
|
path: 'article-edit',
|
|
|
name: 'ArticleEdit',
|
|
name: 'ArticleEdit',
|
|
|
component: () => import('@/views/admin/ArticleEdit.vue'),
|
|
component: () => import('@/views/admin/ArticleEdit.vue'),
|
|
|
- meta: { title: '文章编辑' }
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ meta: { title: '文章编辑', perm: 'articles:manage' }
|
|
|
|
|
+ },
|
|
|
// ========== 分佣裂变系统 ==========
|
|
// ========== 分佣裂变系统 ==========
|
|
|
{
|
|
{
|
|
|
path: 'product-profit-rate',
|
|
path: 'product-profit-rate',
|
|
|
name: 'ProductProfitRate',
|
|
name: 'ProductProfitRate',
|
|
|
component: () => import('@/views/admin/ProductProfitRate.vue'),
|
|
component: () => import('@/views/admin/ProductProfitRate.vue'),
|
|
|
- meta: { title: '产品利润率' }
|
|
|
|
|
|
|
+ meta: { title: '产品利润率', perm: 'system:products' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'withdraw-audit',
|
|
path: 'withdraw-audit',
|
|
|
name: 'WithdrawAudit',
|
|
name: 'WithdrawAudit',
|
|
|
component: () => import('@/views/admin/WithdrawAudit.vue'),
|
|
component: () => import('@/views/admin/WithdrawAudit.vue'),
|
|
|
- meta: { title: '提现审核' }
|
|
|
|
|
|
|
+ meta: { title: '提现审核', perm: 'system:audit' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'education-systems',
|
|
path: 'education-systems',
|
|
|
name: 'EducationSystems',
|
|
name: 'EducationSystems',
|
|
|
component: () => import('@/views/admin/EducationSystems.vue'),
|
|
component: () => import('@/views/admin/EducationSystems.vue'),
|
|
|
- meta: { title: '教育体系管理' }
|
|
|
|
|
|
|
+ meta: { title: '教育体系管理', perm: 'system:education' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'zodiac-configs',
|
|
path: 'zodiac-configs',
|
|
|
name: 'ZodiacConfigs',
|
|
name: 'ZodiacConfigs',
|
|
|
component: () => import('@/views/admin/ZodiacConfigs.vue'),
|
|
component: () => import('@/views/admin/ZodiacConfigs.vue'),
|
|
|
- meta: { title: '星座配置' }
|
|
|
|
|
|
|
+ meta: { title: '星座配置', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'bazi-configs',
|
|
path: 'bazi-configs',
|
|
|
name: 'BaziConfigs',
|
|
name: 'BaziConfigs',
|
|
|
component: () => import('@/views/admin/BaziConfigs.vue'),
|
|
component: () => import('@/views/admin/BaziConfigs.vue'),
|
|
|
- meta: { title: '八字配置' }
|
|
|
|
|
|
|
+ meta: { title: '八字配置', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'blood-type-configs',
|
|
path: 'blood-type-configs',
|
|
|
name: 'BloodTypeConfigs',
|
|
name: 'BloodTypeConfigs',
|
|
|
component: () => import('@/views/admin/BloodTypeConfigs.vue'),
|
|
component: () => import('@/views/admin/BloodTypeConfigs.vue'),
|
|
|
- meta: { title: '血型配置' }
|
|
|
|
|
|
|
+ meta: { title: '血型配置', perm: 'system:config' }
|
|
|
},
|
|
},
|
|
|
// ========== DanShop 电商管理 ==========
|
|
// ========== DanShop 电商管理 ==========
|
|
|
{
|
|
{
|
|
|
path: 'danshop-category',
|
|
path: 'danshop-category',
|
|
|
name: 'DanShopCategory',
|
|
name: 'DanShopCategory',
|
|
|
component: () => import('@/views/admin/DanShopCategoryManage'),
|
|
component: () => import('@/views/admin/DanShopCategoryManage'),
|
|
|
- meta: { title: '商品分类管理' }
|
|
|
|
|
|
|
+ meta: { title: '商品分类管理', perm: 'system:danshop' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'danshop-profit-rule',
|
|
path: 'danshop-profit-rule',
|
|
|
name: 'DanShopProfitRule',
|
|
name: 'DanShopProfitRule',
|
|
|
component: () => import('@/views/admin/DanShopProfitRuleConfig'),
|
|
component: () => import('@/views/admin/DanShopProfitRuleConfig'),
|
|
|
- meta: { title: '分润规则配置' }
|
|
|
|
|
|
|
+ meta: { title: '分润规则配置', perm: 'system:danshop' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'danshop-logistics',
|
|
path: 'danshop-logistics',
|
|
|
name: 'DanShopLogistics',
|
|
name: 'DanShopLogistics',
|
|
|
component: () => import('@/views/admin/DanShopLogisticsManage'),
|
|
component: () => import('@/views/admin/DanShopLogisticsManage'),
|
|
|
- meta: { title: '物流管理' }
|
|
|
|
|
|
|
+ meta: { title: '物流管理', perm: 'system:danshop' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'danshop-product',
|
|
path: 'danshop-product',
|
|
|
name: 'DanShopProduct',
|
|
name: 'DanShopProduct',
|
|
|
component: () => import('@/views/admin/ProductManage.vue'),
|
|
component: () => import('@/views/admin/ProductManage.vue'),
|
|
|
- meta: { title: 'DanShop商品' }
|
|
|
|
|
|
|
+ meta: { title: 'DanShop商品', perm: 'system:products' }
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
path: 'danshop-order',
|
|
path: 'danshop-order',
|
|
|
name: 'DanShopOrder',
|
|
name: 'DanShopOrder',
|
|
|
component: () => import('@/views/admin/OrderManage.vue'),
|
|
component: () => import('@/views/admin/OrderManage.vue'),
|
|
|
- meta: { title: 'DanShop订单' }
|
|
|
|
|
|
|
+ meta: { title: 'DanShop订单', perm: 'system:orders' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'my-families',
|
|
|
|
|
+ name: 'MyFamilies',
|
|
|
|
|
+ component: () => import('@/views/teacher/FamilyList.vue'),
|
|
|
|
|
+ meta: { title: '我的家庭', perm: 'service:family' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'growth-records',
|
|
|
|
|
+ name: 'GrowthRecords',
|
|
|
|
|
+ component: () => import('@/views/teacher/GrowthRecords.vue'),
|
|
|
|
|
+ meta: { title: '成长记录', perm: 'growth:records' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'growth-plans',
|
|
|
|
|
+ name: 'GrowthPlans',
|
|
|
|
|
+ component: () => import('@/views/teacher/GrowthPlans.vue'),
|
|
|
|
|
+ meta: { title: '成长计划', perm: 'growth:plans' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'health-reports',
|
|
|
|
|
+ name: 'HealthReports',
|
|
|
|
|
+ component: () => import('@/views/nutritionist/HealthReports.vue'),
|
|
|
|
|
+ meta: { title: '健康报告', perm: 'health:reports' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'health-indicators',
|
|
|
|
|
+ name: 'HealthIndicators',
|
|
|
|
|
+ component: () => import('@/views/nutritionist/HealthIndicators.vue'),
|
|
|
|
|
+ meta: { title: '健康指标', perm: 'health:indicators' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'health-checkins',
|
|
|
|
|
+ name: 'HealthCheckins',
|
|
|
|
|
+ component: () => import('@/views/nutritionist/HealthCheckins.vue'),
|
|
|
|
|
+ meta: { title: '健康打卡', perm: 'health:checkins' }
|
|
|
},
|
|
},
|
|
|
- // ========== 活动管理(活动管理员) ==========
|
|
|
|
|
{
|
|
{
|
|
|
path: 'activities',
|
|
path: 'activities',
|
|
|
name: 'Activities',
|
|
name: 'Activities',
|
|
|
component: () => import('@/views/admin/Activities.vue'),
|
|
component: () => import('@/views/admin/Activities.vue'),
|
|
|
|
|
+<<<<<<< Updated upstream
|
|
|
meta: { title: '活动管理' }
|
|
meta: { title: '活动管理' }
|
|
|
|
|
+=======
|
|
|
|
|
+ meta: { title: '活动列表', perm: 'activity:list' }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ path: 'activity-review',
|
|
|
|
|
+ name: 'ActivityReview',
|
|
|
|
|
+ component: () => import('@/views/admin/ActivityReview.vue'),
|
|
|
|
|
+ meta: { title: '活动审核', perm: 'activity:review' }
|
|
|
|
|
+>>>>>>> Stashed changes
|
|
|
}
|
|
}
|
|
|
]
|
|
]
|
|
|
}
|
|
}
|
|
@@ -359,7 +411,7 @@ router.beforeEach(async (to, from, next) => {
|
|
|
return next('/login')
|
|
return next('/login')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 4. 登录后首页重定向
|
|
|
|
|
|
|
+ // 4. 登录后首页重定向(多角色)
|
|
|
const roleHomeMap = {
|
|
const roleHomeMap = {
|
|
|
'teacher': '/teacher-dashboard',
|
|
'teacher': '/teacher-dashboard',
|
|
|
'nutritionist': '/dashboard',
|
|
'nutritionist': '/dashboard',
|
|
@@ -370,38 +422,17 @@ router.beforeEach(async (to, from, next) => {
|
|
|
return next({ path: roleHomeMap[role], replace: true })
|
|
return next({ path: roleHomeMap[role], replace: true })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 5. 角色专属路由定义
|
|
|
|
|
- const roleRoutes = {
|
|
|
|
|
- teacher: [
|
|
|
|
|
- 'TeacherDashboard', 'TeacherFamilies', 'TeacherTeam',
|
|
|
|
|
- 'TeacherPackages', 'TeacherOrders', 'TeacherMessages',
|
|
|
|
|
- 'TeacherAssessment', 'GuidePackages', 'GuideFamilyTask',
|
|
|
|
|
- 'TeacherConsult'
|
|
|
|
|
- ],
|
|
|
|
|
- nutritionist: [
|
|
|
|
|
- 'Dashboard', 'Tasks', 'TaskTemplates'
|
|
|
|
|
- ],
|
|
|
|
|
- activity_admin: [
|
|
|
|
|
- 'Dashboard', 'Activities'
|
|
|
|
|
- ],
|
|
|
|
|
- article_admin: [
|
|
|
|
|
- 'Dashboard', 'ArticleCategory', 'ArticleManage', 'ArticleEdit'
|
|
|
|
|
- ]
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 管理员可访问所有路由(无视角色限制)
|
|
|
|
|
- if (role === 'admin') {
|
|
|
|
|
- return next()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查当前路由是否在当前角色的允许列表中
|
|
|
|
|
- const allowedRoutes = roleRoutes[role] || []
|
|
|
|
|
- if (to.name && !allowedRoutes.includes(to.name)) {
|
|
|
|
|
- const fallbackPath = roleHomeMap[role] || '/dashboard'
|
|
|
|
|
- console.warn(`Access denied: Role "${role}" cannot access route "${to.name}"`)
|
|
|
|
|
- return next({ path: fallbackPath, query: { accessDenied: 'role-restricted' }, replace: true })
|
|
|
|
|
|
|
+ // 5. 权限检查:如果路由有 perm 要求,检查用户权限
|
|
|
|
|
+ const requiredPerm = to.meta && to.meta.perm
|
|
|
|
|
+ if (requiredPerm) {
|
|
|
|
|
+ const rolesStr = localStorage.getItem('roles')
|
|
|
|
|
+ const roles = rolesStr ? JSON.parse(rolesStr) : [localStorage.getItem('role')]
|
|
|
|
|
+ const perms = getEffectivePermissions(roles)
|
|
|
|
|
+ if (!hasPermission(perms, requiredPerm)) {
|
|
|
|
|
+ console.warn('Access denied: insufficient permissions for', to.name)
|
|
|
|
|
+ return next({ path: roleHomeMap[role] || '/dashboard', query: { accessDenied: 'no-permission' }, replace: true })
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
return next()
|
|
return next()
|
|
|
})
|
|
})
|
|
|
|
|
|