chanpin3.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <template>
  2. <view class="ezy-page-body xuexi-page-body">
  3. <!-- 滚动区域 -->
  4. <scroll-view v-if="existData" :scroll-with-animation="true" scroll-y :scroll-top="scrollTop"
  5. @scroll="handleScroll">
  6. <view class="xxjl-card-box-padding">
  7. <view class="xxjl-card-box">
  8. <!-- 显示内容 -->
  9. <view class="card-body-box">
  10. <img :src="neirongInfo.cover" />
  11. <view class="body-right">
  12. <view class="right-name">{{ neirongInfo.chanpinName }}</view>
  13. <view class="right-item right-item-mini">等级:{{neirongInfo.dengjiName}}</view>
  14. <view class="right-item">版本:{{neirongInfo.name}}</view>
  15. <view>课程:{{neirongInfo.curKechengName}}</view>
  16. </view>
  17. </view>
  18. <view class="card-progress-box">
  19. <view class="xx-progress-box">
  20. <view class="progress-title">学习进度</view>
  21. <progress :percent="curProcess" class="xx-progress" stroke-width="20"
  22. backgroundColor="#3c7dfd" activeColor="#ffd11c" />
  23. </view>
  24. <ezyActiveVue class="ezy-btn-active jxxx-btn" @aclick="handlePlay(neirongInfo,'jixu')">
  25. </ezyActiveVue>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="xx-item-list">
  30. <view class="xx-item-title">— 以下为当前等级课程目录 —</view>
  31. <view v-for="(item, index) in danyuanList" :key="item.danyuanId">
  32. <!-- 节列表 -->
  33. <ezyActiveVue class="ezy-list-item-active xx-item-box" :class="item.lock?'xx-disabled-item-box':''" @aclick="handlePlay(item,'play')">
  34. <view class="xx-item-status"
  35. :class="item.wanchengFlag == 1 ? 'completed-status' : 'uncompleted-status'"></view>
  36. <img :src="item.cover" />
  37. <view class="xx-text-box">
  38. <view>{{ item.danyuanName }}</view>
  39. <view>{{ item.danyuanIntro }}</view>
  40. </view>
  41. <view v-if="item.lock" class="xx-item-lock-btn"></view>
  42. <view v-else class="xx-item-btn"></view>
  43. </ezyActiveVue>
  44. </view>
  45. <view class="xx-item-title">本级别最后一单元啦~</view>
  46. <view class="xx-more-btn" @click="moreBtn"></view>
  47. </view>
  48. </scroll-view>
  49. <!-- 回到顶部 -->
  50. <view v-show="showGoTop" class="go-top-btn" @click="goTopBtn"></view>
  51. <!-- 无数据占位 -->
  52. <view v-if="!existData" class="ezy-page-body">
  53. <view class="ezy-no-sj">
  54. <icon></icon>
  55. <text>暂无数据</text>
  56. </view>
  57. </view>
  58. <!-- 弹窗组件 -->
  59. <danyuanInfoVue ref="dyRef" v-if="isShow" @close="isShow = false"></danyuanInfoVue>
  60. <!-- 购买提示窗 -->
  61. <tipSmallDialog ref="gmtRef" content="需要购买当前课程才能学习" @confirm-btn="handleConfirmBtn" qrBtnName="前往购买"></tipSmallDialog>
  62. </view>
  63. </template>
  64. <script>
  65. import ezyActiveVue from "@/components/ezyActive/ezyActive.vue";
  66. import CustomTabBar from '@/components/custom-tabbar/index.vue';
  67. import cacheManager from "@/utils/cacheManager.js";
  68. import {
  69. yingyuDanciInfo,
  70. yingyuSave2
  71. } from "@/api/chanpinneirong.js"
  72. import {
  73. onLoad,
  74. onShow,
  75. onHide,
  76. onUnload
  77. } from "@dcloudio/uni-app"
  78. import danyuanInfoVue from '@/pages/xinshuxue/components/danyuanInfo.vue';
  79. import {
  80. toast
  81. } from '../../utils/common';
  82. import {
  83. updateChanpin3Process
  84. } from "./useNeirongChanpin3"
  85. import tipSmallDialog from "@/components/dialog/tipSmallDialog.vue";
  86. // 产品2 计算特训
  87. export default {
  88. data() {
  89. return {
  90. canExitApp: false,
  91. danyuanList: [],
  92. neirongInfo: {},
  93. banbenId: '',
  94. danyuanId: '',
  95. chanpinId: '',
  96. dengjiId: '',
  97. curProcess: '',
  98. existData: false,
  99. isShow: false,
  100. stickyHeight: 0, // 吸顶栏高度(px)
  101. currentStickyTitle: '', // 初始为空,不显示吸顶
  102. currentStickyIntro: '',
  103. currentDanyuanId: '',
  104. currentStickyDengjiId: '',
  105. titlePositions: [],
  106. scrollTop: 0,
  107. showGoTop: false,
  108. scrollThreshold: 300,
  109. }
  110. },
  111. components: {
  112. CustomTabBar,
  113. danyuanInfoVue,
  114. ezyActiveVue,
  115. tipSmallDialog
  116. },
  117. onHide() {
  118. console.log('学习页面隐藏')
  119. },
  120. onUnload() {
  121. // 页面卸载无需特殊处理
  122. },
  123. methods: {
  124. handleConfirmBtn() {
  125. // 加锁视频需要购买
  126. uni.navigateTo({
  127. url: "/pages/chanpinShop/cp4/dingdan"
  128. })
  129. },
  130. initData(banbenId) {
  131. console.log('33333');
  132. const cacheData = cacheManager.get('contentInfo');
  133. if (cacheData) {
  134. console.log('使用缓存数据');
  135. this.updateFromCache();
  136. } else {
  137. console.log('重新请求数据');
  138. this.initFromOptions(banbenId);
  139. }
  140. },
  141. goTopBtn() {
  142. // 替换原来的 uni.pageScrollTo
  143. this.scrollTop = Math.random(); // 先设置一个随机值
  144. this.$nextTick(() => {
  145. this.scrollTop = 0; // 再设置回0
  146. });
  147. this.showGoTop = false;
  148. },
  149. moreBtn() {
  150. uni.switchTab({
  151. url: '/pages/chanpinXuanze/index'
  152. })
  153. },
  154. initFromOptions(banbenId) {
  155. this.loadDataFromApi(banbenId);
  156. },
  157. // 从缓存更新数据方法
  158. updateFromCache() {
  159. console.log('12311');
  160. updateChanpin3Process()
  161. const cacheData = cacheManager.get('contentInfo');
  162. console.log('cacheData 从缓存更新数据方法', cacheData);
  163. if (cacheData) {
  164. this.neirongInfo = {
  165. ...cacheData
  166. };
  167. this.curProcess = cacheData.curProcess;
  168. this.danyuanList = [...(cacheData.danyuanList || [])];
  169. this.banbenId = cacheData.banbenId;
  170. this.dengjiId = cacheData.dengjiId;
  171. if (this.danyuanList.length == 0) {
  172. this.existData = false
  173. } else {
  174. this.existData = true
  175. }
  176. // this.$nextTick(() => {
  177. // this.updateTitlePositions();
  178. // });
  179. } else {
  180. this.existData = false;
  181. }
  182. },
  183. loadDataFromApi(banbenId) {
  184. uni.showLoading({
  185. title: '加载中'
  186. });
  187. this.banbenId = banbenId
  188. this.neirongInfo = {}
  189. this.curProcess = ''
  190. this.danyuanList = []
  191. const req = {
  192. banbenId: banbenId
  193. }
  194. yingyuDanciInfo(req).then(res => {
  195. if (res.code === 0) {
  196. this.neirongInfo = res.data;
  197. this.neirongInfo.danyuanId = res.data.curDanyuanId;
  198. this.curProcess = res.data.curProcess * 100;
  199. this.danyuanList = res.data.danyuanList || [];
  200. if (this.danyuanList.length == 0) {
  201. this.existData = false
  202. } else {
  203. this.existData = true
  204. }
  205. const cacheData = {
  206. ...res.data,
  207. banbenId: banbenId,
  208. };
  209. cacheManager.set('contentInfo', cacheData);
  210. uni.hideLoading();
  211. }
  212. }).catch(res => {
  213. cacheManager.remove("contentInfo");
  214. toast("加载失败,请重试");
  215. uni.hideLoading();
  216. });
  217. },
  218. handleScroll(e) {
  219. const scrollTop = e.detail.scrollTop;
  220. console.log('scrollTop', scrollTop);
  221. this.showGoTop = scrollTop > this.scrollThreshold;
  222. },
  223. getJieAndDanyuan(data, danyuanId) {
  224. for (let danyuan of data.danyuanList) {
  225. if (danyuan.danyuanId == danyuanId) {
  226. return {
  227. danyuan
  228. }
  229. }
  230. }
  231. return null;
  232. },
  233. async saveAndNavigate(danyuanId, da, code) {
  234. if (code == 'jixu') {
  235. if (!da.danyuanId) {
  236. toast("danyuanId 丢失")
  237. return false
  238. }
  239. }
  240. let req = {
  241. "banbenId": this.banbenId,
  242. "danyuanId": da.danyuanId
  243. }
  244. console.log('req', req);
  245. const res = await yingyuSave2(req);
  246. if (res.code == 0) {
  247. let curJieAndDanyuan = this.getJieAndDanyuan(this.neirongInfo, danyuanId);
  248. console.log('curJieAndDanyuan',curJieAndDanyuan);
  249. if (!curJieAndDanyuan) {
  250. toast("未找到课程信息");
  251. return false;
  252. }
  253. const cacheData = cacheManager.get('contentInfo') || {};
  254. cacheData.curKechengName = curJieAndDanyuan.danyuan.danyuanIntro;
  255. cacheData.danyuanId = curJieAndDanyuan.danyuan.danyuanId;
  256. cacheData.curDanyuanId = danyuanId;
  257. cacheData.type = curJieAndDanyuan.danyuan.type;
  258. cacheManager.set('contentInfo', cacheData);
  259. uni.navigateTo({
  260. url: `/pages/chaojidanci/wordList/wordList?danyuanId=${danyuanId}&banbenId=${this.banbenId}`
  261. })
  262. } else {
  263. return false;
  264. }
  265. },
  266. handlePlay(da, code) {
  267. console.log('ddd',da)
  268. if (da.lock && code == 'play') {
  269. this.$refs.gmtRef.handleShow();
  270. // 加锁视频需要购买
  271. // uni.navigateTo({
  272. // url: "/pages/chanpinShop/cp1/dingdan"
  273. // })
  274. return;
  275. }
  276. let danyuanId = code === 'jixu' ? da.curDanyuanId : da.danyuanId;
  277. if (!danyuanId) {
  278. toast("无课程ID");
  279. return;
  280. }
  281. this.saveAndNavigate(danyuanId, da, code);
  282. },
  283. handleClickDanyuan(danyuanId) {
  284. if (!danyuanId) {
  285. toast("danyuanId丢失")
  286. return false
  287. }
  288. this.isShow = true;
  289. setTimeout(() => {
  290. // 更新为点击的动态单元Id [临时]
  291. this.$refs.dyRef.handleShow(danyuanId)
  292. }, 100)
  293. }
  294. },
  295. // 计算吸顶栏下方的偏移(确保内容不被遮挡)
  296. computed: {
  297. }
  298. }
  299. </script>