update:骨架屏

This commit is contained in:
ltx 2026-04-29 17:34:15 +08:00
parent 38a1c1a1cc
commit 030df26336

View File

@ -74,7 +74,21 @@
</el-dropdown>
</div>
</div>
<div class="list">
<!-- 统计卡片 -->
<div class="list" v-if="loading.stats">
<div class="listOne skeleton-card" v-for="i in 6" :key="i">
<el-skeleton animated style="width:100%;display:flex;align-items:center;padding:0 16px 0 20px">
<template #template>
<el-skeleton-item variant="circle" style="width:60px;height:60px;flex-shrink:0" />
<div style="margin-left:16px;flex:1">
<el-skeleton-item variant="h3" style="width:55%;margin-bottom:10px" />
<el-skeleton-item variant="text" style="width:35%" />
</div>
</template>
</el-skeleton>
</div>
</div>
<div class="list" v-else>
<div class="listOne" v-for="(item, index) in data.listData" :key="index">
<div class="left">
<img :src="item.url" alt="">
@ -85,12 +99,29 @@
</div>
</div>
</div>
<!-- 年级均分 & 等级占比 -->
<div class="cont1">
<div class="cont1Left">
<div class="title">
<p>年级体测平均成绩</p>
</div>
<div id="barChart"></div>
<div class="chart-skeleton" v-if="loading.stats">
<el-skeleton animated>
<template #template>
<div class="skeleton-chart-wrap">
<div class="skeleton-bars">
<div class="skeleton-bar-group" v-for="i in 7" :key="i">
<el-skeleton-item variant="rect"
:style="`width:24px;height:${40 + Math.random() * 120}px`" />
<el-skeleton-item variant="text" style="width:32px;margin-top:8px" />
</div>
</div>
</div>
</template>
</el-skeleton>
</div>
<div id="barChart" v-show="!loading.stats"></div>
</div>
<div class="cont1Right">
<div class="title">
@ -108,15 +139,57 @@
</div>
</div>
</div>
<div id="levelbarChart"></div>
<div class="chart-skeleton" v-if="loading.level">
<el-skeleton animated>
<template #template>
<div class="skeleton-chart-wrap">
<div class="skeleton-pie-wrap">
<el-skeleton-item variant="circle" style="width:130px;height:130px" />
<div class="skeleton-pie-legend">
<div class="skeleton-legend-item" v-for="i in 4" :key="i">
<el-skeleton-item variant="circle" style="width:10px;height:10px;flex-shrink:0" />
<el-skeleton-item variant="text" style="width:80px" />
</div>
</div>
</div>
</div>
</template>
</el-skeleton>
</div>
<div id="levelbarChart" v-show="!loading.level"></div>
</div>
</div>
<!-- 班级达标率 -->
<div class="cont3">
<div class="title">
<p>班级体测达标率对比</p>
</div>
<div class="cont3Chart" id="classBarChart"></div>
<div class="chart-skeleton" v-if="loading.stats">
<el-skeleton animated>
<template #template>
<div class="skeleton-chart-wrap">
<div class="skeleton-bars">
<div class="skeleton-bar-group" v-for="i in 8" :key="i">
<div style="display:flex;gap:4px;align-items:flex-end">
<el-skeleton-item variant="rect"
:style="`width:14px;height:${50 + Math.random() * 100}px`" />
<el-skeleton-item variant="rect"
:style="`width:14px;height:${50 + Math.random() * 100}px`" />
<el-skeleton-item variant="rect"
:style="`width:14px;height:${50 + Math.random() * 100}px`" />
</div>
<el-skeleton-item variant="text" style="width:42px;margin-top:8px" />
</div>
</div>
</div>
</template>
</el-skeleton>
</div>
<div class="cont3Chart" id="classBarChart" v-show="!loading.stats"></div>
</div>
<!-- 成绩趋势 -->
<div class="cont4">
<div class="title">
<div class="left">
@ -139,13 +212,41 @@
</el-select>
</div>
</div>
</div>
<div class="cont4Chart" id="trendChart"></div>
<div class="chart-skeleton" v-if="loading.trend">
<el-skeleton animated>
<template #template>
<div class="skeleton-chart-wrap skeleton-line-wrap">
<el-skeleton-item variant="rect" style="width:100%;height:3px;margin-bottom:24px" />
<div class="skeleton-line-dots">
<div class="skeleton-line-dot" v-for="i in 12" :key="i">
<el-skeleton-item variant="circle" style="width:8px;height:8px" />
<el-skeleton-item variant="text" style="width:28px;margin-top:8px" />
</div>
</div>
</div>
</template>
</el-skeleton>
</div>
<div class="cont4Chart" id="trendChart" v-show="!loading.trend"></div>
</div>
<!-- 详细列表 -->
<div class="tableCont">
<p>详细列表</p>
<commonTable :tableNeed="data.tableNeed" @toView="toView" v-if="data.tableNeed.refresh"></commonTable>
<div v-if="loading.stats" class="skeleton-table">
<el-skeleton animated>
<template #template>
<div class="skeleton-table-header">
<el-skeleton-item variant="rect" v-for="i in 6" :key="i" style="height:16px;flex:1;margin:0 8px" />
</div>
<div class="skeleton-table-row" v-for="j in 8" :key="j">
<el-skeleton-item variant="text" v-for="i in 6" :key="i" style="flex:1;margin:0 8px" />
</div>
</template>
</el-skeleton>
</div>
<commonTable :tableNeed="data.tableNeed" @toView="toView" v-else-if="data.tableNeed.refresh"></commonTable>
</div>
</div>
<commonDialog :list="data.dialogData" @cancle="confirm" @confirm="confirm">
@ -180,6 +281,11 @@ import eventBus from '@/eventBus.js';
import { ElMessage } from 'element-plus';
import commonDialog from '@/components/commonDialog/index.vue';
const route = useRoute();
const loading = ref({
stats: true, // 统计卡片 + 年级平均成绩图 + 班级达标率图 + 表格
level: true, // 各体测项目等级占比图
trend: true, // 成绩趋势图
})
const data = ref({
dialogData: {
dialogVisible: false,
@ -406,10 +512,12 @@ async function initCategoryRankRatio(val, val1) {
for (let i in res.data) {
data.value.levelChartData.seriesData.push({ value: (res.data[i] * 100).toFixed(0), name: i })
}
loading.value.level = false
await nextTick()
levelChart(data.value.levelChartData)
}
} catch (error) {
loading.value.level = false
console.error('Error occurred while calling API:', error);
}
}
@ -420,10 +528,12 @@ async function initResultTrends(val, val1, val2) {
if (res.code == 200) {
data.value.chartsData3.ChartCont.xData = res.data.axisX
data.value.chartsData3.ChartCont.seriesData = res.data.axisY
loading.value.trend = false
await nextTick()
trendEcharts(data.value.chartsData3)
}
} catch (error) {
loading.value.trend = false
console.error('Error occurred while calling API:', error);
}
}
@ -459,12 +569,14 @@ async function initGradeWholeDataStats(val) {
i.passRate = (i.passRate * 100).toFixed(0) + '%'
})
data.value.tableNeed.refresh = true
loading.value.stats = false
await nextTick()
averageBar(data.value.averageBarData)
classBar(data.value.classBarData)
}
} catch (error) {
loading.value.stats = false
console.error('Error occurred while calling API:', error);
}
}
@ -1673,5 +1785,104 @@ function toViewStudentDetail(val) {
border-bottom: 1px solid #F5F5F5;
}
}
// ──── 骨架屏公共样式 ────
.skeleton-card {
display: flex;
align-items: center;
}
.chart-skeleton {
width: 100%;
height: 260px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 24px;
box-sizing: border-box;
}
.skeleton-chart-wrap {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 12px;
}
.skeleton-bars {
display: flex;
align-items: flex-end;
justify-content: space-around;
height: 200px;
padding: 0 12px;
.skeleton-bar-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 0;
}
}
.skeleton-pie-wrap {
display: flex;
align-items: center;
justify-content: center;
gap: 32px;
height: 100%;
padding-top: 20px;
.skeleton-pie-legend {
display: flex;
flex-direction: column;
gap: 14px;
.skeleton-legend-item {
display: flex;
align-items: center;
gap: 8px;
}
}
}
.skeleton-line-wrap {
justify-content: center;
padding: 24px 12px 12px;
.skeleton-line-dots {
display: flex;
align-items: flex-end;
justify-content: space-around;
padding: 0 12px;
.skeleton-line-dot {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
}
}
.skeleton-table {
padding: 0 20px 20px;
.skeleton-table-header {
display: flex;
align-items: center;
padding: 14px 0;
border-bottom: 1px solid #F5F5F5;
margin-bottom: 4px;
}
.skeleton-table-row {
display: flex;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid #FAFAFA;
}
}
}
</style>