| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- <script setup lang="ts">
- import CouponItem from '../components/coupon/index.vue'
- import router from '@/router'
- definePage({
- name: 'xsb-confirmOrder',
- islogin: true,
- style: {
- navigationBarTitleText: '提交订单',
- },
- })
- const { selectedAddress, userInfo } = storeToRefs(useUserStore())
- const { SelectShopInfo } = storeToRefs(useSysXsbStore())
- const orderInfo = ref<Api.shoppingCartOrderConfirm>()
- const { totalProduct } = storeToRefs(useSmqjhCartStore())
- const isPay = ref(false)
- const remarks = ref('')
- const initialCouponId = ref<string | undefined>(undefined)
- const confirmedCouponId = ref<string | undefined>(undefined)
- const draftCouponId = ref<string | undefined>(undefined)
- const deliveryType = ref(1)
- // 优惠券选择
- const couponPopup = ref(false)
- const couponList = ref<Api.AppMemberCouponVO[]>([])
- const couponTabActive = ref(0)
- const availableCoupons = computed(() => couponList.value.filter(it => it.isUsed === 2))
- const unavailableCoupons = computed(() => couponList.value.filter(it => it.isUsed !== 2))
- const displayCoupons = computed(() => couponTabActive.value === 0 ? availableCoupons.value : unavailableCoupons.value)
- const confirmedCoupon = computed(() => couponList.value.find(it => it.allowanceId === confirmedCouponId.value))
- const draftCoupon = computed(() => couponList.value.find(it => it.allowanceId === draftCouponId.value))
- const hasManualCouponSelection = computed(() => confirmedCouponId.value !== initialCouponId.value)
- const currentCouponDiscount = computed(() => {
- if (hasManualCouponSelection.value) {
- return Number(confirmedCoupon.value?.discountMoney || 0)
- }
- return Number(orderInfo.value?.coupon || 0)
- })
- const offsetPoints = computed(() => {
- const couponCents = Math.round(currentCouponDiscount.value * 100)
- const money = Math.round(Number(unref(orderInfo)?.transfee) * 100) + Math.round(Number(unref(orderInfo)?.price) * 100) - couponCents
- const cap = Math.max(0, money)
- if (Number(unref(orderInfo)?.offsetPoints) > cap) {
- return cap
- }
- return Number(unref(orderInfo)?.offsetPoints)
- })
- const currentCouponName = computed(() => {
- if (hasManualCouponSelection.value) {
- return getCouponDisplayName(confirmedCoupon.value)
- }
- return getCouponDisplayName(orderInfo.value)
- })
- const displayTotalPrice = computed(() => {
- if (!orderInfo.value) {
- return 0
- }
- if (!hasManualCouponSelection.value) {
- return Number(orderInfo.value.totalPrice || 0)
- }
- const goodsPrice = Number(orderInfo.value.price || 0)
- const freight = Number(orderInfo.value.transfee || 0)
- const pointsDiscount = offsetPoints.value / 100
- return Math.max(0, Number((goodsPrice + freight - currentCouponDiscount.value - pointsDiscount).toFixed(2)))
- })
- const displayDiscountTotal = computed(() => Number((currentCouponDiscount.value + offsetPoints.value / 100).toFixed(2)))
- onLoad((options: any) => {
- orderInfo.value = JSON.parse(options.data)
- couponList.value = orderInfo.value?.orderCouponItemDTOS || []
- initialCouponId.value = orderInfo.value?.allowanceId
- confirmedCouponId.value = initialCouponId.value
- draftCouponId.value = initialCouponId.value
- })
- onShow(() => {
- useUserStore().getuserAddresslist()
- if (selectedAddress.value) {
- getDevryList()
- }
- })
- function getCouponDisplayName(coupon?: Partial<Api.AppMemberCouponVO> & Record<string, any>) {
- return coupon?.activityName || coupon?.couponName || ''
- }
- async function getDevryList() {
- const res = await Apis.xsb.delivery({
- data: {
- memberId: userInfo.value.id,
- shopId: Number(orderInfo.value?.skuList[0].shopId || SelectShopInfo.value?.shopId || 2),
- addressId: selectedAddress.value?.id,
- },
- })
- deliveryType.value = res.data.deliveryType
- console.log(res)
- }
- async function openCouponPopup() {
- draftCouponId.value = confirmedCouponId.value
- couponPopup.value = true
- }
- function handleSelectCoupon(item: Api.AppMemberCouponVO) {
- if (item.isUsed !== 2 || !item.allowanceId) {
- return
- }
- // 再次点击已选中的券则取消选中
- if (draftCouponId.value === item.allowanceId) {
- draftCouponId.value = undefined
- return
- }
- draftCouponId.value = item.allowanceId
- }
- function confirmCoupon() {
- confirmedCouponId.value = draftCouponId.value
- couponPopup.value = false
- }
- async function handlePay() {
- if (!selectedAddress.value) {
- useGlobalToast().show({ msg: '请选择收货地址' })
- return
- }
- if (!orderInfo.value) {
- useGlobalToast().show({ msg: '网络异常!请联系客服' })
- return
- }
- isPay.value = true
- try {
- const orderItemList = orderInfo.value?.skuList.map((it) => {
- return {
- prodCount: it.num,
- skuId: it.skuId,
- }
- })
- const orderNumber = await useUserStore().getOrderPayMent(
- orderInfo.value.transfee,
- 'XSB',
- deliveryType.value,
- Number(orderInfo.value?.skuList[0].shopId || SelectShopInfo.value?.shopId),
- orderItemList,
- unref(remarks),
- confirmedCouponId.value,
- )
- const res = await useUserStore().handleCommonPayMent(orderNumber)
- await useUserStore().clearCart(orderInfo.value.skuList)
- totalProduct.value = null
- if (res.payType !== 1) {
- try {
- await useUserStore().getWxCommonPayment(res)
- await useUserStore().paySuccess('xsb-order', 'subPack-xsb/commonTab/index')
- }
- catch {
- await useUserStore().payError('xsb-order', 'subPack-xsb/commonTab/index')
- }
- }
- else {
- await useUserStore().paySuccess('xsb-order', 'subPack-xsb/commonTab/index')
- }
- }
- catch {
- isPay.value = false
- }
- }
- </script>
- <template>
- <view class="page px20rpx py20rpx">
- <view
- class="mb20rpx rounded-16rpx bg-white p24rpx"
- @click="router.push({ name: 'common-addressList', params: { type: 'select' } })"
- >
- <view class="flex items-center justify-between">
- <view v-if="!selectedAddress" class="flex items-center">
- <wd-icon name="location" size="18px" />
- <view class="ml10rpx text-28rpx">
- 请添加收货地址
- </view>
- </view>
- <view v-else>
- <view class="flex items-center">
- <view v-if="selectedAddress.defaulted" class="mr20rpx">
- <wd-tag type="primary">
- 默认
- </wd-tag>
- </view>
- <view class="flex items-center text-28rpx font-semibold">
- <view>{{ selectedAddress?.consigneeName }} </view>
- <view class="ml20rpx">
- {{ selectedAddress?.consigneeMobile }}
- </view>
- </view>
- </view>
- <view class="mt20rpx flex items-center text-24rpx text-#AAAAAA">
- {{ selectedAddress?.province }} {{ selectedAddress?.city }} {{ selectedAddress?.detailAddress }}
- </view>
- </view>
- <wd-icon name="arrow-right" size="18px" color="#aaa" />
- </view>
- </view>
- <view class="rounded-16rpx bg-white p24rpx">
- <view class="flex items-center text-28rpx font-semibold">
- {{ orderInfo?.shopName }}
- </view>
- <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
- <CollapsePanel :line-height="150">
- <view v-for="item in orderInfo?.skuList" :key="item.id" class="mb20rpx w-full flex items-center">
- <view class="mr20rpx w120rpx flex-shrink-0">
- <image :src="item.pic" class="h120rpx w120rpx" />
- </view>
- <view class="flex-1">
- <view class="w-full flex items-center justify-between font-semibold">
- <view class="text-28rpx">
- {{ item.skuName }}
- </view>
- <view class="text-32rpx text-#FF4D3A">
- ¥{{ item.price }}
- </view>
- </view>
- <view class="text-24rpx text-#AAAAAA">
- 规格:{{ item.spec }}
- </view>
- <view class="text-24rpx text-#AAAAAA">
- ×{{ item.num || 1 }}
- </view>
- </view>
- </view>
- </CollapsePanel>
- </view>
- <view class="mt20rpx rounded-16rpx bg-white p24rpx">
- <view class="mb28rpx flex items-center justify-between text-28rpx">
- <view>商品金额</view>
- <view class="text-#FF4D3A font-semibold">
- ¥{{ orderInfo?.price }}
- </view>
- </view>
- <view class="mb28rpx flex items-center justify-between text-28rpx">
- <view v-if="deliveryType == 3">
- 配送费(即时配送)
- </view>
- <view v-if="deliveryType == 1">
- 快递
- </view>
- <view class="text-#FF4D3A font-semibold">
- ¥{{ orderInfo?.transfee }}
- </view>
- </view>
- <view class="mb28rpx flex items-center justify-between text-28rpx" @click="openCouponPopup">
- <view>优惠券</view>
- <view class="flex items-center">
- <view v-if="currentCouponDiscount > 0" class="text-[#FF4D3A] font-semibold">
- -¥{{ currentCouponDiscount }}
- </view>
- <view v-else class="text-[#AAAAAA]">
- {{ availableCoupons.length > 0 ? `${availableCoupons.length}张可用` : '暂无可用' }}
- </view>
- <wd-icon name="arrow-right" size="18px" color="#aaa" class="ml10rpx" />
- </view>
- </view>
- <view class="flex items-center justify-between text-28rpx">
- <view>积分({{ offsetPoints }})</view>
- <view class="text-#FF4D3A font-semibold">
- - ¥{{ offsetPoints / 100 }}
- </view>
- </view>
- <view class="my24rpx h2rpx w-full bg-#F0F0F0" />
- <view class="flex items-center justify-between text-28rpx">
- <view class="font-semibold">
- 总计:
- </view>
- <view class="text-#FF4D3A font-semibold">
- ¥ {{ displayTotalPrice }}
- </view>
- </view>
- </view>
- <view class="mt20rpx flex items-center rounded-16rpx bg-white p24rpx">
- <view class="w80rpx">
- 备注
- </view>
- <view class="flex-1">
- <wd-input v-model="remarks" placeholder="选填,请先和商家协商一致,付款后商家可见" no-border clearable />
- </view>
- </view>
- <view class="h250rpx" />
- <!-- 优惠券选择弹窗 -->
- <Zpopup v-model="couponPopup" :zindex="100" bg="#fff">
- <view class="ios box-border w-full">
- <view class="px-32rpx pt-32rpx">
- <view class="mb-24rpx text-center text-32rpx font-semibold">
- 优惠券
- </view>
- <view class="mb-24rpx flex items-center">
- <view
- class="mr-16rpx flex-1 rounded-full py-18rpx text-center text-28rpx"
- :class="couponTabActive === 0 ? 'bg-[#9ED605] text-white font-semibold' : 'bg-[#F0F0F0] text-[#666]'"
- @click="couponTabActive = 0"
- >
- 可用券({{ availableCoupons.length }})
- </view>
- <view
- class="flex-1 rounded-full py-18rpx text-center text-28rpx"
- :class="couponTabActive === 1 ? 'bg-[#9ED605] text-white font-semibold' : 'bg-[#F0F0F0] text-[#666]'"
- @click="couponTabActive = 1"
- >
- 不可用券({{ unavailableCoupons.length }})
- </view>
- </view>
- <view class="mb-20rpx flex items-center justify-between text-24rpx">
- <view class="text-[#333]">
- 优惠券共减
- </view>
- <view v-if="draftCoupon" class="text-right text-[#FF4D3A]">
- {{ getCouponDisplayName(draftCoupon) }},可减-¥{{ draftCoupon.discountMoney }}
- </view>
- <view v-else-if="currentCouponDiscount > 0 && currentCouponName" class="text-right text-[#FF4D3A]">
- {{ currentCouponName }},可减¥{{ currentCouponDiscount }}
- </view>
- <view v-else class="text-[#AAAAAA]">
- 暂未选择
- </view>
- </view>
- </view>
- <scroll-view scroll-y class="box-border h-560rpx px-32rpx">
- <view v-for="item in displayCoupons" :key="item.id" class="relative mb-20rpx">
- <view class="relative" @click="handleSelectCoupon(item)">
- <CouponItem :itemcoupon="item" :hide-all-btn="true" />
- <view
- class="absolute right-32rpx top-50% h-44rpx w-44rpx flex items-center justify-center -translate-y-50%"
- >
- <wd-icon v-if="draftCouponId === item.allowanceId" name="check-circle" size="44rpx" color="#FF4D3A" />
- <view v-else class="h-40rpx w-40rpx border-2rpx border-[#ccc] rounded-full border-solid" />
- </view>
- </view>
- <view
- v-if="item.unavailableReason"
- class="relative z-1 w-full rounded-b-16rpx bg-[#FFF4F3] px20rpx py18rpx text-24rpx -mt16rpx"
- >
- <view>
- 不可用原因
- </view>
- <view>
- {{ item.unavailableReason }}
- </view>
- </view>
- </view>
- <view v-if="displayCoupons.length === 0" class="py-80rpx text-center text-28rpx text-[#AAAAAA]">
- 暂无优惠券
- </view>
- </scroll-view>
- </view>
- <template #footer>
- <view class="box-border w-full px24rpx">
- <wd-button size="large" block type="primary" @click="confirmCoupon">
- 确定
- </wd-button>
- </view>
- </template>
- </Zpopup>
- <view class="ios footer fixed bottom-0 left-0 box-border w-full rounded-t-16rpx bg-white px24rpx">
- <view class="box-border w-full flex items-center justify-between py20rpx">
- <view class="flex items-center text-#FF4D3A">
- <view class="font-semibold10 flex items-baseline text-36rpx">
- <text class="text-24rpx">
- ¥
- </text> {{ displayTotalPrice }}
- </view>
- <view class="ml20rpx text-22rpx">
- 共减¥{{ displayDiscountTotal }}
- </view>
- </view>
- <view class="w180-btn w180rpx">
- <wd-button size="large" :loading="isPay" loading-color="#9ED605" @click="handlePay">
- 立即支付
- </wd-button>
- </view>
- </view>
- </view>
- </view>
- </template>
- <style scoped lang="scss">
- .footer {
- box-shadow: 0rpx -6rpx 12rpx 2rpx rgba(0, 0, 0, 0.05);
- }
- .page {
- .w180-btn {
- :deep() {
- .wd-button {
- width: 180rpx !important;
- }
- }
- }
- }
- </style>
|