From 9fddb42ebe36bf48c9485e228b95c868a3fcd5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=A4=A9=E9=AA=84?= <5307576@qq.com> Date: Fri, 12 Jun 2026 17:01:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BE=E8=A1=A8=E7=BB=98=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/styles/main.scss | 138 +++++++++++++ src/mock/dashboard.ts | 310 ++++++++++++++++++++++++++++ src/router/index.ts | 3 + src/views/ContentDashboardView.vue | 199 ++++++++++++++++++ src/views/DashboardView.vue | 260 +++++++++++++++++------ src/views/HospitalDashboardView.vue | 211 +++++++++++++++++++ src/views/TeacherDashboardView.vue | 160 ++++++++++++++ 7 files changed, 1220 insertions(+), 61 deletions(-) create mode 100644 src/views/ContentDashboardView.vue create mode 100644 src/views/HospitalDashboardView.vue create mode 100644 src/views/TeacherDashboardView.vue diff --git a/src/assets/styles/main.scss b/src/assets/styles/main.scss index bd8e0267..3f7405a8 100644 --- a/src/assets/styles/main.scss +++ b/src/assets/styles/main.scss @@ -466,6 +466,10 @@ p { gap: 16px; } +.dashboard-kpis { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + .stat-card { display: flex; align-items: center; @@ -533,12 +537,37 @@ p { gap: 18px; } +.overview-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} + +.wide-chart { + grid-column: span 2; +} + +.tall-chart { + .chart-canvas { + height: 380px; + } +} + +.compact-kpis { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + .content-grid { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(360px, 0.55fr); gap: 18px; } +.hospital-rank-grid, +.content-warning-grid { + grid-template-columns: minmax(0, 1.25fr) minmax(360px, 0.75fr); +} + .chart-panel, .data-section { padding: 18px; @@ -581,6 +610,115 @@ p { height: 300px; } +.rank-list, +.quality-list { + display: grid; + gap: 12px; +} + +.rank-item { + display: grid; + grid-template-columns: 28px minmax(120px, 0.8fr) minmax(160px, 1fr) 58px; + align-items: center; + gap: 12px; + min-height: 36px; + + > span { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 8px; + color: #fff; + font-weight: 700; + background: var(--primary); + } + + strong { + min-width: 0; + overflow: hidden; + font-size: 14px; + text-overflow: ellipsis; + white-space: nowrap; + } + + em { + color: var(--green); + font-size: 12px; + font-style: normal; + text-align: right; + } +} + +.pass-rate-columns { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; + + h3 { + margin: 0 0 12px; + font-size: 15px; + } +} + +.pass-rate-item { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + min-height: 38px; + margin-bottom: 10px; + padding: 10px 12px; + border-radius: 8px; + background: var(--panel-soft); + + strong { + min-width: 0; + overflow: hidden; + font-size: 13px; + text-overflow: ellipsis; + white-space: nowrap; + } + + span { + color: var(--green); + font-weight: 700; + } + + &.danger span { + color: var(--danger); + } +} + +.quality-item { + display: grid; + gap: 8px; + padding: 12px; + border: 1px solid var(--border); + border-radius: 8px; + background: var(--panel-soft); + + strong, + span { + display: block; + } + + strong { + font-size: 14px; + } + + span { + margin-top: 4px; + color: var(--muted); + font-size: 12px; + } +} + +.compact-search { + width: 220px; +} + .page-toolbar { display: flex; align-items: center; diff --git a/src/mock/dashboard.ts b/src/mock/dashboard.ts index 7092645f..70099cef 100644 --- a/src/mock/dashboard.ts +++ b/src/mock/dashboard.ts @@ -41,3 +41,313 @@ export const activityTimeline = [ '方正中心医院导入 86 名学生账号', '内容团队发布卒中识别专题训练包' ] + +export const platformDashboard = { + kpis: [ + { label: '入驻医院/机构数', value: '86', change: '+5 本月', tone: 'blue' }, + { label: '月活跃机构数', value: '73', change: '84.9% 活跃', tone: 'green' }, + { label: '平台总用户数', value: '48,260', change: '+1,246', tone: 'purple' }, + { label: '月活跃用户数', value: '18,936', change: '+12.4%', tone: 'orange' }, + { label: '本月新增训练', value: '28,642', change: '+18.6% 环比', tone: 'blue' }, + { label: '累计训练次数', value: '426,180', change: '+42,908', tone: 'green' }, + { label: '训练完成率', value: '88.7%', change: '+2.3%', tone: 'purple' }, + { label: '平均训练得分', value: '83.6', change: '+1.8 分', tone: 'orange' } + ], + months: ['1月', '2月', '3月', '4月', '5月', '6月'], + trainingTrend: [18620, 21580, 24890, 26930, 30120, 34480], + activeUserTrend: [6420, 7310, 8160, 8940, 10320, 11860], + userComposition: [ + { name: '学生', value: 38260 }, + { name: '带教老师', value: 7240 }, + { name: '医院管理员', value: 2760 } + ], + hourlyTrainingAverage: { + hours: ['00', '03', '06', '09', '12', '15', '18', '21'], + values: [22, 18, 42, 186, 218, 246, 312, 204] + }, + institutionUserDistribution: [ + { name: '方正中心医院', users: 4260, activeUsers: 3120 }, + { name: '华东医学院', users: 3920, activeUsers: 2860 }, + { name: '首都医科附院', users: 3180, activeUsers: 2210 }, + { name: '南城社区医院', users: 1260, activeUsers: 760 }, + { name: '西湖教学医院', users: 1080, activeUsers: 690 } + ], + hospitalTrainingRanking: [ + { name: '方正中心医院', value: 6420 }, + { name: '华东医学院', value: 5880 }, + { name: '首都医科附院', value: 5240 }, + { name: '西湖教学医院', value: 4120 }, + { name: '南城社区医院', value: 3860 }, + { name: '浦江人民医院', value: 3420 }, + { name: '仁济临床学院', value: 3210 }, + { name: '东城中心医院', value: 2860 }, + { name: '松江教学医院', value: 2460 }, + { name: '宁海县医院', value: 2180 } + ], + hospitalScoreRanking: [ + { name: '华东医学院', value: 89.4 }, + { name: '方正中心医院', value: 88.1 }, + { name: '仁济临床学院', value: 86.7 }, + { name: '首都医科附院', value: 85.9 }, + { name: '西湖教学医院', value: 84.2 }, + { name: '南城社区医院', value: 82.7 } + ], + hospitalActivityRanking: [ + { name: '方正中心医院', value: 91, change: '+4.8%' }, + { name: '华东医学院', value: 87, change: '+3.5%' }, + { name: '首都医科附院', value: 84, change: '+2.6%' }, + { name: '西湖教学医院', value: 79, change: '+1.8%' }, + { name: '南城社区医院', value: 73, change: '+5.1%' } + ], + caseKpis: [ + { label: '累计病例总数', value: '1,286', change: '+38 本月', tone: 'green' }, + { label: '本月新增病例数', value: '96', change: '+21.5% 环比', tone: 'blue' } + ], + caseTypeDistribution: [ + { name: '脚本病例', value: 526 }, + { name: '教学病例', value: 418 }, + { name: '传统病例', value: 342 } + ], + caseTypeUsageRate: [ + { name: '脚本病例', value: 82 }, + { name: '教学病例', value: 76 }, + { name: '传统病例', value: 64 } + ], + caseTypeTrainingTrend: { + months: ['1月', '2月', '3月', '4月', '5月', '6月'], + script: [3100, 3480, 4020, 4360, 4880, 5420], + teaching: [2280, 2540, 2880, 3150, 3610, 4080], + traditional: [1620, 1860, 2040, 2290, 2480, 2760], + growth: [5.8, 8.1, 10.2, 7.6, 11.4, 12.8] + }, + topCaseUsage: [ + { name: '急性胸痛鉴别诊断', value: 1842 }, + { name: '卒中早期识别训练', value: 1626 }, + { name: '儿童发热问诊流程', value: 1520 }, + { name: '糖尿病慢病随访', value: 1416 }, + { name: '腹痛急诊处理', value: 1288 }, + { name: '慢阻肺急性加重', value: 1190 }, + { name: '产后出血识别', value: 1042 }, + { name: '肾绞痛处置', value: 968 }, + { name: '甲亢危象判断', value: 884 }, + { name: '儿童哮喘发作', value: 820 } + ], + lowCasePassRates: [ + { name: '产后出血识别', value: 58 }, + { name: '肾绞痛处置', value: 61 }, + { name: '甲亢危象判断', value: 63 }, + { name: '慢阻肺急性加重', value: 66 }, + { name: '复杂腹痛鉴别', value: 68 } + ], + opsTrend: { + days: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], + calls: [14200, 16800, 15900, 18200, 21400, 19600, 23100], + responseTime: [420, 398, 416, 384, 372, 390, 365] + } +} + +export const hospitalDashboard = { + profile: { + name: '方正中心医院', + level: '三甲综合医院', + cooperationDays: 428 + }, + kpis: [ + { label: '本院科室数', value: '18', change: '+2 较上月', tone: 'blue' }, + { label: '带教老师数', value: '86', change: '+6', tone: 'green' }, + { label: '本院学员数', value: '1,260', change: '+84', tone: 'purple' }, + { label: '训练完成率', value: '89.6%', change: '+3.2%', tone: 'orange' }, + { label: '平均训练得分', value: '84.8', change: '+1.6 分', tone: 'green' }, + { label: '累计病例总数', value: '526', change: '+21 本月', tone: 'blue' }, + { label: '当月新增病例', value: '42', change: '+16.7%', tone: 'purple' } + ], + months: ['1月', '2月', '3月', '4月', '5月', '6月'], + trainingCounts: [4260, 4820, 5160, 5880, 6420, 7240], + growthRates: [4.2, 6.6, 7.1, 13.9, 9.2, 12.8], + departmentCases: [ + { name: '心内科', value: 86 }, + { name: '儿科', value: 72 }, + { name: '神经内科', value: 64 }, + { name: '急诊科', value: 58 }, + { name: '内分泌科', value: 46 }, + { name: '呼吸科', value: 42 } + ], + departmentTraining: [ + { name: '心内科', total: 1260, effective: 1120 }, + { name: '儿科', total: 1080, effective: 940 }, + { name: '急诊科', total: 980, effective: 846 }, + { name: '神经内科', total: 920, effective: 790 }, + { name: '内分泌科', total: 760, effective: 690 } + ], + departmentActiveUsers: [ + { name: '心内科', value: 286 }, + { name: '儿科', value: 242 }, + { name: '急诊科', value: 218 }, + { name: '神经内科', value: 204 }, + { name: '呼吸科', value: 166 } + ], + departmentScores: [ + { name: '心内科', value: 88.4 }, + { name: '儿科', value: 86.2 }, + { name: '神经内科', value: 84.6 }, + { name: '急诊科', value: 82.9 }, + { name: '内分泌科', value: 81.8 } + ], + weeklyTrainingRanking: [ + { period: '06/01-06/07', name: '刘一鸣', department: '心内科', count: 34 }, + { period: '06/01-06/07', name: '赵晴', department: '儿科', count: 31 }, + { period: '06/01-06/07', name: '周子涵', department: '急诊科', count: 29 }, + { period: '06/01-06/07', name: '陈思远', department: '神经内科', count: 27 }, + { period: '06/01-06/07', name: '王悦', department: '内分泌科', count: 24 } + ], + studentScoreRanking: [ + { name: '赵晴', value: 94.2 }, + { name: '刘一鸣', value: 92.8 }, + { name: '陈思远', value: 91.1 }, + { name: '周子涵', value: 89.6 }, + { name: '王悦', value: 87.4 } + ], + caseUsageTop: [ + { name: '急性胸痛鉴别诊断', value: 842 }, + { name: '儿童发热问诊流程', value: 720 }, + { name: '卒中早期识别训练', value: 686 }, + { name: '糖尿病慢病随访', value: 602 }, + { name: '腹痛急诊处理', value: 548 }, + { name: '慢阻肺急性加重', value: 502 }, + { name: '产后出血识别', value: 466 }, + { name: '肾绞痛处置', value: 420 }, + { name: '甲亢危象判断', value: 386 }, + { name: '儿童哮喘发作', value: 342 } + ], + passRateBest: [ + { name: '儿童发热问诊流程', rate: 94 }, + { name: '糖尿病慢病随访', rate: 92 }, + { name: '急性胸痛鉴别诊断', rate: 89 }, + { name: '卒中早期识别训练', rate: 87 }, + { name: '儿童哮喘发作', rate: 86 } + ], + passRateWorst: [ + { name: '产后出血识别', rate: 58 }, + { name: '甲亢危象判断', rate: 62 }, + { name: '复杂腹痛鉴别', rate: 65 }, + { name: '肾绞痛处置', rate: 67 }, + { name: '慢阻肺急性加重', rate: 69 } + ], + abilityCompare: [ + { name: '问诊', hospital: 86, platform: 82 }, + { name: '诊断', hospital: 84, platform: 80 }, + { name: '治疗', hospital: 81, platform: 78 }, + { name: '沟通', hospital: 88, platform: 83 }, + { name: '检查', hospital: 83, platform: 79 } + ], + scoreGauge: { + hospital: 84.8, + platform: 82.1 + } +} + +export const contentDashboard = { + kpis: [ + { label: '病例总数', value: '526', change: '+21 本月', tone: 'green' }, + { label: '知识文档数', value: '1,842', change: '+86', tone: 'blue' }, + { label: '待发布病例数', value: '38', change: '12 待审核', tone: 'orange' }, + { label: '本月新增病例', value: '42', change: '+16.7%', tone: 'purple' }, + { label: '病例使用率', value: '76.4%', change: '+5.2%', tone: 'green' }, + { label: '累计训练总次数', value: '68,420', change: '+9.8%', tone: 'blue' } + ], + caseTypeDistribution: [ + { name: '传统病例', value: 166 }, + { name: '教学病例', value: 214 }, + { name: '脚本病例', value: 146 } + ], + caseTypeTraining: [ + { name: '传统病例', value: 9820 }, + { name: '教学病例', value: 18260 }, + { name: '脚本病例', value: 14280 } + ], + departmentCases: [ + { name: '心内科', value: 86 }, + { name: '儿科', value: 72 }, + { name: '神经内科', value: 64 }, + { name: '急诊科', value: 58 }, + { name: '内分泌科', value: 46 }, + { name: '呼吸科', value: 42 } + ], + departmentUsage: [ + { name: '心内科', usedCases: 72, trainingTimes: 12600 }, + { name: '儿科', usedCases: 58, trainingTimes: 10820 }, + { name: '神经内科', usedCases: 52, trainingTimes: 9360 }, + { name: '急诊科', usedCases: 46, trainingTimes: 8680 }, + { name: '内分泌科', usedCases: 36, trainingTimes: 6420 } + ], + difficultyUsage: [ + { name: '初级', cases: 182, usedCases: 148, trainingTimes: 18620 }, + { name: '中级', cases: 238, usedCases: 176, trainingTimes: 28480 }, + { name: '高级', cases: 106, usedCases: 78, trainingTimes: 21320 } + ], + lowPassWarnings: [ + { name: '产后出血识别', department: '妇产科', type: '脚本病例', rate: 58, trainings: 466 }, + { name: '甲亢危象判断', department: '内分泌科', type: '教学病例', rate: 62, trainings: 386 }, + { name: '复杂腹痛鉴别', department: '急诊科', type: '传统病例', rate: 65, trainings: 328 }, + { name: '肾绞痛处置', department: '泌尿外科', type: '脚本病例', rate: 67, trainings: 420 }, + { name: '慢阻肺急性加重', department: '呼吸科', type: '教学病例', rate: 69, trainings: 502 } + ], + hotCases: [ + { name: '急性胸痛鉴别诊断', value: 842 }, + { name: '儿童发热问诊流程', value: 720 }, + { name: '卒中早期识别训练', value: 686 }, + { name: '糖尿病慢病随访', value: 602 }, + { name: '腹痛急诊处理', value: 548 } + ], + caseManagementRows: [ + { name: '急性胸痛鉴别诊断', department: '心内科', author: '王内容', difficulty: '高', type: '脚本病例', scoring: '已上传', project: '检查+检验', status: '启用', audit: '已通过' }, + { name: '儿童发热问诊流程', department: '儿科', author: '李编辑', difficulty: '中', type: '教学病例', scoring: '已上传', project: '检验', status: '启用', audit: '待审核' }, + { name: '产后出血识别', department: '妇产科', author: '王内容', difficulty: '高', type: '脚本病例', scoring: '待完善', project: '检查', status: '启用', audit: '需优化' }, + { name: '糖尿病慢病随访', department: '内分泌科', author: '赵编辑', difficulty: '低', type: '传统病例', scoring: '已上传', project: '检验', status: '启用', audit: '已通过' }, + { name: '肾绞痛处置', department: '泌尿外科', author: '李编辑', difficulty: '中', type: '脚本病例', scoring: '已上传', project: '检查', status: '禁用', audit: '复核中' } + ] +} + +export const teacherDashboard = { + kpis: [ + { label: '我的学生数', value: '46', change: '+4 本月', tone: 'blue' }, + { label: '学生整体平均分', value: '84.2', change: '医院 82.8', tone: 'green' }, + { label: '进行中任务数', value: '6', change: '2 个今日截止', tone: 'orange' }, + { label: '任务完成率', value: '78.5%', change: '+6.1%', tone: 'purple' } + ], + students: [ + { id: 'S-10021', name: '刘一鸣', department: '心内科', trainings: 156, completion: '92%', avgScore: 92.8, weakDimension: '治疗', favoriteType: '脚本病例', lastTraining: '2026-06-11 19:24', pendingTasks: 1 }, + { id: 'S-10032', name: '赵晴', department: '儿科', trainings: 142, completion: '88%', avgScore: 94.2, weakDimension: '检查', favoriteType: '教学病例', lastTraining: '2026-06-12 08:16', pendingTasks: 0 }, + { id: 'S-10048', name: '陈思远', department: '神经内科', trainings: 128, completion: '84%', avgScore: 91.1, weakDimension: '沟通', favoriteType: '脚本病例', lastTraining: '2026-06-10 21:03', pendingTasks: 2 }, + { id: 'S-10053', name: '周子涵', department: '急诊科', trainings: 121, completion: '81%', avgScore: 89.6, weakDimension: '诊断', favoriteType: '传统病例', lastTraining: '2026-06-11 14:42', pendingTasks: 2 }, + { id: 'S-10067', name: '王悦', department: '内分泌科', trainings: 108, completion: '76%', avgScore: 87.4, weakDimension: '问诊', favoriteType: '教学病例', lastTraining: '2026-06-09 18:30', pendingTasks: 3 } + ], + weakRadar: [ + { name: '问诊', value: 82 }, + { name: '诊断', value: 78 }, + { name: '治疗', value: 74 }, + { name: '沟通', value: 86 }, + { name: '检查', value: 76 } + ], + months: ['1月', '2月', '3月', '4月', '5月', '6月'], + trainingTrend: [620, 760, 840, 920, 1080, 1260], + taskCompletion: [ + { name: '胸痛鉴别', done: 38, undone: 8 }, + { name: '发热问诊', done: 34, undone: 12 }, + { name: '卒中识别', done: 29, undone: 17 }, + { name: '慢病随访', done: 41, undone: 5 } + ], + scoreDistribution: [ + { name: '90分以上', value: 18 }, + { name: '80-89分', value: 21 }, + { name: '70-79分', value: 9 }, + { name: '60-69分', value: 4 }, + { name: '60分以下', value: 2 } + ], + taskRows: [ + { id: 'T-202606-001', name: '急性胸痛鉴别诊断', type: '临床思维模拟练习', expected: 46, finished: 38, startedAt: '2026-06-03', deadline: '2026-06-12', avgScore: 86.4, highestScore: 98 }, + { id: 'T-202606-002', name: '儿童发热问诊流程', type: '客观题训练', expected: 46, finished: 34, startedAt: '2026-06-05', deadline: '2026-06-14', avgScore: 88.1, highestScore: 96 }, + { id: 'T-202606-003', name: '卒中早期识别训练', type: '临床思维模拟练习', expected: 46, finished: 29, startedAt: '2026-06-07', deadline: '2026-06-16', avgScore: 82.8, highestScore: 94 }, + { id: 'T-202606-004', name: '糖尿病慢病随访', type: '客观题训练', expected: 46, finished: 41, startedAt: '2026-06-09', deadline: '2026-06-18', avgScore: 90.2, highestScore: 99 } + ] +} diff --git a/src/router/index.ts b/src/router/index.ts index c90a3e4e..f616ee29 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -25,6 +25,9 @@ const routes: RouteRecordRaw[] = [ { path: 'my-students', name: 'MyStudents', component: () => import('@/views/MyStudentsView.vue'), meta: { title: '我的学生' } }, { path: 'teacher-student-relations', name: 'TeacherStudentRelations', component: () => import('@/views/TeacherStudentRelationsView.vue'), meta: { title: '师生关系管理' } }, { path: 'settings', name: 'Settings', component: () => import('@/views/SettingsView.vue'), meta: { title: '系统配置' } }, + { path: 'module/hospital-dashboard', name: 'HospitalDashboard', component: () => import('@/views/HospitalDashboardView.vue'), meta: { title: '医院驾驶舱' } }, + { path: 'module/content-dashboard', name: 'ContentDashboard', component: () => import('@/views/ContentDashboardView.vue'), meta: { title: '内容概览' } }, + { path: 'module/teacher-dashboard', name: 'TeacherDashboard', component: () => import('@/views/TeacherDashboardView.vue'), meta: { title: '教学概览' } }, { path: 'module/content-admin-list', redirect: '/users/content-admins' }, { path: 'module/department-list', redirect: '/departments' }, { path: 'module/doctor-list', redirect: '/users/doctors' }, diff --git a/src/views/ContentDashboardView.vue b/src/views/ContentDashboardView.vue new file mode 100644 index 00000000..71cff3c3 --- /dev/null +++ b/src/views/ContentDashboardView.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue index 48e9b674..d5408f6f 100644 --- a/src/views/DashboardView.vue +++ b/src/views/DashboardView.vue @@ -1,19 +1,19 @@ diff --git a/src/views/HospitalDashboardView.vue b/src/views/HospitalDashboardView.vue new file mode 100644 index 00000000..80b03317 --- /dev/null +++ b/src/views/HospitalDashboardView.vue @@ -0,0 +1,211 @@ + + + diff --git a/src/views/TeacherDashboardView.vue b/src/views/TeacherDashboardView.vue new file mode 100644 index 00000000..28c60343 --- /dev/null +++ b/src/views/TeacherDashboardView.vue @@ -0,0 +1,160 @@ + + +