feat: 图表绘制
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="dashboard-page page-stack">
|
||||
<section class="hero-strip dashboard-hero">
|
||||
<div>
|
||||
<span class="eyebrow">教学数据中心</span>
|
||||
<h1>带教医生教学概览</h1>
|
||||
<p>实时查看所带学生训练画像、任务完成、分数分布和已下发任务情况。</p>
|
||||
</div>
|
||||
<div class="hero-actions">
|
||||
<el-button :icon="Download">导出教学报告</el-button>
|
||||
<el-button :icon="Plus" type="primary">新建任务</el-button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="stats-grid">
|
||||
<article v-for="item in teacherDashboard.kpis" :key="item.label" class="stat-card">
|
||||
<div :class="['stat-mark', item.tone]">{{ item.label.slice(0, 1) }}</div>
|
||||
<div>
|
||||
<span>{{ item.label }}</span>
|
||||
<strong>{{ item.value }}</strong>
|
||||
<em>{{ item.change }}</em>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="data-section">
|
||||
<div class="section-header">
|
||||
<div>
|
||||
<h2>我的学生列表</h2>
|
||||
<p>可替换为学生训练情况表、学习画像表和师生关系表聚合数据</p>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-input class="compact-search" :prefix-icon="Search" placeholder="搜索学生" />
|
||||
<el-button :icon="Search">筛选</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="teacherDashboard.students" row-key="id">
|
||||
<el-table-column prop="id" label="学生ID" width="110" />
|
||||
<el-table-column prop="name" label="姓名" width="100" />
|
||||
<el-table-column prop="department" label="科室" width="110" />
|
||||
<el-table-column prop="trainings" label="累计训练" width="100" />
|
||||
<el-table-column prop="completion" label="完成率" width="90" />
|
||||
<el-table-column prop="avgScore" label="平均分" width="90" />
|
||||
<el-table-column prop="weakDimension" label="薄弱维度" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="warning">{{ row.weakDimension }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="favoriteType" label="最常训练类型" width="130" />
|
||||
<el-table-column prop="lastTraining" label="最近一次训练时间" min-width="160" />
|
||||
<el-table-column prop="pendingTasks" label="待完成任务" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.pendingTasks > 0 ? 'danger' : 'success'">{{ row.pendingTasks }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
<section class="overview-grid">
|
||||
<ChartPanel title="整体薄弱维度" subtitle="问诊、诊断、治疗、沟通、检查平均得分率" :option="weakRadarOption" />
|
||||
<ChartPanel class="wide-chart" title="整体训练次数趋势" subtitle="近6个月所带学生训练总次数" :option="trainingTrendOption" />
|
||||
<ChartPanel class="wide-chart" title="任务完成情况" subtitle="一周内下发任务的已完成与未完成人数" :option="taskCompletionOption" />
|
||||
<ChartPanel title="当前任务得分分布" subtitle="已完成学生的分数分布" :option="scoreDistributionOption" />
|
||||
</section>
|
||||
|
||||
<section class="data-section">
|
||||
<div class="section-header">
|
||||
<div>
|
||||
<h2>任务列表</h2>
|
||||
<p>展示已下发任务情况,后续可接老师创建任务后的统计接口</p>
|
||||
</div>
|
||||
<el-button :icon="Plus" type="primary">新建任务</el-button>
|
||||
</div>
|
||||
<el-table :data="teacherDashboard.taskRows" row-key="id">
|
||||
<el-table-column prop="id" label="任务ID" width="130" />
|
||||
<el-table-column prop="name" label="任务名称" min-width="180" />
|
||||
<el-table-column prop="type" label="类型" min-width="150" />
|
||||
<el-table-column prop="expected" label="应完成人数" width="110" />
|
||||
<el-table-column prop="finished" label="实际完成" width="100" />
|
||||
<el-table-column prop="startedAt" label="开始时间" width="120" />
|
||||
<el-table-column prop="deadline" label="截止时间" width="120" />
|
||||
<el-table-column prop="avgScore" label="平均分" width="90" />
|
||||
<el-table-column prop="highestScore" label="最高成绩" width="100" />
|
||||
<el-table-column label="操作" width="160" fixed="right">
|
||||
<template #default>
|
||||
<el-button link type="primary">修改</el-button>
|
||||
<el-button link type="primary">详情</el-button>
|
||||
<el-button link type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { EChartsOption } from 'echarts'
|
||||
import { Download, Plus, Search } from '@element-plus/icons-vue'
|
||||
import ChartPanel from '@/components/ChartPanel.vue'
|
||||
import { teacherDashboard } from '@/mock/dashboard'
|
||||
|
||||
const axisLine = { lineStyle: { color: '#dce3eb' } }
|
||||
const splitLine = { lineStyle: { color: '#eef2f7' } }
|
||||
|
||||
const weakRadarOption = computed<EChartsOption>(() => ({
|
||||
color: ['#dc2626'],
|
||||
radar: {
|
||||
radius: 94,
|
||||
indicator: teacherDashboard.weakRadar.map(item => ({ name: item.name, max: 100 }))
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'radar',
|
||||
areaStyle: { color: 'rgba(220, 38, 38, 0.12)' },
|
||||
data: [{ value: teacherDashboard.weakRadar.map(item => item.value), name: '平均得分率' }]
|
||||
}
|
||||
]
|
||||
}))
|
||||
|
||||
const trainingTrendOption = computed<EChartsOption>(() => ({
|
||||
color: ['#2563eb'],
|
||||
tooltip: { trigger: 'axis' },
|
||||
grid: { left: 42, right: 20, top: 28, bottom: 32 },
|
||||
xAxis: { type: 'category', data: teacherDashboard.months, axisLine },
|
||||
yAxis: { type: 'value', splitLine },
|
||||
series: [
|
||||
{ name: '训练次数', type: 'line', smooth: true, areaStyle: { color: 'rgba(37, 99, 235, 0.12)' }, data: teacherDashboard.trainingTrend }
|
||||
]
|
||||
}))
|
||||
|
||||
const taskCompletionOption = computed<EChartsOption>(() => ({
|
||||
color: ['#0f766e', '#f59e0b'],
|
||||
tooltip: { trigger: 'axis' },
|
||||
legend: { top: 0 },
|
||||
grid: { left: 42, right: 20, top: 42, bottom: 40 },
|
||||
xAxis: { type: 'category', data: teacherDashboard.taskCompletion.map(item => item.name), axisLine },
|
||||
yAxis: { type: 'value', splitLine },
|
||||
series: [
|
||||
{ name: '已完成', type: 'bar', barWidth: 20, data: teacherDashboard.taskCompletion.map(item => item.done), itemStyle: { borderRadius: [5, 5, 0, 0] } },
|
||||
{ name: '未完成', type: 'bar', barWidth: 20, data: teacherDashboard.taskCompletion.map(item => item.undone), itemStyle: { borderRadius: [5, 5, 0, 0] } }
|
||||
]
|
||||
}))
|
||||
|
||||
const scoreDistributionOption = computed<EChartsOption>(() => ({
|
||||
color: ['#16a34a', '#2563eb', '#f59e0b', '#7c3aed', '#dc2626'],
|
||||
tooltip: { trigger: 'item' },
|
||||
legend: { bottom: 0 },
|
||||
series: [
|
||||
{
|
||||
name: '得分分布',
|
||||
type: 'pie',
|
||||
radius: ['42%', '70%'],
|
||||
center: ['50%', '45%'],
|
||||
data: teacherDashboard.scoreDistribution,
|
||||
label: { formatter: '{b}\n{d}%' }
|
||||
}
|
||||
]
|
||||
}))
|
||||
</script>
|
||||
Reference in New Issue
Block a user