index copy 1.vue 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. <template>
  2. <div class="school">
  3. <div class="top">
  4. <div class="search">
  5. <image src="@/static/images/search.png" mode="" class="search_icon"></image>
  6. <div class="s_input"><u-input v-model="searchValue" type="text" :border="false" /></div>
  7. <div class="searh_btn">查询</div>
  8. </div>
  9. </div>
  10. <view class="CoursePage">
  11. <scroll-view :scroll-y="!detail.vis" class="CourseScrollBody">
  12. <!-- 悬浮窗 -->
  13. <view v-if="!detail.vis && showfu&&img" class="showfu" @click.stop="appectData($event)">
  14. <view class="imgBox">
  15. <image :src="img" mode="widthFix" style="width: 88rpx;height: 88rpx;"></image>
  16. </view>
  17. <image src="@/static/images/school/start.png" mode="widthFix" style="width: 40rpx;"></image>
  18. <image src="@/static/images/school/xx.png" mode="widthFix" style="width: 40rpx;margin-right: 28rpx;"
  19. @click.stop="clearSave"></image>
  20. </view>
  21. <div class="tabs">
  22. <u-tabs ref="tabs" :list="tabList" active-color="#F5222D" :show-bar="false" :current="curTab"
  23. @change="handleChangeTab"></u-tabs>
  24. </div>
  25. <view class="CourseBody">
  26. <view class="CourseList">
  27. <div v-if="courseList.length>0">
  28. <view class="CourseList-item" v-for="(item, i) in courseList" :key="item.id">
  29. <view class="ItemInfo">
  30. <image :src="item.cover" mode="aspectFill" class="ItemInfo-teamcher">
  31. <view class="Info-right">
  32. <view class="Right-title">{{item.name}}</view>
  33. <view class="Right-teacher">{{item.day}} 首席导师·{{item.author}}</view>
  34. <view class="Right-play no_open">
  35. <image v-if="play.ing && play.index === i"
  36. src="@/static/images/school/pause2.png" class="Play-icon"
  37. @click.stop="playSelf($event,item, i)" />
  38. <image v-else src="@/static/images/school/play2.png" class="Play-icon"
  39. @click.stop="playSelf($event,item, i)" />
  40. <view class="Play-Sound">
  41. <view class="SoundWave">
  42. <view v-for="ni in 20" :key="i + '_' + ni" class="Wave-line"
  43. :class="play.ing && play.index === i ? 'active' : ''" />
  44. </view>
  45. </view>
  46. <view class="Play-time">{{ item.seconds | mediaTimeFormatter }}
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. </view>
  52. <!-- <view class="CourseList-item">
  53. <view class="ItemInfo">
  54. <image src="@/static/images/school/teacher.png" mode="aspectFill"
  55. class="ItemInfo-teamcher">
  56. <view class="Info-right">
  57. <view class="Right-title">不得不听的学位争霸赛赛前课</view>
  58. <view class="Right-teacher">2024-10-20 首席导师·李老师</view>
  59. <view class="Right-play">
  60. <template>
  61. <image src="@/static/images/school/play2.png" class="Play-icon" />
  62. </template>
  63. <view class="Play-Sound">
  64. <view class="SoundWave">
  65. <view v-for="ni in 20" :key="i + '_' + ni" class="Wave-line"
  66. :class="play.ing && play.index === i ? 'active' : ''" />
  67. </view>
  68. </view>
  69. <view class="Play-time">120分钟
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. </view> -->
  75. </div>
  76. <div class="empty_image" v-else>
  77. <u-empty text="暂无课程"></u-empty>
  78. </div>
  79. <!-- <template v-if="courseList.length > 0">
  80. <view v-for="(item, i) in courseList" :key="item.id" class="CourseList-item"
  81. @click="toInfo(item, i)">
  82. <view class="ItemInfo">
  83. <image :src="item.cover" mode="aspectFill" class="ItemInfo-teamcher">
  84. <view class="Info-right">
  85. <view class="Right-title">{{ item.name }}</view>
  86. <view class="Right-teacher">{{ item.teacher_name }}</view>
  87. <view class="Right-play" :class="item.status ? '' : 'no_open'">
  88. <template v-if="item.status">
  89. <image v-if="play.ing && play.index === i"
  90. src="@/static/images/school/pause2.png" class="Play-icon"
  91. @click.stop="playSelf($event,item, i)" />
  92. <image v-else src="@/static/images/school/play2.png"
  93. class="Play-icon" @click.stop="playSelf($event,item, i)" />
  94. </template>
  95. <template v-else>
  96. <image src="@/static/images/school/play1.png" class="Play-icon" />
  97. </template>
  98. <view class="Play-Sound">
  99. <view class="SoundWave">
  100. <view v-for="ni in 20" :key="i + '_' + ni" class="Wave-line"
  101. :class="play.ing && play.index === i ? 'active' : ''" />
  102. </view>
  103. </view>
  104. <view class="Play-time">{{ item.seconds | mediaTimeFormatter }}
  105. </view>
  106. </view>
  107. </view>
  108. </view>
  109. </view>
  110. </template>
  111. <template v-else>
  112. <view class="noTip">暂无相关课程</view>
  113. </template> -->
  114. </view>
  115. </view>
  116. </scroll-view>
  117. <view v-if="detail.vis" class="CourseAudioDetail">
  118. <view class="CoursePlay">
  119. <view class="PlayTitle">{{ detail.info.title }}</view>
  120. <view class="PlayTeacher">{{ detail.info.teacher_name }}</view>
  121. <view class="PlayCover">
  122. <image class="CoverImg" mode="aspectFill" :src="detail.info.teacher_img"
  123. :class="play.ing ? 'start' : 'start paused'" />
  124. </view>
  125. <view class="AudioProgress">
  126. <view class="Progress-left">
  127. <audio-slide class="Audio-slide" :allTime="Number(detail.info.course_length)"
  128. :playTime.sync="play.time" @update:progress="moveAudioPlay" @touchStart="audioTouch" />
  129. </view>
  130. <image v-show="params.season > 33" src="@/static/images/school/xia.png" mode="widthFix"
  131. style="width: 60rpx;margin-left: 26rpx;"
  132. @click="goXia(detail.info.title,detail.info.down_link)"></image>
  133. <!-- <view class="Progress-right">倍数</view> -->
  134. </view>
  135. <view class="AudioControl">
  136. <image src="@/static/images/school/prev_15.png" mode="widthFix" @click="prevTime"></image>
  137. <image src="@/static/images/school/prev.png" mode="widthFix" @click="toPrev"></image>
  138. <image v-if="!play.ing" src="@/static/images/school/play.png" mode="widthFix"
  139. @click="detailPlay" />
  140. <image v-else src="@/static/images/school/pause.png" mode="widthFix" @click="detailPlay" />
  141. <image src="@/static/images/school/next.png" mode="widthFix" @click="toNext"></image>
  142. <image src="@/static/images/school/next_15.png" mode="widthFix" @click="nextTime"></image>
  143. </view>
  144. </view>
  145. </view>
  146. </view>
  147. </div>
  148. </template>
  149. <script>
  150. import {
  151. AudioSlide
  152. } from "@/components/audio-slide.vue"
  153. // import {
  154. // GetSeason
  155. // } from '../../api.js'
  156. import {
  157. mapState
  158. } from "vuex"
  159. export default {
  160. components: {
  161. AudioSlide
  162. },
  163. data() {
  164. return {
  165. typd: 0,
  166. saveData: {},
  167. showfu: false,
  168. title_list: [],
  169. title: '赛季点击此处选择',
  170. params: {
  171. page: 1,
  172. page_size: 15,
  173. week: 1,
  174. season: ''
  175. },
  176. page: 1,
  177. last: false,
  178. courseList: [],
  179. tabList: [{
  180. name: '全部'
  181. }],
  182. searchValue: '',
  183. curTab: 0,
  184. img: '',
  185. play: {
  186. self: null,
  187. index: -1,
  188. all: false,
  189. ing: false,
  190. time: 0,
  191. img: ''
  192. },
  193. detail: {
  194. vis: false,
  195. info: {}
  196. }
  197. }
  198. },
  199. computed: {
  200. ...mapState(['userServerInfo'])
  201. },
  202. watch: {
  203. 'params.week'(a) {
  204. if (this.tyed != 1) {
  205. this.toPause()
  206. this.play.ing = false
  207. this.play.index = -1
  208. this.params.page = 1
  209. this.getCourseList()
  210. console.log(0)
  211. } else {
  212. console.log(1)
  213. this.getCourseList()
  214. this.tyed = 0
  215. }
  216. },
  217. "play.all"(a) {
  218. if (a) {
  219. this.play.self.onEnded(() => {
  220. let len = this.courseList.length - 1
  221. if (this.play.index >= len) {
  222. this.play.index = 0
  223. this.play.all = false
  224. this.play.ing = false
  225. return false
  226. }
  227. let _i = this.play.index + 1
  228. if (!this.courseList[_i].status) {
  229. return false
  230. }
  231. this.toPlay(this.courseList[_i].course_link, this.courseList[_i].title, this.courseList[_i]
  232. .cover_url, () => {
  233. this.play.index = _i
  234. })
  235. if (this.detail.vis) {
  236. this.detail.info = this.courseList[_i]
  237. }
  238. })
  239. } else {
  240. this.play.self ? this.play.self.offEnded() : null
  241. }
  242. },
  243. "play.ing"(a) {
  244. if (a) {
  245. this.play.self.onTimeUpdate(() => {
  246. this.play.time = this.play.self.currentTime
  247. })
  248. this.play.self.onEnded(() => {
  249. if (!this.play.all) {
  250. this.toPause()
  251. this.play.time = 0
  252. }
  253. })
  254. } else {
  255. // this.play.self.offTimeUpdate()
  256. }
  257. },
  258. "detail.info": {
  259. handler(a) {
  260. if (a.course_link) {
  261. this.play.self.onTimeUpdate(() => {
  262. this.play.time = this.play.self.currentTime
  263. })
  264. }
  265. },
  266. deep: true,
  267. immediate: true
  268. }
  269. },
  270. filters: {
  271. dateFormatter: (timestamp, fmt) => {
  272. fmt = fmt || "yyyy-MM-dd";
  273. if (typeof timestamp === 'string') {
  274. timestamp = timestamp.replace(/-/g, '/')
  275. }
  276. const $this = new Date(timestamp);
  277. const o = {
  278. "M+": $this.getMonth() + 1,
  279. "d+": $this.getDate(),
  280. "h+": $this.getHours(),
  281. "m+": $this.getMinutes(),
  282. "s+": $this.getSeconds(),
  283. "q+": Math.floor(($this.getMonth() + 3) / 3),
  284. S: $this.getMilliseconds()
  285. };
  286. if (/(y+)/.test(fmt)) {
  287. fmt = fmt.replace(
  288. RegExp.$1,
  289. ($this.getFullYear() + "").substr(4 - RegExp.$1.length)
  290. );
  291. }
  292. for (var k in o) {
  293. if (new RegExp("(" + k + ")").test(fmt)) {
  294. fmt = fmt.replace(
  295. RegExp.$1,
  296. RegExp.$1.length === 1 ?
  297. o[k] :
  298. ("00" + o[k]).substr(("" + o[k]).length)
  299. );
  300. }
  301. }
  302. return fmt;
  303. },
  304. dateWeek(time) {
  305. if (typeof time === 'string') {
  306. time = time.replace(/-/g, '/')
  307. }
  308. let _d = new Date(time).getDay()
  309. let _a = ['日', '一', '二', '三', '四', '五', '六']
  310. return _a[_d]
  311. },
  312. mediaTimeFormatter: num => {
  313. if (!num) return "00:00";
  314. num = Math.floor(num);
  315. let hour = Math.floor(num / 3600);
  316. let minutes = Math.floor((num - hour * 3600) / 60);
  317. let second = num - hour * 3600 - minutes * 60;
  318. if (hour > 0) {
  319. return `${hour > 9 ? hour : "0" + hour}:${
  320. minutes > 9 ? minutes : "0" + minutes
  321. }:${second > 9 ? second : "0" + second}`;
  322. } else {
  323. return `${minutes > 9 ? minutes : "0" + minutes}:${
  324. second > 9 ? second : "0" + second
  325. }`;
  326. }
  327. }
  328. },
  329. onBackPress() {
  330. return false
  331. },
  332. onShow() {
  333. // 从聊天页面回来
  334. if (this.play.self && this.play.ing) { // 正在播放
  335. this.play.self.seek(this.play.time)
  336. this.play.self.play()
  337. } else if (this.play.self && !this.play.ing) { // 暂停播放,显示悬浮窗
  338. if (uni.getStorageSync('saveData')) {
  339. console.log(121212121)
  340. // this.getSave();
  341. // this.showfu = true
  342. // const obj = uni.getStorageSync('saveData')
  343. // this.img = obj.data.teacher_img
  344. }
  345. }
  346. },
  347. onHide() {
  348. // 离开小程序,去聊天
  349. if (this.play.self && !this.play.ing) { // 暂停播放,存储数据
  350. console.log(1121215)
  351. this.saveData.params = this.params
  352. this.saveData.play = this.play
  353. uni.setStorageSync('saveData', this.saveData)
  354. console.log(console.log('存储的saveData', uni.getStorageSync('saveData')))
  355. this.showfu = true
  356. }
  357. },
  358. destroyed() {
  359. // this.toPause()
  360. },
  361. onLoad(e) {
  362. // 从首页进入小程序
  363. // this.getSeasonList()
  364. console.log(uni.getStorageSync('saveData'), 'onload中的saveDate')
  365. // this.getSave();
  366. if (e.week) {
  367. this.params.week = Number(e.week)
  368. }
  369. this.getCategoryLlist()
  370. this.getCourseList()
  371. },
  372. onUnload() {
  373. console.log('onunload')
  374. // 返回首页,存储数据
  375. if (this.play.index != -1) {
  376. this.saveData.params = this.params
  377. this.saveData.play = this.play
  378. uni.setStorageSync('saveData', this.saveData)
  379. console.log(console.log('跳转页面存储的saveData', uni.getStorageSync('saveData')))
  380. }
  381. },
  382. methods: {
  383. // 获取缓存的数据
  384. getSave() {
  385. if (uni.getStorageSync('saveData')) {
  386. this.showfu = true
  387. const obj = uni.getStorageSync('saveData')
  388. if (obj.play && obj.data) {
  389. const {
  390. index,
  391. ing,
  392. time
  393. } = obj.play
  394. this.play.index = index
  395. this.play.ing = ing
  396. const {
  397. course_link,
  398. cover_url,
  399. title,
  400. teacher_img
  401. } = obj.data
  402. this.play.self.src = course_link
  403. this.play.self.coverImgUrl = cover_url
  404. this.play.self.title = title
  405. this.img = obj.data.teacher_img
  406. }
  407. }
  408. },
  409. //下载音频文件
  410. goXia(title, url) {
  411. let that = this
  412. const filePath = wx.env.USER_DATA_PATH + '/' + title + '.mp4'
  413. const downloadTask = uni.downloadFile({
  414. url: url,
  415. filePath: filePath,
  416. success: (res) => {
  417. if (res.statusCode === 200) {
  418. wx.saveVideoToPhotosAlbum({
  419. filePath: filePath,
  420. success: function(red) {
  421. uni.showToast({
  422. title: '下载成功',
  423. icon: 'none'
  424. })
  425. },
  426. fail: function(err) {
  427. uni.showToast({
  428. title: '下载失败',
  429. icon: 'none'
  430. })
  431. }
  432. })
  433. } else {
  434. uni.showToast({
  435. title: '保存失败',
  436. icon: 'none'
  437. })
  438. }
  439. }
  440. })
  441. downloadTask.onProgressUpdate((res) => {
  442. // console.log('下载进度' + res.progress);
  443. uni.showToast({
  444. title: '下载进度' + res.progress + '%',
  445. icon: 'none'
  446. })
  447. // console.log('已经下载的数据长度' + res.totalBytesWritten);
  448. // console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);
  449. })
  450. },
  451. clearSave() {
  452. uni.removeStorageSync('saveData')
  453. this.showfu = false
  454. },
  455. appectData(e) {
  456. const data = uni.getStorageSync('saveData')
  457. if (data.params.week === this.params.week) {
  458. this.tyed = 0
  459. } else {
  460. this.tyed = 1
  461. }
  462. this.params = data.params
  463. this.getSeason(this.params.season)
  464. console.log(this.title_list)
  465. this.play.index = data.play.index
  466. this.play.self.src = data.data.course_link
  467. this.play.time = data.play.time
  468. console.log('play.time', this.play.time)
  469. this.playSelfd(e, data.data, this.play.index) //列表播放
  470. uni.removeStorageSync('saveData')
  471. this.showfu = false
  472. this.toInfo(data.data, this.play.index)
  473. },
  474. // 列表里的暂停播放按钮
  475. playSelfd(e, data, i) {
  476. this.saveData.data = data
  477. uni.removeStorageSync('saveData')
  478. e.stopPropagation()
  479. // this.toPlayd(data.path, data.title, data.cover, () => {
  480. this.toPlayd('https://img.tukuppt.com/newpreview_music/09/00/32/5c89189c4f4cf81405.mp3', data.title, data.cover, () => {
  481. console.log(1, this.play)
  482. this.play.index = i
  483. })
  484. },
  485. toPlayd(src, cb) {
  486. this.play.ing ? this.play.self.pause() : null
  487. this.play.self.src = src;
  488. this.play.self.seek(this.play.time)
  489. this.play.self.play()
  490. this.play.ing = true
  491. cb && cb()
  492. },
  493. getSeason(e) {
  494. // if (e === this.params.season) {
  495. // this.tyed = 0
  496. // } else {
  497. // this.tyed = 1
  498. // }
  499. let i = this.title_list.findIndex(item => item.season == e)
  500. this.title = this.title_list[i].name
  501. this.season = this.title_list[i].season
  502. this.getCourseList()
  503. },
  504. getSeasonList() {
  505. this.$ajax.get(`${GetSeason}`).then(([, {
  506. data: res
  507. }]) => {
  508. if (res.code === 200) {
  509. var arr = res.data
  510. arr.forEach((item, i) => {
  511. item.name = '第' + item.season + '届培训课程表'
  512. })
  513. this.title_list = arr
  514. this.title = this.title_list[0].name
  515. this.season = res.data[0].season
  516. uni.hideLoading()
  517. this.getCourseList()
  518. this.init()
  519. }
  520. })
  521. },
  522. titlePicker(e) {
  523. console.log(e.target.value)
  524. this.title = this.title_list[e.target.value].name
  525. this.season = this.title_list[e.target.value].season
  526. this.toPause()
  527. this.play.ing = false
  528. this.play.index = -1
  529. this.params.page = 1
  530. this.getCourseList()
  531. },
  532. audioTouch() {
  533. this.toPause()
  534. },
  535. mockend() {
  536. this.play.self.seek(212)
  537. },
  538. toBack() {
  539. if (this.detail.vis) {
  540. this.detail.time = 0
  541. this.detail.info = {}
  542. this.detail.vis = false
  543. if (!this.play.ing) { //暂停状态返回列表,显示悬浮窗
  544. this.saveData.params = this.params
  545. this.saveData.play = this.play
  546. uni.setStorageSync('saveData', this.saveData)
  547. this.img = this.saveData.data.teacher_img
  548. console.log(console.log('11存储的saveData1', uni.getStorageSync('saveData')))
  549. this.showfu = true
  550. }
  551. } else {
  552. // console.log(111,this.play.self)
  553. // uni.setStorageSync('floating', this.play)
  554. uni.navigateBack()
  555. }
  556. },
  557. init() {
  558. // this.play.self = uni.createInnerAudioContext()
  559. this.play.self = uni.getBackgroundAudioManager()
  560. },
  561. toPlay(src, title, cover_rul, cb) {
  562. // debugger;
  563. console.log(src, title, cover_rul)
  564. // debugger
  565. this.play.ing ? this.play.self.pause() : null
  566. this.play.self = uni.getBackgroundAudioManager();
  567. console.log('debugger',this.play.self)
  568. this.play.self.title = title;
  569. // this.play.self.coverImgUrl = cover_rul;
  570. this.play.self.src = encodeURI(src)
  571. // this.play.ing = true
  572. // wx.setInnerAudioOption({
  573. // obeyMuteSwitch: false,
  574. // success: function(e) {
  575. // console.log('play success')
  576. // },
  577. // fail: function(e) {
  578. // console.log(e)
  579. // console.log('play fail')
  580. // }
  581. // })
  582. cb && cb()
  583. },
  584. toPause() {
  585. if (!this.play.ing) {
  586. return false
  587. }
  588. this.play.ing = false
  589. this.play.self.pause()
  590. },
  591. playAll() {
  592. if (this.courseList.length === 0) {
  593. uni.showModal({
  594. content: "没有可播放的课程",
  595. showCancel: false
  596. })
  597. return false
  598. }
  599. let _this = this
  600. if (this.play.ing) {
  601. if (this.play.all) {
  602. this.toPause()
  603. } else {
  604. if (this.play.index === -1) {
  605. this.toPause()
  606. } else {
  607. this.play.all = true
  608. }
  609. }
  610. return false
  611. }
  612. if (this.play.index === -1) {
  613. this.toPlay(this.courseList[0].course_link, this.courseList[0].title, this.courseList[0].cover_url,
  614. () => {
  615. this.play.all = true
  616. this.play.index = 0
  617. })
  618. } else {
  619. this.play.ing = true;
  620. this.play.self.play()
  621. }
  622. },
  623. // 列表里的暂停播放按钮
  624. playSelf(e, data, i) {
  625. this.saveData.data = data
  626. uni.removeStorageSync('saveData')
  627. this.showfu = false
  628. e.stopPropagation()
  629. if (this.play.ing && this.play.index === i) {
  630. this.toPause()
  631. return false
  632. }
  633. this.toPlay('https://img.tukuppt.com/newpreview_music/09/00/32/5c89189c4f4cf81405.mp3', data.name, data.cover, () => {
  634. console.log(1, this.play)
  635. this.play.index = i
  636. })
  637. },
  638. //点击课程分类
  639. handleChangeTab(index) {
  640. this.curTab = index
  641. this.resetList()
  642. },
  643. //课程分类
  644. getCategoryLlist() {
  645. this.$u.get('/dwbs/business/category/select-options').then(res => {
  646. console.log(res)
  647. this.tabList = [{
  648. id: 0,
  649. name: '全部'
  650. }].concat(res.data)
  651. })
  652. },
  653. //重置列表请求
  654. resetList() {
  655. this.page = 1
  656. this.last = false
  657. this.courseList = []
  658. this.getCourseList()
  659. },
  660. //课程列表
  661. getCourseList() {
  662. let index = this.curTab
  663. console.log(this.curTab)
  664. this.$u.get('/dwbs/business/schools', {
  665. page: this.page,
  666. name: this.searchValue,
  667. category_id: this.tabList[index].id !== 0 ? this.tabList[index].id : ''
  668. }).then(res => {
  669. let data = res.data.data
  670. if (this.page > 1 && data.length == 0) {
  671. uni.showToast({
  672. title: '暂无更多',
  673. icon: 'none'
  674. })
  675. this.last = true
  676. } else {
  677. this.courseList = this.courseList.concat(data)
  678. }
  679. })
  680. },
  681. toPrev() {
  682. if (this.play.index === 0) {
  683. uni.showModal({
  684. content: "前面没有课程了",
  685. showCancel: false
  686. })
  687. return false
  688. }
  689. let _i = this.play.index - 1
  690. if (!this.courseList[_i].status) {
  691. uni.showModal({
  692. content: "上一个课程还未开始",
  693. showCancel: false
  694. })
  695. return false
  696. }
  697. this.play.time = 0
  698. this.toPlay(this.courseList[_i].course_link, this.courseList[_i].title, this.courseList[_i].cover_url,
  699. () => {
  700. this.play.index = _i
  701. })
  702. this.detail.info = Object.assign({}, this.courseList[_i])
  703. },
  704. toNext() {
  705. let max = this.courseList.length - 1
  706. if (this.play.index >= max) {
  707. uni.showModal({
  708. content: "后面没有课程了",
  709. showCancel: false
  710. })
  711. return false
  712. }
  713. let _i = this.play.index + 1
  714. if (!this.courseList[_i].status) {
  715. uni.showModal({
  716. content: "下一个课程还未开始",
  717. showCancel: false
  718. })
  719. return false
  720. }
  721. this.play.time = 0
  722. this.toPlay(this.courseList[_i].course_link, this.courseList[_i].title, this.courseList[_i].cover_url,
  723. () => {
  724. this.play.index = _i
  725. })
  726. this.detail.info = Object.assign({}, this.courseList[_i])
  727. },
  728. toInfo(data, i) {
  729. uni.removeStorageSync('saveData')
  730. console.log(uni.getStorageInfo('saveData'), '点击详情的save')
  731. console.log(data, 'data')
  732. this.saveData.data = data
  733. this.showfu = false
  734. if (!data.status) {
  735. uni.showModal({
  736. content: '课程还未开始',
  737. showCancel: false
  738. })
  739. return false
  740. }
  741. if (i !== this.play.index) {
  742. // this.play.self.src = data.course_link
  743. this.play.ing ? this.toPause() : null
  744. this.play.index = i
  745. this.play.time = 0
  746. this.play.self.seek(this.play.time)
  747. }
  748. this.detail.info = data
  749. this.detail.vis = true
  750. },
  751. moveAudioPlay({
  752. value
  753. }) {
  754. this.play.time = value
  755. this.play.self.seek(value)
  756. this.toPlay()
  757. },
  758. // 倒退15秒
  759. prevTime() {
  760. this.play.time = this.play.time > 15 ? this.play.time - 15 : 0
  761. this.play.self.seek(this.play.time)
  762. },
  763. // 快进15秒
  764. nextTime() {
  765. let max = Number(this.detail.info.course_length)
  766. this.play.time = this.play.time < max ? this.play.time + 15 : max
  767. this.play.self.seek(this.play.time)
  768. },
  769. // 播放详情里的 播放和暂停
  770. detailPlay() {
  771. if (this.play.ing) { // 暂停
  772. this.toPause()
  773. } else { // 播放
  774. const {
  775. title,
  776. cover_rul,
  777. course_link
  778. } = this.detail.info
  779. this.play.self = uni.getBackgroundAudioManager();
  780. this.play.self.title = title;
  781. this.play.self.coverImgUrl = cover_rul;
  782. this.play.self.src = course_link
  783. // this.play.self.play();
  784. this.play.ing = true;
  785. wx.setInnerAudioOption({
  786. obeyMuteSwitch: false,
  787. success: function(e) {
  788. console.log(e)
  789. console.log('play success')
  790. },
  791. fail: function(e) {
  792. console.log(e)
  793. console.log('play fail')
  794. }
  795. })
  796. }
  797. }
  798. }
  799. }
  800. </script>
  801. <style lang="scss" scoped>
  802. page {
  803. background-color: #f5f5f5;
  804. }
  805. .top {
  806. padding: 12px;
  807. background-color: #FFFFFF;
  808. }
  809. .search {
  810. background: #F9F9FB;
  811. height: 40px;
  812. line-height: 40px;
  813. border-radius: 20px;
  814. display: flex;
  815. align-items: center;
  816. padding: 0 12px;
  817. .search_icon {
  818. width: 24px;
  819. height: 24px;
  820. margin-right: 5px;
  821. }
  822. .s_input {
  823. flex: 1
  824. }
  825. .searh_btn {
  826. background: linear-gradient(91deg, #FF232C 0%, #FF571B 99%);
  827. border-radius: 20px;
  828. text-align: center;
  829. height: 32px;
  830. width: 66px;
  831. line-height: 32px;
  832. font-size: 14px;
  833. color: #FFFFFF;
  834. }
  835. }
  836. .showfu {
  837. width: 268rpx;
  838. height: 96rpx;
  839. background: #5B5B5B;
  840. box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.16);
  841. border-radius: 50rpx;
  842. position: fixed;
  843. right: 44rpx;
  844. bottom: 80rpx;
  845. display: flex;
  846. justify-content: space-between;
  847. align-items: center;
  848. .imgBox {
  849. width: 96rpx;
  850. height: 96rpx;
  851. border: 6rpx solid #FFFFFF;
  852. border-radius: 50%;
  853. overflow: hidden;
  854. }
  855. }
  856. .select {
  857. margin-top: 20rpx;
  858. padding-left: 30rpx;
  859. font-size: 34rpx;
  860. }
  861. .noTip {
  862. padding: 20rpx;
  863. text-align: center;
  864. width: 100%;
  865. color: #999999;
  866. }
  867. $rotate: 0deg;
  868. .CoursePage {
  869. background-color: #FFFFFF;
  870. margin-top: 10px;
  871. border-radius: 10px 10px 0px 0px;
  872. @include page();
  873. display: flex;
  874. flex-direction: column;
  875. justify-content: space-between;
  876. .CourseAudioDetail {
  877. @include page();
  878. position: fixed;
  879. height: 100%;
  880. bottom: 0;
  881. left: 0;
  882. right: 0;
  883. background-color: #FFFFFF;
  884. overflow: hidden;
  885. .CoursePlay {
  886. padding: 30rpx;
  887. width: 100%;
  888. box-sizing: border-box;
  889. display: flex;
  890. align-items: center;
  891. justify-content: flex-start;
  892. flex-direction: column;
  893. .PlayTitle {
  894. width: 100%;
  895. color: #333333;
  896. font-size: 40rpx;
  897. line-height: 60rpx;
  898. text-align: center;
  899. margin-bottom: 40rpx;
  900. }
  901. .PlayTeacher {
  902. color: #999999;
  903. font-size: 32rpx;
  904. line-height: 60rpx;
  905. text-align: center;
  906. margin-bottom: 40rpx;
  907. }
  908. .PlayCover {
  909. width: 496rpx;
  910. height: 496rpx;
  911. border-radius: 50%;
  912. background-color: #333333;
  913. padding: 26rpx;
  914. box-sizing: border-box;
  915. .CoverImg {
  916. display: block;
  917. width: 100%;
  918. height: 100%;
  919. border-radius: 50%;
  920. &.start {
  921. animation: rotate 10s 0s infinite linear;
  922. }
  923. &.paused {
  924. animation-play-state: paused;
  925. }
  926. }
  927. margin-bottom: 150rpx;
  928. }
  929. .AudioProgress {
  930. width: 100%;
  931. display: flex;
  932. align-items: center;
  933. justify-content: space-between;
  934. margin-bottom: 50rpx;
  935. .Progress-right {
  936. color: #EA4A41;
  937. font-size: 24rpx;
  938. margin-left: 30px;
  939. }
  940. .Progress-left {
  941. flex: 1;
  942. min-width: 0;
  943. .Audio-slide {
  944. margin: 0;
  945. }
  946. }
  947. }
  948. .AudioControl {
  949. display: flex;
  950. align-items: center;
  951. justify-content: space-between;
  952. width: 100%;
  953. image {
  954. &:nth-of-type(1),
  955. &:nth-last-of-type(1) {
  956. width: 43rpx;
  957. height: 38rpx;
  958. }
  959. &:nth-of-type(2),
  960. &:nth-last-of-type(2) {
  961. width: 38rpx;
  962. height: 46rpx;
  963. }
  964. &:nth-of-type(3) {
  965. width: 124rpx;
  966. height: 124rpx;
  967. }
  968. }
  969. }
  970. }
  971. }
  972. .CourseScrollBody {
  973. width: 100%;
  974. flex: 1;
  975. overflow: hidden;
  976. position: relative;
  977. }
  978. }
  979. .CourseBody {
  980. width: 100%;
  981. padding: 0 30rpx 30rpx;
  982. box-sizing: border-box;
  983. .CourseWeek {
  984. width: 100%;
  985. display: flex;
  986. align-items: center;
  987. justify-content: space-between;
  988. margin-bottom: 60rpx;
  989. .week {
  990. // width: 192rpx;
  991. padding: 0 30rpx;
  992. height: 68rpx;
  993. border-radius: 68rpx;
  994. text-align: center;
  995. line-height: 68rpx;
  996. background: #F8F8F8;
  997. color: #999999;
  998. font-size: 28rpx;
  999. &.active {
  1000. color: #FFFFFF !important;
  1001. background: linear-gradient(to right, #F97C55, #F44545) !important;
  1002. }
  1003. }
  1004. }
  1005. .CourseList {
  1006. &-item {
  1007. margin-bottom: 40rpx;
  1008. background: #F6F6F6;
  1009. border-radius: 5px;
  1010. &:nth-last-of-type(1) {
  1011. margin-bottom: 0;
  1012. }
  1013. .ItemTitle {
  1014. color: #333333;
  1015. font-size: 32rpx;
  1016. line-height: 44rpx;
  1017. margin-bottom: 30rpx;
  1018. display: flex;
  1019. align-items: center;
  1020. justify-content: space-between;
  1021. &-status {
  1022. height: 44rpx;
  1023. line-height: 44rpx;
  1024. width: 118rpx;
  1025. border: 2rpx solid #999999;
  1026. color: #999999;
  1027. text-align: center;
  1028. font-size: 28rpx;
  1029. box-sizing: border-box;
  1030. &.active {
  1031. border-color: #EA4A41 !important;
  1032. color: #EA4A41 !important;
  1033. }
  1034. }
  1035. }
  1036. .ItemInfo {
  1037. width: 100%;
  1038. display: flex;
  1039. align-items: stretch;
  1040. justify-content: space-between;
  1041. .ItemInfo-teamcher {
  1042. display: block;
  1043. width: 180rpx;
  1044. height: 234rpx;
  1045. }
  1046. .Info-right {
  1047. flex: 1;
  1048. overflow: hidden;
  1049. margin-left: 16rpx;
  1050. display: flex;
  1051. justify-content: space-between;
  1052. flex-direction: column;
  1053. align-items: flex-start;
  1054. padding-top: 4px;
  1055. .Right-title {
  1056. color: #333333;
  1057. font-size: 32rpx;
  1058. line-height: 44rpx;
  1059. }
  1060. .Right-teacher {
  1061. color: #999999;
  1062. font-size: 28rpx;
  1063. line-height: 40rpx;
  1064. }
  1065. .Right-play {
  1066. width: 422rpx;
  1067. height: 60rpx;
  1068. padding: 12rpx 14rpx;
  1069. box-sizing: border-box;
  1070. display: flex;
  1071. align-items: center;
  1072. background: linear-gradient(to right, #F97C55, #F44545);
  1073. border-radius: 60rpx;
  1074. margin-bottom: 22rpx;
  1075. display: flex;
  1076. align-items: center;
  1077. justify-content: space-between;
  1078. &.no_open {
  1079. background: #F8F8F8 !important;
  1080. .Play-time {
  1081. color: #999999 !important;
  1082. }
  1083. /deep/ .Wave-line {
  1084. background: #999999 !important;
  1085. }
  1086. }
  1087. .Play-icon {
  1088. display: block;
  1089. width: 36rpx;
  1090. height: 36rpx;
  1091. }
  1092. .Play-time {
  1093. color: #FFFFFF;
  1094. font-size: 28rpx;
  1095. }
  1096. .Play-Sound {
  1097. flex: 1;
  1098. height: 100%;
  1099. overflow: hidden;
  1100. margin: 0 20rpx;
  1101. }
  1102. }
  1103. }
  1104. }
  1105. }
  1106. }
  1107. }
  1108. .SoundWave {
  1109. width: 100%;
  1110. height: 100%;
  1111. display: flex;
  1112. align-items: center;
  1113. justify-content: space-between;
  1114. .Wave-line {
  1115. width: 4rpx;
  1116. background: #FFFFFF;
  1117. border-radius: 4rpx;
  1118. @for $i from 1 through 20 {
  1119. &:nth-of-type(#{$i}) {
  1120. height: #{random(40)}rpx;
  1121. }
  1122. }
  1123. &.active {
  1124. @for $i from 1 through 20 {
  1125. &:nth-of-type(#{$i}) {
  1126. animation: load 2.5s #{(random(10)*0.2)+ 1}s infinite linear;
  1127. }
  1128. }
  1129. }
  1130. }
  1131. }
  1132. @keyframes load {
  1133. 0% {
  1134. height: 100%;
  1135. }
  1136. 30% {
  1137. height: 20%;
  1138. }
  1139. 60% {
  1140. height: 60%;
  1141. }
  1142. 100% {
  1143. height: 10%;
  1144. }
  1145. }
  1146. @keyframes rotate {
  1147. 100% {
  1148. transform: rotate(360deg);
  1149. }
  1150. }
  1151. </style>