123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- <template>
- <div>
- <!-- 头部地址选择【配送地址】【自提地址】 -->
- <AddressSelection v-model="addressState" class="addressBox" />
-
- <!-- 购买的商品信息 -->
- <v-card class="goodsListBox mb-3 pa-3">
- <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">
- <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>
- </div>
- </template>
- <script setup>
- import { reactive, ref, watch } from 'vue'
- import AddressSelection from './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 emit = defineEmits(['orderCreated'])
- const props = defineProps({
- data: {
- type: String,
- default: '',
- },
- });
- 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: '', // 收件人手机
- });
-
- watch(
- () => props.data,
- (newVal) => {
- if (newVal) {
- state.orderPayload = JSON.parse(newVal);
- tradeConfig()
- }
- },
- { immediate: true },
- // { deep: true }
- )
- 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()
- }
- // 提交订单
- function onConfirm() {
- if (addressState.value.deliveryType === 1 && !addressState.value.addressInfo.id) {
- Snackbar.warning('请选择收货地址')
- return;
- }
- submitOrder()
- }
-
- // 创建订单&跳转
- async function submitOrder() {
- const data = await createOrder({
- items: state.orderPayload.items,
- couponId: state.orderPayload.couponId,
- remark: state.orderPayload.remark,
- 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,
- });
- if (!data.payOrderId && data.payOrderId > 0) return
- emit('orderCreated', data.payOrderId) // 更新购物车列表,如果来自购物车
- // payImmediately(data.payOrderId)
- }
- // 检查库存 & 计算订单价格
- async function getOrderInfo() {
- // 计算价格
- const data = await settlementOrder({
- items: state.orderPayload.items,
- 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();
- }
- });
- defineExpose({
- onConfirm
- })
- </script>
- <style lang="scss" scoped>
- .addressBox {
- margin-bottom: 20px;
- }
- .goodsListBox {
- // background: linear-gradient(to bottom, #e93323 0%, #e93323 100%);
- // background: linear-gradient(to bottom, var(--v-primary-base) 0%, var(--v-primary-base) 100%);
- border-radius: 4px;
- }
- .order-item {
- color: #7a7a7a;
- }
- .total-box-footer {
- .total-num {
- color: #7a7a7a;
- }
- }
- </style>
|