courseModule.vue 8.9 KB

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