From 844cde0fb6f0446931c000745f8581334b8b8873 Mon Sep 17 00:00:00 2001 From: ltx <1006158920@qq.com> Date: Tue, 4 Aug 2026 09:59:35 +0800 Subject: [PATCH] =?UTF-8?q?update=EF=BC=9A=E5=AD=A6=E7=94=9F=E7=AB=AF?= =?UTF-8?q?=E8=AF=BE=E5=A0=82=E6=8A=A5=E5=91=8A=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/parent/report/report.js | 169 ++++++----- pages/parent/report/report.wxml | 38 ++- pages/parent/report/report.wxss | 30 +- .../resource-detail/resource-detail.js | 263 ++++++++++-------- .../resource-detail/resource-detail.json | 5 +- .../resource-detail/resource-detail.wxml | 85 ++++-- .../resource-detail/resource-detail.wxss | 199 +++++++++---- subpackage/teacher/resource/resource.js | 19 +- 8 files changed, 505 insertions(+), 303 deletions(-) diff --git a/pages/parent/report/report.js b/pages/parent/report/report.js index c10fca8..00077af 100644 --- a/pages/parent/report/report.js +++ b/pages/parent/report/report.js @@ -61,6 +61,7 @@ Page({ ], mockMonthData: {}, mockQuarterData: {}, + studentReportLoading: false, }, /** @@ -71,62 +72,95 @@ Page({ const nowYear = now.getFullYear() const nowMonth = now.getMonth() + 1 const nowQuarter = Math.ceil(nowMonth / 3) + const isTrainee = wx.getStorageSync('roleId') && wx.getStorageSync('roleId') == 5 this.setData({ nowYear, nowMonth, nowQuarter, selectedYear: nowYear, selectedMonth: nowMonth, selectedQuarter: nowQuarter, pickerYear: nowYear, + isTrainee, + activeTab: isTrainee ? 0 : 1, }) - - if(wx.getStorageSync('roleId') && wx.getStorageSync('roleId') == 5 ){ - this.setData({ - isTrainee: true - }, () => { - this.getTrainClass(true) - this.fetchFitnessReport() - }) + await this.getTrainClass(true) + if (isTrainee) { + await this.fetchFitnessReport() } else { await this.getStudentReport() } }, - async getStudentReport() { - const res = await getReport() - let list = [] - res.data.categoryScoreList.forEach(e => { - list.push({ - ...e, - width: e.score >= 60 && e.score <= 80 ? (((e.score - 60) / 4)*5 + 25) + '%' : ((e.score - 60) / 0.4 + 2) + '%', - grade: e.score >= 90 ? 'grate' : e.score >= 80 ? 'good' : e.score >= 60 ? 'normal' : '' - }) - }) - - res.data.width = res.data.totalScore >= 60 && res.data.totalScore <= 80 ? (((res.data.totalScore - 60) / 4)*5 + 25) + '%' : ((res.data.totalScore - 60) / 0.4 + 2) + '%', - res.data.grade = res.data.totalScore >= 90 ? 'grate' : res.data.totalScore >= 80 ? 'good' : res.data.totalScore >= 60 ? 'normal' : '' - res.data.totalScore = res.data.totalScore.toFixed(0) - res.data.bodyFunction = res.data.bodyFunction.toFixed(0) - res.data.bodyQuality = res.data.bodyQuality.toFixed(0) - res.data.bodyShape = res.data.bodyShape.toFixed(0) - this.setData({ - report: res.data, - list - }) + _toScoreValue(value) { + const score = Number(value || 0) + return Number.isFinite(score) ? score : 0 + }, + + _formatScore(value) { + return this._toScoreValue(value).toFixed(0) + }, + + _getScoreGrade(score) { + const value = this._toScoreValue(score) + return value >= 90 ? 'grate' : value >= 80 ? 'good' : value >= 60 ? 'normal' : '' + }, + + _getScoreWidth(score) { + const value = Math.max(0, Math.min(100, this._toScoreValue(score))) + if (value >= 60 && value <= 80) return (((value - 60) / 4) * 5 + 25) + '%' + return Math.max(2, (value - 60) / 0.4 + 2) + '%' + }, + + _hasReportRecord(item) { + const scoreTrendChart = (item && item.scoreTrendChart) || {} + const axisY = Array.isArray(scoreTrendChart.axisY) ? scoreTrendChart.axisY : [] + return axisY.length > 0 + }, + + _getAverageScore(items) { + const valid = (items || []).filter(item => item && item.hasRecord) + if (!valid.length) return 0 + return valid.reduce((sum, item) => sum + this._toScoreValue(item.lastScore), 0) / valid.length + }, + + _buildStudentReport(rawData) { + const sourceList = (rawData && rawData.categoryScoreList) || [] + const list = sourceList.map(item => { + const score = this._toScoreValue(item.lastScore) + const scoreTrendChart = item.scoreTrendChart || { axisX: [], axisY: [] } + const reportItem = { ...item, scoreTrendChart } + const hasRecord = this._hasReportRecord(reportItem) + return { ...reportItem, hasRecord, score: this._formatScore(score), width: this._getScoreWidth(score), grade: this._getScoreGrade(score) } + }).filter(item => item.hasRecord) + const shapeList = list.filter(item => item.categoryValue === 1) + const functionList = list.filter(item => item.categoryValue === 2) + const qualityList = list.filter(item => item.categoryValue !== 1 && item.categoryValue !== 2) + const totalScore = this._getAverageScore(list) + return { + report: { totalScore: this._formatScore(totalScore), bodyShape: this._formatScore(this._getAverageScore(shapeList)), bodyFunction: this._formatScore(this._getAverageScore(functionList)), bodyQuality: this._formatScore(this._getAverageScore(qualityList)), width: this._getScoreWidth(totalScore), grade: this._getScoreGrade(totalScore) }, + list, + } + }, + + async getStudentReport() { + this.setData({ studentReportLoading: true }) + try { + const res = await getReport() + const viewData = this._buildStudentReport(res.data || {}) + this.setData({ ...viewData, fitnessItems: viewData.list.map(item => ({ ...item, unit: UNIT_MAP[item.name] || '' })), studentReportLoading: false }) + } catch (e) { + this.setData({ report: {}, list: [], fitnessItems: [], studentReportLoading: false }) + } }, - // 切换体测/课堂 Tab switchTab(e) { const tab = Number(e.currentTarget.dataset.tab) if (tab === this.data.activeTab) return this.setData({ activeTab: tab }, () => { - if (tab === 1) { - // 切到体测报告时绘制雷达图 - this.drawRadarChart(this) - } + if (tab === 0 && this.data.roomList.length === 0) this.getTrainClass(true) + if (this.data.isTrainee && tab === 1) this.drawRadarChart(this) }) }, - // 切换课堂报告子Tab (课堂/月/季度) switchClassroomSubTab(e) { const tab = Number(e.currentTarget.dataset.tab) if (tab === this.data.classroomSubTab) return @@ -409,7 +443,7 @@ Page({ }) this.setData({ roomList: refresh ? newList : [...this.data.roomList, ...newList], - page: this.data.page + 1, + pageIndex: this.data.pageIndex + 1, hasMore: res.data.total > (this.data.pageIndex) * 20, }) @@ -447,16 +481,10 @@ Page({ */ onShow() { tabService.updateIndex(this, 2) - if(wx.getStorageSync('roleId') && wx.getStorageSync('roleId') == 5){ //学员 - this.setData({ - isTrainee:true - }) - } + const isTrainee = wx.getStorageSync('roleId') && wx.getStorageSync('roleId') == 5 + this.setData({ isTrainee }) }, - /** - * 生命周期函数--监听页面隐藏 - */ onHide() { }, @@ -472,53 +500,40 @@ Page({ * 页面相关事件处理函数--监听用户下拉动作 */ async onPullDownRefresh() { - if (this.data.isTrainee) { - const { activeTab, classroomSubTab } = this.data - if (activeTab === 0) { - // 课堂报告 Tab - if (classroomSubTab === 0) { - // 课堂列表 - this.setData({ pageIndex: 1, hasMore: true }, async () => { - await this.getTrainClass(true) - wx.stopPullDownRefresh() - wx.showToast({ title: '刷新成功', icon: 'none' }) - }) - } else if (classroomSubTab === 1) { - // 月报告 - await this.fetchMonthReport() + const { activeTab, classroomSubTab, isTrainee } = this.data + if (activeTab === 0) { + if (classroomSubTab === 0) { + this.setData({ pageIndex: 1, hasMore: true }, async () => { + await this.getTrainClass(true) wx.stopPullDownRefresh() wx.showToast({ title: '刷新成功', icon: 'none' }) - } else if (classroomSubTab === 2) { - // 季度报告 - await this.fetchQuarterReport() - wx.stopPullDownRefresh() - wx.showToast({ title: '刷新成功', icon: 'none' }) - } - } else if (activeTab === 1) { - // 体测报告 Tab - await this.fetchFitnessReport() - this.drawRadarChart(this) + }) + } else if (classroomSubTab === 1) { + await this.fetchMonthReport() + wx.stopPullDownRefresh() + wx.showToast({ title: '刷新成功', icon: 'none' }) + } else if (classroomSubTab === 2) { + await this.fetchQuarterReport() wx.stopPullDownRefresh() wx.showToast({ title: '刷新成功', icon: 'none' }) } + } else if (isTrainee && activeTab === 1) { + await this.fetchFitnessReport() + this.drawRadarChart(this) + wx.stopPullDownRefresh() + wx.showToast({ title: '刷新成功', icon: 'none' }) } else { await this.getStudentReport() wx.stopPullDownRefresh() - wx.showToast({ title: '刷新成功!', icon: 'none' }) + wx.showToast({ title: '刷新成功', icon: 'none' }) } }, - /** - * 页面上拉触底事件的处理函数 - */ onReachBottom() { - this.getTrainClass() + if (this.data.activeTab === 0 && this.data.classroomSubTab === 0) this.getTrainClass() }, - /** - * 用户点击右上角分享 - */ onShareAppMessage() { } -}) \ No newline at end of file +}) diff --git a/pages/parent/report/report.wxml b/pages/parent/report/report.wxml index bedcf79..79ffc29 100644 --- a/pages/parent/report/report.wxml +++ b/pages/parent/report/report.wxml @@ -1,8 +1,17 @@ + + + 课堂报告 + + + {{isTrainee ? '体测报告' : '学生报告'}} + + + - + 健康身体 坚持运动 @@ -102,17 +111,12 @@ - - - - - - 课堂报告 - - - 体测报告 - + + 暂无 + 暂无学生报告数据 + + @@ -136,8 +140,12 @@ - 加载中... - 没有更多了哦~ + 加载中... + 没有更多了哦~ + + 暂无 + 暂无课堂报告数据 + @@ -278,7 +286,7 @@ - + 体测成绩对比 @@ -381,4 +389,4 @@ - \ No newline at end of file + diff --git a/pages/parent/report/report.wxss b/pages/parent/report/report.wxss index 1f52edf..a3bed35 100644 --- a/pages/parent/report/report.wxss +++ b/pages/parent/report/report.wxss @@ -882,4 +882,32 @@ .picker-year-arrow-disabled { opacity: 0.3; color: #ccc; -} \ No newline at end of file +} + +.report-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 260rpx; + margin: 30rpx 0; + background: #fff; + border-radius: 20rpx; + box-shadow: 0 4rpx 16rpx rgba(73,165,252,0.1); + color: #9aa7b2; + font-size: 26rpx; +} + +.report-empty-icon { + width: 96rpx; + height: 96rpx; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 18rpx; + background: #eef8ff; + color: #26A5F6; + font-size: 24rpx; + font-weight: 600; +} diff --git a/subpackage/teacher/resource-detail/resource-detail.js b/subpackage/teacher/resource-detail/resource-detail.js index 385f38a..f380e0f 100644 --- a/subpackage/teacher/resource-detail/resource-detail.js +++ b/subpackage/teacher/resource-detail/resource-detail.js @@ -1,147 +1,164 @@ const utils = require("../../../utils/utils"); -// subpackage/teacher/resource-detail/resource-detail.js Page({ - - /** - * 页面的初始数据 - */ data: { - title: '口令', - value: '00:00', - duration: '00:00', - aduio:null, - data:{}, - isPlay:false, - percent:0, - isReload:false,//是否重复播放 - isShow:false,//是否展示弹窗 + title: "音乐", + data: {}, + playlist: [], + currentIndex: 0, + value: "00:00", + duration: "00:00", + percent: 0, + isPlay: false, + isSingleLoop: false, + isShow: false, + isClosing: false }, - /** - * 生命周期函数--监听页面加载 - */ onLoad(options) { - console.log(JSON.parse(options.data)) + let current = {}; + try { + current = JSON.parse(decodeURIComponent(options.data || "{}")); + } catch (error) { + console.error("资源参数解析失败", error); + } + this.setData({ - data: JSON.parse(options.data), - title: JSON.parse(options.data).id == 1 ? '口令' : JSON.parse(options.data).id == 2 ? '音乐' : '视频' - }) - this.loadAudio(JSON.parse(options.data).resourceUrl) + data: current, + playlist: current.resourceUrl ? [current] : [], + title: current.id == 1 ? "口令" : "音乐" + }); + + this.createAudioContext(); + if (current.resourceUrl) { + this.loadTrack(current, false); + } + + const eventChannel = this.getOpenerEventChannel && this.getOpenerEventChannel(); + if (eventChannel && eventChannel.on) { + eventChannel.on("setPlaylist", ({ playlist = [], currentIndex = 0 }) => { + if (!playlist.length) return; + const safeIndex = Math.min(Math.max(Number(currentIndex) || 0, 0), playlist.length - 1); + this.setData({ playlist, currentIndex: safeIndex, data: playlist[safeIndex] }); + }); + } }, - loadAudio(url) { + createAudioContext() { this.audioCtx = wx.createInnerAudioContext(); - this.audioCtx.src = url - this.audioCtx.onCanplay(() => { - this.audioCtx.duration - this.audioCtx.currentTime - console.log(this.audioCtx.currentTime) - console.log(this.audioCtx.duration) - console.log(this.audioCtx.currentTime) - this.setData({ - value: utils.formatTimeStr(this.audioCtx.currentTime), - duration: utils.formatTimeStr(this.audioCtx.duration), - }) - }) + this.audioCtx.obeyMuteSwitch = false; - this.audioCtx.onTimeUpdate(() => { - console.log('在播放咯') - console.log(this.data.percent) - console.log('在播放咯') - this.audioCtx.duration - this.audioCtx.currentTime - this.setData({ - value: utils.formatTimeStr(this.audioCtx.currentTime), - duration: utils.formatTimeStr(this.audioCtx.duration), - percent:((this.audioCtx.currentTime/this.audioCtx.duration)*100).toFixed(0) - }) - }) + this.audioCtx.onCanplay(() => this.updateProgress()); + this.audioCtx.onTimeUpdate(() => this.updateProgress()); + this.audioCtx.onPlay(() => this.setData({ isPlay: true })); + this.audioCtx.onPause(() => this.setData({ isPlay: false })); + this.audioCtx.onStop(() => this.setData({ isPlay: false })); + this.audioCtx.onEnded(() => { + if (!this.data.isSingleLoop) this.changeTrack(1, true); + }); + this.audioCtx.onError((error) => { + console.error("音频播放失败", error); + this.setData({ isPlay: false }); + wx.showToast({ title: "音频加载失败,请稍后重试", icon: "none" }); + }); }, - btnCilck(){ - console.log(this.audioCtx.src) - if(this.data.isPlay){ - this.audioCtx.pause() - this.setData({ - isPlay:false - }) - }else{ - this.audioCtx.play() - this.setData({ - isPlay:true - }) + loadTrack(track, autoplay = true) { + if (!track || !track.resourceUrl || !this.audioCtx) return; + this.audioCtx.stop(); + this.audioCtx.loop = this.data.isSingleLoop; + this.audioCtx.src = track.resourceUrl; + this.setData({ + data: track, + value: "00:00", + duration: "00:00", + percent: 0, + isPlay: autoplay + }); + if (autoplay) this.audioCtx.play(); + }, + + updateProgress() { + if (!this.audioCtx) return; + const currentTime = Number(this.audioCtx.currentTime) || 0; + const duration = Number(this.audioCtx.duration) || 0; + this.setData({ + value: utils.formatTimeStr(currentTime), + duration: utils.formatTimeStr(duration), + percent: duration ? Math.min((currentTime / duration) * 100, 100) : 0 + }); + }, + + btnCilck() { + if (!this.audioCtx || !this.data.data.resourceUrl) return; + this.data.isPlay ? this.audioCtx.pause() : this.audioCtx.play(); + }, + + playPrevious() { + this.changeTrack(-1, true); + }, + + playNext() { + this.changeTrack(1, true); + }, + + changeTrack(step, autoplay) { + const { playlist, currentIndex } = this.data; + if (!playlist.length) return; + const nextIndex = (currentIndex + step + playlist.length) % playlist.length; + this.setData({ currentIndex: nextIndex }, () => this.loadTrack(playlist[nextIndex], autoplay)); + }, + + selectTrack(e) { + const index = Number(e.currentTarget.dataset.index); + if (!Number.isInteger(index) || !this.data.playlist[index]) return; + this.setData({ currentIndex: index }, () => { + this.loadTrack(this.data.playlist[index], true); + this.hideList(); + }); + }, + + toggleLoop() { + const isSingleLoop = !this.data.isSingleLoop; + if (this.audioCtx) this.audioCtx.loop = isSingleLoop; + this.setData({ isSingleLoop }); + wx.showToast({ title: isSingleLoop ? "单曲循环" : "列表循环", icon: "none" }); + }, + + seekAudio(e) { + if (!this.audioCtx || !this.audioCtx.duration) return; + wx.createSelectorQuery().in(this).select("#audio-progress").boundingClientRect((rect) => { + if (!rect || !rect.width) return; + const ratio = Math.min(Math.max((e.detail.x - rect.left) / rect.width, 0), 1); + this.audioCtx.seek(this.audioCtx.duration * ratio); + }).exec(); + }, + + showList() { + if (this.closeTimer) { + clearTimeout(this.closeTimer); + this.closeTimer = null; } + this.setData({ isShow: true, isClosing: false }); }, - showList(){ - this.setData({ - isShow:true - }) + hideList() { + if (!this.data.isShow || this.data.isClosing) return; + this.setData({ isClosing: true }); + this.closeTimer = setTimeout(() => { + this.setData({ isShow: false, isClosing: false }); + this.closeTimer = null; + }, 240); }, - reload(){ - wx.showToast({ - title: this.data.isReload ?'列表循环':'单曲循环', - icon:'none' - }) - this.audioCtx.loop = true - this.setData({ - isReload:!this.data.isReload - }) - }, - - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady() { + preventClose() {}, - }, - - /** - * 生命周期函数--监听页面显示 - */ - onShow() { - - }, - - /** - * 生命周期函数--监听页面隐藏 - */ - onHide() { - - }, - - /** - * 生命周期函数--监听页面卸载 - */ onUnload() { - if(this.audioCtx){ + if (this.closeTimer) clearTimeout(this.closeTimer); + if (this.audioCtx) { this.audioCtx.stop(); - if(this.audioCtx.destory){ - this.audioCtx.destory(); - } + if (this.audioCtx.destroy) this.audioCtx.destroy(); + this.audioCtx = null; } - }, - - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh() { - - }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom() { - - }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage() { - } -}) \ No newline at end of file +}); diff --git a/subpackage/teacher/resource-detail/resource-detail.json b/subpackage/teacher/resource-detail/resource-detail.json index d28dfb6..6cab79c 100644 --- a/subpackage/teacher/resource-detail/resource-detail.json +++ b/subpackage/teacher/resource-detail/resource-detail.json @@ -1,10 +1,9 @@ { "usingComponents": { "mp-bar": "weui-miniprogram/navigation-bar/navigation-bar", - "mp-icon": "weui-miniprogram/icon/icon", - "mp-half-screen-dialog": "weui-miniprogram/half-screen-dialog/half-screen-dialog" + "mp-icon": "weui-miniprogram/icon/icon" }, "backgroundColorContent": "#f7f7f7", "backgroundColor": "#f7f7f7", "navigationStyle": "custom" -} \ No newline at end of file +} diff --git a/subpackage/teacher/resource-detail/resource-detail.wxml b/subpackage/teacher/resource-detail/resource-detail.wxml index 81ee3a0..ee9e26c 100644 --- a/subpackage/teacher/resource-detail/resource-detail.wxml +++ b/subpackage/teacher/resource-detail/resource-detail.wxml @@ -1,32 +1,73 @@ - - - + + - - - {{data.resourceName}} - - {{value}} - {{duration}} + + + + + + + ♫ + + - - + {{data.resourceName || '暂无音频'}} + {{currentIndex + 1}} / {{playlist.length}} + + + + + + + + + {{value}} + {{duration}} + - - - - + + + {{isSingleLoop ? '单曲' : '列表'}} + + + + + + + + + 列表 - - - - 1 - - - \ No newline at end of file + + + + + 播放列表 + 共 {{playlist.length}} 首 + + × + + + 暂无可播放歌曲 + + {{index === currentIndex && isPlay ? '♪' : index + 1}} + {{item.resourceName}} + {{isPlay ? '播放中' : '当前'}} + + + + + diff --git a/subpackage/teacher/resource-detail/resource-detail.wxss b/subpackage/teacher/resource-detail/resource-detail.wxss index 1af1423..e33ffb5 100644 --- a/subpackage/teacher/resource-detail/resource-detail.wxss +++ b/subpackage/teacher/resource-detail/resource-detail.wxss @@ -1,78 +1,161 @@ -/* subpackage/teacher/resource-detail/resource-detail.wxss */ -.pad{ - padding: 0 30rpx; +.player-page { + min-height: 100vh; box-sizing: border-box; + padding: 0 30rpx 60rpx; + overflow: hidden; + background: linear-gradient(160deg, #42a4fc 0%, #7fc8ff 28%, #f4f8fc 64%, #f7f7f7 100%); } -.card{ - padding: 60rpx 30rpx; - box-sizing: border-box; - box-shadow: 0 10rpx 10rpx rgba(226, 222, 222,.4); - background-color: #fff; - border-radius: 20rpx; - margin-top: 30rpx; +.player-card { + margin-top: 38rpx; + padding: 66rpx 34rpx 54rpx; + border: 1rpx solid rgba(255, 255, 255, .75); + border-radius: 36rpx; + background: rgba(255, 255, 255, .94); + box-shadow: 0 24rpx 60rpx rgba(35, 116, 180, .18); text-align: center; } -.title{ - font-weight: bold; - font-size: 48rpx; -} - -.time{ - display: flex; - align-items: center; - justify-content: space-between; - color: #636363; - font-size: 32rpx; - margin-top: 100rpx; - margin-bottom: 20rpx; -} - -.progress{ - width: 100%; - height: 24rpx; - border-radius: 24rpx; - background-color: #e4e4e4; -} -.active{ - background-color: #FBB716; - border-radius: 24rpx; - height: 24rpx; - width: 10%; - transition: all 0.2s ease; -} - -.btn{ - background-color: #FBB716; +.record-wrap { + width: 330rpx; + height: 330rpx; + margin: 0 auto 52rpx; + padding: 18rpx; + box-sizing: border-box; border-radius: 50%; - width: 140rpx; - height: 140rpx; - margin: auto; + background: rgba(251, 183, 22, .16); + box-shadow: 0 18rpx 38rpx rgba(48, 66, 84, .2); +} + +.record { + position: relative; display: flex; align-items: center; justify-content: center; + width: 100%; + height: 100%; + border-radius: 50%; + background: repeating-radial-gradient(circle, #2d3741 0, #2d3741 10rpx, #202832 11rpx, #202832 17rpx); } -.btnlist{ +.record-playing .record { animation: recordRotate 7s linear infinite; } +.record-line { position: absolute; border: 2rpx solid rgba(255, 255, 255, .2); border-radius: 50%; } +.line-one { width: 210rpx; height: 210rpx; } +.line-two { width: 150rpx; height: 150rpx; } +.record-core { display: flex; - justify-content: space-between; align-items: center; - margin-top: 80rpx; + justify-content: center; + width: 108rpx; + height: 108rpx; + border: 12rpx solid #f7c143; + border-radius: 50%; + background: #fbb716; +} +.record-note { color: #fff; font-size: 52rpx; line-height: 1; } + +@keyframes recordRotate { from { transform: rotate(0); } to { transform: rotate(360deg); } } + +.song-name { + min-height: 58rpx; + overflow: hidden; + color: #1d2a36; + font-size: 42rpx; + font-weight: 600; + line-height: 58rpx; + text-overflow: ellipsis; + white-space: nowrap; } -.img{ - width: 64rpx; - height: 64rpx; - margin: 20rpx; +.song-count { margin-top: 10rpx; color: #96a0aa; font-size: 24rpx; } +.progress-area { margin-top: 70rpx; } +.progress { + width: 100%; + height: 10rpx; + border-radius: 10rpx; + background: #e5eaf0; +} +.active { position: relative; height: 10rpx; border-radius: 10rpx; background: linear-gradient(90deg, #ffd465, #fbb716); } +.progress-dot { + position: absolute; + top: -8rpx; + right: -13rpx; + width: 26rpx; + height: 26rpx; + border: 5rpx solid #fff; + border-radius: 50%; + background: #fbb716; + box-shadow: 0 3rpx 10rpx rgba(251, 183, 22, .55); +} +.time { display: flex; justify-content: space-between; margin-top: 18rpx; color: #87929d; font-size: 25rpx; } + +.btnlist { display: flex; align-items: center; justify-content: space-between; margin-top: 58rpx; } +.play-button { + display: flex; + align-items: center; + justify-content: center; + width: 142rpx; + height: 142rpx; + border-radius: 50%; + background: linear-gradient(145deg, #ffd052, #f5a900); + box-shadow: 0 16rpx 30rpx rgba(251, 183, 22, .35); +} +.switch-icon { width: 62rpx; height: 62rpx; padding: 12rpx; } +.tool-button { display: flex; flex-direction: column; align-items: center; min-width: 72rpx; color: #7e8994; font-size: 21rpx; } +.tool-icon { width: 50rpx; height: 50rpx; margin-bottom: 5rpx; } + +.playlist-mask { + position: fixed; + z-index: 99; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(13, 26, 39, .48); +} +.playlist-mask-enter { animation: maskFadeIn 240ms ease-out both; } +.playlist-mask-leave { animation: maskFadeOut 240ms ease-in both; } +.playlist-panel { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 38rpx 30rpx calc(24rpx + env(safe-area-inset-bottom)); + border-radius: 34rpx 34rpx 0 0; + background: #fff; + box-shadow: 0 -16rpx 50rpx rgba(18, 43, 65, .15); +} +.playlist-panel-enter { animation: playlistSlideUp 300ms cubic-bezier(.22, .8, .3, 1) both; } +.playlist-panel-leave { animation: playlistSlideDown 240ms ease-in both; } + +@keyframes maskFadeIn { + from { opacity: 0; } + to { opacity: 1; } } -.none{ - padding: 0; - margin: 0; - height: 0; +@keyframes maskFadeOut { + from { opacity: 1; } + to { opacity: 0; } } -.weui-half-screen-dialog__ft{ - padding: 0; -} \ No newline at end of file +@keyframes playlistSlideUp { + from { transform: translate3d(0, 100%, 0); } + to { transform: translate3d(0, 0, 0); } +} + +@keyframes playlistSlideDown { + from { transform: translate3d(0, 0, 0); } + to { transform: translate3d(0, 100%, 0); } +} +.playlist-header { display: flex; align-items: center; justify-content: space-between; padding: 0 10rpx 28rpx; } +.playlist-title { color: #172532; font-size: 36rpx; font-weight: 600; } +.playlist-subtitle { margin-top: 6rpx; color: #9aa4ad; font-size: 24rpx; } +.close-button { width: 64rpx; color: #8c969f; font-size: 48rpx; font-weight: 300; line-height: 64rpx; text-align: center; } +.playlist-scroll { max-height: 650rpx; } +.playlist-item { display: flex; align-items: center; min-height: 96rpx; padding: 0 22rpx; border-radius: 18rpx; color: #34424e; } +.playlist-active { color: #eaa400; background: #fff8e8; } +.song-index { width: 52rpx; flex-shrink: 0; color: #a0a9b2; font-size: 26rpx; text-align: left; } +.playlist-active .song-index { color: #f1ac00; } +.playlist-name { overflow: hidden; flex: 1; font-size: 29rpx; text-align: left; text-overflow: ellipsis; white-space: nowrap; } +.playing-label { margin-left: 20rpx; color: #f1ac00; font-size: 22rpx; } +.empty-list { padding: 100rpx 0; color: #a0a9b2; font-size: 28rpx; text-align: center; } diff --git a/subpackage/teacher/resource/resource.js b/subpackage/teacher/resource/resource.js index 79979c5..976d74d 100644 --- a/subpackage/teacher/resource/resource.js +++ b/subpackage/teacher/resource/resource.js @@ -59,10 +59,21 @@ Page({ }else if(this.data.id == 4){ return }else { - const data = e.currentTarget.dataset.item - data.id = this.data.id + const data = Object.assign({}, e.currentTarget.dataset.item, { id: this.data.id }) + const playlist = [] + const collectResources = (nodes) => { + (nodes || []).forEach((node) => { + (node.resourceDetails || []).forEach((item) => playlist.push(Object.assign({}, item, { id: this.data.id }))) + collectResources(node.children) + }) + } + collectResources(this.data.list) + const currentIndex = Math.max(playlist.findIndex((item) => item.resourceUrl === data.resourceUrl), 0) wx.navigateTo({ - url: '/subpackage/teacher/resource-detail/resource-detail?data='+JSON.stringify(data), + url: '/subpackage/teacher/resource-detail/resource-detail?data='+encodeURIComponent(JSON.stringify(data)), + success(res) { + res.eventChannel.emit('setPlaylist', { playlist, currentIndex }) + } }) } }, @@ -115,4 +126,4 @@ Page({ onShareAppMessage() { } -}) \ No newline at end of file +})