courseModule.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. <template>
  2. <!-- style="margin: 20rpx 0;" -->
  3. <view>
  4. <view class="title" @click="openModule(menuItem)">
  5. <text class="title_name" style="margin-left: 10rpx"
  6. >{{ menuItem.name }}
  7. </text>
  8. <view class="fl">
  9. <view
  10. class="title_status"
  11. :class="['grey', 'blue', 'gre'][learnStatus + 1]"
  12. style="margin-right: 20rpx"
  13. >
  14. {{ ["待学习", "学习中", "已学完"][learnStatus + 1] }}
  15. </view>
  16. <image src="/static/icon/up.png" class="icon_up" v-if="down"></image>
  17. <image src="/static/icon/down.png" class="icon_up" v-if="!down"></image>
  18. </view>
  19. </view>
  20. <view v-show="!down">
  21. <view v-for="(itemM, indexM) in list" :key="indexM">
  22. <courseChapter
  23. v-if="itemM.type != 2"
  24. :isLive="false"
  25. :preItem="list[indexM - 1] || preItem"
  26. :sectionMaxNum="sectionMaxNum"
  27. :needOpen="itemM.needOpen || (itemM.moduleId == sectionItem.moduleId && itemM.chapterId == sectionItem.chapterId)"
  28. @toDo="toDo($event)"
  29. :isBuy="isBuy"
  30. :isRebuild="isRebuild"
  31. :menuItem="itemM"
  32. :levelId="levelId + '-' + itemM.chapterId"
  33. >
  34. </courseChapter>
  35. <u-line v-if="indexM < list.length - 1"></u-line>
  36. <!-- 模块卷 -->
  37. <view v-if="itemM.type == 2">
  38. <view
  39. class="examBox"
  40. @click="
  41. toDoModuleExam(
  42. itemM.typeId,
  43. goodsId,
  44. itemM.moduleId,
  45. itemM.chapterId,
  46. itemM,
  47. indexM
  48. )
  49. "
  50. >
  51. <view class="exam">
  52. <view class="eTag">
  53. {{ itemM.doType == 1 ? "练习" : "考试" }}
  54. </view>
  55. <view style="margin-left: 15rpx; flex: 1">{{ itemM.name }}</view>
  56. </view>
  57. <view v-if="isRebuild || itemM.rebuild > 0" class="tagRe"
  58. >待重修</view
  59. >
  60. <view v-else>
  61. <view
  62. :class="{
  63. tagGreen: itemM.learning == 1,
  64. tagRe: itemM.learning == 0 || itemM.rebuild > 0,
  65. }"
  66. >
  67. <text v-if="itemM.learning == 1">合格</text>
  68. <text v-else-if="itemM.learning == 0">不及格(需重考)</text>
  69. <!-- <text v-else>不合格</text> -->
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. </view>
  77. </template>
  78. <script>
  79. import courseChapter from "@/components/course/courseChapter.vue";
  80. export default {
  81. name: "courseModule",
  82. inject: ["paramsFn"],
  83. props: {
  84. preItem: {
  85. default: undefined,
  86. },
  87. needOpen: {
  88. //是否默认展开
  89. type: Boolean,
  90. default: false,
  91. },
  92. menuItem: {
  93. type: Object,
  94. default: {},
  95. },
  96. levelId: {
  97. type: [Number, String],
  98. default: "",
  99. },
  100. isBuy: {
  101. //是否是已购买商品
  102. type: Boolean,
  103. default: false,
  104. },
  105. isRebuild: {
  106. //是否重修目录
  107. type: Boolean,
  108. default: false,
  109. },
  110. sectionMaxNum: {
  111. default: undefined,
  112. },
  113. },
  114. components: {
  115. courseChapter,
  116. },
  117. data() {
  118. return {
  119. down: true,
  120. list: [],
  121. };
  122. },
  123. methods: {
  124. toDo(item) {
  125. this.$emit("toDo", item);
  126. },
  127. openModule(item) {
  128. this.down = !this.down;
  129. if (!this.down && this.list.length == 0) {
  130. if (this.isBuy) {
  131. if (this.isRebuild) {
  132. this.getReChapterList(item.id, item.courseId);
  133. } else {
  134. this.getBuyChapterList(item.id, item.courseId); //已购买目录
  135. }
  136. } else {
  137. this.getChapterList(item.id); //未购买目录
  138. }
  139. }
  140. },
  141. getChapterList(moduleId) {
  142. // url: '/app/common/course/chapterList/'+data,
  143. this.$api.chapterList(moduleId).then((res) => {
  144. if (res.data.code == 200) {
  145. for (let i = 0; i < res.data.data.length; i++) {
  146. let item = res.data.data[i];
  147. item.id = item.chapterId;
  148. item.menuType = 2;
  149. }
  150. this.list = res.data.data;
  151. }
  152. });
  153. },
  154. getReChapterList(moduleId, courseId) {
  155. this.$api
  156. .reChapterList({
  157. moduleId: moduleId,
  158. gradeId: this.gradeId,
  159. courseId: courseId,
  160. rebuild: 1,
  161. orderGoodsId: this.orderGoodsId,
  162. })
  163. .then((res) => {
  164. if (res.data.code == 200) {
  165. for (let i = 0; i < res.data.data.length; i++) {
  166. let item = res.data.data[i];
  167. item.id = item.chapterId;
  168. }
  169. this.list = res.data.data;
  170. }
  171. });
  172. },
  173. getBuyChapterList(moduleId, courseId) {
  174. // course/chapterList
  175. this.$api
  176. .reChapterList({
  177. moduleId: moduleId,
  178. gradeId: this.gradeId,
  179. courseId: courseId,
  180. orderGoodsId: this.orderGoodsId,
  181. })
  182. .then((res) => {
  183. if (res.data.code == 200) {
  184. for (let i = 0; i < res.data.data.length; i++) {
  185. let item = res.data.data[i];
  186. item.id = item.chapterId;
  187. item.menuType = 2;
  188. if (Object.keys(this.sectionItem).length) {
  189. item["needOpen"] =
  190. item.chapterId == this.sectionItem.chapterId ? true : false;
  191. } else {
  192. item["needOpen"] = i == 0 ? true : false;
  193. }
  194. }
  195. this.list = res.data.data;
  196. // console.log('章的列表:', this.list);
  197. }
  198. });
  199. },
  200. /**
  201. * 去做题
  202. */
  203. async toDoModuleExam(
  204. id,
  205. goodsId = 0,
  206. moduleId = 0,
  207. chapterId = 0,
  208. item,
  209. index
  210. ) {
  211. if (item.doType === 2 && item.learning == 1) {
  212. return;
  213. }
  214. if (this.params.orderNum == 2) {
  215. let newRows = [];
  216. newRows = this.menuAllList.filter((e) => e.moduleId == moduleId);
  217. let isAllLearn = newRows.every((item) => {
  218. return item.studyStatus == 1;
  219. });
  220. if (isAllLearn) {
  221. uni.navigateTo({
  222. url:
  223. "/pages2/class/questionBank?courseId=" +
  224. this.courseId +
  225. "&gradeId=" +
  226. this.gradeId +
  227. "&isFromVideo=1&id=" +
  228. id +
  229. "&goodsid=" +
  230. goodsId +
  231. "&moduleId=" +
  232. moduleId +
  233. "&chapterId=" +
  234. chapterId +
  235. "&orderGoodsId=" +
  236. this.orderGoodsId +
  237. "&type=3" +
  238. "&learning=" +
  239. item.learning +
  240. "&isBackVideo=" +
  241. 1,
  242. });
  243. } else {
  244. uni.showToast({
  245. icon: "none",
  246. title: "请学完视频课程再进行练习和测试",
  247. });
  248. }
  249. } else {
  250. uni.navigateTo({
  251. url:
  252. "/pages2/class/questionBank?courseId=" +
  253. this.courseId +
  254. "&gradeId=" +
  255. this.gradeId +
  256. "&isFromVideo=1&id=" +
  257. id +
  258. "&goodsid=" +
  259. goodsId +
  260. "&moduleId=" +
  261. moduleId +
  262. "&chapterId=" +
  263. chapterId +
  264. "&orderGoodsId=" +
  265. this.orderGoodsId +
  266. "&type=3" +
  267. "&learning=" +
  268. item.learning +
  269. "&isBackVideo=" +
  270. 1,
  271. });
  272. }
  273. },
  274. },
  275. computed: {
  276. learnStatus() {
  277. if (!this.isBuy || !this.sectionItem) {
  278. return -2;
  279. }
  280. let { id, courseId } = this.menuItem;
  281. if (
  282. this.sectionItem.courseId == courseId &&
  283. this.sectionItem.moduleId == id
  284. ) {
  285. return 0;
  286. }
  287. const list = this.menuAllList.filter(
  288. (e) => e.courseId == courseId && e.moduleId == id
  289. );
  290. const isAllLearn = list.every((item) => {
  291. return item.studyStatus == 1;
  292. });
  293. return isAllLearn ? 1 : -1;
  294. },
  295. params() {
  296. return this.paramsFn([
  297. "orderGoodsId",
  298. "gradeId",
  299. "courseId",
  300. "sectionItem",
  301. "menuAllList",
  302. "orderNum",
  303. "goodsId",
  304. ]);
  305. },
  306. courseId() {
  307. return this.params.courseId;
  308. },
  309. gradeId() {
  310. return this.params.gradeId;
  311. },
  312. orderGoodsId() {
  313. return this.params.orderGoodsId;
  314. },
  315. goodsId() {
  316. return this.params.goodsId;
  317. },
  318. sectionItem() {
  319. return this.params.sectionItem || {};
  320. },
  321. menuAllList() {
  322. return this.params.menuAllList;
  323. },
  324. },
  325. watch: {
  326. // courseId: {
  327. // handler(val) {
  328. // if (!this.isBuy || !this.sectionItem) return;
  329. // if (this.sectionItem.moduleId == this.menuItem.menuId) {
  330. // this.down = true;
  331. // this.list = [];
  332. // this.openModule(this.menuItem);
  333. // }
  334. // },
  335. // immediate: true,
  336. // },
  337. sectionItem: {
  338. handler(val) {
  339. if (!this.isBuy) return;
  340. if (this.needOpen) {
  341. if(this.list.length == 0){
  342. this.down = true;
  343. this.list = [];
  344. this.openModule(this.menuItem);
  345. }else{
  346. this.down = false
  347. }
  348. }
  349. },
  350. immediate: true,
  351. },
  352. },
  353. };
  354. </script>
  355. <style lang="scss" scoped>
  356. .title {
  357. height: 70rpx;
  358. display: flex;
  359. justify-content: space-between;
  360. align-items: center;
  361. border-bottom: 1rpx solid #eeeeee;
  362. .title_name {
  363. font-size: 24rpx;
  364. font-weight: 500;
  365. color: #333333;
  366. white-space: nowrap;
  367. overflow: hidden;
  368. text-overflow: ellipsis;
  369. }
  370. .icon_up {
  371. width: 24rpx;
  372. height: 24rpx;
  373. }
  374. .title_status {
  375. width: 80rpx;
  376. height: 28rpx;
  377. border-radius: 8rpx;
  378. font-size: 20rpx;
  379. color: #ffffff;
  380. text-align: center;
  381. }
  382. .gre {
  383. background: #34c759;
  384. }
  385. .blue {
  386. background: #409eff;
  387. }
  388. .grey {
  389. background: #909399;
  390. }
  391. }
  392. .examBox {
  393. display: flex;
  394. align-items: center;
  395. justify-content: space-between;
  396. .exam {
  397. font-size: 30rpx;
  398. display: flex;
  399. align-items: center;
  400. margin: 20rpx 0;
  401. }
  402. .eTag {
  403. width: 64rpx;
  404. height: 36rpx;
  405. text-align: center;
  406. line-height: 36rpx;
  407. font-size: 20rpx;
  408. background: #007aff;
  409. border-radius: 8rpx;
  410. color: #ffffff;
  411. }
  412. }
  413. .tagRe {
  414. // width: 80rpx;
  415. line-height: 28rpx;
  416. padding: 0 8rpx;
  417. height: 28rpx;
  418. background: #ff3b30;
  419. border-radius: 8rpx;
  420. font-size: 20rpx;
  421. color: #ffffff;
  422. text-align: center;
  423. }
  424. .tagGreen {
  425. width: 80rpx;
  426. height: 28rpx;
  427. background: #34c759;
  428. border-radius: 8rpx;
  429. font-size: 20rpx;
  430. color: #ffffff;
  431. text-align: center;
  432. }
  433. </style>