merchapp/java-mall-app-shop-admin/pages/order/components/retrunOrderItem.vue
2025-11-07 11:56:03 +08:00

1149 lines
26 KiB
Vue

<template>
<view class="order_item">
<view class="expresser expresser-2">
<view class="header">
<text class="symbol">#</text>
<text>{{ currOrderItem.orderNum }}</text>
</view>
<view class="footer">
<view class="status">{{ currOrderItem.return_state_name }}</view>
</view>
</view>
<view class="user">
<view class="header">
<view class="info">
<view class="name">{{ currOrderItem.da_name }}/</view>
<view class="mobile">{{ currOrderItem.da_mobile }}</view>
</view>
<view class="box">
<view class="btn_call" @click="makePhone(currOrderItem.da_mobile)">
联系顾客
</view>
</view>
</view>
<view class="body">
<view class="info">
{{
currOrderItem.da_province +
currOrderItem.da_city +
currOrderItem.da_county +
currOrderItem.da_address
}}
</view>
<view class="box">
<!-- <view class="btn_map"></view> -->
</view>
</view>
<view class="footer">
<view class="info">
<text>退货理由:</text>
{{ currOrderItem.return_buyer_message }}
</view>
<view
class="info info_proof"
v-if="
currOrderItem.detailsInfo &&
currOrderItem.detailsInfo.items[0].return_item_image.length > 0
"
>
<text>退货凭据</text>
<view class="img_content">
<u--image
class="proof_img"
v-for="(imgItem, imgIndex) of currOrderItem.detailsInfo.items[0]
.return_item_image"
:key="imgIndex"
:showLoading="true"
:src="imgItem"
width="80px"
height="80px"
@click="
handlerShowImg(
currOrderItem.detailsInfo.items[0].return_item_image
)
"
>
{{ imgItem }}
</u--image>
</view>
</view>
</view>
</view>
<view class="goods">
<view class="single" v-if="!currOrderItem.showRefundOrderInfo">
<view class="body">
<view class="info">
<image
v-for="(item, index) of currOrderItem.items.slice(0, 3)"
:src="item.order_item_image"
mode="aspectFit"
class="img"
/>
<view class="total">共{{ currOrderItem.items.length }}件商品</view>
</view>
</view>
<view class="footer">
<view class="text">合计</view>
<view class="prize_type">¥</view>
<view class="prize_num">{{ sumBigInts }}</view>
</view>
</view>
<view class="list" v-if="currOrderItem.showRefundOrderInfo">
<view class="item" v-for="(group, index2) of currOrderItem.items">
<image :src="group.order_item_image" mode="aspectFit" class="img" />
<view class="box">
<view class="tit">{{ group.product_name }}</view>
<view class="desc">
<view class="total">数量X{{ group.return_item_num }}</view>
<view class="price">¥{{ group.item_unit_price }}</view>
</view>
</view>
</view>
</view>
</view>
<view
class="result"
style="border: none"
v-if="currOrderItem.showRefundOrderInfo"
>
<view class="cell">
<view class="header">商品总额</view>
<view class="body">
<text>¥</text>
<text class="total">{{ sumBigInts }}</text>
</view>
</view>
<view class="cell">
<view class="header">实际退款总额</view>
<view class="body">
¥
<text class="count">{{ currOrderItem.return_refund_amount }}</text>
</view>
</view>
</view>
<view class="result" v-if="currOrderItem.showRefundOrderInfo">
<view class="cell">
<view class="header">订单编号</view>
<view class="body">
<view class="order_num">{{ currOrderItem.order_id }}</view>
<view class="btn_copy" @click="copy(currOrderItem.order_id, 'order')">
复制
</view>
</view>
</view>
<view class="cell">
<view class="header">申请时间</view>
<view class="body">{{ currOrderItem.return_add_time }}</view>
</view>
<view class="cell" v-if="currOrderItem.da_time">
<view class="header">下单时间</view>
<view class="body">{{ currOrderItem.da_time }}</view>
</view>
<view class="cell">
<view class="header">配送方式</view>
<view class="body">
{{ deliveryTypeName(currOrderItem.delivery_type_id) }}
</view>
</view>
<view class="cell">
<view class="header">退货单号</view>
<view class="body">
<view class="order_num">
{{ currOrderItem.return_id }}
</view>
<view
class="btn_copy"
@click="copy(currOrderItem.return_id, 'retrunId')"
>
复制
</view>
</view>
</view>
</view>
<view class="tool">
<view class="header" @click="handerShowRefundOrderInfo">
<template>
{{ currOrderItem.showRefundOrderInfo ? "收起" : "更多订单信息" }}
<u-icon
style="display: inline-block; margin-left: 6rpx"
:name="
currOrderItem.showRefundOrderInfo ? 'arrow-up' : 'arrow-down'
"
size="8"
color="#cccccc"
></u-icon>
</template>
</view>
<view class="body" v-if="currOrderItem.return_state_id == 3105">
<view
class="btn btn_cancel"
@click="handelOpenReturnOrderPopup('noPass')"
>
拒绝退款
</view>
<view
class="btn btn_refund"
@click="handelOpenReturnOrderPopup('pass')"
>
同意退款
</view>
</view>
</view>
<u-popup
class="return-order-popup"
:show="showReturnOrderPopup"
mode="center"
round="12"
@close="showReturnOrderPopup = false"
>
<view class="return-order-popup-content">
<view class="title">
{{ returnOrderType == "pass" ? "同意退款" : "拒绝退款" }}
</view>
<view class="radio-content" v-if="returnOrderType == 'pass'">
<view class="radio-type-name">退货类型:</view>
<view class="radio-list">
<tui-radio-group class="radio-group" @change="handelRaddio">
<view v-for="(item, index) in radioItems" :key="index">
<tui-radio
:checked="item.checked"
:value="item.value"
color="#07c160"
borderColor="#999"
></tui-radio>
<text class="radio-name">{{ item.name }}</text>
</view>
</tui-radio-group>
</view>
</view>
<view class="popup-textarea">
<u--textarea
class="textarea"
v-model="retrunOrderMsg"
placeholder="请输入原因"
:border="'surround'"
count
:maxlength="40"
:height="100"
></u--textarea>
</view>
<view class="popup-btn-list">
<u-button
class="btn-item"
:hairline="true"
:plain="true"
shape="circle"
@click="showReturnOrderPopup = false"
>
取消
</u-button>
<u-button
v-if="dashboardInfo.store_info.store_biz_state == 1"
class="btn-item btn-item-2"
:hairline="true"
:plain="true"
shape="circle"
@click="handerRetrunOrder()"
>
确认
</u-button>
</view>
</view>
</u-popup>
<tui-gallery
:urls="showImgList"
:show="showImg"
@hide="hideImg"
></tui-gallery>
<u-toast ref="uToast"></u-toast>
</view>
</template>
<script>
import {
GetExpediteSFOrder,
GetInitiativeOrderRefund,
GetSalesReturnOrderDetails,
GetOrderPicking,
GetSalesReturnOrderNoPass,
GetSalesReturnOrderPass,
} from "@/api/order";
import tuiRadio from "@/components/tui-radio/tui-radio.vue";
import tuiRadioGroup from "@/components/tui-radio-group/tui-radio-group.vue";
import {
makePhoneCall,
} from "@/utils/callPhone";
export default {
props: {
orderItem: {
type: Object,
default: () => {},
},
isErrorOrder: {
type: Boolean,
default: false,
},
orderItemIndex: {
type: Number,
default: 0,
},
dashboardInfo: {
type: Object,
default: () => {},
},
salesReturnBtnSearchAcitve: {
type: Number,
default: 3105,
},
},
components: {
tuiRadio,
tuiRadioGroup,
},
data() {
return {
sfStatus: [
{
id: 1,
label: "已接单",
},
{
id: 2,
label: "订单取消",
},
{
id: 10,
label: "配送员接单",
},
{
id: 12,
label: "配送员到店",
},
{
id: 15,
label: "配送中",
},
{
id: 17,
label: "配送员妥投完单",
},
{
id: 22,
label: "配送员撤单",
},
{
id: 91,
label: "骑士上报异常",
},
{
id: 31,
label: "取消中",
},
],
deliveryType: [
{
id: 5,
label: "自提",
},
{
id: 10,
label: "普通快递",
},
{
id: 16,
label: "同城配送",
},
],
commodityCheckBoxList: [],
refreshInterval: null, // 全局定时器
showOrderPickingPopup: false,
currOrderItem: {
items: [],
},
isRefreshing: false,
showImgList: [],
showImg: false,
returnOrderType: "",
radioOrderType: "",
radioItems: [
{
name: "不用退货",
value: "0",
checked: true,
},
{
name: "需要退货",
value: "1",
checked: false,
},
],
retrunOrderMsg: "",
showReturnOrderPopup: false,
};
},
computed: {
sumBigInts() {
// 高精度累加
const sum =
this.currOrderItem.items.reduce((acc, item) => {
// 将数值转换为字符串以避免浮点数精度问题
const current =
typeof item.return_item_subtotal === "string"
? parseFloat(item.return_item_subtotal)
: item.return_item_subtotal;
// 使用乘以100再除以100的方法来避免浮点数精度问题
return acc + Math.round(current * 100);
}, 0) / 100;
return sum;
},
},
created() {
this.currOrderItem = JSON.parse(JSON.stringify(this.orderItem));
},
methods: {
sfFormatStatus(id) {
let label = "";
this.sfStatus.forEach((item) => {
if (item.id == id) {
label = item.label;
}
});
return label;
},
deliveryTypeName(id) {
let label = "";
this.deliveryType.forEach((item) => {
if (item.id == id) {
label = item.label;
}
});
return label;
},
async handerExpedite() {
let params = {
order_id: this.item.order_id,
};
let res = await GetExpediteSFOrder(params);
if (res && res.status == 200) {
uni.$u.toast("催单成功");
}
},
handerShowRefundOrderInfo() {
if (!this.currOrderItem.showRefundOrderInfo) {
this.getSalesReturnOrderDetails();
}
this.currOrderItem.showRefundOrderInfo =
!this.currOrderItem.showRefundOrderInfo;
},
async getSalesReturnOrderDetails() {
let params = {
return_id: this.currOrderItem.return_id,
};
let res = await GetSalesReturnOrderDetails(params);
if (res && res.status == 200) {
this.currOrderItem = {
...this.currOrderItem,
detailsInfo: res.data,
};
console.log("currOrderItem", this.currOrderItem);
}
},
handelOpenReturnOrderPopup(type) {
this.showReturnOrderPopup = true;
this.returnOrderType = type;
},
makePhone(phone) {
makePhoneCall(phone)
// // #ifdef H5
// uni.showToast({
// title: "H5环境不支持",
// icon: "none",
// });
// // #endif
// // #ifdef APP-PLUS
// uni.makePhoneCall({
// phoneNumber: phone,
// success: function () {
// console.log("拨打电话成功");
// },
// fail: function () {
// console.log("拨打电话失败");
// },
// });
// // #endif
},
copy(num, type) {
uni.setClipboardData({
data: num,
success: function () {
uni.showToast({
title: `${type == "order" ? "订单编号" : "退货单号"}复制成功`,
icon: "none",
});
},
});
},
handelRaddio(e) {
this.radioOrderType = e.detail.value;
},
handerShowCancelOrder() {
this.showCancelOrderPopup = true;
this.isCancelOrder = true;
},
handerShowPartOrderRefund() {
let _item = JSON.parse(JSON.stringify(this.currOrderItem));
_item.order_items.forEach((group) => {
group.order_item_quantity_2 = group.order_item_quantity;
});
this.currOrderItem = _item;
this.showPartOrderRefundPopup = true;
this.isCancelOrder = false;
},
handlerShowImg(imgList) {
this.showImg = true;
const _imgList = imgList.map((item) => {
return {
src: item,
desc: "",
};
});
this.showImgList = _imgList;
console.log(this.showImgList);
},
hideImg() {
this.showImg = false;
},
async handerRetrunOrder() {
if (this.returnOrderType == "noPass") {
let params = {
return_id: this.currOrderItem.return_id,
return_store_message: this.retrunOrderMsg,
};
let res = await GetSalesReturnOrderNoPass(params);
if (res && res.status == 200) {
this.showReturnOrderPopup = false;
this.$refs.uToast.show({
message: "拒绝退款成功",
type: "success",
duration: 1000,
zIndex: 12000,
});
this.$emit("handerRefreshSalesReturnOrderList");
}
} else {
let params = {
return_flag: this.radioOrderType,
return_id: this.currOrderItem.return_id,
return_store_message: this.retrunOrderMsg,
};
if (this.radioOrderType == 1) {
params.receiving_address = 2;
}
let res = await GetSalesReturnOrderPass(params);
if (res && res.status == 200) {
this.showReturnOrderPopup = false;
this.$refs.uToast.show({
message: "同意退款成功",
type: "success",
duration: 1000,
zIndex: 12000,
});
this.$emit("handerRefreshSalesReturnOrderList");
}
}
this.showReturnOrderPopup = false;
},
},
};
</script>
<style lang="scss" scoped>
@import "@/styles/variables.scss";
.order_item {
padding: 24rpx;
margin-bottom: 24rpx;
border-radius: 12rpx;
background: #fff;
font-size: 24rpx;
color: #222;
.expresser {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.header {
text {
font-size: 48rpx;
}
}
.body {
flex: 1;
padding-left: 24rpx;
position: relative;
// &::after {
// position: absolute;
// right: 0;
// top: 0;
// height: 100%;
// display: block;
// content: " ";
// width: 1px;
// background-image: linear-gradient(to bottom, #000 80%, transparent 20%);
// background-size: 100% 16rpx;
// opacity: 0.2;
// }
.item {
display: flex;
align-items: center;
&.info {
margin-bottom: 8rpx;
}
.time {
color: rgba(34, 34, 34, 0.9);
}
.name {
font-weight: bold;
display: flex;
align-items: center;
&::before {
display: block;
content: " ";
width: 36rpx;
height: 36rpx;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6rpx;
margin-right: 12rpx;
background: url("@/static/icon_mt.png") no-repeat 50% 50%;
background-size: 28rpx 28rpx;
}
}
.btn_call {
display: flex;
align-items: center;
margin-left: 24rpx;
&::before {
display: block;
content: " ";
width: 32rpx;
height: 32rpx;
background: url("@/static/icon_phone.png") no-repeat;
background-size: 100%;
}
}
}
}
.footer {
width: 228rpx;
position: relative;
&::after {
position: absolute;
left: 0;
top: 0;
height: 100%;
display: block;
content: " ";
width: 1px;
background-image: linear-gradient(to bottom, #000 80%, transparent 20%);
background-size: 100% 16rpx;
opacity: 0.2;
}
.status {
text-align: center;
font-size: 28rpx;
font-weight: bold;
color: red;
}
}
}
.expresser-2 {
.header {
display: flex;
align-items: center;
.symbol {
margin-right: 4rpx;
font-size: 24rpx;
}
}
}
.user {
margin-bottom: 24rpx;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
.info {
display: flex;
align-items: center;
.name {
font-size: 28rpx;
font-weight: bold;
}
}
.btn_call {
display: flex;
align-items: center;
&::before {
display: block;
content: " ";
width: 32rpx;
height: 32rpx;
background: url("@/static/icon_phone.png") no-repeat;
background-size: 100%;
}
}
}
.body {
display: flex;
justify-content: space-between;
align-items: center;
.btn_map {
width: 36rpx;
height: 36rpx;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 6rpx;
background: url("@/static/icon_map.png") no-repeat 50% 50%;
background-size: 28rpx 28rpx;
}
.box {
padding-left: 40rpx;
}
.info {
text-align: left;
color: rgba(34, 34, 34, 0.75);
}
}
.footer {
.info {
margin: 16rpx 0 24rpx;
background: rgba(254, 247, 234, 0.5);
padding: 12rpx 24rpx;
border-radius: 8rpx;
text {
color: #ff801f;
display: inline-block;
margin-right: 12rpx;
}
}
.info_proof {
.img_content {
display: flex;
flex-wrap: wrap;
justify-content: left;
.proof_img {
margin: 20rpx;
}
}
}
&::after {
display: block;
content: " ";
height: 1px;
background-image: linear-gradient(to right, #000 50%, transparent 20%);
background-size: 16rpx 100%;
opacity: 0.2;
}
}
}
.goods {
margin-bottom: 24rpx;
.single {
display: flex;
justify-content: space-between;
align-items: center;
.body {
display: flex;
align-items: center;
.info {
display: flex;
align-items: center;
}
.img {
width: 96rpx;
height: 96rpx;
margin-right: 12rpx;
border-radius: 10rpx;
background: #666;
}
}
.footer {
display: flex;
align-items: baseline;
line-height: 36rpx;
.text {
color: #666;
}
.prize_type {
margin-left: 14rpx;
}
.prize_num {
font-size: 28rpx;
}
}
}
.list {
margin-bottom: 24rpx;
.item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.img {
width: 96rpx;
height: 96rpx;
border-radius: 10rpx;
background: #666;
}
.box {
flex: 1;
padding: 0 24rpx;
.desc {
display: flex;
color: #666;
padding-top: 8rpx;
.total {
margin-right: 24rpx;
}
}
}
.counter {
display: flex;
justify-content: flex-end;
align-items: baseline;
min-width: 156rpx;
.prize_type {
font-weight: bold;
padding-left: 12rpx;
}
.prize_num {
font-size: 28rpx;
font-weight: bold;
}
}
}
}
}
.result {
border-top: 1px solid rgba(0, 0, 0, 0.1);
padding-top: 24rpx;
.cell {
color: #666666;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.body {
display: flex;
align-items: center;
}
.red {
color: #fe411b;
}
text {
color: #222;
}
.total {
font-size: 28rpx;
font-weight: bold;
}
.count {
font-size: 36rpx;
font-weight: bold;
}
.order_num {
display: flex;
align-items: center;
&::after {
display: block;
content: " ";
width: 1px;
height: 24rpx;
margin: 0 12rpx;
background: #ccc;
}
}
}
}
.tool {
display: flex;
justify-content: space-between;
align-items: center;
.header {
color: #666;
display: flex;
align-items: center;
.icon {
margin-left: 8rpx;
}
}
.body {
display: flex;
justify-content: space-between;
align-items: center;
.btn {
width: 132rpx;
height: 48rpx;
line-height: 48rpx;
text-align: center;
border: 1px solid #666;
border-radius: 8rpx;
margin-left: 24rpx;
}
.btn_refund {
border-color: $base-color;
color: $base-color;
}
}
}
.part-order-refund-popup {
::v-deep.u-popup__content {
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
}
::v-deep.u-fade-enter-to {
z-index: 10079 !important;
}
.part-order-refund-popup-content {
.part-order-refund-popup-title {
font-size: 32rpx;
padding: 40rpx;
text-align: center;
font-weight: bold;
}
.affirm-popup-form {
padding: 20rpx 60rpx;
}
.radio-list {
.commodity-info-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 28rpx;
.commodity-info-box {
display: flex;
align-items: center;
justify-content: space-between;
.commodity-info-img {
margin-right: 20rpx;
width: 120rpx;
height: 120rpx;
}
}
}
}
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 64rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
.affirm-popup {
::v-deep.u-popup__content {
border-radius: 16rpx;
}
::v-deep.u-fade-enter-to {
z-index: 10076 !important;
}
.affirm-popup-content {
width: 600rpx;
.affirm-popup-title {
padding: 60rpx 0 20rpx;
text-align: center;
font-size: 28rpx;
font-weight: bold;
}
.affirm-popup-tips {
padding: 0 32rpx;
font-size: 28rpx;
text-align: center;
}
.u-form {
padding: 0 60rpx;
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 64rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
}
::v-deep.u-toast {
.u-transition {
z-index: 12000;
}
}
.return-order-popup {
.return-order-popup-content {
width: 600rpx;
min-height: 600rpx;
.title {
margin: 36rpx;
text-align: center;
font-weight: bold;
font-size: 36rpx;
}
.radio-content {
display: flex;
justify-content: space-between;
align-items: center;
margin: 60rpx 40rpx 40rpx;
.radio-type-name {
font-weight: 500;
}
.radio-list {
flex: 1;
.radio-group {
display: flex;
align-items: center;
justify-content: space-around;
line-height: 40rpx;
.radio-name {
margin-left: 8rpx;
}
}
}
}
.popup-textarea {
margin: 28rpx;
.textarea {
border: 1px solid #eeeff3;
}
}
.popup-btn-list {
display: flex;
margin: 50rpx;
.btn-item {
width: 46%;
height: 80rpx;
border-color: #909193;
&::after {
border: none;
}
}
.btn-item-2 {
background: $base-color;
color: #fff;
border: none;
}
}
}
}
}
</style>