|
@@ -0,0 +1,188 @@
|
|
|
|
+<template>
|
|
|
|
+ <v-card class="default-width pa-5 mb-5" style="min-height: 75vh; margin-top: 70px;">
|
|
|
|
+ <div>
|
|
|
|
+ <!-- 头部地址选择【配送地址】【自提地址】 -->
|
|
|
|
+ <AddressSelection v-model="addressState" class="addressBox elevation-3" />
|
|
|
|
+
|
|
|
|
+ <!-- 购买的商品信息 -->
|
|
|
|
+ <v-card class="goodsListBox my-3 pa-3 elevation-5">
|
|
|
|
+ <s-goods-item
|
|
|
|
+ v-for="(item, index) in state.orderInfo.items"
|
|
|
|
+ :key="item.skuId"
|
|
|
|
+ :img="item.picUrl"
|
|
|
|
+ :title="item.spuName"
|
|
|
|
+ :skuText="item.properties.map((property) => property.valueName).join(' ')"
|
|
|
|
+ :price="item.price"
|
|
|
|
+ :num="item.count"
|
|
|
|
+ :style="{'marginTop': index ? '8px' : '0px'}"
|
|
|
|
+ />
|
|
|
|
+ </v-card>
|
|
|
|
+
|
|
|
|
+ <!-- 价格信息 -->
|
|
|
|
+ <div>
|
|
|
|
+ <div>
|
|
|
|
+ <!-- <div class="order-item d-flex color-666">
|
|
|
|
+ <div class="item-title mr-3 ">商品金额:</div>
|
|
|
|
+ <div>¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}</div>
|
|
|
|
+ </div> -->
|
|
|
|
+ <!-- 快递配置时,信息的展示 -->
|
|
|
|
+ <!-- <div
|
|
|
|
+ class="order-item d-flex"
|
|
|
|
+ v-if="addressState.deliveryType === 1"
|
|
|
|
+ >
|
|
|
|
+ <div class="item-title mr-3">运{{ spaces() }}费:</div>
|
|
|
|
+ <div>
|
|
|
|
+ <span class="text-red" v-if="state.orderInfo.price.deliveryPrice > 0">
|
|
|
|
+ +¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
|
|
|
|
+ </span>
|
|
|
|
+ <div class="item-value" v-else>免运费</div>
|
|
|
|
+ </div>
|
|
|
|
+ </div> -->
|
|
|
|
+ <!-- 门店自提时,需要填写姓名和手机号 -->
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="mt-5">
|
|
|
|
+ <v-text-field
|
|
|
|
+ v-model="state.orderPayload.remark"
|
|
|
|
+ label="订单备注"
|
|
|
|
+ placeholder="建议留言前先与商家沟通"
|
|
|
|
+ variant="outlined"
|
|
|
|
+ density="compact"
|
|
|
|
+ color="primary"
|
|
|
|
+ ></v-text-field>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="total-box-footer d-flex flex-column align-end">
|
|
|
|
+ <div class="d-flex">
|
|
|
|
+ <div class="mr-3">
|
|
|
|
+ <span class="total-num">共</span>
|
|
|
|
+ <span class="mx-1" style="color: var(--v-primary-base);">{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}</span>
|
|
|
|
+ <span class="total-num">件</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div>合计支付:</div>
|
|
|
|
+ <div class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}元</div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="text-center">
|
|
|
|
+ <div>请在30分钟内完成支付,支付成功后可以随机抽取赠送的房券。</div>
|
|
|
|
+ <v-btn class="elevation-5" color="primary" width="250">立即支付</v-btn>
|
|
|
|
+ <div>支付时间还剩余30分27秒</div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </v-card>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup>
|
|
|
|
+defineOptions({ name: 'mall-order-settlement' })
|
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
|
+import { reactive, ref, onMounted, watch } from 'vue'
|
|
|
|
+import AddressSelection from '@/views/mall/components/details/order/addressSelection.vue'
|
|
|
|
+import sGoodsItem from '@/views/mall/components/s-goods-item'
|
|
|
|
+import { fen2yuan } from '@/hooks/web/useGoods'
|
|
|
|
+import { spaces } from '@/utils/index.js'
|
|
|
|
+import { getTradeConfig, createOrder, settlementOrder } from '@/api/mall/trade'
|
|
|
|
+import Snackbar from '@/plugins/snackbar'
|
|
|
|
+
|
|
|
|
+const route = useRoute()
|
|
|
|
+const router = useRouter()
|
|
|
|
+const { id } = route.params
|
|
|
|
+const { count } = route.query
|
|
|
|
+
|
|
|
|
+const state = reactive({
|
|
|
|
+ orderPayload: {},
|
|
|
|
+ orderInfo: {
|
|
|
|
+ items: [], // 商品项列表
|
|
|
|
+ price: {}, // 价格信息
|
|
|
|
+ },
|
|
|
|
+ showCoupon: false, // 是否展示优惠劵
|
|
|
|
+ couponInfo: [], // 优惠劵列表
|
|
|
|
+ showDiscount: false, // 是否展示营销活动
|
|
|
|
+ // ========== 积分 ==========
|
|
|
|
+ pointStatus: false, //是否使用积分
|
|
|
|
+});
|
|
|
|
+// 检测支付环境
|
|
|
|
+const payState = reactive({
|
|
|
|
+ orderType: 'goods', // 订单类型; goods - 商品订单, recharge - 充值订单
|
|
|
|
+ orderInfo: {}, // 支付单信息
|
|
|
|
+ payStatus: 0, // 0=检测支付环境, -2=未查询到支付单信息, -1=支付已过期, 1=待支付,2=订单已支付
|
|
|
|
+ payMethods: [], // 可选的支付方式
|
|
|
|
+ payment: '', // 选中的支付方式
|
|
|
|
+});
|
|
|
|
+const addressState = ref({
|
|
|
|
+ addressInfo: {}, // 选择的收货地址
|
|
|
|
+ deliveryType: undefined, // 收货方式:1-快递配送,2-门店自提
|
|
|
|
+ isPickUp: true, // 门店自提是否开启
|
|
|
|
+ pickUpInfo: {}, // 选择的自提门店信息
|
|
|
|
+ receiverName: '', // 收件人名称
|
|
|
|
+ receiverMobile: '', // 收件人手机
|
|
|
|
+});
|
|
|
|
+async function tradeConfig () {
|
|
|
|
+ // 获取交易配置
|
|
|
|
+ const data = await getTradeConfig();
|
|
|
|
+ addressState.value.isPickUp = data.deliveryPickUpEnabled;
|
|
|
|
+ // 价格计算
|
|
|
|
+ // 情况一:先自动选择“快递物流”
|
|
|
|
+ addressState.value.deliveryType = 1;
|
|
|
|
+ let orderCode = await getOrderInfo();
|
|
|
|
+ if (orderCode === 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 情况二:失败,再自动选择“门店自提”
|
|
|
|
+ if (addressState.value.isPickUp) {
|
|
|
|
+ addressState.value.deliveryType = 2;
|
|
|
|
+ let orderCode = await getOrderInfo();
|
|
|
|
+ if (orderCode === 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 情况三:都失败,则不选择
|
|
|
|
+ addressState.value.deliveryType = undefined;
|
|
|
|
+ await getOrderInfo()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 检查库存 & 计算订单价格
|
|
|
|
+async function getOrderInfo() {
|
|
|
|
+ // 计算价格
|
|
|
|
+ const data = await settlementOrder({
|
|
|
|
+ items: [{ skuId: id, count }],
|
|
|
|
+ couponId: state.orderPayload.couponId,
|
|
|
|
+ deliveryType: addressState.value.deliveryType,
|
|
|
|
+ addressId: addressState.value.addressInfo.id, // 收件地址编号
|
|
|
|
+ pickUpStoreId: addressState.value.pickUpInfo.id, //自提门店编号
|
|
|
|
+ receiverName: addressState.value.receiverName, // 选择门店自提时,该字段为联系人名
|
|
|
|
+ receiverMobile: addressState.value.receiverMobile, // 选择门店自提时,该字段为联系人手机
|
|
|
|
+ pointStatus: state.pointStatus,
|
|
|
|
+ combinationActivityId: state.orderPayload.combinationActivityId,
|
|
|
|
+ combinationHeadId: state.orderPayload.combinationHeadId,
|
|
|
|
+ seckillActivityId: state.orderPayload.seckillActivityId,
|
|
|
|
+ pointActivityId: state.orderPayload.pointActivityId,
|
|
|
|
+ });
|
|
|
|
+ state.orderInfo = data;
|
|
|
|
+ state.couponInfo = data.coupons || [];
|
|
|
|
+ // 设置收货地址
|
|
|
|
+ if (state.orderInfo.address) {
|
|
|
|
+ addressState.value.addressInfo = state.orderInfo.address;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 使用 watch 监听地址和配送方式的变化
|
|
|
|
+ watch(addressState, async (newAddress, oldAddress) => {
|
|
|
|
+ // 如果收货地址或配送方式有变化,则重新计算价格
|
|
|
|
+ if (
|
|
|
|
+ newAddress.addressInfo.id !== oldAddress.addressInfo.id ||
|
|
|
|
+ newAddress.deliveryType !== oldAddress.deliveryType
|
|
|
|
+ ) {
|
|
|
|
+ await getOrderInfo();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+onMounted(async () => {
|
|
|
|
+ if (!id || !count) return router.go(-1)
|
|
|
|
+ await tradeConfig()
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+</script>
|