mallPage.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <template>
  2. <view class="ezy-mall-page">
  3. <view class="icon-title-navBar-box">
  4. <view @click="goBack" class="nav-bar-icon"></view>
  5. <text class="nav-bar-title">鹅状元进阶营</text>
  6. </view>
  7. <view class="ezy-tab-border">
  8. <uni-segmented-control :current="productData.current" :values="productData.items" active-color="#3A7FE9"
  9. @clickItem="onChangeTab" class="ezy-tab-box" />
  10. <view>
  11. <view v-if="productData.current === 0">
  12. <scroll-view scroll-y="true" :scroll-into-view="scrollIntoId" class="order-scroll-view">
  13. <!--数学-->
  14. <view :id="'item-' + item.id" v-for="item in productData.list" :key="item.id"
  15. class="mall-list-item">
  16. <view class="mall-content-box">
  17. <img :src='item.cover' class="mall-image" />
  18. <view class="content-body-box">
  19. <view class="content-name">
  20. <view class="name-text">{{item.name}}</view>
  21. </view>
  22. <view class="content-text">{{item.intro}}</view>
  23. <view class="content-row">
  24. <view class="content-yuanjia">原价:{{item.yuanjia}}</view>
  25. <view class="shop-car-box" @click="addProduct(item)">
  26. <icon v-if="productData.selectedIds.includes(item.id)" class="car-change">
  27. </icon>
  28. </view>
  29. </view>
  30. </view>
  31. </view>
  32. <view class="mall-bottom-row">
  33. <view v-if="item.type ==1" class="kcb-btn" @click="productBtn">课程包明细<icon>
  34. </icon>
  35. </view>
  36. <view class="hdj-text">活动价:{{item.xianjia}}</view>
  37. </view>
  38. </view>
  39. </scroll-view>
  40. </view>
  41. <view v-if="productData.current === 1">
  42. <view>英语</view>
  43. </view>
  44. <!-- <view v-if="productData.current === 2">
  45. <view>语文</view>
  46. </view> -->
  47. </view>
  48. </view>
  49. <view class="footer-mall-pay-box">
  50. <view class="mall-left-box" @click="detailBtn">
  51. <!-- 需要换成从接口中取得 wgy -->
  52. <view class="price-icon-box">
  53. <text class="red-price fh-text">¥</text>
  54. <text class="red-price">{{totalPrice}}</text>明细
  55. <icon :class="mxjtClass"></icon>
  56. </view>
  57. <view>购买即同意虚拟产品不支持退订</view>
  58. </view>
  59. <!-- 微信 -->
  60. <view class="pay-status-box" v-if="showPayWay" @click="switchPayWay">
  61. <icon class="wx-icon"></icon>微信
  62. </view>
  63. <!-- 支付宝 -->
  64. <view class="pay-status-box" v-if="!showPayWay" @click="switchPayWay">
  65. <icon class="zfb-icon"></icon>支付宝
  66. </view>
  67. <!-- 苹果 -->
  68. <view class="pay-status-box apple-status-box" v-if="false">
  69. <icon class="apple-icon"></icon>apple
  70. </view>
  71. <view class="pay-btn">立即支付</view>
  72. </view>
  73. <detail-dialog ref="mallDetailPopup" :selected-list="getSelectedProducts"></detail-dialog>
  74. <!--
  75. <product-dialog ref="mallProductPopup" @payBtn="payBtn"></product-dialog> -->
  76. </view>
  77. </template>
  78. <script setup>
  79. import {
  80. reactive,
  81. computed,
  82. nextTick,
  83. ref
  84. } from "vue";
  85. import {
  86. getMallist
  87. } from "@/api/productMall.js";
  88. import {
  89. onLoad
  90. } from "@dcloudio/uni-app";
  91. import {
  92. toast,
  93. getUserIdentity
  94. } from "@/utils/common";
  95. import cacheManager from '@/utils/cacheManager.js';
  96. import CustomTabBar from '@/components/custom-tabbar/custom-tabbar.vue';
  97. import detailDialog from './detailDialog.vue'
  98. import productDialog from './productDialog.vue'
  99. const showPayWay = ref(true)
  100. const showDetail = ref(false)
  101. const mxjtClass = ref('mxjt-sq-icon')
  102. const mallDetailPopup = ref(null);
  103. const mallProductPopup = ref(null);
  104. let scrollIntoId = ref(null)
  105. const productData = reactive({
  106. items: ['数学', '英语'],
  107. current: 1,
  108. from: '',
  109. cardId: '',
  110. list: [],
  111. selectedIds: [] // 新增选中状态存储
  112. })
  113. const totalPrice = computed(() => {
  114. return productData.list
  115. .filter(item => productData.selectedIds.includes(item.id))
  116. .reduce((sum, item) => sum + parseFloat(item.xianjia || 0), 0)
  117. .toFixed(2)
  118. })
  119. const getSelectedProducts = computed(() => {
  120. return productData.list.filter(item => productData.selectedIds.includes(item.id));
  121. });
  122. function updateSelection(selectedIds) {
  123. productData.selectedIds = selectedIds;
  124. }
  125. function switchPayWay() {
  126. showPayWay.value = !showPayWay.value
  127. }
  128. function productBtn() {
  129. mallProductPopup.value.detailShow();
  130. }
  131. function detailBtn() {
  132. showDetail.value = !showDetail.value;
  133. if (showDetail.value) {
  134. mxjtClass.value = 'mxjt-zk-icon';
  135. mallDetailPopup.value.detailShow();
  136. } else {
  137. mxjtClass.value = 'mxjt-sq-icon';
  138. mallDetailPopup.value.detailCloseBtn();
  139. }
  140. }
  141. function handlePay(item) {
  142. if (productData.selectedIds.length === 0) {
  143. toast("请选择至少一个商品");
  144. return;
  145. }
  146. // uni.redirectTo({
  147. // url: `/pages/pay/svip?cardIds=${productData.selectedIds.join(',')}&formPage=my`
  148. // });
  149. }
  150. function onChangeTab(e) {
  151. console.log('e', e);
  152. productData.current = e.currentIndex
  153. productData.selectedIds = [] // 清空选中
  154. getMore()
  155. }
  156. function getMore() {
  157. const opt = {
  158. subjectId: productData.current + 1
  159. }
  160. getMallist(opt).then(res => {
  161. if (res.code == 0) {
  162. productData.list = res.data
  163. // 初始化选中状态(当有外部cardId时)
  164. if (productData.cardId) {
  165. const exist = res.data.some(item => item.id == productData.cardId)
  166. if (exist) {
  167. productData.selectedIds = [Number(productData.cardId)]
  168. }
  169. }
  170. nextTick(() => {
  171. scrollToIdFun(productData.cardId)
  172. })
  173. }
  174. }).catch(err => {
  175. toast("获取产品数据失败")
  176. return false
  177. })
  178. }
  179. function scrollToIdFun(targetId) {
  180. const index = productData.list.findIndex(item => item.id == targetId)
  181. console.log('index', index);
  182. if (index > -1) {
  183. // 安卓设备需要双保险
  184. scrollIntoId.value = `item-${targetId}`
  185. setTimeout(() => {
  186. scrollIntoId.value = `item-${targetId}`
  187. }, 300)
  188. }
  189. }
  190. function addProduct(item) {
  191. console.log('item', item);
  192. const temp = [...productData.selectedIds]
  193. const index = temp.indexOf(item.id)
  194. index > -1 ? temp.splice(index, 1) : temp.push(item.id)
  195. productData.selectedIds = temp
  196. console.log('productData.selectedIds', productData.selectedIds);
  197. }
  198. function isItemSelected(id) {
  199. return productData.cardId ?
  200. id == productData.cardId // 有外部cardId时严格匹配
  201. :
  202. productData.selectedIds.includes(id) // 无cardId时检查选中列表
  203. }
  204. function goBack() {
  205. if (productData.from == 'daoPage') {
  206. uni.redirectTo({
  207. url: '/pages/study/index'
  208. })
  209. } else {
  210. uni.redirectTo({
  211. url: '/pages/my/index'
  212. })
  213. }
  214. }
  215. onLoad((options) => {
  216. if (options.from == 'daoPage') {
  217. productData.current = Number(options.subjectId) - 1
  218. productData.cardId = options.cardId
  219. productData.from = options.from
  220. } else {
  221. productData.current = Number(cacheManager.get('auth').subjectId) - 1
  222. }
  223. getMore();
  224. })
  225. </script>
  226. <style>
  227. </style>