提交 fd7bc1bd authored 作者: 王鹏飞's avatar 王鹏飞

feat: 对接数据可视化接口

上级 840c9345
import httpRequest from '@/utils/axios'
export function getResourceChart(params?: Record<string, any>) {
return httpRequest.get('/api/resource/v1/teaching/chart/resource', { params })
}
export function getLearningChart(params?: Record<string, any>) {
return httpRequest.get('/api/resource/v1/teaching/chart/learning', { params })
}
export function getTeachingChart(params?: Record<string, any>) {
return httpRequest.get('/api/resource/v1/teaching/chart/teaching', { params })
}
export function getOriginChart(params?: Record<string, any>) {
return httpRequest.get('/api/resource/v1/teaching/chart/origin', { params })
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { VideoCamera, Suitcase, FolderOpened, Files, Monitor } from '@element-plus/icons-vue' import { VideoCamera, Suitcase, FolderOpened, Files, Monitor } from '@element-plus/icons-vue'
import { getResourceChart } from '../api'
// 统计数据 // 统计数据
const statsData = ref({ const statsData = ref({
...@@ -43,68 +44,14 @@ let electiveTypeChart = null ...@@ -43,68 +44,14 @@ let electiveTypeChart = null
let courseTrendChart = null let courseTrendChart = null
let videoUploadTrendChart = null let videoUploadTrendChart = null
// 模拟数据加载 const loadData = async () => {
const loadData = () => { const { data } = await getResourceChart()
// 基础统计数据 statsData.value = { ...statsData.value, ...(data.stats || {}) }
statsData.value = { resourceTypeData.value = data.resourceTypeData || []
videoCount: 1250, courseTypeData.value = data.courseTypeData || []
coursewareCount: 890, electiveTypeData.value = data.electiveTypeData || []
lessonPlanCount: 650, courseTrendData.value = data.courseTrendData || { dates: [], values: [] }
otherResourceCount: 320, videoUploadTrendData.value = data.videoUploadTrendData || { dates: [], values: [] }
courseCount: 180,
todayNewVideo: 15,
todayNewCourseware: 8,
todayNewLessonPlan: 12,
todayNewOtherResource: 5,
todayNewCourse: 3,
}
// 资源类型占比数据
resourceTypeData.value = [
{ name: '视频资源', value: 1250 },
{ name: '课件资源', value: 890 },
{ name: '教案资源', value: 650 },
{ name: '其他资源', value: 320 },
]
// 课程类型占比数据
courseTypeData.value = [
{ name: '必修课', value: 120 },
{ name: '选修课', value: 45 },
{ name: '实践课', value: 10 },
{ name: '理论课', value: 5 },
]
// 选课类型占比数据
electiveTypeData.value = [
{ name: '公共选修', value: 25 },
{ name: '专业选修', value: 15 },
{ name: '通识选修', value: 5 },
]
// 生成最近30天的走势数据
const dates = []
const courseValues = []
const videoValues = []
const today = new Date()
for (let i = 29; i >= 0; i--) {
const date = new Date(today)
date.setDate(date.getDate() - i)
dates.push(date.toISOString().split('T')[0])
courseValues.push(Math.floor(Math.random() * 10) + 1)
videoValues.push(Math.floor(Math.random() * 20) + 5)
}
courseTrendData.value = {
dates,
values: courseValues,
}
videoUploadTrendData.value = {
dates,
values: videoValues,
}
} }
// 初始化图表 // 初始化图表
...@@ -359,8 +306,8 @@ const disposeAllCharts = () => { ...@@ -359,8 +306,8 @@ const disposeAllCharts = () => {
videoUploadTrendChart = null videoUploadTrendChart = null
} }
onMounted(() => { onMounted(async () => {
loadData() await loadData()
setTimeout(() => { setTimeout(() => {
initCharts() initCharts()
}, 100) }, 100)
......
<script setup> <script setup>
import { ref, onMounted, onUnmounted } from 'vue' import { nextTick, ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { User, School, Trophy, TrendCharts, Monitor, Document } from '@element-plus/icons-vue' import { User, School, Trophy, TrendCharts, Monitor, Document } from '@element-plus/icons-vue'
import { getTeachingChart } from '../api'
// 教学数据统计 // 教学数据统计
const teachingStats = ref({ const teachingStats = ref({
...@@ -33,48 +34,46 @@ let scoreDistributionChart = null ...@@ -33,48 +34,46 @@ let scoreDistributionChart = null
let subjectScoreChart = null let subjectScoreChart = null
let scoreTrendChart = null let scoreTrendChart = null
// 加载模拟数据 const loadData = async () => {
const loadData = () => { const { data } = await getTeachingChart()
// 教学数据统计 teachingStats.value = { ...teachingStats.value, ...(data.stats || {}) }
teachingStats.value = { learningProgressData.value = data.learningProgressData || { students: [], progress: [] }
totalTeachers: 128, scoreAnalysisData.value = data.scoreAnalysisData || { distribution: [], subjects: [], trends: { months: [], scores: [] } }
totalStudents: 2850,
totalCourses: 76,
totalClasses: 38,
avgScore: 87.2,
completionRate: 94.5,
}
// 学习进度数据
learningProgressData.value = {
students: ['计算机1班', '数学1班', '物理1班', '化学1班', '英语1班', '语文1班'],
progress: [92, 88, 85, 90, 87, 83],
}
// 成绩分析数据
scoreAnalysisData.value = {
distribution: [
{ name: '优秀(90-100)', value: 35, count: 998 },
{ name: '良好(80-89)', value: 40, count: 1140 },
{ name: '中等(70-79)', value: 20, count: 570 },
{ name: '及格(60-69)', value: 4, count: 114 },
{ name: '不及格(<60)', value: 1, count: 28 },
],
subjects: [
{ name: '数学', score: 89.5 },
{ name: '英语', score: 85.2 },
{ name: '计算机', score: 92.8 },
{ name: '物理', score: 87.6 },
{ name: '化学', score: 88.9 },
{ name: '语文', score: 84.3 },
],
trends: {
months: ['1月', '2月', '3月', '4月', '5月', '6月'],
scores: [85.2, 86.8, 87.5, 88.1, 87.9, 87.2],
},
}
} }
const toChartNumber = (value) => Number(value) || 0
const roundedMax = (value, minValue) => {
const current = Math.max(toChartNumber(value), minValue)
const magnitude = 10 ** Math.max(0, Math.floor(Math.log10(current)) - 1)
return Math.ceil((current * 1.2) / magnitude) * magnitude
}
const overviewMetrics = () => [
{
name: '教师数量',
value: toChartNumber(teachingStats.value.totalTeachers),
max: roundedMax(teachingStats.value.totalTeachers, 10),
},
{
name: '学生数量',
value: toChartNumber(teachingStats.value.totalStudents),
max: roundedMax(teachingStats.value.totalStudents, 100),
},
{
name: '课程数量',
value: toChartNumber(teachingStats.value.totalCourses),
max: roundedMax(teachingStats.value.totalCourses, 10),
},
{
name: '班级数量',
value: toChartNumber(teachingStats.value.totalClasses),
max: roundedMax(teachingStats.value.totalClasses, 10),
},
{ name: '平均成绩', value: toChartNumber(teachingStats.value.avgScore), max: 100 },
{ name: '完成率', value: toChartNumber(teachingStats.value.completionRate), max: 100 },
]
// 初始化图表 // 初始化图表
const initCharts = () => { const initCharts = () => {
// 教学数据总览 // 教学数据总览
...@@ -93,16 +92,9 @@ const initCharts = () => { ...@@ -93,16 +92,9 @@ const initCharts = () => {
}, },
tooltip: {}, tooltip: {},
radar: { radar: {
indicator: [ indicator: overviewMetrics().map(({ name, max }) => ({ name, max })),
{ name: '教师数量', max: 150 },
{ name: '学生数量', max: 3000 },
{ name: '课程数量', max: 100 },
{ name: '班级数量', max: 50 },
{ name: '平均成绩', max: 100 },
{ name: '完成率', max: 100 },
],
center: ['50%', '60%'], center: ['50%', '60%'],
radius: '70%', radius: '62%',
}, },
series: [ series: [
{ {
...@@ -110,14 +102,7 @@ const initCharts = () => { ...@@ -110,14 +102,7 @@ const initCharts = () => {
type: 'radar', type: 'radar',
data: [ data: [
{ {
value: [ value: overviewMetrics().map(({ value }) => value),
teachingStats.value.totalTeachers,
teachingStats.value.totalStudents,
teachingStats.value.totalCourses,
teachingStats.value.totalClasses,
teachingStats.value.avgScore,
teachingStats.value.completionRate,
],
name: '当前数据', name: '当前数据',
areaStyle: { color: 'rgba(64, 158, 255, 0.3)' }, areaStyle: { color: 'rgba(64, 158, 255, 0.3)' },
}, },
...@@ -232,7 +217,7 @@ const initCharts = () => { ...@@ -232,7 +217,7 @@ const initCharts = () => {
scoreDistributionChart.setOption(option) scoreDistributionChart.setOption(option)
} }
// 学科成绩柱状图 // 课程成绩柱状图
const subjectEl = document.getElementById('subjectScoreChart') const subjectEl = document.getElementById('subjectScoreChart')
if (subjectEl) { if (subjectEl) {
if (subjectScoreChart) { if (subjectScoreChart) {
...@@ -241,7 +226,7 @@ const initCharts = () => { ...@@ -241,7 +226,7 @@ const initCharts = () => {
subjectScoreChart = echarts.init(subjectEl) subjectScoreChart = echarts.init(subjectEl)
const option = { const option = {
title: { title: {
text: '各学科平均成绩', text: '课程平均成绩 Top10',
left: 'center', left: 'center',
top: '5%', top: '5%',
textStyle: { fontSize: 16 }, textStyle: { fontSize: 16 },
...@@ -359,11 +344,10 @@ const disposeAllCharts = () => { ...@@ -359,11 +344,10 @@ const disposeAllCharts = () => {
scoreTrendChart = null scoreTrendChart = null
} }
onMounted(() => { onMounted(async () => {
loadData() await loadData()
setTimeout(() => { await nextTick()
initCharts() initCharts()
}, 500)
window.addEventListener('resize', handleResize) window.addEventListener('resize', handleResize)
}) })
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论