<template> <s-layout title="确认订单"> <!-- TODO:这个判断先删除 v-if="state.orderInfo.need_address === 1" --> <view class="bg-white address-box ss-m-b-14 ss-r-b-10" @tap="onSelectAddress"> <s-address-item :item="state.addressInfo" :spuType="state.orderPayload.spuType" :hasBorderBottom="false"> <view class="ss-rest-button"> <text class="_icon-forward" /> </view> </s-address-item> </view> <!-- 商品信息 --> <!-- {{shopsByNames}} --> <view class="order-card-box ss-m-b-14" v-for="(items, name) in shopsByNames" :key="name"> <view class="title-text ss-p-x-20 ss-p-t-20"> {{name}} </view> <s-goods-item v-for="item in items.items" :key="item?.skuId" :img="item?.picUrl" :title="item?.spuName" :skuText="item?.properties?.map((property) => property.valueName).join(' ')" :price="item.highPrecisionPrice ? item?.highPrecisionPrice :item?.price " :num="item?.count" :virtualPirce="item.highPrecisionPrice ? true :false " /> <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10"> <view class="item-title">运费</view> <view class="ss-flex ss-col-center"> {{items.price.deliveryPrice?"¥"+fen2yuan(items.price.deliveryPrice):"包邮"}} </view> </view> <!-- 暂不做开发票 --> <!-- <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10"> <view class="item-title">开具发票</view> <view class="ss-flex ss-col-center"> <text class="item-value" :class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'"> {{ state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '不开具发票' }} </text> <text class="_icon-forward item-icon" /> </view> </view> --> <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10"> <view class="item-title">订单备注</view> <view class="ss-flex ss-col-center"> <uni-easyinput maxlength="20" placeholder="建议留言前先与商家沟通" v-model="items.remark" :inputBorder="false" :clearable="false" /> </view> </view> <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10" v-if="state.orderPayload.spuType == 0"> <view class="item-title">数量</view> <view class="ss-flex ss-col-center"> {{totalItemCount}} </view> </view> <view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10" v-else> <view class="item-title">总价</view> <view class="ss-flex ss-col-center"> <image src="@/static/icon/points.png" v-if="state.orderPayload.spuPayType == 2" style="width:30rpx;height:30rpx"></image> <text v-else>¥</text> {{fen2yuan(items.price.payPrice)}} </view> </view> </view> <!-- 价格信息 --> <view class="bg-white total-card-box ss-p-20 ss-m-b-14 ss-r-10"> <view class="title-text"> 价格明细 </view> <view class="total-box-content border-bottom"> <view class="order-item ss-flex ss-col-center ss-row-between"> <view class="item-title">商品总价 共{{totalItemCount}}件商品</view> <view class="ss-flex ss-col-center"> <text class="item-value ss-m-r-24"> <image src="@/static/icon/points.png" v-if="state.orderPayload.spuPayType == 2" style="width:30rpx;height:30rpx"></image> <text v-else>¥</text> <text v-if="state.orderPayload.highPrecision">{{ fen2yuan6(state.orderInfo.price.virtualTotalPrice) }} </text> <text v-else> {{ fen2yuan(state.orderInfo.price.totalPrice) }} </text> </text> </view> </view> <!-- TODO 非繁人:接入积分 --> <view class="order-item ss-flex ss-col-center ss-row-between"> <view class="item-title">运费</view> <view class="ss-flex ss-col-center"> <text class="item-value ss-m-r-24"> <image src="@/static/icon/points.png" v-if="state.orderPayload.spuPayType == 2" style="width:30rpx;height:30rpx"></image> <text v-else>¥</text> {{ fen2yuan(state.orderInfo.price.deliveryPrice) }} </text> </view> </view> <view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderPayload.spuPayType != 2"> <view class="item-title">积分抵扣</view> <view class="ss-flex ss-col-center" @tap="state.showPoints = true"> <!-- <text class="item-value text-red"> </text> --> <text class="item-value" :class="state.usedPoint > 0 ? 'text-red' : 'text-disabled'"> {{ state.usedPoint > 0 ? ' 可抵扣' + state.usedPoint + '元' : '不使用积分' }} </text> <text class="_icon-forward item-icon" /> </view> </view> <!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 --> <!-- 暂时隐藏优惠卷 --> <!-- <view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0" > <view class="item-title">优惠券</view> <view class="ss-flex ss-col-center" @tap="state.showCoupon = true"> <text class="item-value text-red" v-if="state.orderPayload.couponId > 0"> -¥{{ fen2yuan(state.orderInfo.price.couponPrice) }} </text> <text class="item-value" :class="state.couponInfo.length > 0 ? 'text-red' : 'text-disabled'" v-else > {{ state.couponInfo.length > 0 ? state.couponInfo.length + ' 张可用' : '暂无可用优惠券' }} </text> <text class="_icon-forward item-icon" /> </view> </view> --> <!-- <view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.price.discountPrice > 0" > <view class="item-title">活动优惠</view> <view class="ss-flex ss-col-center"> @tap="state.showDiscount = true" TODO 非繁人:后续要把优惠信息打进去 <text class="item-value text-red"> -¥{{ fen2yuan(state.orderInfo.price.discountPrice) }} </text> <text class="_icon-forward item-icon" /> </view> </view> --> </view> <view class="total-box-footer ss-font-28 ss-flex ss-row-right ss-col-center ss-m-r-28"> <view class="total-num ss-m-r-20"> 共{{ totalItemCount }}件 </view> <view>合计:</view> <view class="total-num text-red ss-flex"> <image src="@/static/icon/points.png" class='ss-m-r-10' v-if="state.orderPayload.spuPayType == 2" style="width:30rpx;height:30rpx"></image> <text v-else>¥</text> <text v-if="state.orderPayload.highPrecision">{{ fen2yuan6(state.orderInfo.price.virtualTotalPrice) }} </text> <text v-else-if="state.orderPayload.spuPayType == 2">{{ fen2yuan(state.orderInfo.price.payPrice) - 0.01 }} </text> <text v-else>{{ fen2yuan(state.orderInfo.price.payPrice) }} </text> </view> </view> </view> <!-- 积分--> <s-points-pop v-model="state.couponInfo" :currentMemberPoints="state.currentMemberPoints" :currentTotalPrice="state.currentTotalPrice" :currentDeliveryPrice="state.currentDeliveryPrice" :show="state.showPoints" @confirm="onInputPoints" @close="state.showPoints = false" /> <!-- 满额折扣弹框 TODO 非繁人:后续要把优惠信息打进去 --> <!-- <s-discount-list v-model="state.orderInfo" :show="state.showDiscount" @close="state.showDiscount = false" /> --> <!-- 底部 --> <su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200"> <view class="footer-box border-top ss-flex ss-row-between ss-p-x-20 ss-col-center"> <view class="total-box-footer ss-flex ss-col-center"> <view v-if="state.orderPayload.highPrecision"> <image src="@/static/icon/points.png" v-if="state.orderPayload.spuPayType == 2" style="width:30rpx;height:30rpx"></image> {{ fen2yuan6(state.orderInfo.price.virtualPayPrice) - 0.01 }} ¥0.01 </view> <view class="total-num ss-font-30 text-red " v-else-if="state.orderPayload.spuPayType == 2"> <image src="@/static/icon/points.png" v-if="state.orderPayload.spuPayType == 2" style="width:30rpx;height:30rpx"></image> {{ state.usedPoint }} ¥0.01 </view> <view class="total-num ss-font-30 text-red" v-else> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }} </view> </view> <button class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main" @tap="onConfirm"> 提交订单 </button> </view> </su-fixed> </s-layout> </template> <script setup> import { reactive, computed } from 'vue'; import { onLoad } from '@dcloudio/uni-app'; import sheep from '@/sheep'; import { isEmpty } from 'lodash'; import OrderApi from '@/sheep/api/trade/order'; import CouponApi from '@/sheep/api/promotion/coupon'; import { fen2yuan, points2point, fen2yuan6 } from '@/sheep/hooks/useGoods'; const state = reactive({ orderPayload: {}, orderInfo: { items: [], // 商品项列表 price: {}, // 价格信息 }, addressInfo: {}, // 选择的收货地址 showPoints: false, // 是否积分抵扣 couponInfo: [], // 优惠劵列表 showDiscount: false, // 是否展示营销活动 currentMemberPoints: 0, //用户当前可用积分 usedPoint: 0, //用户使用的积分 currentTotalPrice: 0, //当前的整个订单的总价格 currentDeliveryPrice: 0 // 当前订单的总运费 }); // 返回来的数据根据店铺名过滤 TODO const shopsByNames = computed(() => { // console.log(state.orderInfo.shopRespVOMap) const shops = {}; try { Object.keys(state.orderInfo.shopRespVOMap).forEach(shopId => { const shopName = state.orderInfo.shopNameMap[shopId]; if (shopName) { shops[shopName] = state.orderInfo.shopRespVOMap[shopId]; shops[shopName].remark = "" shops[shopName].shopId = shopId } }); } catch (e) { // console.log(e) } return shops; }); // 计算所有商品的总数 const totalItemCount = computed(() => { let totalCount = 0; Object.values(shopsByNames.value).forEach(shop => { shop.items.forEach(item => { totalCount += item.count; }); }); return totalCount; }); // 选择地址 function onSelectAddress() { uni.$once('SELECT_ADDRESS', (e) => { changeConsignee(e.addressInfo); }); console.log(state.orderPayload.spuType) // 如果是虚拟商品 进入选虚拟地址 if (state.orderPayload.spuType) { sheep.$router.go('/pages/user/address/list'); } else { sheep.$router.go('/pages/user/dummyAddress/list'); } } // 更改收货人地址&计算订单信息 async function changeConsignee(addressInfo = {}) { if (!isEmpty(addressInfo)) { state.addressInfo = addressInfo; } await getOrderInfo(); } // 使用积分 async function onInputPoints(points) { if (points == undefined) { points = 0 } const payprice = state.currentTotalPrice state.orderInfo.price.payPrice = (payprice - points) * 100 state.usedPoint = points state.showPoints = false; } // 提交订单 function onConfirm() { if (!state.addressInfo.id) { sheep.$helper.toast('请选择收货地址'); return; } if (parseFloat(state.usedPoint) > parseFloat(state.currentMemberPoints)) { sheep.$helper.toast('可用积分不足'); return; } submitOrder(); } // 截取小数 不保留四舍五入 /** * @param number 数字 * @param decimals 小数点位数 * */ function customRound(number, decimals) { let factor = Math.pow(10, decimals); let tempNumber = Math.floor(number * factor) / factor; return tempNumber.toFixed(decimals); } // 创建订单&跳转 async function submitOrder() { // 处理每个店铺的留言 以{店铺id:留言}的形式返回 const shops = shopsByNames.value; const shopRemarks = {}; Object.keys(shops).forEach(shopName => { const shop = shops[shopName]; shopRemarks[shop.shopId] = shop.remark; }); // 如果不是高精度商品 就走原来的程序,如果是高精度的商品,就拿到高精度返回的商品总价 / 100 然后保留四位小数再干掉两位,实现积分可以刚好大于当前积分的0.01 const usedPoint = state.orderPayload.highPrecision ? customRound((state.orderInfo.price.virtualPayPrice / 100 ), 2): state.usedPoint; const { code, data } = await OrderApi.createOrder({ items: state.orderPayload.items, couponId: state.orderPayload.couponId, addressId: state.addressInfo.id, deliveryType: state.orderPayload.spuType == 1 ? 1 : 3, // TODO 非繁人:需要支持【门店自提】 pointStatus: false, // TODO 非繁人:需要支持【积分选择】 combinationActivityId: state.orderPayload.combinationActivityId, combinationHeadId: state.orderPayload.combinationHeadId, seckillActivityId: state.orderPayload.seckillActivityId, payIntegral: usedPoint, // payIntegral: 0.95, shopRemarks: shopRemarks }); if (code !== 0) { return; } // 更新购物车列表,如果来自购物车 if (state.orderPayload.items[0].cartId > 0) { sheep.$store('cart').getList(); } // 跳转到支付页面 sheep.$router.redirect('/pages/pay/index', { id: data.payOrderId, }); } // 检查库存 & 计算订单价格 async function getOrderInfo() { // 每次查询设置订单之前 看有没有评论 如果有评论就存到shopRemarks const shops = shopsByNames.value let shopRemarks = {}; if (Object.keys(shops).length !== 0) { Object.keys(shops).forEach(shopName => { const shop = shops[shopName]; shopRemarks[shopName] = shop.remark; }); } const { data, code } = await OrderApi.settlementOrder({ items: state.orderPayload.items, couponId: state.orderPayload.couponId, addressId: state.addressInfo.id, deliveryType: state.orderPayload.spuType == 1 ? 1 : 3, // TODO 非繁人:需要支持【门店自提】 pointStatus: false, // TODO 非繁人:需要支持【积分选择】 combinationActivityId: state.orderPayload.combinationActivityId, combinationHeadId: state.orderPayload.combinationHeadId, seckillActivityId: state.orderPayload.seckillActivityId, usedPoint: state.usedPoint, addressType: state.orderPayload.spuType == 1 ? 1 : 2 //如果是虚拟产品 }); if (code !== 0) { return; } state.orderInfo = data; // 如果shopRemarks有评论的话 就放回shopsByNames if (Object.keys(shopRemarks).length !== 0) { Object.keys(shopRemarks).forEach(shopName => { shopsByNames.value[shopName].remark = shopRemarks[shopName] }); } // 设置收货地址 if (state.orderInfo.address) { state.addressInfo = state.orderInfo.address; } state.currentMemberPoints = points2point(state.orderInfo.currentQuota) state.currentTotalPrice = fen2yuan(state.orderInfo.price.payPrice) state.currentDeliveryPrice = fen2yuan(state.orderInfo.price.deliveryPrice) // console.log("父",state.currentTotalPrice) if (state.orderPayload.spuPayType == 2) { state.usedPoint = state.currentTotalPrice - 0.01 console.log(state.spuType) } } // 获取可用优惠券 // async function getCoupons() { // const { // code, // data // } = await CouponApi.getMatchCouponList( // state.orderInfo.price.payPrice, // state.orderInfo.items.map((item) => item.spuId), // state.orderPayload.items.map((item) => item.skuId), // state.orderPayload.items.map((item) => item.categoryId), // ); // if (code === 0) { // state.couponInfo = data; // } // } onLoad(async (options) => { if (!options.data) { sheep.$helper.toast('参数不正确,请检查!'); return; } state.orderPayload = JSON.parse(options.data); console.log(state.orderPayload) await getOrderInfo(); }); </script> <style lang="scss" scoped> :deep() { .uni-input-wrapper { width: 320rpx; } .uni-easyinput__content-input { font-size: 28rpx; height: 72rpx; text-align: right !important; padding-right: 0 !important; .uni-input-input { font-weight: 500; color: #333333; font-size: 26rpx; height: 32rpx; margin-top: 4rpx; } } .uni-easyinput__content { display: flex !important; align-items: center !important; justify-content: right !important; } } .order-card-box, .address-box, .total-card-box { background: white; margin: 20rpx; border-radius: 20rpx; } .title-text { font-size: 30rpx; font-weight: bold; line-height: 42rpx; } .score-img { width: 36rpx; height: 36rpx; margin: 0 4rpx; } .order-item { height: 80rpx; .item-title { font-size: 28rpx; font-weight: 400; } .item-value { font-size: 28rpx; font-weight: 500; font-family: OPPOSANS; } .text-disabled { color: #bbbbbb; } .item-icon { color: $dark-9; } .remark-input { text-align: right; } .item-placeholder { color: $dark-9; font-size: 26rpx; text-align: right; } } .total-box-footer { height: 90rpx; .total-num { color: #333333; font-family: OPPOSANS; } } .footer-box { height: 100rpx; .submit-btn { width: 230rpx; height: 70rpx; font-size: 28rpx; font-weight: 500; .goto-pay-text { line-height: 28rpx; } } .cancel-btn { width: 230rpx; height: 80rpx; font-size: 26rpx; background-color: #e5e5e5; color: $dark-9; } } .title { font-size: 36rpx; font-weight: bold; color: #333333; } .subtitle { font-size: 28rpx; color: #999999; } .cicon-checkbox { font-size: 36rpx; color: var(--ui-BG-Main); } .cicon-box { font-size: 36rpx; color: #999999; } </style>