Files
en-edu/enlish-vue/src/layouts/components/student/PlanHistoryChart.vue
lbw bf2a80917c style(ui): 优化页面容器及布局样式,调整头部组件图标和交互
- 为多个页面容器添加最小高度类,保证页面满屏显示
- 调整部分主内容区高度样式,增强布局一致性和视觉整洁
- 替换头部组件Logo为自定义SVG图标,提升品牌识别度
- 优化头部用户菜单按钮交互和样式,统一暗黑模式视觉效果
- 调整TTS页面词汇列表布局,支持移动端和桌面端不同显示方式
- 修改学生详情页面样式,提升各模块容器的统一性和分隔感
- 修正历史数据日期格式,将“T”替换为空格以增强可读性
2026-01-05 11:21:55 +08:00

132 lines
3.1 KiB
Vue

<template>
<div style="width: 100%; height: 260px;">
<div ref="elRef" style="width: 100%; height: 100%;"></div>
</div>
</template>
<script setup>
import { defineProps, ref, onMounted, onUnmounted, watch } from 'vue'
import { findStudentPlanHistory } from '@/api/studentLessonPlans'
const props = defineProps({
studentId: { type: [Number, String], required: true }
})
const elRef = ref(null)
let chart = null
let echartsLib = null
const rows = ref([])
function sortData(arr) {
return Array.isArray(arr)
? arr.slice().sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime())
: []
}
function toSource(arr) {
return sortData(arr).map(it => ({
startTime: it.startTime.replace('T', ' '),
totalCount: Number(it.totalCount) || 0,
planId: it.planId ?? null,
id: it.id ?? null
}))
}
function buildOption(source) {
return {
dataset: [
{
id: 'dataset_history',
source: source
}
],
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
nameLocation: 'middle'
},
yAxis: {
name: 'Total Count',
min: 0
},
series: [
{
type: 'line',
datasetId: 'dataset_history',
showSymbol: false,
encode: {
x: 'startTime',
y: 'totalCount',
itemName: 'startTime',
tooltip: ['totalCount']
}
}
]
}
}
function resize() {
if (chart) chart.resize()
}
async function ensureEcharts() {
try {
const mod = await import('echarts')
echartsLib = mod
} catch (e) {
if (window.echarts) {
echartsLib = window.echarts
} else {
await new Promise(resolve => {
const s = document.createElement('script')
s.src = 'https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js'
s.onload = resolve
document.head.appendChild(s)
})
echartsLib = window.echarts
}
}
}
async function render() {
if (!elRef.value) return
await ensureEcharts()
if (!echartsLib) return
if (!chart) {
chart = echartsLib.init(elRef.value)
window.addEventListener('resize', resize)
}
const source = toSource(rows.value)
const option = buildOption(source)
chart.setOption(option)
}
async function fetch() {
if (props.studentId === undefined || props.studentId === null) return
const res = await findStudentPlanHistory(Number(props.studentId))
const d = res?.data?.data ?? []
rows.value = Array.isArray(d) ? d : []
}
onMounted(async () => {
await fetch()
await render()
})
onUnmounted(() => {
window.removeEventListener('resize', resize)
if (chart) {
chart.dispose()
chart = null
}
})
watch(() => props.studentId, async () => {
await fetch()
await render()
})
</script>