mallPage.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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" @payBtn="payBtn"></detail-dialog>
  74. <product-dialog ref="mallProductPopup" @payBtn="payBtn"></product-dialog>
  75. </view>
  76. </template>
  77. <script setup>
  78. import {
  79. reactive,
  80. computed,
  81. nextTick,
  82. ref
  83. } from "vue";
  84. import {
  85. getMallist
  86. } from "@/api/productMall.js";
  87. import {
  88. onLoad
  89. } from "@dcloudio/uni-app";
  90. import {
  91. toast,
  92. getUserIdentity
  93. } from "@/utils/common";
  94. import cacheManager from '@/utils/cacheManager.js';
  95. import CustomTabBar from '@/components/custom-tabbar/custom-tabbar.vue';
  96. import detailDialog from './detailDialog.vue'
  97. import productDialog from './productDialog.vue'
  98. const showPayWay = ref(true)
  99. const showDetail = ref(false)
  100. const mxjtClass = ref('mxjt-sq-icon')
  101. const mallDetailPopup = ref(null);
  102. const mallProductPopup = ref(null);
  103. let scrollIntoId = ref(null)
  104. const productData = reactive({
  105. items: ['数学', '英语'],
  106. current: 1,
  107. from: '',
  108. cardId: '',
  109. list: [],
  110. selectedIds: [] // 新增选中状态存储
  111. })
  112. const totalPrice = computed(() => {
  113. return productData.list
  114. .filter(item => productData.selectedIds.includes(item.id))
  115. .reduce((sum, item) => sum + parseFloat(item.xianjia || 0), 0)
  116. .toFixed(2)
  117. })
  118. function switchPayWay() {
  119. showPayWay.value = !showPayWay.value
  120. }
  121. function productBtn() {
  122. mallProductPopup.value.detailShow();
  123. }
  124. function detailBtn() {
  125. showDetail.value = !showDetail.value;
  126. if (showDetail.value) {
  127. mxjtClass.value = 'mxjt-zk-icon';
  128. mallDetailPopup.value.detailShow();
  129. } else {
  130. mxjtClass.value = 'mxjt-sq-icon';
  131. mallDetailPopup.value.detailCloseBtn();
  132. }
  133. }
  134. function handlePay(item) {
  135. uni.redirectTo({
  136. url: `/pages/pay/svip?cardId=${item.cardId}&formPage=my&orderId=${item.id}`
  137. })
  138. }
  139. function onChangeTab(e) {
  140. console.log('e', e);
  141. productData.current = e.currentIndex
  142. productData.selectedIds = [] // 清空选中
  143. getMore()
  144. }
  145. function getMore() {
  146. const opt = {
  147. subjectId: productData.current + 1
  148. }
  149. getMallist(opt).then(res => {
  150. if (res.code == 0) {
  151. productData.list = res.data
  152. // 初始化选中状态(当有外部cardId时)
  153. if (productData.cardId) {
  154. const exist = res.data.some(item => item.id == productData.cardId)
  155. if (exist) {
  156. productData.selectedIds = [Number(productData.cardId)]
  157. }
  158. }
  159. nextTick(() => {
  160. scrollToIdFun(productData.cardId)
  161. })
  162. }
  163. }).catch(err => {
  164. toast("获取产品数据失败")
  165. return false
  166. })
  167. }
  168. function scrollToIdFun(targetId) {
  169. const index = productData.list.findIndex(item => item.id == targetId)
  170. console.log('index', index);
  171. if (index > -1) {
  172. // 安卓设备需要双保险
  173. scrollIntoId.value = `item-${targetId}`
  174. setTimeout(() => {
  175. scrollIntoId.value = `item-${targetId}`
  176. }, 300)
  177. }
  178. }
  179. function addProduct(item) {
  180. console.log('item', item);
  181. const temp = [...productData.selectedIds]
  182. const index = temp.indexOf(item.id)
  183. index > -1 ? temp.splice(index, 1) : temp.push(item.id)
  184. productData.selectedIds = temp
  185. console.log('productData.selectedIds', productData.selectedIds);
  186. }
  187. function isItemSelected(id) {
  188. return productData.cardId ?
  189. id == productData.cardId // 有外部cardId时严格匹配
  190. :
  191. productData.selectedIds.includes(id) // 无cardId时检查选中列表
  192. }
  193. function goBack() {
  194. if (productData.from == 'daoPage') {
  195. uni.redirectTo({
  196. url: '/pages/study/index'
  197. })
  198. } else {
  199. uni.redirectTo({
  200. url: '/pages/my/index'
  201. })
  202. }
  203. }
  204. onLoad((options) => {
  205. if(options.from =='daoPage'){
  206. productData.current = Number(options.subjectId) - 1
  207. productData.cardId = options.cardId
  208. productData.from = options.from
  209. }else{
  210. productData.current = Number(cacheManager.get('auth').subjectId)-1
  211. }
  212. getMore();
  213. })
  214. </script>
  215. <style>
  216. </style>