courseChapter.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. <template>
  2. <view>
  3. <view class="title" @click="openChapter(menuItem)">
  4. <u-icon name="arrow-down" color="#999" size="24" v-if="!down"></u-icon>
  5. <u-icon name="arrow-right" color="#999" size="24" v-if="down"></u-icon>
  6. <text class="menu_name">{{ menuItem.name }}</text>
  7. </view>
  8. <view v-show="!down">
  9. <view v-for="(itemM, indexM) in list" :key="indexM">
  10. <view v-if="itemM.type != 2">
  11. <courseSection
  12. ref="ChapterSection"
  13. :isLive="isLive"
  14. :orderGoodsId="orderGoodsId"
  15. :sectionMaxNum="sectionMaxNum"
  16. :preItem="list[indexM - 1] || preItem"
  17. :learningOrder="learningOrder"
  18. :courseId="courseId"
  19. @playEnd="refreshList($event)"
  20. :goodsId="goodsId"
  21. :isBuy="isBuy"
  22. :nextMenuItem="findNextSection(indexM)"
  23. :isRebuild="isRebuild"
  24. :gradeId="gradeId"
  25. :menuItem="itemM"
  26. :levelId="levelId + '-' + itemM.sectionId"
  27. :testType="2"
  28. :ChapterSectionExam='sectionExam'
  29. ></courseSection>
  30. <!-- @togoBack='togoBack()' -->
  31. <u-line v-if="indexM < list.length - 1"></u-line>
  32. </view>
  33. <view v-if="itemM.type == 2">
  34. <u-line></u-line>
  35. <view
  36. class="examBox"
  37. @click="
  38. toDo(
  39. itemM.typeId,
  40. goodsId,
  41. itemM.moduleId,
  42. itemM.chapterId,
  43. itemM,
  44. indexM
  45. )
  46. "
  47. >
  48. <view class="exam">
  49. <view class="eTag">{{
  50. itemM.doType == 1 ? "练习" : "考试"
  51. }}</view>
  52. <view style="margin-left: 15rpx; flex: 1">{{ itemM.name }}</view>
  53. </view>
  54. <view v-if="isRebuild || itemM.rebuild > 0" class="tagRe"
  55. >待重修</view
  56. >
  57. <view v-else>
  58. <view
  59. :class="{
  60. tagGreen: itemM.learning == 1,
  61. tagRe: itemM.learning == 0 || itemM.rebuild > 0,
  62. }"
  63. >
  64. <text v-if="itemM.rebuild > 0">待重测</text>
  65. <text v-else-if="itemM.learning == 1">合格</text>
  66. <text v-else-if="itemM.learning == 0">不合格</text>
  67. </view>
  68. </view>
  69. </view>
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. </template>
  75. <script>
  76. import { mapGetters, mapMutations } from "vuex";
  77. import courseSection from "@/components/course/courseSection.vue";
  78. export default {
  79. name: "courseChapter",
  80. props: {
  81. isLive: false,
  82. orderGoodsId: {
  83. default: 0,
  84. },
  85. preItem: {
  86. default: undefined,
  87. },
  88. learningOrder: {
  89. //是否设置学习顺序 1 章节顺序 0不设置 2从头学到尾顺序
  90. type: Number,
  91. default: 0,
  92. },
  93. needOpen: {
  94. //是否默认展开
  95. type: Boolean,
  96. default: false,
  97. },
  98. menuItem: {
  99. type: Object,
  100. default: {},
  101. },
  102. isBuy: {
  103. type: Boolean,
  104. default: false,
  105. },
  106. levelId: {
  107. type: String,
  108. default: "",
  109. },
  110. goodsId: {
  111. type: Number,
  112. default: 0,
  113. },
  114. courseId: {
  115. type: Number,
  116. default: 0,
  117. },
  118. isRebuild: {
  119. type: Boolean,
  120. default: false,
  121. },
  122. gradeId: {
  123. type: Number,
  124. default: 0,
  125. },
  126. sectionMaxNum: {
  127. default: undefined,
  128. },
  129. // 商品类型 1视频2题库 3补考 4前培 5虚拟赠送题库 6直播
  130. goodsType: {
  131. type: [Number, String],
  132. default: 0,
  133. },
  134. },
  135. components: {
  136. courseSection,
  137. },
  138. data() {
  139. return {
  140. down: true,
  141. list: [],
  142. examList: {},
  143. canLearn: false, //是否全部视频看完才可以练习、测试
  144. sectionExam: [],
  145. };
  146. },
  147. onLoad() {},
  148. created() {},
  149. mounted() {
  150. if (this.needOpen && this.chapterOpen) {
  151. this.updateChapterOpen(false);
  152. this.openChapter(this.menuItem);
  153. }
  154. },
  155. onPageShow() {
  156. if (this.isBuy) {
  157. this.refreshList({ isRebuild: this.isRebuild });
  158. }
  159. },
  160. methods: {
  161. ...mapMutations(["updateChapterOpen"]),
  162. // 调用节的方法
  163. // togoBack(value) {
  164. // this.$refs.ChapterSection[0].ChapterExam()
  165. // },
  166. goodsTodayStudySectionNum() {
  167. return new Promise((resolve) => {
  168. this.$api
  169. .goodsTodayStudySectionNum({
  170. goodsId: this.goodsId,
  171. gradeId: this.gradeId,
  172. })
  173. .then((res) => {
  174. if (res.data.code == 200) {
  175. resolve(res.data.data);
  176. }
  177. });
  178. });
  179. },
  180. refreshList(isRebuild) {
  181. let moduleId = this.menuItem.moduleId ? this.menuItem.moduleId : 0;
  182. if (this.isRebuild) {
  183. this.getReSectionList(
  184. this.menuItem.id,
  185. this.menuItem.courseId,
  186. moduleId
  187. );
  188. } else {
  189. this.getBuySectionList(
  190. this.menuItem.id,
  191. this.menuItem.courseId,
  192. moduleId
  193. );
  194. // this.getMenuExamList(item.id,item.courseId,moduleId)
  195. }
  196. this.$emit("playEnd", { isRebuild: isRebuild.isRebuild });
  197. },
  198. findNextSection(index) {
  199. for (let i = index + 1; i < this.list.length; i++) {
  200. return this.list[i];
  201. }
  202. return {};
  203. },
  204. studyRecordMenuAllList() {
  205. return new Promise((resolve) => {
  206. this.$api
  207. .studyRecordMenuAllList({
  208. courseId: this.courseId,
  209. gradeId: this.gradeId,
  210. goodsId: this.goodsId,
  211. })
  212. .then((res) => {
  213. if (res.data.code == 200) {
  214. resolve(res.data.data);
  215. }
  216. });
  217. });
  218. },
  219. gradeCheckGoodsStudy(id) {
  220. let moduleId = this.menuItem.moduleId || 0;
  221. let chapterId = this.menuItem.chapterId || 0;
  222. let sectionId = this.menuItem.sectionId || this.menuItem.menuId;
  223. return new Promise((resolve) => {
  224. this.$api
  225. .gradeCheckGoodsStudy({
  226. goodsId: this.goodsId,
  227. gradeId: this.gradeId,
  228. moduleId: this.menuItem.moduleId || 0,
  229. chapterId: this.menuItem.chapterId || 0,
  230. examId: id,
  231. })
  232. .then((res) => {
  233. resolve(res.data.data);
  234. });
  235. });
  236. },
  237. // 新增用户视频学习日志
  238. studyLog() {
  239. this.$http({
  240. url: '/user/study/log',
  241. method: 'post',
  242. data: {
  243. goodsId: this.goodsId,
  244. courseId: this.courseId,
  245. moduleId: this.menuItem.moduleId || 0,
  246. chapterId: this.menuItem.chapterId || 0,
  247. sectionId: this.menuItem.sectionId || this.menuItem.menuId,
  248. fromPlat: 1, //来源平台 1小程序 2PC网站
  249. goodsType: this.goodsType, // 商品类型 1视频2题库 3补考 4前培 5虚拟赠送题库 6直播
  250. orderGoodsId: this.orderGoodsId,
  251. }
  252. }).then((res) => {
  253. console.log('考试的用户学习日志:', res)
  254. })
  255. },
  256. /**
  257. * 去做题
  258. */
  259. async toDo(id, goodsId = 0, moduleId = 0, chapterId = 0, item, index) {
  260. let learnNum = await this.goodsTodayStudySectionNum();
  261. let hasLearn = await this.gradeCheckGoodsStudy(id);
  262. if (this.sectionMaxNum > 0) {
  263. if (learnNum >= this.sectionMaxNum && !hasLearn) {
  264. uni.showToast({
  265. icon: "none",
  266. title: `每天最多学习${this.sectionMaxNum}节`,
  267. });
  268. return;
  269. }
  270. }
  271. // console.log(this.learningOrder, "this.learningOrder");
  272. if (this.learningOrder == 1) {
  273. if (this.canLearn) {
  274. let num = await this.bankRecordDoNum(item.typeId);
  275. //有次数限制
  276. if (item.answerNum - num > 0 && item.answerNum > 0) {
  277. // this.$set(this.list[index],'doNum',(item.doNum+1))
  278. // console.log(this.list[index]);
  279. uni.navigateTo({
  280. url:
  281. "/pages2/class/questionBank?courseId=" +
  282. this.courseId +
  283. "&gradeId=" +
  284. this.gradeId +
  285. "&isFromVideo=1&id=" +
  286. id +
  287. "&goodsid=" +
  288. goodsId +
  289. "&moduleId=" +
  290. moduleId +
  291. "&chapterId=" +
  292. chapterId +
  293. "&orderGoodsId=" +
  294. this.orderGoodsId +
  295. "&type=1" + '&learning=' + item.learning
  296. ,
  297. });
  298. this.studyLog()
  299. //没有答题次数限制
  300. } else if (item.answerNum == 0) {
  301. uni.navigateTo({
  302. url:
  303. "/pages2/class/questionBank?courseId=" +
  304. this.courseId +
  305. "&gradeId=" +
  306. this.gradeId +
  307. "&isFromVideo=1&id=" +
  308. id +
  309. "&goodsid=" +
  310. goodsId +
  311. "&moduleId=" +
  312. moduleId +
  313. "&chapterId=" +
  314. chapterId +
  315. "&orderGoodsId=" +
  316. this.orderGoodsId +
  317. "&type=1" + '&learning=' + item.learning,
  318. });
  319. this.studyLog()
  320. } else {
  321. uni.showToast({
  322. icon: "none",
  323. title: "该试卷只能答题" + item.answerNum + "次",
  324. });
  325. return;
  326. }
  327. } else {
  328. uni.showToast({
  329. icon: "none",
  330. title: "请按顺序学完视频课程再进行练习和测试",
  331. });
  332. }
  333. } else if (this.learningOrder == 2 && !item.rebuild) {
  334. let canLearn = this.list[index - 1].learning == 1;
  335. let rows = await this.studyRecordMenuAllList();
  336. let isStop = false;
  337. let newRows = [];
  338. for (let i = 0; i < rows.length; i++) {
  339. let moduleTrue = rows[i].moduleId == moduleId;
  340. let chapterTrue = rows[i].chapterId == chapterId;
  341. if (moduleTrue && chapterTrue) {
  342. isStop = true;
  343. if (rows[i].sectionType != 2) {
  344. //忽略直播
  345. newRows.push(rows[i]);
  346. }
  347. } else {
  348. if (!isStop) {
  349. if (rows[i].sectionType != 2) {
  350. //忽略直播
  351. newRows.push(rows[i]);
  352. }
  353. } else {
  354. break;
  355. }
  356. }
  357. }
  358. // console.log(newRows);
  359. let isAllLearn = newRows.every((item) => {
  360. return item.studyStatus == 1;
  361. });
  362. if (isAllLearn) {
  363. //之前的都学完了
  364. // if(canLearn) { //视频的上一节学完
  365. let num = await this.bankRecordDoNum(item.typeId);
  366. //有次数限制
  367. if (item.answerNum - num > 0 && item.answerNum > 0) {
  368. // this.$set(this.list[index],'doNum',(item.doNum+1))
  369. // console.log(this.list[index]);
  370. uni.navigateTo({
  371. url:
  372. "/pages2/class/questionBank?courseId=" +
  373. this.courseId +
  374. "&gradeId=" +
  375. this.gradeId +
  376. "&isFromVideo=1&id=" +
  377. id +
  378. "&goodsid=" +
  379. goodsId +
  380. "&moduleId=" +
  381. moduleId +
  382. "&chapterId=" +
  383. chapterId +
  384. "&orderGoodsId=" +
  385. this.orderGoodsId +
  386. "&type=1" + '&learning=' + item.learning,
  387. });
  388. this.studyLog()
  389. //没有答题次数限制
  390. } else if (item.answerNum == 0) {
  391. uni.navigateTo({
  392. url:
  393. "/pages2/class/questionBank?courseId=" +
  394. this.courseId +
  395. "&gradeId=" +
  396. this.gradeId +
  397. "&isFromVideo=1&id=" +
  398. id +
  399. "&goodsid=" +
  400. goodsId +
  401. "&moduleId=" +
  402. moduleId +
  403. "&chapterId=" +
  404. chapterId +
  405. "&orderGoodsId=" +
  406. this.orderGoodsId +
  407. "&type=1" + '&learning=' + item.learning,
  408. });
  409. this.studyLog()
  410. } else {
  411. uni.showToast({
  412. icon: "none",
  413. title: "该试卷只能答题" + item.answerNum + "次",
  414. });
  415. return;
  416. }
  417. } else {
  418. uni.showToast({
  419. icon: "none",
  420. title: "请学完视频课程再进行练习和测试",
  421. });
  422. }
  423. } else {
  424. let num = await this.bankRecordDoNum(item.typeId);
  425. //有次数限制
  426. if (item.answerNum - item.doNum > 0 && item.answerNum > 0) {
  427. // this.$set(this.list[index],'doNum',(item.doNum+1))
  428. // console.log(this.list[index]);
  429. uni.navigateTo({
  430. url:
  431. "/pages2/class/questionBank?courseId=" +
  432. this.courseId +
  433. "&gradeId=" +
  434. this.gradeId +
  435. "&isFromVideo=1&id=" +
  436. id +
  437. "&goodsid=" +
  438. goodsId +
  439. "&moduleId=" +
  440. moduleId +
  441. "&chapterId=" +
  442. chapterId +
  443. "&orderGoodsId=" +
  444. this.orderGoodsId +
  445. "&type=1" + '&learning=' + item.learning,
  446. });
  447. this.studyLog()
  448. //没有答题次数限制
  449. } else if (item.answerNum == 0) {
  450. uni.navigateTo({
  451. url:
  452. "/pages2/class/questionBank?courseId=" +
  453. this.courseId +
  454. "&gradeId=" +
  455. this.gradeId +
  456. "&isFromVideo=1&id=" +
  457. id +
  458. "&goodsid=" +
  459. goodsId +
  460. "&moduleId=" +
  461. moduleId +
  462. "&chapterId=" +
  463. chapterId +
  464. "&orderGoodsId=" +
  465. this.orderGoodsId +
  466. "&type=1" + '&learning=' + item.learning,
  467. });
  468. this.studyLog()
  469. } else {
  470. uni.showToast({
  471. icon: "none",
  472. title: "该试卷只能答题" + item.answerNum + "次",
  473. });
  474. return;
  475. }
  476. }
  477. },
  478. bankRecordDoNum(examId) {
  479. return new Promise((resolve) => {
  480. this.$api
  481. .bankRecordDoNum({
  482. goodsId: this.goodsId,
  483. gradeId: this.gradeId,
  484. chapterId: this.menuItem.id,
  485. courseId: this.courseId,
  486. moduleId: 0,
  487. examId: examId,
  488. })
  489. .then((res) => {
  490. resolve(res.data.data);
  491. });
  492. });
  493. },
  494. async openChapter(item) {
  495. // console.log('---zhang',this.menuItem, this.down,this.list, item.id, item.courseId, item.moduleId);
  496. this.down = !this.down;
  497. if (!this.down && this.list.length == 0) {
  498. // console.log(item.id, 69);
  499. //获取章下面所有节试卷列表
  500. await this.$api.reSectionExamList({
  501. chapterId: item.chapterId || item.menuId,
  502. courseId: item.courseId,
  503. gradeId: item.gradeId
  504. }).then((res) => {
  505. if (res.data.code == 200) {
  506. this.sectionExam = res.data.data || []
  507. }
  508. })
  509. if (this.isBuy) {
  510. let moduleId = item.moduleId ? item.moduleId : 0;
  511. if (this.isRebuild) {
  512. this.getReSectionList(item.id, item.courseId, moduleId);
  513. } else {
  514. this.getBuySectionList(item.id, item.courseId, moduleId);
  515. // this.getMenuExamList(item.id,item.courseId,moduleId)
  516. }
  517. } else {
  518. this.getSectionList(item.id);
  519. }
  520. }
  521. },
  522. getMenuExamList(chapterId, courseId, moduleId) {
  523. let self = this;
  524. this.$api
  525. .menuExamList({
  526. chapterId: chapterId,
  527. courseId: courseId,
  528. moduleId: moduleId,
  529. })
  530. .then((res) => {
  531. if (res.data.code == 200) {
  532. self.examList = res.data.rows;
  533. }
  534. });
  535. },
  536. getSectionList(chapterId) {
  537. let self = this;
  538. // url: '/app/common/course/sectionList/'+data,
  539. this.$api.sectionList(chapterId).then((res) => {
  540. if (res.data.code == 200) {
  541. for (let i = 0; i < res.data.data.length; i++) {
  542. let item = res.data.data[i];
  543. item.id = item.sectionId;
  544. item.menuType = 3;
  545. //判断是否试听
  546. item.tryListen = false;
  547. if (self.goodsAuditionConfigIdList.indexOf(item.id) !== -1) {
  548. item.tryListen = true;
  549. }
  550. }
  551. let newArr = res.data.data.filter((item) => {
  552. return item.type != 2;
  553. });
  554. this.canLearn = newArr.every((item) => {
  555. if (item.learning == 1) {
  556. return true;
  557. } else {
  558. return false;
  559. }
  560. });
  561. self.list = res.data.data;
  562. }
  563. });
  564. },
  565. getReSectionList(chapterId, courseId, moduleId) {
  566. let self = this;
  567. this.$api
  568. .reSectionList({
  569. chapterId: chapterId,
  570. gradeId: this.gradeId,
  571. courseId: courseId,
  572. rebuild: 1,
  573. moduleId: moduleId,
  574. })
  575. .then((res) => {
  576. if (res.data.code == 200) {
  577. for (let i = 0; i < res.data.data.length; i++) {
  578. let item = res.data.data[i];
  579. item.id = item.sectionId;
  580. item.menuType = 3;
  581. //判断是否试听
  582. item.tryListen = false;
  583. if (self.goodsAuditionConfigIdList.indexOf(item.id) !== -1) {
  584. item.tryListen = true;
  585. }
  586. }
  587. let newArr = res.data.data.filter((item) => {
  588. return item.type != 2;
  589. });
  590. this.canLearn = newArr.every((item) => {
  591. if (item.learning == 1) {
  592. return true;
  593. } else {
  594. return false;
  595. }
  596. });
  597. self.list = res.data.data;
  598. }
  599. });
  600. },
  601. getBuySectionList(chapterId, courseId, moduleId) {
  602. let self = this;
  603. this.$api
  604. .reSectionList({
  605. chapterId: chapterId,
  606. gradeId: this.gradeId,
  607. courseId: courseId,
  608. moduleId: moduleId,
  609. })
  610. .then((res) => {
  611. if (res.data.code == 200) {
  612. for (let i = 0; i < res.data.data.length; i++) {
  613. let item = res.data.data[i];
  614. item.id = item.sectionId;
  615. item.menuType = 3;
  616. //判断是否试听
  617. item.tryListen = false;
  618. if (self.goodsAuditionConfigIdList.indexOf(item.id) !== -1) {
  619. item.tryListen = true;
  620. }
  621. }
  622. let newArr = res.data.data.filter((item) => {
  623. return item.type != 2;
  624. });
  625. this.canLearn = newArr.every((item) => {
  626. if (item.learning == 1) {
  627. return true;
  628. } else {
  629. return false;
  630. }
  631. });
  632. self.list = res.data.data;
  633. }
  634. });
  635. },
  636. },
  637. computed: { ...mapGetters(["goodsAuditionConfigIdList", "chapterOpen"]) },
  638. };
  639. </script>
  640. <style lang="scss" scoped>
  641. .tagRe {
  642. width: 80rpx;
  643. height: 28rpx;
  644. background: #ff3b30;
  645. border-radius: 8rpx;
  646. font-size: 20rpx;
  647. color: #ffffff;
  648. text-align: center;
  649. }
  650. .tagGreen {
  651. width: 80rpx;
  652. height: 28rpx;
  653. background: #34c759;
  654. border-radius: 8rpx;
  655. font-size: 20rpx;
  656. color: #ffffff;
  657. text-align: center;
  658. }
  659. .eTag {
  660. width: 64rpx;
  661. height: 36rpx;
  662. text-align: center;
  663. line-height: 36rpx;
  664. font-size: 20rpx;
  665. background: #007aff;
  666. border-radius: 8rpx;
  667. color: #ffffff;
  668. }
  669. .examBox {
  670. display: flex;
  671. align-items: center;
  672. justify-content: space-between;
  673. }
  674. .exam {
  675. font-size: 30rpx;
  676. display: flex;
  677. align-items: center;
  678. margin: 20rpx 0;
  679. }
  680. .icon_up {
  681. width: 24rpx;
  682. height: 24rpx;
  683. }
  684. .title {
  685. // margin-bottom: 30rpx;
  686. height: 78rpx;
  687. display: flex;
  688. align-items: center;
  689. border-bottom: 1rpx solid #EEEEEE;
  690. .menu_name {
  691. font-size: 24rpx;
  692. font-family: PingFang SC;
  693. font-weight: bold;
  694. color: #333;
  695. white-space: nowrap;
  696. overflow: hidden;
  697. text-overflow: ellipsis;
  698. margin-left: 8rpx;
  699. }
  700. }
  701. </style>