yindongqi a93999c041 feat: 优化分销中心、购物车和订单详情页功能
- 在分销中心页面添加导航栏并优化UI显示
- 在购物车页面增加打包费计算和显示
- 在订单详情页优化订单状态显示和导航逻辑
2025-04-13 21:23:15 +08:00

611 lines
13 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="page flex-col">
<view class="box_4 flex-col">
<view class="section_1 flex-col">
<view class="section_7 flex-row"></view>
<view class="section_8 flex-row">
<text class="text_2">{{ title }}</text>
</view>
</view>
<view class="text-wrapper_9 flex-row justify-between">
<text
v-for="(item, index) in tabList"
:key="index"
:class="[
'tab-text',
current === index ? 'tab-active' : 'tab-inactive',
]"
@tap="change({ type: item.type, index })"
>
{{ item.name }}
</text>
</view>
</view>
<view class="box_5 flex-col">
<!-- 订单列表 -->
<view
v-for="(item, index) in orders"
:key="index"
class="section_4 flex-col"
@tap="detail(item.orderId)"
>
<view class="group_3 flex-row justify-between">
<view class="text-group_3 flex-col justify-between">
<text class="text_6">{{ item.shop.name }}</text>
<text class="text_7"
>下单日期{{ formatDateTime(item.createTime) }}</text
>
</view>
<view class="section_9 flex-col justify-between">
<!-- <view class="text-wrapper_4 flex-col">
<text
class="text_8"
:style="{ color: getStatusColor(item._status._title) }"
>{{ item._status._title }}</text
>
</view> -->
<view class="text-wrapper_10 flex-row justify-between">
<text class="text_9">¥</text>
<text class="text_10">{{ item.payPrice }}</text>
</view>
</view>
</view>
<!-- 订单商品信息 -->
<view class="order-goods flex-col">
<view
class="flex goods-item"
v-for="(good, goodIndex) in item.cartInfo"
:key="goodIndex"
>
<image
:src="good.image"
mode="aspectFill"
class="goods-image"
></image>
<view class="flex flex-column goods-info">
<view class="goods-title">{{ good.title }}</view>
<view class="goods-spec">{{ good.spec }}</view>
<view class="goods-price"
>×{{ good.number }} ¥{{ good.price }}</view
>
</view>
</view>
</view>
<!-- 操作按钮 -->
<!-- 支付按钮 -->
<view class="group_4 flex-row">
<view
v-if="item.statusDto.type === '0'"
class="text-wrapper_6 flex-col action-button"
@tap.stop="handlePay(item)"
>
<text class="text_11">支付</text>
</view>
<!-- 发票按钮 -->
<view
v-if="item.statusDto.type === '4'"
class="text-wrapper_6 flex-col action-button"
@tap.stop="handleInvoice(item)"
>
<text class="text_11">
{{
item.invoiceStatus === "UNREQUESTED"
? "申请发票"
: item.invoiceStatus === "REQUESTED"
? "申请中"
: item.invoiceStatus === "SUCCESS"
? "下载发票"
: "申请失败"
}}
</text>
</view>
<view
v-if="item.paid > 0 && item.status < 2 && item.refundStatus == 0"
class="text-wrapper_6 flex-col action-button"
@tap.stop="receive(item)"
>
<text class="text_11">确认收到餐</text>
</view>
<view
class="text-wrapper_6 flex-col action-button detail-button"
@tap.stop="detail(item.orderId)"
>
<text class="text_11">订单详情</text>
</view>
</view>
</view>
<!-- 空状态 -->
<uv-empty v-if="orders.length == 0" mode="order"></uv-empty>
</view>
</view>
</template>
<script setup>
import { ref, computed } from "vue";
import { useMainStore } from "@/store/store";
import { storeToRefs } from "pinia";
import {
onLoad,
onPullDownRefresh,
onReachBottom,
onShow,
} from "@dcloudio/uni-app";
import { formatDateTime, kmUnit } from "@/utils/util";
import { orderGetOrders, orderReceive } from "@/api/order";
import { applyInvoice } from "@/api/order";
// 确保导入payUnify方法
import { payUnify } from "@/api/order";
import { isWeixin } from "@/utils/util";
const main = useMainStore();
const { isLogin } = storeToRefs(main);
const title = ref("我的订单");
const page = ref(1);
const pageSize = ref(10);
const orders = ref([]);
const tabList = ref([
{
type: -1,
name: "全部",
},
{
type: 0,
name: "待支付",
},
{
type: 1,
name: "进行中",
},
{
type: 4,
name: "已完成",
},
{
type: -3,
name: "退款单",
},
]);
const current = ref(0);
const type = ref(-1);
const goodsNum = computed(() => {
//计算单个饮品添加到购物车的数量
return (goods) => {
let num = 0;
goods.forEach((good) => (num += parseInt(good.number)));
return num;
};
});
onLoad(() => {
if (!isLogin.value) {
uni.navigateTo({ url: "/pages/components/pages/login/login" });
}
onShow();
});
onShow(() => {
if (isLogin.value) {
getOrders(true); // 每次显示页面时刷新订单数据
}
});
onPullDownRefresh(() => {
getOrders(true);
});
onReachBottom(() => {
getOrders(false);
});
// tab栏切换
const change = (e) => {
console.log("e;", e.type);
console.log("e.index;", e.index);
type.value = e.type;
getOrders(true);
current.value = e.index;
};
const getOrders = async (isRefresh = false) => {
uni.showLoading({
title: "加载中",
});
if (isRefresh) {
orders.value = [];
page.value = 1;
}
let ordersData = await orderGetOrders({
page: page.value,
limit: pageSize.value,
type: type.value,
});
if (ordersData) {
orders.value = orders.value.concat(ordersData);
page.value += 1;
}
uni.stopPullDownRefresh();
uni.hideLoading();
};
const detail = (id) => {
uni.navigateTo({
url: "/pages/components/pages/orders/detail?id=" + id,
});
};
const handlePay = async (item) => {
// uni.showLoading({ title: "加载中" });
try {
// 调用支付接口
let from = "routine";
// #ifdef H5
from = "h5";
if (isWeixin()) {
from = "wechat";
}
// #endif
let data = await payUnify({
uni: item.orderId,
from: from,
paytype: "weixin",
});
if (!data) {
// uni.hideLoading();
return;
}
if (data.trade_type === "JSAPI") {
// #ifdef MP-WEIXIN
uni.requestPayment({
provider: "wxpay",
timeStamp: data.data.timeStamp,
nonceStr: data.data.nonceStr,
package: data.data.package,
signType: "MD5",
paySign: data.data.paySign,
success: function () {
uni.showToast({ title: "支付成功" });
getOrders(true); // 刷新订单列表
},
fail: function (err) {
console.log("支付失败:", err);
// uni.hideLoading();
},
});
// #endif
}
} catch (error) {
console.error("支付异常:", error);
// uni.hideLoading();
}
};
const handleInvoice = async (item) => {
if (item.invoiceStatus === "UNREQUESTED") {
// 申请发票
const res = await applyInvoice(item.orderId);
if (res) {
uni.showToast({ title: "发票申请已提交", icon: "success" });
await getOrders(true); // 刷新订单列表
}
} else if (item.invoiceStatus === "SUCCESS") {
// 下载发票
if (item.invoiceAddress) {
uni.showLoading({
title: "加载中",
mask: true,
});
uni.downloadFile({
url: item.invoiceAddress,
success: (res) => {
uni.hideLoading();
if (res.statusCode === 200) {
uni.openDocument({
filePath: res.tempFilePath,
fileType: "pdf",
showMenu: true,
});
}
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: "发票下载失败",
icon: "none",
});
console.error("下载发票失败:", err);
},
});
}
}
};
// 确认收到货
const receive = async (order) => {
let data = await orderReceive({ uni: order.orderId });
if (data) {
await getOrders(true);
}
};
</script>
<style>
@import "./common.css";
.page {
background-color: rgba(244, 244, 239, 1);
position: relative;
width: 750rpx;
min-height: 100vh;
overflow-x: hidden;
}
.box_4 {
background-color: rgba(255, 255, 255, 1);
width: 750rpx;
height: 289rpx;
}
.section_1 {
background-color: rgba(255, 255, 255, 0);
height: 176rpx;
width: 750rpx;
}
.section_7 {
width: 678rpx;
height: 33rpx;
margin: 31rpx 0 0 56rpx;
}
.section_8 {
width: 703rpx;
height: 64rpx;
margin: 36rpx 0 12rpx 38rpx;
}
.text_2 {
width: 120rpx;
height: 42rpx;
overflow-wrap: break-word;
color: rgba(0, 0, 0, 1);
font-size: 30rpx;
font-family: PingFang SC-Medium;
font-weight: 500;
text-align: center;
white-space: nowrap;
line-height: 30rpx;
margin: 11rpx 0 0 259rpx;
}
.text-wrapper_9 {
width: 673rpx;
height: 45rpx;
margin: 40rpx 0 28rpx 40rpx;
}
.tab-text {
height: 36rpx;
overflow-wrap: break-word;
font-size: 26rpx;
font-family: PingFang SC-Regular;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 26rpx;
}
.tab-active {
color: rgba(34, 34, 34, 0.95);
font-size: 32rpx;
font-family: PingFang SC-Medium;
font-weight: 500;
}
.tab-inactive {
color: rgba(153, 153, 153, 0.95);
}
.box_5 {
width: 750rpx;
min-height: 600rpx;
padding-bottom: 30rpx;
}
.section_4 {
background-color: rgba(255, 255, 255, 1);
border-radius: 24px;
min-height: 208rpx;
width: 686rpx;
margin: 28rpx 0 0 32rpx;
padding-bottom: 20rpx;
}
.group_3 {
width: 662rpx;
height: 120rpx;
margin-left: 24rpx;
}
.text-group_3 {
width: 477rpx;
height: 88rpx;
margin-top: 32rpx;
}
.text_6 {
width: 438rpx;
height: 38rpx;
overflow-wrap: break-word;
color: rgba(34, 34, 34, 1);
font-size: 28rpx;
font-family: PingFang SC-Medium;
font-weight: 500;
text-align: left;
white-space: nowrap;
line-height: 28rpx;
}
.text_7 {
width: 477rpx;
height: 34rpx;
overflow-wrap: break-word;
color: rgba(153, 153, 153, 1);
font-size: 24rpx;
font-family: PingFang SC-Regular;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 24rpx;
margin-top: 16rpx;
}
.section_9 {
width: 104rpx;
height: 96rpx;
}
.text-wrapper_4 {
background-color: rgba(244, 244, 244, 1);
border-radius: 0px 24px 8px 0px;
height: 38rpx;
border: 1px solid rgba(211, 211, 211, 1);
width: 104rpx;
}
.text_8 {
width: 72rpx;
height: 34rpx;
overflow-wrap: break-word;
font-size: 24rpx;
font-family: PingFang SC-Regular;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 24rpx;
margin: 2rpx 0 0 16rpx;
}
.text-wrapper_10 {
width: 65rpx;
height: 39rpx;
margin: 19rpx 0 0 7rpx;
}
.text_9 {
width: 2rpx;
height: 39rpx;
overflow-wrap: break-word;
color: rgba(0, 0, 0, 1);
font-size: 20rpx;
font-family: PingFang SC-Semibold;
font-weight: 600;
text-align: right;
white-space: nowrap;
padding-right: 20rpx;
/* line-height: 194rpx; */
}
.text_10 {
width: auto;
height: 36rpx;
overflow-wrap: break-word;
color: rgba(0, 0, 0, 1);
font-size: 26rpx;
font-family: PingFang SC-Semibold;
font-weight: 600;
text-align: right;
white-space: nowrap;
line-height: 26rpx;
}
.group_4 {
width: 100%;
height: 50rpx;
margin: 6rpx 0 20rpx 0;
display: flex;
justify-content: flex-end;
padding-right: 24rpx;
}
.text-wrapper_6 {
background-color: rgba(82, 172, 65, 1);
border-radius: 25px;
height: 54rpx;
width: 138rpx;
display: flex;
justify-content: center;
align-items: center;
}
.action-button {
margin-left: 20rpx;
}
.detail-button {
background-color: rgba(244, 244, 244, 1);
}
.detail-button .text_11 {
color: rgba(68, 68, 68, 1);
}
.text_11 {
width: auto;
height: 34rpx;
overflow-wrap: break-word;
padding: 0 10rpx;
color: rgba(255, 255, 255, 1);
font-size: 24rpx;
font-family: PingFang SC-Medium;
font-weight: 500;
text-align: center;
white-space: nowrap;
/* line-height: 24rpx; */
}
.order-goods {
padding: 0 24rpx;
margin-top: 10rpx;
}
.goods-item {
margin-bottom: 15rpx;
}
.goods-image {
width: 100rpx;
height: 100rpx;
border-radius: 8rpx;
margin-right: 20rpx;
}
.goods-info {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.goods-title {
font-size: 26rpx;
color: rgba(34, 34, 34, 1);
font-weight: 500;
}
.goods-spec {
font-size: 22rpx;
color: rgba(153, 153, 153, 1);
}
.goods-price {
font-size: 22rpx;
color: rgba(0, 0, 0, 1);
}
</style>