// 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() {}, })