feat: 订单详情交互调整

This commit is contained in:
duanshuwen
2025-10-30 21:21:05 +08:00
parent 2b9afb936e
commit 90723fa277
10 changed files with 230 additions and 308 deletions

View File

@@ -0,0 +1,54 @@
<template>
<view class="bg-white border-box rounded-12 p-12 mb-12">
<view class="flex flex-items-center flex-justify-between mb-4">
<view class="flex flex-items-center">
<text class="font-size-16 color-171717 line-height-24 font-500">
订单金额
</text>
<text class="amt font-size-18 font-bold color-FF3D60 ml-4">
{{ orderData.payAmt }}
</text>
</view>
</view>
<view
v-if="orderData.orderStatus === '0'"
class="font-size-11 color-99A0AE"
>
超时后订单将自动取消
</view>
<view
v-if="['1', '2'].includes(orderData.orderStatus)"
class="border-box border-top flex flex-items-center flex-justify-between font-size-12 pt-12 mt-12"
>
<view class="color-525866">取消政策及说明</view>
<view class="flex flex-items-center" @click="emit('click')">
<text class="color-2D91FF mr-4">查看详情</text>
<uni-icons type="right" size="12" color="#99A0AE" />
</view>
</view>
</view>
</template>
<script setup>
import { defineProps, defineEmits } from "vue";
const props = defineProps({
orderData: {
type: Object,
required: true,
default: () => ({}),
},
});
const emit = defineEmits(["click"]);
</script>
<style scoped lang="scss">
.amt {
&::before {
content: "¥";
font-size: 16px;
font-weight: 500;
}
}
</style>

View File

