2026-04-28 16:50:36 +08:00

181 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// subpackage/teacher/student-fitness-detail/student-fitness-detail.js
import uCharts from '../../../utils/chart/u-charts';
import { getReport } from '../../../utils/serve/parent';
var uChartsInstance = {};
const UNIT_MAP = {
'BMI': 'kg/m²',
'肺活量': 'ml',
'坐位体前屈': 'cm',
'立定跳远': 'cm',
'一分钟跳绳': '个',
'一分钟仰卧起坐': '个',
};
Page({
data: {
fitnessItems: [],
fitnessReport: [],
radarCWidth: 300,
radarCHeight: 300,
pixelRatio: 2,
showFitnessPopup: false,
selectedFitnessItem: null,
studentNo: '',
readyFired: false,
},
async onLoad(options) {
wx.showLoading({ title: '加载中' });
this.setData({ studentNo: options.studentNo || '' });
try {
const res = await getReport({ studentNo: options.studentNo });
const rawList = (res.data && res.data.categoryScoreList) || [];
const list = rawList.filter(item => !(item.name && item.name.includes('米') && item.name.includes('跑')));
// 雷达图根据 gradeId 过滤不适用的项目
const gradeId = list.length > 0 ? list[0].gradeId : null;
let radarList = list;
if (gradeId !== null && gradeId !== undefined) {
if (gradeId <= 2) {
radarList = list.filter(item => item.name !== '一分钟仰卧起坐' && item.name !== '立定跳远');
} else if (gradeId > 2 && gradeId <= 6) {
radarList = list.filter(item => item.name !== '立定跳远');
} else if (gradeId > 6) {
radarList = list.filter(item => item.name !== '一分钟跳绳');
}
}
const fitnessItems = list.map(item => ({
...item,
unit: UNIT_MAP[item.name] || '',
}));
this.setData({
fitnessReport: radarList,
fitnessItems,
}, () => {
// 如果 onReady 已经触发,数据到位后立即绘图
if (this.data.readyFired) {
this.drawRadarChart(this);
}
});
} catch (e) {
this.setData({ fitnessItems: [] });
}
wx.hideLoading();
},
onReady() {
const info = wx.getWindowInfo();
const pixelRatio = info.pixelRatio;
const rpxRatio = info.windowWidth / 750;
const radarCWidth = Math.floor(info.windowWidth - 2 * 30 * rpxRatio);
const radarCHeight = Math.floor(radarCWidth * 1.05);
this.setData({ radarCWidth, radarCHeight, pixelRatio, readyFired: true }, () => {
// 如果数据已经加载完,直接绘图;否则等 onLoad 回调里触发
if (this.data.fitnessReport && this.data.fitnessReport.length > 0) {
this.drawRadarChart(this);
}
});
},
drawRadarChart(that) {
const list = that.data.fitnessReport || [];
// 长文本自动换行(超过5字在中间插入换行)
const categories = list.map(i => {
const name = i.name || '';
if (name.length > 5) {
const mid = Math.ceil(name.length / 2);
return name.slice(0, mid) + '\n' + name.slice(mid);
}
return name;
});
const prevData = list.map(i => i.prevScore || 0);
const currentData = list.map(i => i.lastScore || 0);
// 本次成绩数据标签:显示分数 + 等级
const currentDataLabels = list.map(i => {
const score = i.lastScore != null ? i.lastScore : '';
const rank = i.rank != null ? i.rank : '';
return rank ? score + '\n' + rank : String(score);
});
const query = wx.createSelectorQuery().in(that);
query.select('#radarCanvas').fields({ node: true, size: true }).exec(res => {
if (!res[0]) return;
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
canvas.width = (res[0].width + 20) * that.data.pixelRatio;
canvas.height = (res[0].height + 20) * that.data.pixelRatio;
uChartsInstance['radarCanvas'] = new uCharts({
type: 'radar',
context: ctx,
width: that.data.radarCWidth * that.data.pixelRatio,
height: that.data.radarCHeight * that.data.pixelRatio,
categories,
series: [
{ name: '上次成绩', data: prevData, color: '#4A90E2', dataLabel: false },
{ name: '本次成绩', data: currentData, color: '#E74C3C', dataLabels: currentDataLabels, textColor: '#E74C3C', textSize: 11 },
],
pixelRatio: that.data.pixelRatio,
animation: true,
tapLegend: true,
background: 'rgba(0,0,0,0)',
color: ['#4A90E2', '#E74C3C'],
padding: [0, 0, 0, 15],
legend: {
show: true,
position: 'bottom',
float: 'center',
fontSize: 12,
lineHeight: 11,
margin: 0,
itemGap: 20,
},
extra: {
radar: {
gridType: that.data.fitnessReport.length === 4 ? 'circle' : 'radar',
gridColor: '#CCCCCC',
gridCount: 4,
opacity: 0.15,
gridEvenShow: true,
gridOddShow: true,
labelShow: true,
labelColor: '#333',
fontSize: 13,
labelMargin: 30,
labelPointShow: false,
max: 100,
},
},
});
});
},
showFitnessScore(e) {
const item = e.currentTarget.dataset.item;
this.setData({ selectedFitnessItem: item, showFitnessPopup: true });
},
closeFitnessPopup() {
this.setData({ showFitnessPopup: false, selectedFitnessItem: null });
},
goFitnessDetail() {
const item = this.data.selectedFitnessItem;
if (!item) return;
this.setData({ showFitnessPopup: false });
wx.setStorageSync('fitnessDetailItem', item);
wx.navigateTo({
url: '/subpackage/parent/fitness-detail/fitness-detail',
});
},
onShow() {},
onHide() {},
onUnload() {},
onPullDownRefresh() {},
onReachBottom() {},
onShareAppMessage() {},
})