detail.vue 24 KB

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