@@ -3,19 +3,21 @@
class="footer bg-white border-box flex flex-items-center flex-justify-between p-12"
>
<button
v-if="shouldShowButton"
v-if="['1', '2'].includes(statusCode)"
class="left border-none border-box bg-white rounded-10 flex flex-items-center flex-justify-center font-size-14 font-500 color-525866 mr-12"
@click="emit('refund')"
>
取消订单
申请退款
</button>
<button
:class="[
'right border-none rounded-10 flex flex-full flex-items-center flex-justify-center font-size-14 font-500',
'right border-none rounded-10 flex flex-full flex-items-center flex-justify-center font-size-14 font-500 color-white',
{
'bg-FF3D60 color-white': statusCode === '0',
'bg-color-f5f7fa color-525866': statusCode === '2',
'bg-FF3D60': statusCode === '0',
'bg-2D91FF': ['1', '2', '3', '5', '6'].includes(statusCode),
},
]"
@click="handleButtonClick"
>
{{ buttonText }}
</button>
@@ -23,7 +25,8 @@
</template>
<script setup>
import { defineProps, computed, ref, defineEmits } from "vue";
import { defineProps, defineEmits, computed } from "vue";
import { orderPayNow } from "@/request/api/OrderApi";
const props = defineProps({
orderData: {
@@ -47,8 +50,8 @@ const buttonText = computed(() => {
switch (statusCode.value) {
case "0": // 待支付状态
return "立即支付";
case "2": // 待使用状态
return "申请退款";
case "1": // 已取消状态
case "2": // 已取消状态
case "3": // 已取消状态
case "5": // 已关闭状态
case "6": // 已完成状态
@@ -56,10 +59,74 @@ const buttonText = computed(() => {
}
});
// 是否显示按钮(待支付、待使用、已取消、已关闭、已完成)
const shouldShowButton = computed(() => {
return ["0", "2", "3", "5", "6"].includes(statusCode.value);
});
// 定义事件发射器
const emit = defineEmits(["refund", "refresh"]);
// 处理按钮点击事件
const handleButtonClick = async (orderData) => {
try {
// 再次预定跳转商品详情
if (["3", "5", "6"].includes(statusCode.value)) {
uni.navigateTo({
url: `/pages/goods/index?commodityId=${orderData.commodityId}`,
});
}
// 待支付状态,调用支付接口
if (statusCode.value === "0") {
const orderId = orderData.orderId;
const payWay = orderData.payWay;
const paySource = orderData.paySource;
const res = await orderPayNow({ orderId, payWay, paySource });
console.log("确认订单---2:", res);
// 检查接口返回数据
if (!res || !res.data) {
uni.showToast({ title: "订单创建失败,请重试", icon: "none" });
return;
}
const { data } = res;
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
// 验证支付参数是否完整
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
// console.error("支付参数不完整:", {
// nonceStr: !!nonceStr,
// packageVal: !!packageVal,
// paySign: !!paySign,
// signType: !!signType,
// timeStamp: !!timeStamp,
// });
uni.showToast({ title: "支付参数错误,请重试", icon: "none" });
return;
}
// 调用微信支付
uni.requestPayment({
provider: "wxpay",
timeStamp: String(timeStamp), // 确保为字符串类型
nonceStr: String(nonceStr),
package: String(packageVal), // 确保为字符串类型
signType: String(signType),
paySign: String(paySign),
success: () => {
uni.showToast({
title: "支付成功",
icon: "success",
success: () => emit("refresh"),
});
},
fail: () => {
uni.showToast({ title: "支付失败,请重试", icon: "none" });
},
});
}
} catch (error) {
console.error("操作失败:", error);
}
};
</script>
<style lang="scss" scoped>

View File

@@ -1,5 +1,8 @@
<template>
<view class="border-box bg-white p-12 rounded-12 mb-12">
<view
v-if="commodityTypeCode === '0'"
class="border-box bg-white p-12 rounded-12 mb-12"
>
<!-- 酒店类型入住离店日期部分 -->
<DateRangeSection
v-if="orderData.commodityTypeCode === '0'"
@@ -10,22 +13,44 @@
{{ orderData.commodityName }}
</view>
<view class="border-box border-bottom">
<view class="font-size-12 color-99A0AE line-height-16 pb-12">
{{ orderData.commodityDescription }}
</view>
<!-- 权益部分 -->
<view class="flex flex-items-center mb-8">
<text
class="bg-F7F7F7 border-box rounded-4 font-size-11 color-525866 mr-4 pt-4 pb-4 pl-6 pr-6"
v-for="(item, index) in orderData.commodityFacilityList"
:key="index"
>
{{ item }}
</text>
</view>
<view
class="border-box border-bottom font-size-12 color-99A0AE line-height-16 pb-12"
>
{{ orderData.commodityDescription }}
</view>
<!-- 权益部分 -->
<view class="border-box flex flex-items-center pt-12">
<text
class="bg-F7F7F7 border-box rounded-4 font-size-11 color-525866 mr-4 pt-4 pb-4 pl-6 pr-6"
v-for="(item, index) in commodityFacilityList"
:key="index"
>
{{ item }}
</text>
</view>
</view>
<view
v-if="commodityTypeCode !== '0'"
class="border-box bg-white p-12 rounded-12 mb-12"
>
<view
class="font-size-16 font-500 color-000 line-height-24 ellipsis-1 mb-8"
>
{{ orderData.commodityName }}
</view>
<view class="flex font-size-12">
<text class="w-60 color-99A0AE">购买数量</text>
<text class="color-525866">{{ commodityAmount }}</text>
</view>
<view
v-if="orderData.orderStatus === '0'"
class="border-box border-top pt-12 font-size-14 font-500 color-171717 mt-12"
>[电子凭证]直接验证使用</view
>
</view>
</template>
@@ -54,6 +79,21 @@ const selectedDate = computed(() => {
totalDays,
};
});
const commodityTypeCode = computed(() => props.orderData.commodityTypeCode);
const commodityAmount = computed(() => {
// 门票单位:张、餐饮单位:份
const { commodityAmount } = props.orderData;
return commodityTypeCode.value === "2"
? `${parseInt(commodityAmount)}`
: `${parseInt(commodityAmount)}`;
});
// 取3个权益
const commodityFacilityList = computed(() => {
return props.orderData.commodityFacilityList.slice(0, 3) || [];
});
</script>
<style scoped lang="scss">

View File

@@ -70,14 +70,8 @@ const displayItems = computed(() => {
const { orderData } = props;
const { orderType } = orderData;
// 工单情况orderType 为 undefined
if (orderType === undefined) {
return [
{ label: LABELS.CREATE_TIME, value: orderData.createTime },
{ label: LABELS.CONTACT_GUEST, value: orderData.userName },
{ label: LABELS.CONTACT_PHONE, value: orderData.userPhone },
];
}
// 去掉末尾连续、、
const formattedPhone = orderData.contactPhone.replace(/、+$/, "");
// 订单情况:根据 orderType 返回不同的显示项
switch (orderType) {
@@ -97,7 +91,7 @@ const displayItems = computed(() => {
),
},
{ label: LABELS.VISITOR_NAME, value: orderData.visitorName },
{ label: LABELS.CONTACT_PHONE, value: orderData.contactPhone },
{ label: LABELS.CONTACT_PHONE, value: formattedPhone },
];
case ORDER_TYPES.TICKET:

View File

@@ -1,7 +1,7 @@
<template>
<view
class="order-card bg-white border-box p-12 rounded-12 m-12"
@click="handleCardClick"
@click.stop="handleCardClick"
>
<!-- 卡片头部 -->
<view class="card-header flex items-center">
@@ -24,6 +24,15 @@
<!-- 卡片内容 -->
<OrderCardContent :order-data="orderData" />
<view v-if="orderData.orderStatus === '0'" class="text-right">
<button
class="go-pay border-box border-none font-size-14 color-white bg-FF3D60 rounded-5 inline-block text-center line-height-30"
@click.stop="handleCardClick"
>
去支付
</button>
</view>
</view>
</template>

View File

@@ -14,31 +14,18 @@
:class="[
{
'color-FF3D60': statusCode === '0',
'color-21B466': statusCode === '1',
'color-21B466': ['1', '2'].includes(statusCode),
},
]"
>
{{ payStatusText }}
{{ statusText }}
</text>
</view>
</view>
</template>
<script setup>
import { defineProps, computed, ref, defineEmits } from "vue";
import { orderPayNow } from "@/request/api/OrderApi";
// 支付方式映射常量
const PAY_STATUS_MAP = {
0: "未支付",
1: "已支付",
};
// 加载状态
const isLoading = ref(false);
// 定义事件发射器
const emit = defineEmits(["show-refund-popup", "pay-success"]);
import { defineProps, computed } from "vue";
const props = defineProps({
orderData: {
@@ -57,108 +44,9 @@ const props = defineProps({
const statusCode = computed(() => props.orderData.orderStatus);
// 使用计算属性缓存支付方式文本
const payStatusText = computed(() => PAY_STATUS_MAP[statusCode.value]);
// 格式化金额显示
const formattedAmount = computed(() => {
const amount = props.orderData.payAmt;
return amount ? `${parseFloat(amount).toFixed(2)}` : "0.00";
});
// 处理按钮点击事件
const handleButtonClick = async (orderData) => {
if (isLoading.value) return; // 防止重复点击
try {
isLoading.value = true;
const status = orderData.orderStatus;
if (status === "2") {
// 情况2待使用状态显示退款弹窗
emit("show-refund-popup");
return; // 直接返回,不执行后续代码
}
// 再次预定跳转商品详情
if (["3", "5", "6"].includes(status)) {
uni.navigateTo({
url: `/pages/goods/index?commodityId=${orderData.commodityId}`,
});
}
// 待支付状态,调用支付接口
if (status === "0") {
const orderId = orderData.orderId;
const payWay = orderData.payWay;
const paySource = orderData.paySource;
const res = await orderPayNow({ orderId, payWay, paySource });
console.log("确认订单---2:", res);
// 检查接口返回数据
if (!res || !res.data) {
uni.showToast({
title: "订单创建失败,请重试",
icon: "none",
duration: 2000,
});
return;
}
const { data } = res;
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
// 验证支付参数是否完整
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
console.error("支付参数不完整:", {
nonceStr: !!nonceStr,
packageVal: !!packageVal,
paySign: !!paySign,
signType: !!signType,
timeStamp: !!timeStamp,
});
uni.showToast({
title: "支付参数错误,请重试",
icon: "none",
duration: 2000,
});
return;
}
// 调用微信支付
uni.requestPayment({
provider: "wxpay",
timeStamp: String(timeStamp), // 确保为字符串类型
nonceStr: String(nonceStr),
package: String(packageVal), // 确保为字符串类型
signType: String(signType),
paySign: String(paySign),
success: () => {
uni.showToast({
title: "支付成功",
icon: "success",
duration: 2000,
success: () => {
emit("pay-success");
},
});
},
fail: (err) => {
uni.showToast({
title: "支付失败,请重试",
icon: "none",
duration: 2000,
});
},
});
}
} catch (error) {
console.error("操作失败:", error);
} finally {
isLoading.value = false;
}
};
const statusText = computed(() =>
statusCode.value === "0" ? "未支付" : "已支付"
);
</script>
<style scoped lang="scss"></style>