Files
dajiankang-uniapp/pages/order/confirm.vue
PC-202306242200\Administrator 1c24452b6c first commit
2026-03-28 23:10:55 +08:00

502 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<!-- 顶部导航 -->
<wd-navbar title="下单" :bordered="false" left-arrow custom-style="background-color: transparent !important;" safeAreaInsetTop @click-left="back"></wd-navbar>
<!-- 收货地址 -->
<view class="address-card" @click="selectAddress">
<view class="address-content">
<view v-if="address" class="address-text">
<view class="province-city">{{ address.receiverArea }} {{ address.receiverAddress }}</view>
<view class="address-detail">{{ address.receiverName }} {{ address.receiverPhone }}</view>
</view>
<view v-else class="address-text">请选择地址</view>
<view class="arrow-right">
<image src="/static/y.png" style="width: 45rpx; height: 45rpx"></image>
</view>
</view>
</view>
<!-- 商品列表 -->
<view class="product-section">
<view class="section-title">商品信息</view>
<view class="product-list">
<view class="product-item" @click="viewProduct">
<image class="product-image" :src="goods.cover" mode="aspectFill"></image>
<view class="product-info">
<view class="product-name">{{ goods.name }}</view>
<view class="product-spec">{{ goods.specs }}</view>
<view class="product-price">{{ goods.currentPrice }}</view>
</view>
</view>
<view class="arrow-right">
<image src="/static/y.png" style="width: 45rpx; height: 45rpx"></image>
</view>
</view>
<view class="price-item" style="margin-top: 25rpx">
<text class="price-label">商品数量</text>
<view class="price-value">
<wd-input-number v-model="dataFrom.goodsNum" />
</view>
</view>
</view>
<!-- 订单备注 -->
<view class="remark-section">
<view class="section-title">订单备注</view>
<view class="remark-content">
<wd-textarea style="height: 100rpx" v-model="dataFrom.note" placeholder="请填写订单备注" />
</view>
</view>
<!-- 支付方式 -->
<view class="price-section">
<view class="section-title">支付方式</view>
<!-- 余额支付 -->
<view class="price-item-pay" :class="{ 'active-border': dataFrom.payType === 1 }" @click="dataFrom.payType = 1">
<view style="width: 350rpx; text-align: center" class="price-label">余额支付</view>
<view style="width: 1rpx; background-color: #f7f7f7; height: 30rpx"></view>
<view style="width: 350rpx; color: #ff2929; text-align: center" class="price-value">
<text style="color: #aaa">可用余额</text>
{{ userInfo.money || 0 }}
</view>
</view>
<view v-if="dataFrom.payType === 1 && userInfo.userRights" class="price-item">
<view style="color: #aaa; font-size: 24rpx">
当前权益等级{{ userInfo.userRights.rights.rightsName }}
<text style="margin-left: 30rpx">
可享受折扣
<text style="color: #ff2929">{{ userInfo.userRights.rights.rightsDiscount / 10 }}</text>
</text>
</view>
</view>
<!-- 权益货值支付 -->
<view class="price-item-pay" v-if="userInfo.userRights" :class="{ 'active-border': dataFrom.payType === 2 }" @click="dataFrom.payType = 2">
<view style="width: 350rpx; text-align: center" class="price-label">权益货值</view>
<view style="width: 1rpx; background-color: #f7f7f7; height: 30rpx"></view>
<view style="width: 350rpx; color: #ff2929; text-align: center" class="price-value">
<text style="color: #aaa">可用抵扣</text>
{{ userInfo.userRights.pice || 0 }}
</view>
</view>
<view v-if="dataFrom.payType === 2" class="price-item">
<view style="color: #aaa; font-size: 24rpx">提示抵扣金额不足时自动使用余额补足</view>
</view>
<!-- 混合支付 -->
<view class="price-item-pay" :class="{ 'active-border': dataFrom.payType === 3 }" @click="dataFrom.payType = 3" v-if="userInfo.userRights">
<view style="display: flex; align-items: center; justify-content: space-between; width: 100%">
<view style="width: 350rpx; text-align: center" class="price-label">混合支付</view>
<view style="width: 1rpx; background-color: #f7f7f7; height: 30rpx"></view>
<view style="width: 350rpx; color: #ff2929; text-align: center" class="price-value">
<view v-if="totalAmount > userInfo.userRights.pice + userInfo.money">
<view>
<text style="color: #aaa">余额</text>
{{ min(userInfo.money, totalAmount - userInfo.userRights.pice) }}
</view>
<view>
<text style="color: #aaa">抵扣</text>
{{ min(userInfo.userRights.pice, totalAmount - userInfo.money) }}
</view>
</view>
<view v-else>
<view>
<text style="color: #aaa">余额</text>
{{ max(0, totalAmount - userInfo.userRights.pice) }}
</view>
<view v-if="min(totalAmount - (totalAmount - userInfo.userRights.pice), userInfo.userRights.pice) > totalAmount">
<text style="color: #aaa">抵扣</text>
{{ totalAmount }}
</view>
<view v-else>
<text style="color: #aaa">抵扣</text>
{{ min(totalAmount - (totalAmount - userInfo.userRights.pice), userInfo.userRights.pice) }}
</view>
</view>
</view>
</view>
</view>
<view v-if="dataFrom.payType === 3" class="price-item">
<view style="color: #aaa; font-size: 24rpx">提示混合支付时优先使用抵扣金额</view>
</view>
</view>
<view style="height: 130rpx"></view>
<!-- 底部结算栏 -->
<view class="footer">
<view class="total-price">
合计
<text style="color: #ff2929">{{ formatPrice(paymentAmount) }}</text>
</view>
<view class="pay-button" @click="submitOrder">确认支付</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { toast } from '@/utils/fun.js';
import api from '@/api/index';
import { Store } from '@/store';
const store = Store();
// 用户信息
const userInfo = computed(() => {
if (!store.userInfo.userRights) {
dataFrom.value.payType = 1;
}
return (
store.userInfo || {
inviteCode: '',
nickname: '',
mobile: '',
avatar: '',
paywallet: { balance: 0 },
userRights: null
}
);
});
// 商品信息
const goods = ref({});
const address = ref(null);
// 表单数据
const dataFrom = ref({
goodsId: null,
goodsNum: 1,
totalAmount: 0,
payableAmount: 0,
payAmount: 0,
payType: 1,
receiverId: null,
note: '',
orderType: 1
});
// 计算总金额
const totalAmount = computed(() => {
return goods.value.currentPrice * dataFrom.value.goodsNum;
});
// 计算实际支付金额
const paymentAmount = computed(() => {
if (dataFrom.value.payType === 1) {
const discount = userInfo.value.userRights?.rights?.rightsDiscount || 100;
return (totalAmount.value * discount) / 100;
}
return totalAmount.value;
});
// 提交订单
const submitOrder = () => {
let data = JSON.parse(JSON.stringify(dataFrom.value));
if (!address.value) {
uni.showToast({
title: '请选择收货地址',
icon: 'none'
});
return;
}
uni.showLoading({
mask: true
});
// 设置收货地址
data.receiverId = address.value?.id;
if (data.payType == 1) {
// 设置支付金额
data.payAmount = paymentAmount.value;
data.totalAmount = totalAmount.value;
data.payableAmount = paymentAmount.value;
data.totalAmount = totalAmount.value;
}
if (data.payType == 2) {
// 设置抵扣金额
data.deductibleAmount = totalAmount.value;
data.totalAmount = totalAmount.value;
data.deductionAmount = totalAmount.value;
data.totalAmount = totalAmount.value;
}
if (data.payType == 3) {
if (userInfo.value.userRights.pice < totalAmount.value) {
data.deductibleAmount = userInfo.value.userRights.pice;
data.deductionAmount = userInfo.value.userRights.pice;
data.payAmount = totalAmount.value - userInfo.value.userRights.pice;
data.payableAmount = totalAmount.value - userInfo.value.userRights.pice;
data.totalAmount = totalAmount.value;
} else {
// 设置抵扣金额
data.deductibleAmount = totalAmount.value;
data.totalAmount = totalAmount.value;
data.deductionAmount = totalAmount.value;
data.totalAmount = totalAmount.value;
data.payType = 2;
}
}
api.orderCreate(data)
.then((res) => {
uni.hideLoading();
uni.navigateTo({
url: '/pages/order/success?id=' + res
});
})
.catch(() => {
uni.hideLoading();
});
};
// 加载数据
onLoad(async (options) => {
dataFrom.value.goodsId = options.id;
await store.usersGetInfo();
api.goodsInfo({ id: options.id }).then((res) => {
goods.value = res;
});
api.addressPage({ isDefault: 1 }).then((res) => {
if (res.list.length) {
address.value = res.list[0];
dataFrom.value.receiverId = address.value.id;
}
});
uni.$on('address', (e) => {
address.value = e;
});
});
// 工具函数
const min = (a, b) => Math.min(a, b);
const max = (a, b) => Math.max(a, b);
const formatPrice = (price) => `¥ ${parseFloat(price).toFixed(2)}`;
// 其他方法
const selectAddress = () => {
uni.navigateTo({
url: '/pages/address/list?type=1'
});
};
const viewProduct = () => {
uni.navigateTo({
url: '/pages/goods/goods?id=' + goods.value.id
});
};
const back = () => {
uni.navigateBack();
};
</script>
<style scoped lang="scss">
.container {
display: flex;
flex-direction: column;
background-color: #f5f5f5;
position: relative;
}
.address-card {
margin: 25rpx;
margin-bottom: 0;
padding: 30rpx;
background-color: #fff;
border-radius: 16rpx;
}
.address-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.address-text {
flex: 1;
}
.province-city {
font-size: 15px;
margin-bottom: 5px;
}
.address-detail {
font-size: 14px;
color: #666;
}
.arrow-right {
color: #ccc;
font-size: 18px;
}
.product-section {
margin: 25rpx;
padding: 30rpx;
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 0;
}
.section-title {
font-size: 15px;
color: #333;
margin-bottom: 15px;
font-weight: 500;
}
.product-list {
display: flex;
justify-content: space-between;
align-items: center;
}
.product-item {
display: flex;
align-items: center;
}
.product-image {
width: 80px;
height: 80px;
border-radius: 4px;
margin-right: 10px;
}
.product-info {
flex: 1;
}
.product-name {
font-size: 14px;
margin-bottom: 5px;
}
.product-spec {
font-size: 13px;
color: #999;
margin: 10rpx 0;
}
.product-price {
font-size: 36rpx;
font-weight: bold;
color: #ff2929;
}
.price-section {
margin: 25rpx;
padding: 30rpx;
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 0;
}
.price-item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15px;
}
.price-item-pay {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15rpx;
padding: 24rpx 0rpx;
border: 1rpx solid #f7f7f7;
border-radius: 10rpx;
background-color: #f7f7f7;
}
.price-total {
display: flex;
align-items: center;
justify-content: space-between;
}
.price-label {
font-size: 14px;
color: #333;
}
.price-value {
font-size: 14px;
color: #333;
}
.total {
color: #ff2929;
font-weight: 500;
}
.remark-section {
margin: 25rpx;
padding: 30rpx;
background-color: #fff;
border-radius: 16rpx;
margin-bottom: 0;
}
.remark-content {
border-radius: 16rpx;
border: 1rpx solid #f7f7f7;
overflow: hidden;
height: 100rpx;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: space-between;
align-items: center;
height: 100rpx;
padding: 0 30rpx;
background-color: #fff;
border-top: 1rpx solid #eee;
}
.total-price {
font-size: 15px;
color: #333;
}
.pay-button {
background-color: #799675;
color: #fff;
font-size: 16px;
padding: 0 30px;
height: 36px;
line-height: 36px;
border-radius: 18px;
}
.active-border {
background-color: rgba(121, 150, 117, 0.1);
border: 1rpx solid #799675;
.price-label {
color: #799675;
}
}
</style>