chanpin2.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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 jieList" :key="item.jieId">
  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.jieName }}</view>
  39. <view>{{ item.jieIntro }}</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. shuxueChanpinDengjiInfo,
  70. shuxueSave2
  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. updateChanpin2Process
  84. } from "./useNeirongChanpin2"
  85. import tipSmallDialog from "@/components/dialog/tipSmallDialog.vue";
  86. // 产品2 计算特训
  87. export default {
  88. data() {
  89. return {
  90. canExitApp: false,
  91. jieList: [],
  92. neirongInfo: {},
  93. banbenId: '',
  94. jieId: '',
  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/cp2/dingdan"
  128. })
  129. },
  130. initData(dengjiId) {
  131. console.log('阿斯顿发送到发送到饭撒的');
  132. const cacheData = cacheManager.get('contentInfo');
  133. if (cacheData) {
  134. console.log('使用缓存数据');
  135. this.updateFromCache();
  136. } else {
  137. console.log('重新请求数据');
  138. this.initFromOptions(dengjiId);
  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(dengjiId) {
  155. this.loadDataFromApi(dengjiId);
  156. },
  157. // 从缓存更新数据方法
  158. updateFromCache() {
  159. console.log('12311');
  160. updateChanpin2Process()
  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.jieList = [...(cacheData.jieList || [])];
  169. this.dengjiId = cacheData.dengjiId
  170. if (this.jieList.length == 0) {
  171. this.existData = false
  172. } else {
  173. this.existData = true
  174. }
  175. // this.$nextTick(() => {
  176. // this.updateTitlePositions();
  177. // });
  178. } else {
  179. this.existData = false;
  180. }
  181. },
  182. loadDataFromApi(dengjiId) {
  183. uni.showLoading({
  184. title: '加载中'
  185. });
  186. this.dengjiId = dengjiId
  187. this.neirongInfo = {}
  188. this.curProcess = ''
  189. this.jieList = []
  190. const req = {
  191. dengjiId: dengjiId
  192. }
  193. shuxueChanpinDengjiInfo(req).then(res => {
  194. if (res.code === 0) {
  195. this.neirongInfo = res.data;
  196. this.neirongInfo.jieId = res.data.curJieId;
  197. this.curProcess = res.data.curProcess * 100;
  198. this.jieList = res.data.jieList || [];
  199. if (this.jieList.length == 0) {
  200. this.existData = false
  201. } else {
  202. this.existData = true
  203. }
  204. const cacheData = {
  205. ...res.data,
  206. dengjiId: dengjiId,
  207. };
  208. cacheManager.set('contentInfo', cacheData);
  209. uni.hideLoading();
  210. }
  211. }).catch(res => {
  212. cacheManager.remove("contentInfo");
  213. toast("加载失败,请重试");
  214. uni.hideLoading();
  215. });
  216. },
  217. handleScroll(e) {
  218. const scrollTop = e.detail.scrollTop;
  219. console.log('scrollTop', scrollTop);
  220. this.showGoTop = scrollTop > this.scrollThreshold;
  221. },
  222. getJieAndDanyuan(data, jieId) {
  223. for (let jie of data.jieList) {
  224. if (jie.jieId == jieId) {
  225. return {
  226. jie
  227. }
  228. }
  229. }
  230. return null;
  231. },
  232. async saveAndNavigate(jieId, da, code) {
  233. if (code == 'jixu') {
  234. if (!da.jieId) {
  235. toast("jieId 丢失")
  236. return false
  237. }
  238. }
  239. let req = {
  240. "dengjiId": da.dengjiId,
  241. "jieId": da.jieId
  242. }
  243. console.log('req', req);
  244. const res = await shuxueSave2(req);
  245. if (res.code == 0) {
  246. let curJieAndDanyuan = this.getJieAndDanyuan(this.neirongInfo, jieId);
  247. console.log('curJieAndDanyuan',curJieAndDanyuan);
  248. if (!curJieAndDanyuan) {
  249. toast("未找到课程信息");
  250. return false;
  251. }
  252. const cacheData = cacheManager.get('contentInfo') || {};
  253. cacheData.curKechengName = curJieAndDanyuan.jie.jieIntro;
  254. cacheData.jieId = curJieAndDanyuan.jie.jieId;
  255. cacheData.curJieId = jieId;
  256. cacheData.type = curJieAndDanyuan.jie.type;
  257. cacheManager.set('contentInfo', cacheData);
  258. uni.navigateTo({
  259. url: `/pages/jisuantexun/lookShipin?jieId=${jieId}`
  260. })
  261. } else {
  262. return false;
  263. }
  264. },
  265. handlePlay(da, code) {
  266. console.log('ddd',da)
  267. if (da.lock && code == 'play') {
  268. this.$refs.gmtRef.handleShow();
  269. // 加锁视频需要购买
  270. // uni.navigateTo({
  271. // url: "/pages/chanpinShop/cp1/dingdan"
  272. // })
  273. return;
  274. }
  275. let jieId = code === 'jixu' ? da.curJieId : da.jieId;
  276. if (!jieId) {
  277. toast("无课程ID");
  278. return;
  279. }
  280. this.saveAndNavigate(jieId, da, code);
  281. },
  282. handleClickDanyuan(jieId) {
  283. if (!jieId) {
  284. toast("jieId丢失")
  285. return false
  286. }
  287. this.isShow = true;
  288. setTimeout(() => {
  289. // 更新为点击的动态单元Id [临时]
  290. this.$refs.dyRef.handleShow(jieId)
  291. }, 100)
  292. },
  293. handleBack() {
  294. uni.navigateTo({
  295. url: `/pages/chanpinXuanze/banben?dengjiId=` + this.dengjiId
  296. })
  297. },
  298. },
  299. // 计算吸顶栏下方的偏移(确保内容不被遮挡)
  300. computed: {
  301. }
  302. }
  303. </script>