index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. <script setup lang="ts">
  2. import CouponItem from '../components/coupon/index.vue'
  3. import router from '@/router'
  4. const { userMemberInfo } = storeToRefs(useUserStore())
  5. definePage({
  6. name: 'xsb-confirmOrder',
  7. islogin: true,
  8. style: {
  9. navigationBarTitleText: '提交订单',
  10. },
  11. })
  12. const { selectedAddress, userInfo } = storeToRefs(useUserStore())
  13. const { SelectShopInfo } = storeToRefs(useSysXsbStore())
  14. const { Location } = storeToRefs(useAddressStore())
  15. type ConfirmOrderInfo = Api.shoppingCartOrderConfirm & Partial<Api.AppletOrderSkuVo>
  16. const orderInfo = ref<ConfirmOrderInfo>()
  17. const { totalProduct } = storeToRefs(useSmqjhCartStore())
  18. const isPay = ref(false)
  19. const remarks = ref('')
  20. const initialCouponId = ref<string | undefined>(undefined)
  21. const confirmedCouponId = ref<string | undefined>(undefined)
  22. const draftCouponId = ref<string | undefined>(undefined)
  23. const list = ref<string[]>(['即时配送', '自提'])
  24. const current = ref('即时配送')
  25. const model = reactive<{
  26. value1: string
  27. value2: string
  28. }>({
  29. value1: '',
  30. value2: '',
  31. })
  32. const mobilePattern = /^1[3-9]\d{9}$/
  33. const mobileRules = [{ required: true, pattern: mobilePattern, message: '请输入正确的手机号' }]
  34. const deliveryType = ref(1)
  35. const isMemberGiftOrder = computed(() => !!orderInfo.value?.memberGiftItems?.length)
  36. const isSingleSkuOrder = computed(() => (orderInfo.value?.skuList?.length || 0) <= 1)
  37. const isSelfPickup = computed(() => current.value === '自提')
  38. const shopAddressInfo = computed(() => orderInfo.value?.shopAddressDTO)
  39. const shopDistanceText = computed(() => {
  40. const distance = shopAddressInfo.value?.distance
  41. if (distance === undefined || distance === null) {
  42. return ''
  43. }
  44. return `距你${Number(distance).toFixed(2)}km`
  45. })
  46. // 优惠券选择
  47. const couponPopup = ref(false)
  48. const couponList = ref<Api.AppMemberCouponVO[]>([])
  49. const couponTabActive = ref(0)
  50. const availableCoupons = computed(() => couponList.value.filter(it => it.isUsed === 2))
  51. const unavailableCoupons = computed(() => couponList.value.filter(it => it.isUsed !== 2))
  52. const displayCoupons = computed(() => couponTabActive.value === 0 ? availableCoupons.value : unavailableCoupons.value)
  53. const confirmedCoupon = computed(() => couponList.value.find(it => it.allowanceId === confirmedCouponId.value))
  54. const draftCoupon = computed(() => couponList.value.find(it => it.allowanceId === draftCouponId.value))
  55. const hasManualCouponSelection = computed(() => confirmedCouponId.value !== initialCouponId.value)
  56. const currentCouponDiscount = computed(() => {
  57. if (hasManualCouponSelection.value) {
  58. return Number(confirmedCoupon.value?.discountMoney || 0)
  59. }
  60. return Number(orderInfo.value?.coupon || 0)
  61. })
  62. const memberDiscountCents = computed(() => {
  63. if (!isMemberGiftOrder.value && userMemberInfo.value?.active) {
  64. return Math.round(Number(unref(orderInfo)?.memberDiscountAmount || 0) * 100)
  65. }
  66. return 0
  67. })
  68. const offsetPoints = computed(() => {
  69. const couponCents = Math.round(currentCouponDiscount.value * 100)
  70. const freightCents = isSelfPickup.value ? 0 : Math.round(Number(unref(orderInfo)?.transfee) * 100)
  71. const money = freightCents + Math.round(Number(unref(orderInfo)?.price) * 100) - couponCents - memberDiscountCents.value
  72. const cap = Math.max(0, money)
  73. if (Number(unref(orderInfo)?.offsetPoints) > cap) {
  74. return cap
  75. }
  76. return Number(unref(orderInfo)?.offsetPoints)
  77. })
  78. const currentCouponName = computed(() => {
  79. if (hasManualCouponSelection.value) {
  80. return getCouponDisplayName(confirmedCoupon.value)
  81. }
  82. return getCouponDisplayName(orderInfo.value)
  83. })
  84. const displayTotalPrice = computed(() => {
  85. if (!orderInfo.value) {
  86. return 0
  87. }
  88. const goodsPrice = Number(orderInfo.value.price || 0)
  89. const freight = Number(deliveryType.value !== 2 ? orderInfo.value.transfee : 0)
  90. const couponDiscount = hasManualCouponSelection.value
  91. ? Number(confirmedCoupon.value?.discountMoney || 0)
  92. : Number(orderInfo.value?.coupon || 0)
  93. const pointsDiscount = offsetPoints.value / 100
  94. const memberDiscount = memberDiscountCents.value / 100
  95. return Math.max(0, Number((goodsPrice + freight - couponDiscount - pointsDiscount - memberDiscount).toFixed(2)))
  96. })
  97. const displayDiscountTotal = computed(() => Number((currentCouponDiscount.value + offsetPoints.value / 100 + memberDiscountCents.value / 100).toFixed(2)))
  98. const giftOriginalTotal = computed(() => {
  99. if (!isMemberGiftOrder.value)
  100. return 0
  101. return Number((Number(orderInfo.value?.price || 0) + Number(orderInfo.value?.transfee || 0)).toFixed(2))
  102. })
  103. onLoad((options: any) => {
  104. orderInfo.value = JSON.parse(options.data)
  105. console.log(orderInfo.value, '===商品数据===')
  106. syncCouponState()
  107. deliveryType.value = current.value === '自提' ? 2 : 3
  108. // model.value1 = userInfo.value?.nickName || ''
  109. model.value2 = userInfo.value?.mobile || ''
  110. })
  111. onShow(() => {
  112. useUserStore().getuserAddresslist()
  113. if (orderInfo.value && current.value === '即时配送' && (isSingleSkuOrder.value || isMemberGiftOrder.value)) {
  114. getConfirmOrder()
  115. }
  116. })
  117. watch(current, async (value) => {
  118. deliveryType.value = value === '自提' ? 2 : 3
  119. if (orderInfo.value && (isSingleSkuOrder.value || isMemberGiftOrder.value)) {
  120. await getConfirmOrder()
  121. }
  122. })
  123. function getCouponDisplayName(coupon?: Partial<Api.AppMemberCouponVO> & Record<string, any>) {
  124. return coupon?.activityName || coupon?.couponName || ''
  125. }
  126. function syncCouponState() {
  127. couponList.value = orderInfo.value?.orderCouponItemDTOS || []
  128. initialCouponId.value = orderInfo.value?.allowanceId
  129. confirmedCouponId.value = initialCouponId.value
  130. draftCouponId.value = initialCouponId.value
  131. }
  132. function getOrderConfirmParams() {
  133. const firstSku = orderInfo.value?.skuList?.[0]
  134. return {
  135. skuId: firstSku?.skuId,
  136. num: Number(firstSku?.num || 1),
  137. channelId: userInfo.value?.channelId,
  138. shopId: Number(firstSku?.shopId || SelectShopInfo.value?.shopId || 2),
  139. dvyType: deliveryType.value,
  140. }
  141. }
  142. async function getConfirmOrder() {
  143. const params: Record<string, any> = getOrderConfirmParams()
  144. if (!params.skuId) {
  145. return
  146. }
  147. if (isSelfPickup.value) {
  148. if (!Location.value.latitude || !Location.value.longitude) {
  149. useGlobalToast().show('暂无定位缓存,无法计算自提点距离')
  150. }
  151. else {
  152. params.latitude = Location.value.latitude
  153. params.longitude = Location.value.longitude
  154. }
  155. }
  156. const res = await Apis.xsb.skuOrderConfirm({
  157. data: params,
  158. })
  159. if (isMemberGiftOrder.value) {
  160. // 赠品订单仅更新配送费和店铺地址信息,保留原始商品数据
  161. orderInfo.value = {
  162. ...orderInfo.value,
  163. transfee: res.data.transfee ?? orderInfo.value?.transfee ?? 0,
  164. shopAddressDTO: res.data.shopAddressDTO ?? orderInfo.value?.shopAddressDTO,
  165. } as ConfirmOrderInfo
  166. }
  167. else {
  168. const originalSku = orderInfo.value?.skuList?.[0]
  169. const skuList = res.data.sku
  170. ? [{ ...res.data.sku, id: originalSku?.id, num: params.num, shopId: params.shopId }]
  171. : (orderInfo.value?.skuList || [])
  172. orderInfo.value = {
  173. ...orderInfo.value,
  174. ...res.data,
  175. skuList,
  176. } as ConfirmOrderInfo
  177. syncCouponState()
  178. }
  179. }
  180. function openShopLocation() {
  181. uni.openLocation({
  182. latitude: Number(shopAddressInfo.value?.shopLat) || 0,
  183. longitude: Number(shopAddressInfo.value?.shopLng) || 0,
  184. name: shopAddressInfo.value?.shopName,
  185. address: shopAddressInfo.value?.shopAddress,
  186. })
  187. }
  188. async function openCouponPopup() {
  189. draftCouponId.value = confirmedCouponId.value
  190. couponPopup.value = true
  191. }
  192. function handleSelectCoupon(item: Api.AppMemberCouponVO) {
  193. if (item.isUsed !== 2 || !item.allowanceId) {
  194. return
  195. }
  196. // 再次点击已选中的券则取消选中
  197. if (draftCouponId.value === item.allowanceId) {
  198. draftCouponId.value = undefined
  199. return
  200. }
  201. draftCouponId.value = item.allowanceId
  202. }
  203. function confirmCoupon() {
  204. confirmedCouponId.value = draftCouponId.value
  205. couponPopup.value = false
  206. }
  207. async function handleH5PayResult(orderNumber: string): Promise<boolean> {
  208. const isPaySuccess = await useUserStore().pollOrderPaySuccess(orderNumber)
  209. if (isPaySuccess) {
  210. router.replace({ name: 'xsb-order' })
  211. return true
  212. }
  213. useGlobalToast().show({ msg: '暂未查询到支付成功,请稍后在订单列表查看' })
  214. isPay.value = false
  215. return false
  216. }
  217. async function handlePay() {
  218. if (!isSelfPickup.value && !selectedAddress.value) {
  219. useGlobalToast().show({ msg: '请选择收货地址' })
  220. return
  221. }
  222. if (!orderInfo.value) {
  223. useGlobalToast().show({ msg: '网络异常!请联系客服' })
  224. return
  225. }
  226. if (isSelfPickup.value) {
  227. if (!model.value1) {
  228. useGlobalToast().show({ msg: '请填写联系人' })
  229. return
  230. }
  231. if (!mobilePattern.test(model.value2)) {
  232. useGlobalToast().show({ msg: '请输入正确的手机号' })
  233. return
  234. }
  235. }
  236. isPay.value = true
  237. try {
  238. if (isMemberGiftOrder.value) {
  239. console.log('=====赠品订单')
  240. if (!selectedAddress.value) {
  241. useGlobalToast().show({ msg: '请选择收货地址' })
  242. return
  243. }
  244. await Apis.sys.giftsReceive({
  245. data: {
  246. addressId: selectedAddress.value.id,
  247. items: orderInfo.value.memberGiftItems,
  248. },
  249. })
  250. await useUserStore().paySuccess('xsb-order', 'subPack-xsb/commonTab/index')
  251. return
  252. }
  253. const orderItemList = orderInfo.value?.skuList.map((it) => {
  254. return {
  255. prodCount: it.num,
  256. skuId: it.skuId,
  257. }
  258. })
  259. const orderNumber = await useUserStore().getOrderPayMent(
  260. deliveryType.value !== 2 ? orderInfo.value.transfee : 0,
  261. 'XSB',
  262. deliveryType.value,
  263. Number(orderInfo.value?.skuList[0].shopId || SelectShopInfo.value?.shopId),
  264. orderItemList,
  265. unref(remarks),
  266. confirmedCouponId.value,
  267. isSelfPickup.value
  268. ? {
  269. consigneeName: model.value1,
  270. consigneeMobile: model.value2,
  271. }
  272. : undefined,
  273. )
  274. const payMent = await useUserStore().getPayMent(orderNumber)
  275. const skuList = orderInfo.value?.skuList || []
  276. await useUserStore().clearCart(skuList)
  277. totalProduct.value = null
  278. isPay.value = false
  279. if (payMent.payType !== 'point') {
  280. try {
  281. // #ifdef H5
  282. useUserStore().handleCommonWechatPay(orderNumber)
  283. await handleH5PayResult(orderNumber)
  284. // #endif
  285. // #ifdef MP-WEIXIN
  286. const res = await useUserStore().handleCommonPayMent(orderNumber)
  287. await useUserStore().getWxCommonPayment(res)
  288. await useUserStore().paySuccess('xsb-order', 'subPack-xsb/commonTab/index')
  289. // #endif
  290. }
  291. catch {
  292. await useUserStore().payError('xsb-order', 'subPack-xsb/commonTab/index')
  293. }
  294. }
  295. else {
  296. await useUserStore().handleCommonPayMent(orderNumber)
  297. await useUserStore().paySuccess('xsb-order', 'subPack-xsb/commonTab/index')
  298. }
  299. }
  300. catch {
  301. isPay.value = false
  302. }
  303. }
  304. </script>
  305. <template>
  306. <view class="page px20rpx py20rpx">
  307. <wd-segmented v-model:value="current" :options="list" />
  308. <view
  309. v-if="current === '即时配送'"
  310. class="my20rpx rounded-16rpx bg-white p24rpx"
  311. @click="router.push({ name: 'common-addressList', params: { type: 'select' } })"
  312. >
  313. <view class="flex items-center justify-between">
  314. <view v-if="!selectedAddress" class="flex items-center">
  315. <wd-icon name="location" size="18px" />
  316. <view class="ml10rpx text-28rpx">
  317. 请添加收货地址
  318. </view>
  319. </view>
  320. <view v-else>
  321. <view class="flex items-center">
  322. <view v-if="selectedAddress.defaulted" class="mr20rpx">
  323. <wd-tag type="primary">
  324. 默认
  325. </wd-tag>
  326. </view>
  327. <view class="flex items-center text-28rpx font-semibold">
  328. <view>{{ selectedAddress?.consigneeName }} </view>
  329. <view class="ml20rpx">
  330. {{ selectedAddress?.consigneeMobile }}
  331. </view>
  332. </view>
  333. </view>
  334. <view class="mt20rpx flex items-center text-24rpx text-#AAAAAA">
  335. {{ selectedAddress?.province }} {{ selectedAddress?.city }} {{ selectedAddress?.detailAddress }}
  336. </view>
  337. </view>
  338. <wd-icon name="arrow-right" size="18px" color="#aaa" />
  339. </view>
  340. </view>
  341. <view v-else class="my20rpx rounded-16rpx bg-white p24rpx">
  342. <view class="flex items-center gap-50rpx">
  343. <view class="flex-1">
  344. <view class="text-28rpx font-semibold">
  345. 自提点:{{ shopAddressInfo?.shopName || orderInfo?.shopName || '暂无门店信息' }}
  346. </view>
  347. <view class="mt-20rpx text-24rpx text-#AAAAAA">
  348. {{ shopAddressInfo?.shopAddress || '暂无门店地址' }}
  349. </view>
  350. </view>
  351. <view class="flex-shrink-0" @click="openShopLocation">
  352. <view v-if="shopDistanceText" class="mb-20rpx text-24rpx text-#AAAAAA">
  353. {{ shopDistanceText }}
  354. </view>
  355. <wd-icon name="location" size="22px" color="var(--them-color)" />
  356. </view>
  357. </view>
  358. <view>
  359. <view class="mt-20rpx flex items-center">
  360. <view class="w100rpx text-28rpx">
  361. 联系人:
  362. </view>
  363. <wd-input
  364. v-model="model.value1"
  365. prop="value1"
  366. clearable
  367. placeholder="请输入联系人"
  368. :rules="[{ required: true, message: '请填写联系人' }]"
  369. />
  370. </view>
  371. <view class="mt-20rpx flex items-center">
  372. <view class="w140rpx text-28rpx">
  373. 预留电话:
  374. </view>
  375. <wd-input
  376. v-model="model.value2"
  377. prop="value2"
  378. clearable
  379. placeholder="请输入预留电话"
  380. :rules="mobileRules"
  381. />
  382. </view>
  383. </view>
  384. </view>
  385. <view class="rounded-16rpx bg-white p24rpx">
  386. <view class="flex items-center text-28rpx font-semibold">
  387. {{ orderInfo?.shopName }}
  388. </view>
  389. <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
  390. <CollapsePanel :line-height="150">
  391. <view v-for="item in orderInfo?.skuList" :key="item.id" class="mb20rpx w-full flex items-center">
  392. <view class="mr20rpx w120rpx flex-shrink-0">
  393. <image :src="item.pic" class="h120rpx w120rpx" />
  394. </view>
  395. <view class="flex-1">
  396. <view class="w-full flex items-center justify-between font-semibold">
  397. <view class="text-28rpx">
  398. <text v-if="isMemberGiftOrder" class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
  399. 赠品
  400. </text>
  401. {{ item.skuName }}
  402. </view>
  403. <view class="text-32rpx text-#FF4D3A">
  404. ¥{{ item.price }}
  405. </view>
  406. </view>
  407. <view class="text-24rpx text-#AAAAAA">
  408. 规格:{{ item.spec }}
  409. </view>
  410. <view class="text-24rpx text-#AAAAAA">
  411. ×{{ item.num || 1 }}
  412. </view>
  413. </view>
  414. </view>
  415. </CollapsePanel>
  416. </view>
  417. <view class="mt20rpx rounded-16rpx bg-white p24rpx">
  418. <view class="mb28rpx flex items-center justify-between text-28rpx">
  419. <view>商品金额</view>
  420. <view class="text-#FF4D3A font-semibold">
  421. ¥{{ orderInfo?.price }}
  422. </view>
  423. </view>
  424. <view class="mb28rpx flex items-center justify-between text-28rpx">
  425. <view v-if="deliveryType == 3">
  426. 配送费(即时配送)
  427. </view>
  428. <view v-if="deliveryType == 1">
  429. 快递
  430. </view>
  431. <view v-if="deliveryType == 2">
  432. 自提
  433. </view>
  434. <view class="text-#FF4D3A font-semibold">
  435. ¥{{ deliveryType == 2 ? '0.00' : orderInfo?.transfee }}
  436. </view>
  437. </view>
  438. <view v-if="!isMemberGiftOrder && userMemberInfo.active && orderInfo?.memberBenefitDesc && orderInfo?.memberDiscountAmount" class="mb28rpx flex items-center justify-between text-28rpx">
  439. <view>{{ orderInfo?.memberBenefitDesc }}</view>
  440. <view class="text-#FF4D3A font-semibold">
  441. -¥{{ orderInfo?.memberDiscountAmount }}
  442. </view>
  443. </view>
  444. <view v-if="!isMemberGiftOrder" class="mb28rpx flex items-center justify-between text-28rpx" @click="openCouponPopup">
  445. <view>优惠券</view>
  446. <view class="flex items-center">
  447. <view v-if="currentCouponDiscount > 0" class="text-[#FF4D3A] font-semibold">
  448. -¥{{ currentCouponDiscount }}
  449. </view>
  450. <view v-else class="text-[#AAAAAA]">
  451. {{ availableCoupons.length > 0 ? `${availableCoupons.length}张可用` : '暂无可用' }}
  452. </view>
  453. <wd-icon name="arrow-right" size="18px" color="#aaa" class="ml10rpx" />
  454. </view>
  455. </view>
  456. <view v-if="!isMemberGiftOrder" class="flex items-center justify-between text-28rpx">
  457. <view>积分({{ offsetPoints }})</view>
  458. <view class="text-#FF4D3A font-semibold">
  459. - ¥{{ offsetPoints / 100 }}
  460. </view>
  461. </view>
  462. <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
  463. <view class="flex items-center justify-between text-28rpx">
  464. <view class="font-semibold">
  465. 总计:
  466. </view>
  467. <view v-if="isMemberGiftOrder" class="flex items-center">
  468. <text class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
  469. 赠品
  470. </text>
  471. <text class="text-#AAAAAA line-through">
  472. ¥{{ giftOriginalTotal }}
  473. </text>
  474. </view>
  475. <view v-else class="text-#FF4D3A font-semibold">
  476. ¥ {{ displayTotalPrice }}
  477. </view>
  478. </view>
  479. </view>
  480. <view v-if="isMemberGiftOrder" class="mt20rpx flex items-center gap-20rpx rounded-16rpx bg-white p24rpx">
  481. <wd-icon name="warning" size="16px" color="#FF4D3A" />
  482. <text class="text-24rpx">
  483. 本商品为会员权益赠品,购买后不支持售后
  484. </text>
  485. </view>
  486. <view class="mt20rpx flex items-center rounded-16rpx bg-white p24rpx">
  487. <view class="w80rpx">
  488. 备注
  489. </view>
  490. <view class="flex-1">
  491. <wd-input v-model="remarks" placeholder="选填,请先和商家协商一致,付款后商家可见" clearable no-border />
  492. </view>
  493. </view>
  494. <view class="h250rpx" />
  495. <!-- 优惠券选择弹窗 -->
  496. <Zpopup v-model="couponPopup" :zindex="100" bg="#fff">
  497. <view class="ios box-border w-full">
  498. <view class="px-32rpx pt-32rpx">
  499. <view class="mb-24rpx text-center text-32rpx font-semibold">
  500. 优惠券
  501. </view>
  502. <view class="mb-24rpx flex items-center">
  503. <view
  504. class="mr-16rpx flex-1 rounded-full py-18rpx text-center text-28rpx"
  505. :class="couponTabActive === 0 ? 'bg-[var(--them-color)] text-white font-semibold' : 'bg-[#F0F0F0] text-[#666]'"
  506. @click="couponTabActive = 0"
  507. >
  508. 可用券({{ availableCoupons.length }})
  509. </view>
  510. <view
  511. class="flex-1 rounded-full py-18rpx text-center text-28rpx"
  512. :class="couponTabActive === 1 ? 'bg-[var(--them-color)] text-white font-semibold' : 'bg-[#F0F0F0] text-[#666]'"
  513. @click="couponTabActive = 1"
  514. >
  515. 不可用券({{ unavailableCoupons.length }})
  516. </view>
  517. </view>
  518. <view class="mb-20rpx flex items-center justify-between text-24rpx">
  519. <view class="text-[#333]">
  520. 优惠券共减
  521. </view>
  522. <view v-if="draftCoupon" class="text-right text-[#FF4D3A]">
  523. {{ getCouponDisplayName(draftCoupon) }},可减-¥{{ draftCoupon.discountMoney }}
  524. </view>
  525. <view v-else-if="currentCouponDiscount > 0 && currentCouponName" class="text-right text-[#FF4D3A]">
  526. {{ currentCouponName }},可减¥{{ currentCouponDiscount }}
  527. </view>
  528. <view v-else class="text-[#AAAAAA]">
  529. 暂未选择
  530. </view>
  531. </view>
  532. </view>
  533. <scroll-view scroll-y class="box-border h-560rpx px-32rpx">
  534. <view v-for="item in displayCoupons" :key="item.id" class="relative mb-20rpx">
  535. <view class="relative" @click="handleSelectCoupon(item)">
  536. <CouponItem :itemcoupon="item" :hide-all-btn="true" />
  537. <view
  538. class="absolute right-32rpx top-50% h-44rpx w-44rpx flex items-center justify-center -translate-y-50%"
  539. >
  540. <wd-icon v-if="draftCouponId === item.allowanceId" name="check-circle" size="44rpx" color="#FF4D3A" />
  541. <view v-else class="h-40rpx w-40rpx border-2rpx border-[#ccc] rounded-full border-solid" />
  542. </view>
  543. </view>
  544. <view
  545. v-if="item.unavailableReason"
  546. class="relative z-1 w-full rounded-b-16rpx bg-[#FFF4F3] px20rpx py18rpx text-24rpx -mt16rpx"
  547. >
  548. <view>
  549. 不可用原因
  550. </view>
  551. <view>
  552. {{ item.unavailableReason }}
  553. </view>
  554. </view>
  555. </view>
  556. <view v-if="displayCoupons.length === 0" class="py-80rpx text-center text-28rpx text-[#AAAAAA]">
  557. 暂无优惠券
  558. </view>
  559. </scroll-view>
  560. </view>
  561. <template #footer>
  562. <view class="box-border w-full px24rpx">
  563. <wd-button size="large" block type="primary" @click="confirmCoupon">
  564. 确定
  565. </wd-button>
  566. </view>
  567. </template>
  568. </Zpopup>
  569. <view class="ios footer fixed bottom-0 left-0 z-10 box-border w-full rounded-t-16rpx bg-white px24rpx">
  570. <view class="box-border w-full flex items-center justify-between py20rpx">
  571. <view v-if="isMemberGiftOrder" class="flex items-center">
  572. <text class="mr-8rpx rounded-8rpx bg-#FF4D3A px-12rpx py-4rpx text-22rpx text-#FFF">
  573. 赠品
  574. </text>
  575. <text class="text-32rpx text-#AAAAAA line-through">
  576. ¥{{ giftOriginalTotal }}
  577. </text>
  578. </view>
  579. <view v-else class="flex items-center text-#FF4D3A">
  580. <view class="font-semibold10 flex items-baseline text-36rpx">
  581. <text class="text-24rpx">
  582. </text> {{ displayTotalPrice }}
  583. </view>
  584. <view class="ml20rpx text-22rpx">
  585. 共减¥{{ displayDiscountTotal }}
  586. </view>
  587. </view>
  588. <view class="w180-btn w180rpx">
  589. <wd-button size="large" :loading="isPay" loading-color="#9ED605" @click="handlePay">
  590. 立即支付
  591. </wd-button>
  592. </view>
  593. </view>
  594. </view>
  595. </view>
  596. </template>
  597. <style scoped lang="scss">
  598. .footer {
  599. box-shadow: 0rpx -6rpx 12rpx 2rpx rgba(0, 0, 0, 0.05);
  600. }
  601. .page {
  602. .w180-btn {
  603. :deep() {
  604. .wd-button {
  605. width: 180rpx !important;
  606. }
  607. }
  608. }
  609. }
  610. </style>