detail.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. <template>
  2. <view>
  3. <view style="position: fixed;width: 100%;z-index: 999;background: #FFFFFF;top: 0;" id="top">
  4. <view class="video_box" v-if="!startStatus">
  5. <image :src="$method.splitImgHost(detail.coverUrl)" style="width: 100%;height: 460rpx;"></image>
  6. <image v-if="false" class="video_play" src="/static/play.png" @click="startVideo"></image>
  7. </view>
  8. <view v-else class="video_box" style="width: 100%;height: 460rpx;">
  9. <polyv-player
  10. id="playerVideo"
  11. playerId="playerVideo"
  12. height="460rpx"
  13. :vid="vid"
  14. :showSettingBtn="true"
  15. :enablePlayGesture="true"
  16. @statechange="onStateChange"
  17. :autoplay="autoplay"
  18. :isAllowSeek="isAllowSeek"
  19. :playbackRate="playbackRate"
  20. ></polyv-player>
  21. </view>
  22. <view>
  23. <u-row>
  24. <u-col span="10">
  25. <view class="video_t1">{{ detail.courseName }}</view>
  26. </u-col>
  27. <u-col span="2">
  28. <view class="video_t1_t" @click="openPhoto">
  29. <image src="/static/icon/jy_icon.png" style="width: 40rpx;height: 40rpx;"></image>
  30. 讲义
  31. </view>
  32. </u-col>
  33. </u-row>
  34. </view>
  35. <u-line color="#D6D6DB" />
  36. <view style="display: flex;justify-content: center;">
  37. <view style="width: 280px;">
  38. <u-tabs :list="list" font-size="24" bar-width="80" :current="current" @change="change" active-color="#007AFF"></u-tabs>
  39. </view>
  40. </view>
  41. <u-line color="#D6D6DB" />
  42. </view>
  43. <view class="box">
  44. <!--目录 -->
  45. <view v-show="current == 0">
  46. <view class="menuBox" v-for="(item, index) in reMenuList">
  47. <!--模块 -->
  48. <view v-if="item.type == 1"><courseModule :isRebuild="true" :isBuy="true" :menuItem="item" :levelId="item.menuId"></courseModule></view>
  49. <!--章 -->
  50. <view v-if="item.type == 2"><courseChapter :isRebuild="true" :isBuy="true" :menuItem="item" :levelId="'0-'+item.menuId"></courseChapter></view>
  51. <!--节 -->
  52. <view v-if="item.type == 3"><courseSection :isRebuild="true" :isBuy="true" :menuItem="item" :levelId="'0-0-'+item.menuId"></courseSection></view>
  53. </view>
  54. </view>
  55. <!--目录 -->
  56. <view v-show="current == 1">
  57. <view class="menuBox" v-for="(item, index) in menuList">
  58. <!--模块 -->
  59. <view v-if="item.type == 1"><courseModule :isBuy="true" :menuItem="item" :levelId="item.menuId"></courseModule></view>
  60. <!--章 -->
  61. <view v-if="item.type == 2"><courseChapter :isBuy="true" :menuItem="item" :levelId="'0-'+item.menuId"></courseChapter></view>
  62. <!--节 -->
  63. <view v-if="item.type == 3"><courseSection :isBuy="true" :menuItem="item" :levelId="'0-0-'+item.menuId"></courseSection></view>
  64. </view>
  65. </view>
  66. <!--笔记 -->
  67. <view v-show="current == 2">
  68. <view class="inputBottom">
  69. <view style="width: 10%;"><image src="/static/icon/note3.png" style="width: 39rpx;height: 39rpx;margin:0 29rpx;"></image></view>
  70. <view style="width: 73%;height: 88rpx;margin-bottom: 15rpx;">
  71. <u-input height="78" fixed="true" :placeholder="placeholder" type="textarea" :custom-style="inputStyle" v-model="value" />
  72. </view>
  73. <view style="color: #007AFF;font-size: 30rpx;font-weight: bold;width: 15%;text-align: center;">提交</view>
  74. </view>
  75. <view v-for="(item, index) in menuList">
  76. <view class="dateBox">2021年10月30日</view>
  77. <view class="noteBox">
  78. <view class="tBox">
  79. <image src="/static/icon/note1.png" style="width: 39rpx;height: 39rpx;margin:0 29rpx;"></image>
  80. <view class="title leftPadding">施工承发包模式-施工合同与物资采购合同</view>
  81. </view>
  82. <view class="tBox2">
  83. <view class="title" style="width: 39rpx;height: 39rpx;margin:0 29rpx;">00:20</view>
  84. <view class="t2Content leftPadding">这是一段用户记录的笔记本文,当内容过长时 需要换行,完整显示文字内容。</view>
  85. </view>
  86. <view class="tBox">
  87. <image src="/static/icon/note2.png" style="width: 39rpx;height: 39rpx;margin:0 29rpx;"></image>
  88. <view class="title leftPadding">施工承发包模式-施工合同与物资采购合同</view>
  89. </view>
  90. <view style="margin-left: 97rpx;" class="t2Content leftPadding">这是一段用户记录的笔记本文,当内容过长时 需要换行,完整显示文字内容。</view>
  91. </view>
  92. </view>
  93. </view>
  94. <!--答疑 -->
  95. <view v-show="current == 3">
  96. <view class="inputBottom">
  97. <view style="width: 73%;height: 88rpx;margin-bottom: 15rpx;margin-left: 10% ;">
  98. <u-input height="78" fixed="true" placeholder="您可以在这里输入答疑内容" type="textarea" :custom-style="inputStyle" v-model="value" />
  99. </view>
  100. <view style="color: #007AFF;font-size: 30rpx;font-weight: bold;width: 15%;text-align: center;">提交</view>
  101. </view>
  102. <view v-for="(item, index) in menuList" style="background-color: #FFFFFF;">
  103. <view class="chat_box">
  104. <view><image src="https://file-dev.xyyxt.net/oss/images/avatar/20210623/1624414559368_44562477.png" style="width: 64rpx;height: 64rpx;"></image></view>
  105. <view style="margin-left: 15rpx;">
  106. <view class="chat1">倪虹洁</view>
  107. <view class="chat2">2021/10/31 09:36:23</view>
  108. <view class="chat3">老师的课讲得太棒了!</view>
  109. </view>
  110. </view>
  111. <u-line color="#D6D6DB" />
  112. </view>
  113. </view>
  114. </view>
  115. <!-- 播放前拍照start -->
  116. <u-popup v-model="photoPopup" mode="bottom" border-radius="32" :mask-close-able="false">
  117. <view class="photoBox">
  118. <view class="photoTop">
  119. <view class="sqzz" v-if="true">
  120. <u-icon name="close" color="#333333" size="30" @click="closePhoto"></u-icon>
  121. </view>
  122. <view class="centersq">
  123. 请正视手机屏幕
  124. </view>
  125. <view class="sqzz">
  126. </view>
  127. </view>
  128. <view class="photoCenter">
  129. <camera device-position="front" flash="off" @error="error" style="width: 100%; height: 100%" v-if="photoPopup"></camera>
  130. <view class="custom">
  131. <image src="@/pages2/static/zhezhao.png" mode=""></image>
  132. </view>
  133. </view>
  134. <view class="btnResult" @click="takePhoto">
  135. 拍照
  136. </view>
  137. </view>
  138. </u-popup>
  139. <!-- 播放前拍照end -->
  140. </view>
  141. </template>
  142. <script>
  143. import eventHub from '@/common/eventHub.js';
  144. import courseModule from '@/components/course/courseModule.vue';
  145. import courseChapter from '@/components/course/courseChapter.vue';
  146. import courseSection from '@/components/course/courseSection.vue';
  147. import { mapGetters } from 'vuex';
  148. export default {
  149. components: {
  150. courseModule,
  151. courseChapter,
  152. courseSection
  153. },
  154. data() {
  155. return {
  156. startStatus: false,
  157. detail: {},
  158. courseId: 0,
  159. placeholder: '您可以在这里输入笔记内容\n还可以点击左侧图标为笔记加上时间标记',
  160. inputStyle: {
  161. background: 'rgba(244, 244, 244, 0.98)',
  162. borderRadius: '24rpx',
  163. padding: '8rpx',
  164. marginBottom: '10rpx'
  165. },
  166. playbackRate: [0.5, 0.8, 1.0],
  167. list: [
  168. {
  169. name: '重修目录'
  170. },
  171. {
  172. name: '目录'
  173. },
  174. {
  175. name: '笔记'
  176. },
  177. {
  178. name: '答疑'
  179. }
  180. ],
  181. menuList: [
  182. ],
  183. current: 1,
  184. vid:'',
  185. goodsId:0,
  186. goodsData:{},
  187. photoPopup:false,
  188. goodsPlayConfig:null,
  189. autoplay:false,
  190. isAllowSeek:'no',
  191. playbackRate: [1.0],
  192. timer:null,
  193. goodsPhotographConfig:null,
  194. intervalTimeList:[],// 间隔拍照时长
  195. intervalTimeIndex:0 ,//当前处于哪个时间段拍照
  196. playTime:0 ,//页面播放时长,不含暂停
  197. currentTime:0,
  198. avatarUrl:'',
  199. ossAvatarUrl:'',
  200. studyDuration:0, // 当前视频时长
  201. gradeId:0,
  202. chapterId:0,
  203. moduleId:0,
  204. reMenuList: [
  205. ],
  206. };
  207. },
  208. onUnload() {},
  209. computed: { ...mapGetters(['userInfo','playSectionId']) },
  210. onLoad(option) {
  211. this.courseId = option.id;
  212. this.goodsId = uni.getStorageSync('courseGoodsId');
  213. this.courseDetail();
  214. this.getMenuList();
  215. this.getGoodsDetail()
  216. },
  217. onShow() {},
  218. onUnload() {
  219. if(this.playSectionId>0){
  220. //退出提交记录
  221. this.ossAvatarUrl = ""
  222. this.postStudyRecord()
  223. //清除正在播放的节ID
  224. this.$store.commit('setPlaySectionId', {playSectionId :0});
  225. }
  226. },
  227. mounted() {
  228. eventHub.$on('getSection', item => {
  229. if(this.timer){
  230. clearInterval(this.timer);
  231. }
  232. if(this.vid){
  233. //切换视频
  234. var polyvPlayerContext = this.selectComponent('#playerVideo');
  235. polyvPlayerContext.changeVid(item.recordingUrl)
  236. }else{
  237. this.vid = item.recordingUrl
  238. }
  239. this.startStatus = true
  240. this.startTime = 0
  241. });
  242. eventHub.$on('levelId', item => {
  243. let arr = item.split('-')
  244. //点击节获取的各层级ID
  245. this.moduleId = arr[0]
  246. this.chapterId = arr[1]
  247. console.log(item,99)
  248. });
  249. },
  250. methods: {
  251. postStudyRecord(status=0) {
  252. let self = this;
  253. let data = {
  254. photo:self.ossAvatarUrl,
  255. sectionId:parseInt(self.playSectionId),
  256. goodsId:parseInt(self.goodsId),
  257. courseId:parseInt(self.courseId),
  258. studyDuration:parseInt(self.studyDuration),
  259. gradeId:parseInt(self.gradeId),
  260. chapterId:parseInt(self.chapterId),
  261. moduleId:parseInt(self.moduleId)
  262. }
  263. if(status>0){
  264. data.status = status
  265. }
  266. console.log("提交接口",data)
  267. this.$api.studyRecord(data).then(res => {
  268. console.log(res)
  269. });
  270. },
  271. uploadFile(options, int) {
  272. var self = this;
  273. return new Promise((resolve, reject) => {
  274. var data = {
  275. imageStatus: int
  276. };
  277. self.$api.aliyunpolicy(data).then(res => {
  278. if(res.data.code!=200){
  279. self.$method.showToast('签名错误'+JSON.stringify(res.data))
  280. return
  281. }
  282. var ossToken = res.data.data.resultContent;
  283. if(ossToken.host==null||ossToken.host==undefined){
  284. self.$method.showToast('上传路径报错'+JSON.stringify(res.data))
  285. return
  286. }
  287. uni.uploadFile({
  288. url: ossToken.host,
  289. name: 'file',
  290. filePath: options,
  291. fileType: 'image',
  292. header: {
  293. AuthorizationToken: 'WX ' + uni.getStorageSync('token')
  294. },
  295. formData: {
  296. key: ossToken.dir,
  297. OSSAccessKeyId: ossToken.accessid,
  298. policy: ossToken.policy,
  299. Signature: ossToken.signature,
  300. callback: ossToken.callback,
  301. success_action_status: 200
  302. },
  303. success: result => {
  304. if (result.statusCode === 200) {
  305. self.ossAvatarUrl = ossToken.dir;
  306. resolve();
  307. } else {
  308. uni.showToast({
  309. title: '上传失败',
  310. icon: 'none'
  311. });
  312. return;
  313. }
  314. },
  315. fail: error => {
  316. uni.showToast({
  317. title: '上传接口报错'+error,
  318. icon: 'none'
  319. });
  320. return;
  321. }
  322. });
  323. });
  324. });
  325. },
  326. imageInfos(){
  327. var self = this
  328. return new Promise((resolve, reject) => {
  329. uni.getImageInfo({
  330. src: self.avatarUrl,
  331. success: async res => {
  332. let canvasWidth = res.width; //图片原始长宽
  333. let canvasHeight = res.height;
  334. if (canvasWidth > 1000 || canvasHeight > 1000) {
  335. uni.compressImage({
  336. src: self.avatarUrl,
  337. quality: 75,
  338. width: '50%',
  339. height: '50%',
  340. success: async rest => {
  341. const waitUpload = await self.uploadFile(rest.tempFilePath, 0);
  342. resolve()
  343. }
  344. });
  345. } else {
  346. console.log('无需压缩');
  347. const waitUpload = await self.uploadFile(self.avatarUrl, 0);
  348. resolve()
  349. }
  350. }
  351. });
  352. });
  353. },
  354. timeEvent() {
  355. let self = this
  356. var polyvPlayerContext = this.selectComponent('#playerVideo');
  357. if (polyvPlayerContext != null) {
  358. let PlayCurrentTime = polyvPlayerContext.getCurrentTime();
  359. this.studyDuration = PlayCurrentTime
  360. if(this.currentTime<PlayCurrentTime){
  361. this.playTime+=(PlayCurrentTime-this.currentTime)
  362. this.currentTime = PlayCurrentTime
  363. }else{
  364. this.currentTime = PlayCurrentTime
  365. }
  366. //判断是否需要拍照
  367. if(this.intervalTimeList.length>this.intervalTimeIndex){
  368. let photoTime = Number(this.intervalTimeList[this.intervalTimeIndex]) * 60 //获取拍照秒数
  369. if(photoTime<this.playTime){
  370. //启动拍照
  371. //暂停
  372. polyvPlayerContext.exitFullScreen()
  373. polyvPlayerContext.pause()
  374. this.openPhoto();
  375. this.intervalTimeIndex++
  376. }
  377. }
  378. }
  379. },
  380. onStateChange(newstate, oldstate) {
  381. if (newstate.detail.newstate == 'playing') {
  382. //开始播放
  383. if(this.timer){
  384. clearInterval(this.timer);
  385. }
  386. this.timer = setInterval(this.timeEvent, 1500);//定时器
  387. }
  388. if (newstate.detail.newstate == 'pause') {
  389. //暂停提交记录
  390. /* this.ossAvatarUrl = ""
  391. this.postStudyRecord() */
  392. }
  393. if (newstate.detail.newstate == 'ended') {
  394. this.ossAvatarUrl = ""
  395. this.postStudyRecord(1)
  396. }
  397. },
  398. //拍照
  399. openPhoto(){
  400. this.photoPopup = true
  401. },
  402. async submit(){
  403. const waitYS = await this.imageInfos();
  404. this.postStudyRecord()//提交记录
  405. //恢复播放
  406. var polyvPlayerContext = this.selectComponent('#playerVideo');
  407. if (polyvPlayerContext != null) {
  408. polyvPlayerContext.play();
  409. }
  410. console.log(this.ossAvatarUrl,"拍照完成456")
  411. },
  412. //确认拍照
  413. takePhoto() {
  414. var self = this
  415. const ctx = uni.createCameraContext();
  416. ctx.takePhoto({
  417. quality: 'high',
  418. success: res => {
  419. console.log(res.tempImagePath)
  420. self.avatarUrl = res.tempImagePath
  421. self.submit()
  422. self.photoPopup = false
  423. },
  424. fail: err => {
  425. console.log(err)
  426. }
  427. });
  428. },
  429. //拍照报错
  430. error(e) {
  431. console.log(e.detail);
  432. },
  433. //关闭相机
  434. closePhoto(){
  435. this.photoPopup = false
  436. },
  437. getGoodsDetail(){
  438. let self = this
  439. this.$api.goodsDetail(this.goodsId).then(res => {
  440. self.goodsData = res.data.data;
  441. self.gradeId = self.goodsData.gradeId
  442. self.getReMenuList() //获取重修目录
  443. if(self.goodsData.goodsPlayConfig){
  444. self.goodsPlayConfig = JSON.parse(self.goodsData.goodsPlayConfig);
  445. if(self.goodsPlayConfig.autoPlay>0){
  446. self.autoplay = true
  447. }
  448. if(self.goodsPlayConfig.drag>0){
  449. self.isAllowSeek = "yes"
  450. }
  451. if(self.goodsPlayConfig.speed>0){
  452. self.playbackRate = [0.5,0.8,1.0,1.25,1.5,2.0]
  453. }
  454. }
  455. if(self.goodsData.goodsPhotographConfig){
  456. self.goodsPhotographConfig = JSON.parse(self.goodsData.goodsPhotographConfig);
  457. if(self.goodsPhotographConfig.intervalTime){
  458. self.intervalTimeList = self.goodsPhotographConfig.intervalTime.split(',')
  459. }
  460. }
  461. })
  462. },
  463. startVideo() {
  464. this.startStatus = true;
  465. },
  466. getReMenuList() {
  467. let self = this;
  468. this.$api.menuList({ courseId: this.courseId,rebuild:1,gradeId:this.gradeId }).then(res => {
  469. if (res.data.code == 200) {
  470. for (let i = 0; i < res.data.rows.length; i++) {
  471. let item = res.data.rows[i];
  472. item.down = true;
  473. item.id = item.menuId;
  474. item.name = item.menuName;
  475. }
  476. self.reMenuList = res.data.rows;
  477. }
  478. });
  479. },
  480. getMenuList() {
  481. let self = this;
  482. this.$api.menuList({ courseId: this.courseId }).then(res => {
  483. if (res.data.code == 200) {
  484. for (let i = 0; i < res.data.rows.length; i++) {
  485. let item = res.data.rows[i];
  486. item.down = true;
  487. item.id = item.menuId;
  488. item.name = item.menuName;
  489. }
  490. self.menuList = res.data.rows;
  491. }
  492. });
  493. },
  494. courseDetail() {
  495. let self = this;
  496. this.$api.courseDetail(this.courseId).then(res => {
  497. if (res.data.code == 200) {
  498. self.detail = res.data.data;
  499. self.gradeId = self.detail.gradeId
  500. }
  501. });
  502. },
  503. open(item) {
  504. item.showChildren = !item.showChildren;
  505. },
  506. change(index) {
  507. this.current = index;
  508. }
  509. }
  510. };
  511. </script>
  512. <style lang="scss" scope>
  513. .photoBox{
  514. .photoTop{
  515. height: 74upx;
  516. display: flex;
  517. align-items: center;
  518. justify-content: space-between;
  519. padding: 0upx 38upx;
  520. .sqzz{
  521. width: 28upx;
  522. height: 28upx;
  523. display: flex;
  524. align-items: center;
  525. justify-content: center;
  526. }
  527. .centersq{
  528. color: #333;
  529. font-size: 30upx;
  530. font-weight: 500;
  531. }
  532. }
  533. .photoCenter{
  534. width: 750upx;
  535. height: 979upx;
  536. position: relative;
  537. .custom{
  538. width: 750upx;
  539. height: 979upx;
  540. position: absolute;
  541. top: 0;
  542. left: 0;
  543. image{
  544. width: 100%;
  545. height: 100%;
  546. }
  547. }
  548. }
  549. .btnResult{
  550. height: 100upx;
  551. width: 100%;
  552. background-color: #07c160;
  553. text-align: center;
  554. line-height: 100upx;
  555. color: #fff;
  556. font-size: 32upx;
  557. font-weight: bold;
  558. }
  559. }
  560. .chat_box {
  561. display: flex;
  562. padding: 20rpx;
  563. }
  564. .chat3 {
  565. font-size: 30rpx;
  566. font-family: PingFang SC;
  567. font-weight: 500;
  568. color: #666666;
  569. margin-top: 10rpx;
  570. }
  571. .chat2 {
  572. font-size: 20rpx;
  573. font-family: PingFang SC;
  574. font-weight: 500;
  575. color: #999999;
  576. margin-top: 10rpx;
  577. }
  578. .chat1 {
  579. font-size: 24rpx;
  580. font-family: PingFang SC;
  581. font-weight: 500;
  582. color: #333333;
  583. }
  584. .leftPadding {
  585. margin-left: 8rpx;
  586. }
  587. .t2Content {
  588. font-size: 30rpx;
  589. font-family: PingFang SC;
  590. font-weight: bold;
  591. color: #333333;
  592. line-height: 48rpx;
  593. }
  594. .tBox2 {
  595. display: flex;
  596. padding-top: 10rpx;
  597. }
  598. .tBox {
  599. display: flex;
  600. align-items: center;
  601. padding-top: 10rpx;
  602. }
  603. .title {
  604. font-size: 24rpx;
  605. color: #999999;
  606. }
  607. page {
  608. padding-top: 10px;
  609. padding-top: constant(safe-area-inset-top);
  610. padding-top: env(safe-area-inset-top);
  611. }
  612. .inputBottom {
  613. position: fixed;
  614. left: 0;
  615. bottom: 0;
  616. background: #ffffff;
  617. height: 98rpx;
  618. display: flex;
  619. align-items: center;
  620. width: 100%;
  621. }
  622. .noteBox {
  623. width: 100%;
  624. background: #ffffff;
  625. border-radius: 16rpx;
  626. padding: 10rpx;
  627. }
  628. .dateBox {
  629. width: 216rpx;
  630. height: 48rpx;
  631. background: #ffffff;
  632. border-radius: 24rpx;
  633. font-size: 24rpx;
  634. color: #666666;
  635. text-align: center;
  636. line-height: 48rpx;
  637. margin: 20rpx 0;
  638. }
  639. .t_content1 {
  640. color: #007aff;
  641. margin-left: 10rpx;
  642. }
  643. .tag1 {
  644. border: 2rpx solid #007aff;
  645. border-radius: 8rpx;
  646. font-size: 20rpx;
  647. color: #007aff;
  648. padding: 5rpx;
  649. }
  650. .b_title {
  651. color: #333333;
  652. font-size: 30rpx;
  653. font-weight: bold;
  654. }
  655. page {
  656. background: #eaeef1;
  657. }
  658. .menuBox {
  659. width: 100%;
  660. background: #ffffff;
  661. border-radius: 16rpx;
  662. padding: 20rpx;
  663. margin-bottom: 20rpx;
  664. }
  665. .btnspric {
  666. border-top: 1rpx solid #eee;
  667. display: flex;
  668. align-items: center;
  669. justify-content: space-between;
  670. height: 108rpx;
  671. padding-left: 43rpx;
  672. padding-right: 32rpx;
  673. }
  674. .btnspric > .lefprL {
  675. font-size: 36rpx;
  676. color: #0c141f;
  677. font-weight: bold;
  678. }
  679. .btnspric > .lefprR {
  680. padding: 0rpx 24rpx;
  681. height: 60rpx;
  682. line-height: 60rpx;
  683. text-align: center;
  684. color: #fff;
  685. background: #32467b;
  686. border-radius: 24rpx;
  687. box-shadow: 0rpx 0rpx 16rpx 4rpx rgba(145, 156, 178, 0.1);
  688. }
  689. .yhj,
  690. .hdyhj {
  691. padding: 24rpx 29rpx 24rpx 34rpx;
  692. }
  693. .yhj {
  694. border-bottom: 16rpx solid #f9f9f9;
  695. }
  696. .yhjtit {
  697. font-size: 30rpx;
  698. color: #0c141f;
  699. font-weight: 500;
  700. margin-bottom: 14rpx;
  701. }
  702. .yhjList {
  703. display: flex;
  704. align-items: center;
  705. justify-content: space-between;
  706. margin-bottom: 14rpx;
  707. }
  708. .yhjList > .yhjLefts {
  709. display: flex;
  710. align-items: center;
  711. }
  712. .yhjLefts > .yhl {
  713. color: #32467b;
  714. font-size: 30rpx;
  715. margin-right: 31rpx;
  716. }
  717. .yhjLefts > .yhbq {
  718. font-size: 24rpx;
  719. color: #ff9500;
  720. border-radius: 18rpx;
  721. background-color: rgba(255, 149, 0, 0.2);
  722. border: 2rpx solid #ff9500;
  723. height: 38rpx;
  724. line-height: 38rpx;
  725. padding: 0rpx 16rpx;
  726. }
  727. .ts {
  728. font-size: 24rpx;
  729. color: #999;
  730. margin: 14rpx 0rpx;
  731. padding-right: 29rpx;
  732. padding-left: 34rpx;
  733. }
  734. .yh {
  735. padding-top: 20rpx;
  736. }
  737. .yh > .yhtitle {
  738. display: flex;
  739. align-items: center;
  740. justify-content: space-between;
  741. padding-right: 29rpx;
  742. padding-left: 34rpx;
  743. }
  744. .priceBxs {
  745. display: flex;
  746. align-items: center;
  747. }
  748. .priceBxs > .pricleft {
  749. border-radius: 24rpx;
  750. border: 1rpx solid #e91313;
  751. background-color: rgba(233, 19, 19, 0.1);
  752. padding: 0rpx 18rpx;
  753. height: 49rpx;
  754. line-height: 49rpx;
  755. text-align: center;
  756. font-size: 30rpx;
  757. font-weight: 500;
  758. color: #e91313;
  759. margin-right: 13rpx;
  760. }
  761. .topBox {
  762. padding: 32rpx 32rpx 24rpx;
  763. border-bottom: 1rpx solid #eeeeee;
  764. }
  765. .topBox > .boldFonstType {
  766. font-weight: 500;
  767. font-size: 30rpx;
  768. margin: 16rpx 0rpx 23rpx;
  769. }
  770. .topBox > .firstTopL {
  771. display: flex;
  772. align-items: center;
  773. }
  774. .topBox > .firstTopL > .imageBs {
  775. width: 331rpx;
  776. height: 160rpx;
  777. border-radius: 6rpx;
  778. overflow: hidden;
  779. margin-right: 8rpx;
  780. box-shadow: 0rpx 6rpx 6rpx 0rpx rgba(47, 67, 121, 0.08);
  781. }
  782. .topBox > .firstTopL > .imageBs > image {
  783. width: 100%;
  784. height: 100%;
  785. }
  786. .topBox > .firstTopL > .textBs {
  787. font-size: 30rpx;
  788. font-weight: bold;
  789. color: #0c141f;
  790. }
  791. .content {
  792. padding: 24rpx;
  793. text-align: left;
  794. }
  795. .catalogBox {
  796. display: flex;
  797. align-items: center;
  798. flex-wrap: nowrap;
  799. overflow-x: auto;
  800. padding-left: 38rpx;
  801. max-height: 305rpx;
  802. overflow-y: auto;
  803. transition: all 0.4s;
  804. }
  805. .catalogBox > .catalogA {
  806. min-width: 200rpx;
  807. height: 48rpx;
  808. line-height: 48rpx;
  809. // text-align: center;
  810. border: 2rpx solid transparent;
  811. white-space: nowrap;
  812. text-overflow: ellipsis;
  813. overflow: hidden;
  814. word-break: break-all;
  815. border-radius: 10rpx;
  816. background: rgba(22, 119, 255, 0.05);
  817. padding-left: 19rpx;
  818. box-sizing: border-box;
  819. padding-right: 15rpx;
  820. margin-right: 16rpx;
  821. margin-bottom: 20rpx;
  822. margin-top: 15rpx;
  823. font-size: 24rpx;
  824. color: #666;
  825. }
  826. .catalogBox > .activesq {
  827. border-color: #1677ff;
  828. }
  829. .changeCatalogBox {
  830. display: block;
  831. }
  832. .catalogBox::-webkit-scrollbar {
  833. display: none; /* Chrome Safari */
  834. }
  835. .box {
  836. position: relative;
  837. top: 650rpx;
  838. padding-bottom: 88rpx;
  839. margin: 20rpx;
  840. }
  841. .price_t2 {
  842. font-size: 18rpx;
  843. font-family: PingFang SC;
  844. font-weight: 500;
  845. text-decoration: line-through;
  846. color: #999999;
  847. }
  848. .price_t1 {
  849. font-size: 33rpx;
  850. font-family: PingFang SC;
  851. font-weight: bold;
  852. color: #e91313;
  853. }
  854. .sc_t {
  855. font-size: 22rpx;
  856. color: #000000;
  857. }
  858. .sc {
  859. width: 29rpx;
  860. height: 29rpx;
  861. }
  862. .buy {
  863. width: 138rpx;
  864. height: 48rpx;
  865. line-height: 48rpx;
  866. background: #32467b;
  867. border-radius: 10rpx;
  868. color: #ffffff;
  869. font-size: 28rpx;
  870. text-align: center;
  871. vertical-align: middle;
  872. position: absolute;
  873. right: 30rpx;
  874. }
  875. .video_body {
  876. padding-bottom: 96rpx;
  877. }
  878. .footer_tab {
  879. position: fixed;
  880. bottom: 0;
  881. height: 96rpx;
  882. width: 100%;
  883. background-color: #ffffff;
  884. }
  885. .tj_box {
  886. width: 50%;
  887. display: inline-block;
  888. text-align: center;
  889. margin: 10rpx 0;
  890. }
  891. .teacher_t {
  892. font-size: 24rpx;
  893. font-family: PingFang SC;
  894. font-weight: 400;
  895. color: #666666;
  896. line-height: 36rpx;
  897. margin-left: 15rpx;
  898. }
  899. .teacher_img {
  900. width: 87rpx;
  901. height: 129rpx;
  902. }
  903. .t2 {
  904. font-size: 24rpx;
  905. font-family: PingFang SC;
  906. color: #666666;
  907. line-height: 36rpx;
  908. margin: 15rpx;
  909. }
  910. .r_t2 {
  911. width: 201rpx;
  912. height: 49rpx;
  913. background: rgba(22, 119, 255, 0.05);
  914. border: 1rpx solid #32467b;
  915. border-radius: 16rpx;
  916. color: #666666;
  917. font-size: 23rpx;
  918. text-align: center;
  919. display: flex;
  920. align-items: center;
  921. padding: 5rpx;
  922. }
  923. .scroll_box {
  924. width: 100%;
  925. height: 60rpx;
  926. background: #ffffff;
  927. box-shadow: 0rpx 0rpx 16rpx 4rpx rgba(145, 156, 178, 0.1);
  928. white-space: nowrap;
  929. overflow: hidden;
  930. margin: 15rpx 0;
  931. }
  932. .r_sliper {
  933. padding: 0 20rpx;
  934. }
  935. .top_line {
  936. width: 6rpx;
  937. height: 22rpx;
  938. background: #32467b;
  939. margin-right: 10rpx;
  940. }
  941. .video_t2 {
  942. font-size: 24rpx;
  943. font-family: PingFang SC;
  944. font-weight: 500;
  945. color: #666666;
  946. }
  947. .video_t1 {
  948. height: 80rpx;
  949. color: #333333;
  950. line-height: 80rpx;
  951. font-size: 30rpx;
  952. font-family: PingFang SC;
  953. font-weight: bold;
  954. color: #333333;
  955. }
  956. .video_t1_t {
  957. display: flex;
  958. flex-direction: column;
  959. height: 80rpx;
  960. color: #333333;
  961. text-align: center;
  962. align-items: center;
  963. border-left: solid 1px #d6d6db;
  964. }
  965. .video_play {
  966. position: absolute;
  967. width: 95rpx;
  968. height: 95rpx;
  969. top: 0;
  970. left: 0;
  971. right: 0;
  972. bottom: 0;
  973. margin: auto;
  974. }
  975. .video_box {
  976. position: relative;
  977. }
  978. .rotoct {
  979. transform: rotate(90deg);
  980. }
  981. </style>