courseSection.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. <template>
  2. <view style="display: flex; justify-content: space-between; align-items: center" @click="getVideo">
  3. <view style="
  4. display: flex;
  5. justify-content: space-between;
  6. align-items: center;
  7. margin: 20rpx 0;
  8. width: 100%;
  9. ">
  10. <view style="display: flex; align-items: center; flex: 1">
  11. <view class="tag tagColor1" v-if="menuItem.sectionType == 1">视频</view>
  12. <view class="tag tagColor2" v-if="menuItem.sectionType == 2">直播</view>
  13. <view class="tag tagColor3" v-if="menuItem.sectionType == 3">回放</view>
  14. <view class="t_content">
  15. <view v-if="menuItem.sectionType == 1" :class="{ color1: isActive }">{{ menuItem.name || "" }}
  16. </view>
  17. <view v-if="menuItem.sectionType == 2" :class="{ color2: isActive }">{{ menuItem.name || "" }}
  18. </view>
  19. <view v-if="menuItem.sectionType == 3" :class="{ color3: isActive }">{{ menuItem.name || "" }}
  20. </view>
  21. <view style="font-size: 20rpx; color: #ff3b30"
  22. v-if="menuItem.sectionType == 2 && menuItem.liveStartTime">
  23. <view v-if="menuItem.liveStartTime > nowTime || !isBuy">
  24. <text>{{
  25. $method.timestampToTime(menuItem.liveStartTime, (isDay = false))
  26. }}</text>-
  27. <text>{{
  28. $method.timestampToTime(menuItem.liveEndTime, (isDay = false))
  29. }}</text>
  30. </view>
  31. <template v-if="isLast()">
  32. <view v-if="liveLast.watchStatus == 'live'">
  33. <text>直播中</text>
  34. </view>
  35. <view v-if="liveLast.watchStatus == 'end'">
  36. <text>当前直播回放视频请稍后再查看</text>
  37. </view>
  38. </template>
  39. </view>
  40. <view style="font-size: 20rpx; color: #ff3b30" v-if="menuItem.sectionType == 3">
  41. <view v-if="!menuItem.recordingUrl">
  42. <text>当前直播回放视频请稍后再查看</text>
  43. </view>
  44. <view v-else> 回放中 </view>
  45. </view>
  46. </view>
  47. <view v-if="menuItem.sectionType == null">{{
  48. menuItem.name || ""
  49. }}</view>
  50. <!-- 学习中 -->
  51. <view v-if="isActive" class="learnings">
  52. <image src="/pages3/static/imgs/learning_icon.gif" class="learning_icon"></image>
  53. </view>
  54. </view>
  55. <view style="font-size: 20rpx; color: #ff3b30"
  56. v-if="menuItem.liveStartTime && menuItem.sectionType != 3 && isBuy">
  57. <template v-if="!isLast() && !isLive">
  58. <view class="tagWillPlay" v-if="menuItem.liveStartTime > nowTime">
  59. <text>待开播</text>
  60. </view>
  61. <view class="tagPlaying" v-if="
  62. menuItem.liveStartTime <= nowTime &&
  63. menuItem.liveEndTime > nowTime
  64. ">
  65. <text>直播中</text>
  66. </view>
  67. <view class="tagPlayed" v-if="menuItem.liveEndTime < nowTime">
  68. <text>已结束</text>
  69. </view>
  70. </template>
  71. </view>
  72. <!-- 直播课程没有学习状态 -->
  73. <template v-if="!isLive">
  74. <view v-if="isRebuild || menuItem.rebuild > 0" class="tagRe">待重修</view>
  75. <view v-else>
  76. <view v-if="menuItem.learning == 1" class="tagGreen">已学完</view>
  77. </view>
  78. </template>
  79. <view v-if="checkTest()" class="exercises" @click.stop="toDoSectionExam()">
  80. <text class="exe_w">习题</text>
  81. <u-icon name="arrow-right" color="#498AFE" size="28"></u-icon>
  82. </view>
  83. </view>
  84. <view v-if="isTryListen" class="tryBox"> 试看 </view>
  85. </view>
  86. </template>
  87. <script>
  88. import {
  89. mapGetters
  90. } from "vuex";
  91. export default {
  92. name: "courseSection",
  93. inject: ["paramsFn"],
  94. props: {
  95. isLive: false, //是否是直播课
  96. preItem: {
  97. default: undefined,
  98. },
  99. menuItem: {
  100. type: Object,
  101. default: {},
  102. },
  103. isBuy: {
  104. type: Boolean,
  105. default: false,
  106. },
  107. levelId: {
  108. type: String,
  109. default: "",
  110. },
  111. isRebuild: {
  112. type: Boolean,
  113. default: false,
  114. },
  115. nextMenuItem: {
  116. type: Object,
  117. default: () => {
  118. return {};
  119. },
  120. },
  121. sectionMaxNum: {
  122. default: undefined,
  123. },
  124. // 章->所有节试卷列表
  125. ChapterSectionExam: {
  126. type: Array,
  127. default: () => [],
  128. },
  129. // 区分是模块试卷还是章试卷,3是模块试卷
  130. testType: {
  131. type: Number,
  132. default: 0,
  133. },
  134. },
  135. watch: {
  136. menuItem(val) {
  137. console.log(val, "val");
  138. },
  139. },
  140. data() {
  141. return {
  142. nowTime: 0,
  143. playId: "",
  144. clickLock: false, //点击锁,防止连续点击多次
  145. moduleSectionExam: [], // 模块下的所有节试卷列表
  146. chapterExams: {},
  147. moduleExams: {},
  148. // newMenuAllList: [],
  149. };
  150. },
  151. onLoad() {},
  152. created() {
  153. if (this.testType == 3) {
  154. // 模块下的所有节试卷列表
  155. this.$api
  156. .reSectionExamList({
  157. chapterId: 0,
  158. courseId: this.courseId,
  159. gradeId: this.gradeId,
  160. orderGoodsId: this.orderGoodsId,
  161. })
  162. .then((res) => {
  163. if (res.data.code == 200) {
  164. this.moduleSectionExam = res.data.data || [];
  165. }
  166. });
  167. }
  168. },
  169. mounted() {
  170. this.nowTime = Number(new Date().getTime() / 1000).toFixed(0);
  171. this.isBuy &&
  172. uni.$on("playEnd", () => {
  173. if (this.isActive) {
  174. this.$emit("playEnd");
  175. }
  176. });
  177. },
  178. methods: {
  179. isLast() {
  180. if (this.liveLast) {
  181. let sectionASame =
  182. this.liveLast.sectionId ==
  183. (this.menuItem.sectionId || this.menuItem.menuId);
  184. let chapterSame =
  185. this.liveLast.chapterId == (this.menuItem.chapterId || 0);
  186. let moduleSame =
  187. this.liveLast.moduleId == (this.menuItem.moduleId || 0);
  188. return sectionASame && chapterSame && moduleSame;
  189. } else {
  190. return false;
  191. }
  192. },
  193. toDoSectionExam() {
  194. if (this.testType == 3) {
  195. this.ModuleExam();
  196. } else {
  197. this.ChapterExam();
  198. }
  199. },
  200. checkTest() {
  201. let data =
  202. this.testType == 3 ? this.moduleSectionExam : this.ChapterSectionExam;
  203. let id =
  204. this.testType == 3 ? this.menuItem.menuId : this.menuItem.sectionId;
  205. if (!data) {
  206. return false;
  207. }
  208. return data.some((e) => e.sectionId == id);
  209. },
  210. ChapterExam() {
  211. this.chapterExams = this.ChapterSectionExam.find(
  212. (e) => e.sectionId == this.menuItem.sectionId
  213. );
  214. let moduleId = this.chapterExams.moduleId || 0;
  215. let chapterId = this.chapterExams.chapterId || 0;
  216. let sectionId = this.chapterExams.sectionId || this.chapterExams.menuId;
  217. uni.navigateTo({
  218. url: "/pages2/class/questionBank?courseId=" +
  219. this.courseId +
  220. "&gradeId=" +
  221. this.gradeId +
  222. "&isFromVideo=1&id=" +
  223. this.chapterExams.typeId +
  224. "&goodsid=" +
  225. this.goodsId +
  226. "&moduleId=" +
  227. moduleId +
  228. "&chapterId=" +
  229. chapterId +
  230. "&sectionId=" +
  231. sectionId +
  232. "&orderGoodsId=" +
  233. this.orderGoodsId +
  234. "&type=2",
  235. });
  236. },
  237. ModuleExam() {
  238. let sectionId = this.menuItem.sectionId || this.menuItem.menuId;
  239. this.moduleExams = this.moduleSectionExam.find(
  240. (e) => e.sectionId == sectionId
  241. );
  242. let moduleId = this.moduleExams.moduleId || 0;
  243. let chapterId = this.moduleExams.chapterId || 0;
  244. uni.navigateTo({
  245. url: "/pages2/class/questionBank?courseId=" +
  246. this.courseId +
  247. "&gradeId=" +
  248. this.gradeId +
  249. "&isFromVideo=1&id=" +
  250. this.moduleExams.typeId +
  251. "&goodsid=" +
  252. this.goodsId +
  253. "&moduleId=" +
  254. moduleId +
  255. "&chapterId=" +
  256. chapterId +
  257. "&sectionId=" +
  258. sectionId +
  259. "&orderGoodsId=" +
  260. this.orderGoodsId +
  261. "&type=2",
  262. });
  263. },
  264. gradeCheckGoodsStudy() {
  265. return new Promise((resolve) => {
  266. this.$api
  267. .gradeCheckGoodsStudy({
  268. goodsId: this.goodsId,
  269. gradeId: this.gradeId,
  270. moduleId: this.menuItem.moduleId || 0,
  271. chapterId: this.menuItem.chapterId || 0,
  272. sectionId: this.menuItem.sectionId || this.menuItem.menuId,
  273. orderGoodsId: this.orderGoodsId,
  274. })
  275. .then((res) => {
  276. resolve(res.data.data);
  277. });
  278. });
  279. },
  280. goodsTodayStudySectionNum() {
  281. return new Promise((resolve) => {
  282. this.$api
  283. .goodsTodayStudySectionNum({
  284. goodsId: this.goodsId,
  285. gradeId: this.gradeId,
  286. orderGoodsId: this.orderGoodsId,
  287. })
  288. .then((res) => {
  289. if (res.data.code == 200) {
  290. resolve(res.data.data);
  291. }
  292. });
  293. });
  294. },
  295. getVideo() {
  296. if (this.clickLock) {
  297. return;
  298. }
  299. if (this.$method.isGoLogin()) {
  300. return;
  301. }
  302. if (this.menuItem.id == this.sectionId && this.menuItem.sectionType !== 2) {
  303. return;
  304. }
  305. this.clickLock = true;
  306. // && !this.menuItem.isRebuild
  307. if (this.params.orderNum == 2 && this.menuItem.sectionType !== 2) {
  308. //要按从头到尾顺序学习, 且不是重修课程
  309. if (this.preItem) {
  310. let rows = this.menuAllList;
  311. let newRows = [];
  312. for (let i = 0; i < rows.length; i++) {
  313. let moduleTrue =
  314. rows[i].moduleId == this.menuItem.moduleId ||
  315. rows[i].moduleId == 0;
  316. let chapterTrue =
  317. rows[i].chapterId == this.menuItem.chapterId ||
  318. rows[i].chapterId == 0;
  319. let sectionTrue =
  320. rows[i].sectionId == this.menuItem.sectionId ||
  321. rows[i].sectionId == this.menuItem.menuId;
  322. if (moduleTrue && chapterTrue && sectionTrue) {
  323. break;
  324. } else {
  325. if (rows[i].sectionType != 2) {
  326. newRows.push(rows[i]);
  327. }
  328. }
  329. }
  330. let isAllLearn = newRows.every((item) => {
  331. return item.studyStatus == 1;
  332. });
  333. if (isAllLearn) {
  334. this.playVideo();
  335. } else {
  336. uni.showToast({
  337. icon: "none",
  338. title: "请按顺序学习视频课程",
  339. });
  340. }
  341. } else {
  342. //第一章第一节
  343. this.playVideo();
  344. }
  345. } else {
  346. this.playVideo();
  347. }
  348. setTimeout(() => {
  349. this.clickLock = false;
  350. }, 3000);
  351. },
  352. studyRecordGetChannelBasicInfo(channelId) {
  353. return new Promise((resolve) => {
  354. this.$api
  355. .studyRecordGetChannelBasicInfo({
  356. channelId,
  357. })
  358. .then((res) => {
  359. resolve(res.data.data);
  360. });
  361. });
  362. },
  363. async playVideo() {
  364. if (!this.isBuy) {
  365. if (this.isTryListen) {
  366. uni.$emit("getSection", this.menuItem, this.isTryListen);
  367. }
  368. //非购买
  369. this.clickLock = false;
  370. return;
  371. }
  372. if (this.menuItem.sectionType == 1 || this.menuItem.sectionType == 3) {
  373. let learnNum = await this.goodsTodayStudySectionNum();
  374. let hasLearn = await this.gradeCheckGoodsStudy();
  375. if (this.sectionMaxNum > 0) {
  376. if (learnNum >= this.sectionMaxNum && !hasLearn) {
  377. uni.showToast({
  378. icon: "none",
  379. title: `每天最多学习${this.sectionMaxNum}节`,
  380. });
  381. this.clickLock = false;
  382. return;
  383. }
  384. }
  385. if (!this.menuItem.recordingUrl) {
  386. uni.showToast({
  387. title: "暂无播放地址数据",
  388. icon: "none",
  389. });
  390. this.clickLock = false;
  391. return;
  392. }
  393. if (!this.userInfo) {
  394. await this.$store.dispatch('getUserInfo')
  395. }
  396. // 回放
  397. if (this.menuItem.sectionType == 3) {
  398. let moduleId = this.menuItem.moduleId || 0;
  399. let chapterId = this.menuItem.chapterId || 0;
  400. let sectionId = this.menuItem.sectionId || this.menuItem.menuId;
  401. let uuid = new Date().valueOf() + "";
  402. // buyCourse 是否购买课程:1是 0否,type=vod是回放
  403. let encode = encodeURIComponent(
  404. this.other.hostLive +
  405. "/pages/live/index?token=" +
  406. uni.getStorageSync("token") +
  407. "&userInfo=" +
  408. JSON.stringify(this.userInfo) +
  409. "&channelId=" +
  410. this.menuItem.liveUrl +
  411. "&gradeId=" +
  412. this.gradeId +
  413. "&courseId=" +
  414. this.courseId +
  415. "&goodsId=" +
  416. this.goodsId +
  417. "&orderGoodsId=" +
  418. this.orderGoodsId +
  419. "&sectionId=" +
  420. sectionId +
  421. "&chapterId=" +
  422. chapterId +
  423. "&moduleId=" +
  424. moduleId +
  425. "&buyCourse=1" +
  426. "&ident=" +
  427. uuid +
  428. "&sectionType=3" +
  429. "&vid=" +
  430. this.menuItem.recordingUrl
  431. );
  432. uni.navigateTo({
  433. url: `/pages5/webview/index?url=` + encode,
  434. });
  435. return;
  436. }
  437. // console.log('===设置播放的节IDthis.menuItem,', this.menuItem, this.playId);
  438. uni.$emit("getSection", this.menuItem);
  439. uni.$emit("isRebuild", this.isRebuild);
  440. }
  441. if (this.menuItem.sectionType == 2) {
  442. let learnNum = await this.goodsTodayStudySectionNum();
  443. let hasLearn = await this.gradeCheckGoodsStudy();
  444. if (this.sectionMaxNum > 0 && this.menuItem.sectionType !== 2) {
  445. if (learnNum >= this.sectionMaxNum && !hasLearn) {
  446. uni.showToast({
  447. icon: "none",
  448. title: `每天最多学习${this.sectionMaxNum}节`,
  449. });
  450. this.clickLock = false;
  451. return;
  452. }
  453. }
  454. if (!this.menuItem.liveUrl) {
  455. uni.showToast({
  456. title: "暂无直播地址数据",
  457. icon: "error",
  458. });
  459. return;
  460. }
  461. let data = await this.studyRecordGetChannelBasicInfo(
  462. this.menuItem.liveUrl
  463. );
  464. let nowTime = +this.$method.timest();
  465. if (this.menuItem.liveStartTime > nowTime) {
  466. if (data.watchStatus == "end" || data.watchStatus == "playback") {
  467. this.clickLock = false;
  468. uni.showToast({
  469. title: "直播未开始",
  470. icon: "none",
  471. });
  472. return;
  473. }
  474. } else if (
  475. this.menuItem.liveStartTime < nowTime &&
  476. this.menuItem.liveEndTime > nowTime
  477. ) {
  478. if (data.watchStatus == "end" || data.watchStatus == "playback") {
  479. this.clickLock = false;
  480. uni.showToast({
  481. title: "暂无直播",
  482. icon: "none",
  483. });
  484. return;
  485. }
  486. } else if (this.menuItem.liveEndTime < nowTime) {
  487. if (!data) {
  488. uni.showToast({
  489. title: "直播已结束",
  490. icon: "none",
  491. });
  492. return;
  493. }
  494. if (data.watchStatus == "end" || data.watchStatus == "playback") {
  495. this.clickLock = false;
  496. uni.showToast({
  497. title: "直播已结束",
  498. icon: "none",
  499. });
  500. return;
  501. }
  502. }
  503. let moduleId = this.menuItem.moduleId || 0;
  504. let chapterId = this.menuItem.chapterId || 0;
  505. let sectionId = this.menuItem.sectionId || this.menuItem.menuId;
  506. let uuid = new Date().valueOf() + "";
  507. // buyCourse 是否购买课程:1是 0否
  508. let encode = encodeURIComponent(
  509. this.other.hostLive +
  510. "/pages/live/index?token=" +
  511. uni.getStorageSync("token") +
  512. "&userInfo=" +
  513. JSON.stringify(this.userInfo) +
  514. "&channelId=" +
  515. this.menuItem.liveUrl +
  516. "&gradeId=" +
  517. this.gradeId +
  518. "&courseId=" +
  519. this.courseId +
  520. "&goodsId=" +
  521. this.goodsId +
  522. "&orderGoodsId=" +
  523. this.orderGoodsId +
  524. "&sectionId=" +
  525. sectionId +
  526. "&chapterId=" +
  527. chapterId +
  528. "&moduleId=" +
  529. moduleId +
  530. "&buyCourse=1" +
  531. "&ident=" +
  532. uuid +
  533. "&sectionType=2"
  534. );
  535. uni.navigateTo({
  536. url: `/pages5/webview/index?url=` + encode,
  537. });
  538. return;
  539. }
  540. },
  541. },
  542. computed: {
  543. ...mapGetters(["userInfo", "liveLast", "other"]),
  544. isActive() {
  545. if (!this.isBuy || !this.sectionItem) {
  546. return false;
  547. }
  548. let moduleId = this.menuItem.moduleId || 0;
  549. let chapterId = this.menuItem.chapterId || 0;
  550. let sectionId = this.menuItem.sectionId || this.menuItem.menuId;
  551. let moduleId1 = this.sectionItem.moduleId || 0;
  552. let chapterId1 = this.sectionItem.chapterId || 0;
  553. let sectionId1 = this.sectionItem.sectionId || this.sectionItem.menuId;
  554. return (
  555. moduleId == moduleId1 &&
  556. chapterId == chapterId1 &&
  557. sectionId == sectionId1
  558. );
  559. },
  560. params() {
  561. return this.paramsFn([
  562. "orderGoodsId",
  563. "gradeId",
  564. "courseId",
  565. "sectionItem",
  566. "menuAllList",
  567. "orderNum",
  568. "goodsId",
  569. "sectionId",
  570. "listenConfigList",
  571. ]);
  572. },
  573. courseId() {
  574. return this.params.courseId;
  575. },
  576. gradeId() {
  577. return this.params.gradeId;
  578. },
  579. orderGoodsId() {
  580. return this.params.orderGoodsId;
  581. },
  582. sectionItem() {
  583. return this.params.sectionItem;
  584. },
  585. menuAllList() {
  586. return this.params.menuAllList;
  587. },
  588. goodsId() {
  589. return this.params.goodsId;
  590. },
  591. sectionId() {
  592. return this.params.sectionId;
  593. },
  594. isTryListen() {
  595. let {
  596. listenConfigList
  597. } = this.params;
  598. return (
  599. listenConfigList &&
  600. listenConfigList.find(
  601. (e) =>
  602. e.sectionId == this.menuItem.sectionId ||
  603. e.sectionId == this.menuItem.menuId
  604. )
  605. );
  606. },
  607. },
  608. };
  609. </script>
  610. <style scoped lang="scss">
  611. .tagGreen {
  612. width: 80rpx;
  613. height: 28rpx;
  614. background: #34c759;
  615. border-radius: 8rpx;
  616. font-size: 20rpx;
  617. color: #ffffff;
  618. text-align: center;
  619. }
  620. .tagWillPlay {
  621. width: 80rpx;
  622. height: 28rpx;
  623. background: #ebf4ff;
  624. border-radius: 8rpx;
  625. font-size: 20rpx;
  626. color: #007aff;
  627. text-align: center;
  628. }
  629. .tagPlaying {
  630. width: 80rpx;
  631. height: 28rpx;
  632. background: #fff7eb;
  633. border-radius: 8rpx;
  634. font-size: 20rpx;
  635. color: #ff9500;
  636. text-align: center;
  637. }
  638. .tagPlayed {
  639. width: 80rpx;
  640. height: 28rpx;
  641. background: #eeeeee;
  642. border-radius: 8rpx;
  643. font-size: 20rpx;
  644. color: #666666;
  645. text-align: center;
  646. }
  647. .tagRe {
  648. width: 80rpx;
  649. height: 28rpx;
  650. background: #ff3b30;
  651. border-radius: 8rpx;
  652. font-size: 20rpx;
  653. color: #ffffff;
  654. text-align: center;
  655. }
  656. .tryBox {
  657. width: 103rpx;
  658. height: 48rpx;
  659. background: #fff;
  660. border-radius: 24rpx;
  661. color: #3577e8;
  662. font-size: 24rpx;
  663. line-height: 48rpx;
  664. text-align: center;
  665. border: 1rpx solid #3577e8;
  666. }
  667. .icon_up {
  668. width: 24rpx;
  669. height: 24rpx;
  670. }
  671. .t_content3 {
  672. color: #007aff;
  673. }
  674. .t_content2 {
  675. color: #007aff;
  676. }
  677. .t_content1 {
  678. color: #007aff;
  679. }
  680. .t_content {
  681. font-size: 30rpx;
  682. margin-left: 10rpx;
  683. color: #666666;
  684. flex: 1;
  685. }
  686. .tagColor3 {
  687. border: 2rpx solid #ff9500;
  688. color: #ff9500;
  689. }
  690. .tagColor2 {
  691. border: 2rpx solid #ff3b30;
  692. color: #ff3b30;
  693. }
  694. .tagColor1 {
  695. border: 2rpx solid #007aff;
  696. color: #007aff;
  697. }
  698. .color3 {
  699. color: #ff9500;
  700. }
  701. .color2 {
  702. color: #ff3b30;
  703. }
  704. .color1 {
  705. color: #007aff;
  706. }
  707. .tag {
  708. border-radius: 8rpx;
  709. font-size: 20rpx;
  710. padding: 4rpx 10rpx;
  711. }
  712. .exercises {
  713. margin-left: 10rpx;
  714. font-size: 26rpx;
  715. color: #498afe;
  716. >text {
  717. margin-right: 6rpx;
  718. }
  719. }
  720. .learnings {
  721. margin-right: 8rpx;
  722. .learning_icon {
  723. width: 40rpx;
  724. height: 40rpx;
  725. margin-right: 4rpx;
  726. }
  727. }
  728. </style>