courseSection.vue 20 KB

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