Files
wagoo-douy3/src/pages/client/order/components/OrderItem.vue
2026-03-30 10:14:58 +08:00

429 lines
11 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="$emit('concactService', data)">
联系客服
</view> -->
<!-- <view
class="flex-center fs-24 app-fc-main status-btn"
@click.stop="$emit('afterSale', data)"
>
申请售后
</view> -->
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('refund', data)">
退款
</view> -->
<refund-button
mode="2"
order-status="1"
:order-id="data.order_no"
:refund-total-amount="(data.actual_price || 0) * 100"
:compact="true"
@refund="handleRefund"
@error="handleError"
style="width:140rpx;height:68rpx;"
/>
<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 RefundButton from "@/components/RefundButton.vue";
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,
RefundButton
},
options: {
styleIsolation: "shared",
},
computed: {
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: {
handleRefund(e) {
console.log('退款结果:', e.detail)
if (e.detail.status === 'success') {
uni.showToast({ title: '退款申请已提交', icon: 'success' })
this.$emit('refund', this.data)
} else {
uni.showToast({ title: '退款失败', icon: 'none' })
}
},
handleError(e) {
console.error('组件错误:', e.detail)
},
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>