Files
wagoo-douy3/src/pages/client/order/components/OrderItem.vue
2026-04-08 10:47:25 +08:00

572 lines
15 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="order-item">
<view class="flex-row-between order-title" @click="jumpToDetails">
<text class="fs-24 app-fc-normal">
订单编号{{ data.order_no || "-" }}
</text>
<!-- 待支付状态显示倒计时横幅 -->
<view
v-if="
data.status === SHOP_ORDER_UNPAY &&
!data.tui_status &&
countDownTime > 0
"
class="order-status-banner"
>
<view class="status-banner-left">
<text class="status-text">等待付款</text>
</view>
<view class="status-banner-right">
<text class="countdown-text">{{
formatCountdown(countDownTime)
}}</text>
</view>
</view>
<!-- 其他状态:显示原有样式 -->
<view
v-else-if="
([
SHOP_ORDER_CANCEL,
SHOP_ORDER_UNPAY,
SHOP_ORDER_UNSLIVER,
SHOP_ORDER_UNRECEIVE,
SHOP_ORDER_DONE,
SHOP_ORDER_UNREMARK,
].includes(data.status) &&
!data.tui_status) ||
[SHOP_ORDER_AFTERSALE_REJECT].includes(data.tui_status)
"
class="flex-center fs-24 order-btn"
:class="[
![SHOP_ORDER_DONE, SHOP_ORDER_CANCEL, SHOP_ORDER_UNREMARK].includes(
data.status
)
? 'app-fc-mark confirm'
: 'cancel',
]"
>
{{ orderStatus }}
</view>
<view
v-if="
[SHOP_ORDER_AFTERSALE, SHOP_ORDER_AFTERSALE_DONE].includes(
data.tui_status
)
"
class="flex-center fs-24 order-btn cancel"
>
{{ refundOrderStatus }}
</view>
</view>
<view
class="order-content"
:class="{ 'split-border': showStatusBtn }"
@click="jumpToDetails"
>
<good-info :data="data.items" :actual_price="data.actual_price" />
<view
v-if="data.type && data.type !== 1"
class="fs-24 app-fc-mark order-type"
>
随车订单
</view>
</view>
<view v-if="showStatusBtn" class="order-btns">
<!-- 待支付 -->
<template v-if="[SHOP_ORDER_UNPAY].includes(data.status)">
<view
class="flex-center fs-24 app-fc-main cancel-order-btn"
@click.stop="$emit('cancelOrder', data)"
>
取消订单
</view>
<view class="order-btns-right">
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
联系客服
</view> -->
<view
class="flex-center fs-24 app-fc-white status-btn confirm"
@click.stop="$emit('pay', data)"
>
立即支付
</view>
</view>
</template>
<!-- 待预约 -->
<template v-if="[SHOP_ORDER_UNSLIVER].includes(data.status)">
<view class="order-btns-right">
<view
class="flex-center fs-24 app-fc-main status-btn"
@click.stop="remindRefund(data.order_id)"
>
申请退款
</view>
<view
class="flex-center fs-24 app-fc-white status-btn confirm"
@click.stop="jumpToReservation"
>
立即预约
</view>
</view>
</template>
<!-- 待收货 -->
<template v-if="[SHOP_ORDER_UNRECEIVE].includes(data.status)">
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
联系客服
</view> -->
<view
class="flex-center fs-24 app-fc-main status-btn"
@click.stop="$emit('afterSale', data)"
>
申请售后
</view>
<!-- 随车订单不显示物流 -->
<!-- <view v-if="data.pay_type !== pay_type_BYCAR" class="flex-center fs-24 app-fc-main status-btn"
@click.stop="$emit('checkSliver', data)">
查看物流
</view> -->
<view
class="flex-center fs-24 app-fc-white status-btn confirm"
@click.stop="$emit('confirmSliver', data)"
>
确认收货
</view>
</template>
<!-- 已签收未评价 -->
<template v-if="[SHOP_ORDER_UNREMARK].includes(data.status)">
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
联系客服
</view> -->
<view
class="flex-center fs-24 app-fc-white status-btn confirm"
@click.stop="$emit('remark', data)"
>
立即评价
</view>
</template>
<!-- 已完成 -->
<template v-if="[SHOP_ORDER_DONE].includes(data.status)">
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
联系客服
</view> -->
<view
class="flex-center fs-24 app-fc-white status-btn confirm"
style="visibility: hidden"
>
</view>
</template>
<template v-if="[SHOP_ORDER_DONE].includes(data.status)">
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
联系客服
</view> -->
<view
class="flex-center fs-24 app-fc-white status-btn confirm"
@click.stop="$emit('remarkDetails', data)"
>
查看评价
</view>
</template>
</view>
</view>
</template>
<script>
import PopUpModal from "@/components/PopUpModal.vue";
import GoodInfo from "./GoodInfo.vue";
import { walletTransaction, cancelPetOrderMall } from "../../../../api/login";
import {
SHOP_ORDER_STATUS,
SHOP_ORDER_UNPAY,
SHOP_ORDER_UNSLIVER,
SHOP_ORDER_UNRECEIVE,
SHOP_ORDER_DONE,
SHOP_ORDER_CANCEL,
SHOP_ORDER_AFTERSALE,
SHOP_ORDER_AFTERSALE_DONE,
SHOP_ORDER_AFTERSALE_REJECT,
SHOP_ORDER_AFTERSALE_STATUS,
SHOP_ORDER_UNREMARK,
pay_type_ADDRESS,
pay_type_BYCAR,
pay_type_BYPET,
} from "@/constants/app.business";
export default {
props: {
data: {
type: Object,
default: () => {},
},
},
data() {
return {
pay_type_ADDRESS,
pay_type_BYCAR,
pay_type_BYPET,
SHOP_ORDER_STATUS,
SHOP_ORDER_UNPAY,
SHOP_ORDER_UNSLIVER,
SHOP_ORDER_UNRECEIVE,
SHOP_ORDER_DONE,
SHOP_ORDER_CANCEL,
SHOP_ORDER_AFTERSALE,
SHOP_ORDER_AFTERSALE_DONE,
SHOP_ORDER_AFTERSALE_REJECT,
SHOP_ORDER_UNREMARK,
showCancelModal: false,
countDownTime: 0,
countDownTimer: null,
};
},
components: {
GoodInfo,
PopUpModal,
},
options: {
styleIsolation: "shared",
},
computed: {
// 抖音退款组件需要的订单ID
orderId() {
return this.data.order_id || this.data.order_no || "";
},
// 抖音退款组件需要的订单状态1=待核销/待发货2=已核销/已发货)
orderStatusForSDK() {
// 根据你的业务状态映射到抖音SDK需要的状态
// SHOP_ORDER_UNSLIVER = 待发货 -> 映射为 1
if (this.data.status === SHOP_ORDER_UNSLIVER) {
return 1;
}
// SHOP_ORDER_UNRECEIVE = 待收货 -> 映射为 2
if (this.data.status === SHOP_ORDER_UNRECEIVE) {
return 2;
}
return 1;
},
// 订单总金额(单位:分)
orderTotalAmount() {
const price = this.data.actual_price || 0;
// 转换为分
return Math.round(parseFloat(price) * 100);
},
// UniApp 需要传入的退款参数对象
refundParams() {
return {
reasonCode: [410],
note: "用户申请退款",
applySource: 101,
afterSaleType: 3,
needRefundPackFee: true,
};
},
orderStatus() {
return SHOP_ORDER_STATUS[this.data.status] || "";
},
refundOrderStatus() {
return SHOP_ORDER_AFTERSALE_STATUS[this.data.tui_status] || "";
},
showStatusBtn() {
return (
([
SHOP_ORDER_UNPAY,
SHOP_ORDER_UNSLIVER,
SHOP_ORDER_UNRECEIVE,
SHOP_ORDER_DONE,
SHOP_ORDER_UNREMARK,
].includes(this.data.status) &&
!this.data.tui_status) ||
[SHOP_ORDER_AFTERSALE_REJECT].includes(this.data.tui_status)
);
},
},
watch: {
showCancelModal(val) {
this.$emit("disableScroll", val);
},
"data.daojishi"(newVal) {
if (this.data.status === this.SHOP_ORDER_UNPAY && newVal) {
this.countDownTime = newVal;
this.startCountDown();
}
},
"data.status"(newVal) {
if (newVal === this.SHOP_ORDER_UNPAY && this.data.daojishi) {
this.countDownTime = this.data.daojishi;
this.startCountDown();
} else {
this.stopCountDown();
}
},
},
mounted() {
// console.log(this.data,'--=')
if (this.data.status === SHOP_ORDER_UNPAY && this.data.daojishi) {
this.countDownTime = this.data.daojishi;
this.startCountDown();
}
},
beforeDestroy() {
this.stopCountDown();
},
methods: {
remindRefund(id) {
const data = {
id: Number(id),
};
uni.showLoading({
icon: "none",
title: "处理中",
mask: true,
});
cancelPetOrderMall(data)
.then((res) => {
uni.hideLoading();
const plugin = tt.requirePlugin("lifeServicePlugin");
let res1 = {
code: 0,
result: "success",
msg: "success",
data: {
outOrderNo: "DYG177556196373493862814838179",
refundInfo: {
reason:["计划有变,暂时不需要了"],
reasonCode:[401],
},
goodsList: [
{ goodsId: "7625832097692813354", goodsType: 1, quantity: 1 },
],
},
};
plugin.applyRefund({
goodsList: res1.data.goodsList,
outOrderNo: res1.data.outOrderNo,
refundInfo: res1.data.refundInfo,
success: (res) => {
uni.showToast({
title: "退款申请已提交",
icon: "success",
});
this.$emit("refund", this.data);
},
fail: (err) => {
console.log("退款失败:", err);
// 处理session过期错误
if (err && err.errMsg && err.errMsg.includes("session已过期")) {
uni.showModal({
title: "提示",
content: "会话已过期,请重新登录后再试",
showCancel: false,
confirmText: "确定",
success: () => {
// 清除当前用户信息并跳转到登录页
this.$store.dispatch("user/deleteToken");
this.$store.dispatch("user/clearUserInfo");
uni.clearStorageSync();
uni.reLaunch({
url: "/pages/client/auth/index",
});
},
});
} else {
uni.showToast({
title: err?.errMsg || err?.msg || "退款失败,请重试",
icon: "none",
});
}
},
});
})
.catch((err) => {
uni.hideLoading();
console.error("获取退款信息失败:", err);
uni.showToast({
title: err?.msg || "获取退款信息失败",
icon: "none",
});
});
},
// 退款回调(组件触发)
handleRefund(event) {
const { status, result, outOrderNo } = event.detail;
console.log("退款回调:", { status, result, outOrderNo });
if (status === "success") {
uni.showToast({
title: "退款申请已提交",
icon: "success",
});
this.$emit("refund", this.data);
} else {
uni.showToast({
title: result?.errMsg || "退款失败,请稍后重试",
icon: "none",
});
}
},
// 错误处理
handleError(event) {
console.error("退款组件报错:", event.detail);
uni.showToast({
title: "组件加载失败,请稍后重试",
icon: "none",
});
},
startCountDown() {
this.stopCountDown();
if (this.countDownTime > 0) {
this.countDownTimer = setInterval(() => {
if (this.countDownTime > 0) {
this.countDownTime--;
} else {
this.stopCountDown();
// 倒计时结束,可以触发刷新
this.$emit("countdownEnd", this.data);
}
}, 1000);
}
},
stopCountDown() {
if (this.countDownTimer) {
clearInterval(this.countDownTimer);
this.countDownTimer = null;
}
},
formatCountdown(seconds) {
const hour = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds - hour * 3600) / 60);
return `${hour}小时${minutes}分钟`;
},
orderCancel() {
this.showCancelModal = false;
},
cancel() {
this.showCancelModal = false;
},
jumpToDetails() {
this.$emit("jumpToDetails", this.data);
},
jumpToReservation() {
uni.reLaunch({
url: "/pages/client/index/index?activePageId=reservationPage",
});
},
},
};
</script>
<style lang="scss" scoped>
.order-item {
width: calc(100vw - 40rpx);
background: #fff;
margin: 20rpx;
border-radius: 30rpx;
box-sizing: border-box;
padding: 20rpx;
margin-bottom: 0;
.order-title {
padding-bottom: 20rpx;
border-bottom: 1rpx solid #ececec;
.order-btn {
width: 104rpx;
height: 48rpx;
border-radius: 48rpx;
&.confirm {
background: #fef6ff;
}
&.cancel {
background: #f7f7f7;
color: #afa5ae;
}
}
.order-status-banner {
display: flex;
align-items: center;
border-radius: 48rpx;
overflow: hidden;
.status-banner-left {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background: #ff19a0;
padding: 8rpx;
flex-shrink: 0;
border-radius: 10px 0px 10px 10px;
.status-text {
font-size: 20rpx;
color: #ffffff;
}
}
.status-banner-right {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background: #fff0f8;
padding: 8rpx;
flex-shrink: 0;
.countdown-text {
font-size: 20rpx;
color: #ff19a0;
}
}
}
}
.order-btns {
padding-top: 20rpx;
display: flex;
justify-content: flex-end;
align-items: center;
.cancel-order-btn {
font-size: 24rpx;
color: #9b939a;
padding: 16rpx 0;
}
.order-btns-right {
display: flex;
align-items: center;
}
.status-btn {
width: 70px;
height: 34px;
// padding: 16rpx 20rpx;
border-radius: 64rpx;
border: 1px solid #ff19a0;
margin-left: 20rpx;
&.confirm {
color: $app_color_main;
border: 1px solid $app_color_main;
}
}
}
::v-deep {
.good-info-multi {
padding-top: 20rpx;
}
}
}
</style>