first commit

This commit is contained in:
PC-202306242200\Administrator
2026-03-28 23:10:55 +08:00
commit 1c24452b6c
1735 changed files with 150474 additions and 0 deletions

501
pages/order/confirm.vue Normal file
View File

@@ -0,0 +1,501 @@
<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>