1. 侧边栏:根据角色过滤菜单,无可访问子菜单时隐藏父菜单 2. Dashboard:智能工牌分析、统计卡片、最近考试仅对学员显示 3. 快捷操作:根据角色显示不同的操作入口 4. 欢迎语:根据角色显示不同的欢迎信息 5. 学习天数:改为基于注册日期计算(至少为1天) 6. 成长路径:AI分析按钮仅对学员显示 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -379,6 +379,8 @@ const menuConfig = [
|
||||
|
||||
// 获取菜单路由
|
||||
const menuRoutes = computed(() => {
|
||||
const userRole = authManager.getUserRole()
|
||||
|
||||
// 仅保留当前用户可访问的菜单项和启用的功能
|
||||
const filterChildren = (children: any[] = []) =>
|
||||
children.filter((child: any) => {
|
||||
@@ -389,7 +391,22 @@ const menuRoutes = computed(() => {
|
||||
return true
|
||||
})
|
||||
|
||||
// 根据角色预过滤顶级菜单
|
||||
const roleMenuFilter = (route: any): boolean => {
|
||||
// 管理者中心:仅 admin 和 manager 可见
|
||||
if (route.path === '/manager') {
|
||||
return userRole === 'admin' || userRole === 'manager'
|
||||
}
|
||||
// 系统管理:仅 admin 可见
|
||||
if (route.path === '/admin') {
|
||||
return userRole === 'admin'
|
||||
}
|
||||
// 数据分析:所有登录用户可见(但子菜单会进一步过滤)
|
||||
return true
|
||||
}
|
||||
|
||||
return menuConfig
|
||||
.filter(roleMenuFilter) // 先按角色过滤顶级菜单
|
||||
.map((route: any) => {
|
||||
const next = { ...route }
|
||||
if (route.children && route.children.length > 0) {
|
||||
@@ -398,8 +415,10 @@ const menuRoutes = computed(() => {
|
||||
return next
|
||||
})
|
||||
.filter((route: any) => {
|
||||
// 有子菜单且至少一个可访问
|
||||
if (route.children && route.children.length > 0) return true
|
||||
// 有子菜单的必须至少有一个可访问的子项
|
||||
if (route.children !== undefined) {
|
||||
return route.children.length > 0
|
||||
}
|
||||
// 无子菜单时检查自身路径
|
||||
return authManager.canAccessRoute(route.path)
|
||||
})
|
||||
|
||||
@@ -4,7 +4,15 @@
|
||||
<div class="welcome-card card">
|
||||
<div class="welcome-content">
|
||||
<h1 class="welcome-title">欢迎回来,{{ userName }}!</h1>
|
||||
<p class="welcome-desc">今天是您学习的第 <span class="highlight">{{ learningDays }}</span> 天,继续加油!</p>
|
||||
<p class="welcome-desc" v-if="userRole === 'trainee'">
|
||||
今天是您学习的第 <span class="highlight">{{ learningDays }}</span> 天,继续加油!
|
||||
</p>
|
||||
<p class="welcome-desc" v-else-if="userRole === 'manager'">
|
||||
管理您的团队,助力成员成长
|
||||
</p>
|
||||
<p class="welcome-desc" v-else>
|
||||
系统运行正常,一切尽在掌控
|
||||
</p>
|
||||
</div>
|
||||
<div class="welcome-image">
|
||||
<el-icon :size="120" color="#667eea">
|
||||
@@ -13,8 +21,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计卡片 -->
|
||||
<div class="stats-grid">
|
||||
<!-- 统计卡片 - 仅学员显示 -->
|
||||
<div class="stats-grid" v-if="userRole === 'trainee'">
|
||||
<div class="stat-card card" v-for="stat in stats" :key="stat.title">
|
||||
<div class="stat-icon" :style="{ backgroundColor: stat.bgColor }">
|
||||
<el-icon :size="24" :color="stat.color">
|
||||
@@ -24,7 +32,7 @@
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ stat.value }}</div>
|
||||
<div class="stat-title">{{ stat.title }}</div>
|
||||
<div class="stat-trend" :class="stat.trend > 0 ? 'up' : 'down'">
|
||||
<div class="stat-trend" :class="stat.trend > 0 ? 'up' : 'down'" v-if="stat.trend !== 0">
|
||||
<el-icon :size="12">
|
||||
<component :is="stat.trend > 0 ? 'Top' : 'Bottom'" />
|
||||
</el-icon>
|
||||
@@ -48,8 +56,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 最近考试 -->
|
||||
<div class="recent-exams">
|
||||
<!-- 最近考试 - 仅学员显示 -->
|
||||
<div class="recent-exams" v-if="userRole === 'trainee'">
|
||||
<h2 class="section-title">最近考试</h2>
|
||||
<div v-if="recentExams.length > 0" class="exam-list">
|
||||
<div class="exam-item card" v-for="exam in recentExams" :key="exam.id">
|
||||
@@ -99,6 +107,7 @@ const router = useRouter()
|
||||
// 获取当前用户信息
|
||||
const currentUser = computed(() => authManager.getCurrentUser())
|
||||
const userName = computed(() => currentUser.value?.full_name || currentUser.value?.username || '用户')
|
||||
const userRole = computed(() => authManager.getUserRole())
|
||||
const learningDays = ref(0)
|
||||
|
||||
// 统计数据
|
||||
@@ -156,37 +165,64 @@ const loadStatistics = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 快捷操作
|
||||
const quickActions = ref([
|
||||
// 快捷操作配置(包含角色限制)
|
||||
const allQuickActions = [
|
||||
{
|
||||
title: '智能工牌分析',
|
||||
desc: 'AI能力评估与成长路径规划',
|
||||
icon: 'TrendCharts',
|
||||
color: '#e6a23c',
|
||||
path: '/trainee/growth-path'
|
||||
path: '/trainee/growth-path',
|
||||
roles: ['trainee'] // 仅学员可见
|
||||
},
|
||||
{
|
||||
title: '课程中心',
|
||||
desc: '查看可用课程',
|
||||
icon: 'Collection',
|
||||
color: '#67c23a',
|
||||
path: '/trainee/course-center'
|
||||
path: '/trainee/course-center',
|
||||
roles: ['trainee', 'manager', 'admin'] // 所有角色可见
|
||||
},
|
||||
{
|
||||
title: '查分中心',
|
||||
desc: '查看成绩和分析报告',
|
||||
icon: 'DataAnalysis',
|
||||
color: '#409eff',
|
||||
path: '/trainee/score-report'
|
||||
path: '/trainee/score-report',
|
||||
roles: ['trainee'] // 仅学员可见
|
||||
},
|
||||
{
|
||||
title: 'AI陪练',
|
||||
desc: '智能陪练系统',
|
||||
icon: 'ChatLineRound',
|
||||
color: '#f56c6c',
|
||||
path: '/trainee/ai-practice-center'
|
||||
path: '/trainee/ai-practice-center',
|
||||
roles: ['trainee', 'manager', 'admin'] // 所有角色可见
|
||||
},
|
||||
{
|
||||
title: '团队看板',
|
||||
desc: '查看团队学习情况',
|
||||
icon: 'DataBoard',
|
||||
color: '#667eea',
|
||||
path: '/manager/team-dashboard',
|
||||
roles: ['manager', 'admin'] // 管理者和管理员可见
|
||||
},
|
||||
{
|
||||
title: '课程管理',
|
||||
desc: '管理培训课程内容',
|
||||
icon: 'Notebook',
|
||||
color: '#909399',
|
||||
path: '/manager/course-management',
|
||||
roles: ['manager', 'admin'] // 管理者和管理员可见
|
||||
}
|
||||
])
|
||||
]
|
||||
|
||||
// 根据角色过滤快捷操作
|
||||
const quickActions = computed(() => {
|
||||
const role = userRole.value
|
||||
if (!role) return []
|
||||
return allQuickActions.filter(action => action.roles.includes(role))
|
||||
})
|
||||
|
||||
// 最近考试
|
||||
const recentExams = ref<any[]>([])
|
||||
|
||||
@@ -31,7 +31,14 @@
|
||||
<div class="ability-radar card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">能力评估</h3>
|
||||
<el-button type="primary" size="small" @click="analyzeSmartBadgeData" :loading="analyzing">
|
||||
<!-- AI智能工牌分析仅对学员开放 -->
|
||||
<el-button
|
||||
v-if="userInfo.role === 'trainee'"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="analyzeSmartBadgeData"
|
||||
:loading="analyzing"
|
||||
>
|
||||
<el-icon><TrendCharts /></el-icon>
|
||||
AI 分析智能工牌数据
|
||||
</el-button>
|
||||
@@ -302,7 +309,7 @@
|
||||
<p class="empty-description">
|
||||
{{ analyzing ? '正在分析您的智能工牌数据,为您推荐最适合的课程' : '暂无智能工牌数据,请先使用智能工牌记录对话' }}
|
||||
</p>
|
||||
<el-button v-if="!analyzing" type="primary" @click="analyzeSmartBadgeData">
|
||||
<el-button v-if="!analyzing && userInfo.role === 'trainee'" type="primary" @click="analyzeSmartBadgeData">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
重新分析
|
||||
</el-button>
|
||||
|
||||
Reference in New Issue
Block a user