654 lines
18 KiB
Vue
654 lines
18 KiB
Vue
<template>
|
||
<div v-loading="loading">
|
||
<el-drawer title="订单详情" size="60%" v-model="drawer" direction="rtl" @close="reset">
|
||
<div class="header">
|
||
<div class="title" style="text-align: center">【收银订单】</div>
|
||
<div class="container" v-if="user">
|
||
<div class="info_content">
|
||
<div class="item">
|
||
<div class="label">会员信息</div>
|
||
<div class="row">
|
||
<div>会员昵称:-{{ user.nickName || "" }}</div>
|
||
<div>联系电话:-{{ user.phone || "" }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div v-else>
|
||
<h3>服务员下单</h3>
|
||
</div>
|
||
<div class="table">
|
||
<div class="item">
|
||
<div class="t">订单状态</div>
|
||
<div class="b">
|
||
<el-tag :type="detail.status == 'closed' ? 'success' : 'warning'">
|
||
{{ statusFilter(detail.status) }}
|
||
</el-tag>
|
||
</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="t">订单金额</div>
|
||
<div class="b">¥{{ returnOriginAmount }}</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="t">订单类型</div>
|
||
<div class="b">
|
||
{{ sendTypeFilter(detail.sendType) }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="table">
|
||
<div class="item">
|
||
<div class="t">订单编号</div>
|
||
<div class="b">
|
||
{{ detail.orderNo }}
|
||
</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="t">下单时间</div>
|
||
<div class="b">{{ timeFilter(detail.createdAt) }}</div>
|
||
</div>
|
||
<div class="item">
|
||
<div class="t">支付时间</div>
|
||
<div class="b">
|
||
{{ timeFilter(detail.createdAt) }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="container">
|
||
<!-- <el-tabs v-model="type" @tab-click="getTableData"> -->
|
||
<!-- <el-tab-pane label="基本信息" name="1"> -->
|
||
<div class="info_content">
|
||
<!-- <div class="item">
|
||
<div class="label">会员信息</div>
|
||
<div class="row">
|
||
<div>会员昵称:-</div>
|
||
<div>联系电话:-</div>
|
||
</div>
|
||
</div> -->
|
||
<div class="item">
|
||
<div class="label">收款详情</div>
|
||
<!-- <div class="row">
|
||
<div>商品金额:¥{{ detail.productAmount }}</div>
|
||
<div>打包费:{{ detail.packFee || "-" }}</div>
|
||
</div> -->
|
||
<div class="row">
|
||
<div>打包费:{{ detail.packFee || "-" }}</div>
|
||
<div>订单原价:¥{{ detail.originAmount }}</div>
|
||
<div>优惠金额:¥{{ detail.discountAmount }}</div>
|
||
<div>积分抵扣:¥{{ detail.pointsDiscountAmount }}</div>
|
||
<div>
|
||
实收金额:
|
||
<span style="color: red">¥{{ detail.payAmount }}</span>
|
||
<el-button
|
||
v-if="detail.status != 'unpaid' && detail.refundAmount < detail.payAmount"
|
||
size="small"
|
||
type="danger"
|
||
class="u-m-l-10"
|
||
@click="tuikuan()"
|
||
>
|
||
<span>退款</span>
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<div class="row">
|
||
<div>
|
||
退款金额:¥{{ detail.refundAmount }}
|
||
<span
|
||
style="color: #ff9731; cursor: pointer"
|
||
v-if="detail.isRefund"
|
||
@click="type = '3'"
|
||
>
|
||
退款详情>
|
||
</span>
|
||
</div>
|
||
<div>支付方式:{{ returnPayType(detail.payType) }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="margin-bottom: 16px; font-size: 16px">商品信息</div>
|
||
<template v-for="(item, index) in detail.detailMap" :key="index">
|
||
<h4>第{{ index }}次下单</h4>
|
||
<el-table
|
||
:data="item"
|
||
:ref="'refTable' + index"
|
||
@select-all="tableSelectAll($event, index)"
|
||
>
|
||
<!-- <el-table-column type="selection" width="55" /> -->
|
||
<el-table-column label="数量" type="selection">
|
||
<template v-slot="scope">
|
||
<div v-if="detail.status == 'unpaid'">
|
||
<el-checkbox
|
||
v-if="scope.row.num - scope.row.returnNum > 0"
|
||
v-model="scope.row.checked"
|
||
/>
|
||
</div>
|
||
<div v-else>
|
||
<el-checkbox
|
||
v-if="scope.row.num - scope.row.refundNum > 0"
|
||
v-model="scope.row.checked"
|
||
/>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="商品">
|
||
<template v-slot="scope">
|
||
<div class="shop_info">
|
||
<el-image
|
||
:src="scope.row.productImg"
|
||
style="width: 40px; height: 40px"
|
||
></el-image>
|
||
<div class="info">
|
||
<span :class="[scope.row.isVip == 1 ? 'colorStyle' : '']">
|
||
{{ scope.row.productName }}
|
||
</span>
|
||
<span style="color: #999">{{ scope.row.productSkuName }}</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="下单数量">
|
||
<template v-slot="scope">x{{ scope.row.num }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="退菜数量">
|
||
<template v-slot="scope">x{{ scope.row.returnNum }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="单价">
|
||
<template v-slot="scope">¥{{ scope.row.unitPrice }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="小计">
|
||
<template v-slot="scope">¥{{ scope.row.payAmount }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="实付">
|
||
<template v-slot="scope">¥{{ scope.row.payAmount }}</template>
|
||
</el-table-column>
|
||
|
||
<el-table-column
|
||
v-if="detail.status == 'unpaid'"
|
||
label="可退菜数量"
|
||
align="center"
|
||
width="130px"
|
||
>
|
||
<template v-slot="scope">
|
||
<el-input-number
|
||
v-if="scope.row.checked"
|
||
:min="0"
|
||
style="width: 100px"
|
||
v-model="scope.row.selNumber"
|
||
:max="scope.row.num - scope.row.returnNum"
|
||
></el-input-number>
|
||
<span class="" v-else>{{ scope.row.num - scope.row.returnNum }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column v-else label="可退款数量" align="center" width="130px">
|
||
<template v-slot="scope">
|
||
<el-input-number
|
||
v-if="scope.row.checked"
|
||
:min="0"
|
||
style="width: 100px"
|
||
v-model="scope.row.selNumber"
|
||
:max="scope.row.num - scope.row.refundNum - scope.row.returnNum"
|
||
></el-input-number>
|
||
<span class="" v-else>
|
||
{{ scope.row.num - scope.row.refundNum - scope.row.returnNum }}
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="已退款数量" width="100" align="center">
|
||
<template v-slot="scope">
|
||
<span v-if="detail.status == 'unpaid'">{{ scope.row.returnNum }}</span>
|
||
<span v-else>{{ scope.row.refundNum }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作">
|
||
<template v-slot="scope">
|
||
<template v-if="detail.status != 'unpaid'">
|
||
<el-button
|
||
v-if="canTuikuan(scope.row)"
|
||
link
|
||
size="small"
|
||
@click="tuikuan(scope.row)"
|
||
>
|
||
<span>退款</span>
|
||
</el-button>
|
||
<span class="color-999" v-if="scope.row.status == 'refund'">已退款</span>
|
||
</template>
|
||
<template v-if="detail.status == 'unpaid'">
|
||
<el-button
|
||
v-if="canTuicai(scope.row)"
|
||
link
|
||
size="small"
|
||
@click="tuicai(scope.row)"
|
||
>
|
||
<span>退菜</span>
|
||
</el-button>
|
||
<span class="color-999" v-else>已退菜</span>
|
||
</template>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</template>
|
||
<!-- 退款 -->
|
||
<div
|
||
class="u-p-20 u-flex u-row-right"
|
||
v-if="detail.status !== 'refund' && detail.status !== 'unpaid'"
|
||
>
|
||
<el-checkbox
|
||
v-model="allSelected"
|
||
@change="allSelectedChange"
|
||
label="全选"
|
||
></el-checkbox>
|
||
<el-button type="danger" class="u-m-l-20" @click.stop="tuikuan('all')">退款</el-button>
|
||
</div>
|
||
<!-- 退菜 -->
|
||
<div class="u-p-20 u-flex u-row-right" v-if="detail.status == 'unpaid'">
|
||
<el-checkbox
|
||
v-model="allSelected"
|
||
@change="allSelectedChange"
|
||
label="全选"
|
||
></el-checkbox>
|
||
<el-button type="danger" class="u-m-l-20" @click.stop="tuicai('all')">退菜</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-drawer>
|
||
<!-- 退款 -->
|
||
<return-money
|
||
:modal="false"
|
||
ref="refReturnMoney"
|
||
:max="selGoods.num"
|
||
:goods="selGoods"
|
||
@confirm="refReturnMoneyConfirm"
|
||
></return-money>
|
||
<!-- 退菜 -->
|
||
<order-return-cart ref="refReturnCart" @confirm="refReturnCartConfirm"></order-return-cart>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import returnMoney from "./return-money.vue";
|
||
import orderReturnCart from "./order-return-cart.vue";
|
||
import { ElMessage } from "element-plus";
|
||
import { returnOptionsLabel } from "../config/config";
|
||
import * as $util from "../order_goods_util.js";
|
||
import orderApi from "@/api/order/order";
|
||
import shopUserApi from "@/api/account/shopUser";
|
||
import orderEnum from "./orderEnum";
|
||
import dayjs from "dayjs";
|
||
export default {
|
||
components: {
|
||
returnMoney,
|
||
orderReturnCart,
|
||
},
|
||
data() {
|
||
return {
|
||
allSelected: false,
|
||
user: "",
|
||
orderEnum,
|
||
drawer: false,
|
||
type: "1",
|
||
detail: "",
|
||
loading: false,
|
||
refoundList: [],
|
||
selGoods: { num: 1 },
|
||
};
|
||
},
|
||
|
||
watch: {
|
||
drawer: function (newval) {
|
||
if (!newval) {
|
||
this.close();
|
||
}
|
||
},
|
||
},
|
||
computed: {
|
||
vipDiscountAmount() {
|
||
return 0;
|
||
},
|
||
youHuiJinE() {
|
||
const n = 0;
|
||
|
||
return n;
|
||
},
|
||
//计算订单原金额
|
||
returnOriginAmount() {
|
||
let amount = 0;
|
||
if (this.detail && this.detail.originAmount) {
|
||
return this.detail.originAmount;
|
||
}
|
||
if (!this.detail) {
|
||
return 0;
|
||
}
|
||
for (let i in this.detail.detailMap) {
|
||
amount += this.detail.detailMap[i].reduce((pre, cur) => {
|
||
return pre + cur.payAmount;
|
||
}, 0);
|
||
}
|
||
|
||
return amount.toFixed(2);
|
||
},
|
||
},
|
||
methods: {
|
||
tableSelect(e) {
|
||
console.log(e);
|
||
},
|
||
tableSelectAll(e, index) {
|
||
const arr = this.detail.detailMap[index];
|
||
for (let i in arr) {
|
||
arr[i].checked = e.length ? true : false;
|
||
}
|
||
},
|
||
tableSelectionChange(e) {
|
||
console.log(e);
|
||
},
|
||
rowClick(row, index) {
|
||
this.$refs["refTable" + index][0].toggleRowSelection(row);
|
||
},
|
||
selectionChange(e) {
|
||
console.log(e);
|
||
},
|
||
allSelectedChange(newval) {
|
||
for (let i in this.detail.detailMap) {
|
||
for (let key in this.detail.detailMap[i]) {
|
||
this.detail.detailMap[i][key].checked = newval;
|
||
}
|
||
}
|
||
},
|
||
reset() {
|
||
this.user = "";
|
||
this.allSelected = false;
|
||
this.$emit("close");
|
||
},
|
||
returnPayType(payType) {
|
||
if (!payType) {
|
||
return "";
|
||
}
|
||
console.log(payType.replace("_pay", ""));
|
||
return returnOptionsLabel("payType", payType.replace("_pay", ""));
|
||
},
|
||
to2(n) {
|
||
return Number(n).toFixed(2);
|
||
},
|
||
orderTypeFilter(t) {
|
||
if (t) {
|
||
return t && orderEnum.orderType.find((item) => item.key == t).label;
|
||
} else {
|
||
return t;
|
||
}
|
||
},
|
||
sendTypeFilter(t) {
|
||
if (t) {
|
||
return orderEnum.sendType.find((item) => item.key == t).label;
|
||
} else {
|
||
return t;
|
||
}
|
||
},
|
||
statusFilter(t) {
|
||
return returnOptionsLabel("status", t);
|
||
},
|
||
timeFilter(t) {
|
||
if (t) {
|
||
return dayjs(t).format("YYYY-MM-DD HH:mm:ss");
|
||
} else {
|
||
return "-";
|
||
}
|
||
},
|
||
isShowGoodsVipPrice(item) {
|
||
return $util.isShowGoodsVipPrice(item);
|
||
},
|
||
isUseCalcPrice(item) {
|
||
return $util.isUseCalcPrice(this.detail, item);
|
||
},
|
||
close() {
|
||
console.log("drawer close");
|
||
this.$emit("close");
|
||
},
|
||
isTui(item) {
|
||
return $util.isTui(item);
|
||
},
|
||
canTuikuan(item) {
|
||
return $util.canTuiKuan(this.detail, item);
|
||
},
|
||
canTuicai(item) {
|
||
return $util.canTuicai(this.detail, item);
|
||
},
|
||
async refReturnMoneyConfirm(e) {
|
||
const res = await orderApi.refundOrder({
|
||
...e,
|
||
orderId: this.detail.id,
|
||
});
|
||
ElMessage.success("退款成功");
|
||
this.update();
|
||
},
|
||
update() {
|
||
this.tbOrderInfoDetail(this.detail.id);
|
||
},
|
||
async refReturnCartConfirm(e) {
|
||
const res = await orderApi.refundOrder({
|
||
...e,
|
||
orderId: this.detail.id,
|
||
});
|
||
ElMessage.success("退菜成功");
|
||
this.update();
|
||
},
|
||
tuikuan(item) {
|
||
if (!item) {
|
||
this.$refs.refReturnMoney.open([], this.detail);
|
||
return;
|
||
}
|
||
let arr = [];
|
||
if (item === "all") {
|
||
for (let i in this.detail.detailMap) {
|
||
this.detail.detailMap[i].map((v) => {
|
||
if (v.checked && v.selNumber) {
|
||
arr.push(v);
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
arr = [item];
|
||
}
|
||
if (arr.length == 0) {
|
||
return ElMessage.error("请选择要退款的商品和数量");
|
||
}
|
||
this.$refs.refReturnMoney.open(arr, this.detail);
|
||
},
|
||
tuicai(item) {
|
||
let arr = [];
|
||
if (item === "all") {
|
||
for (let i in this.detail.detailMap) {
|
||
this.detail.detailMap[i].map((v) => {
|
||
if (v.checked && v.selNumber) {
|
||
arr.push(v);
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
arr = [item];
|
||
}
|
||
if (arr.length == 0) {
|
||
return ElMessage.error("请选择要退菜的商品和数量");
|
||
}
|
||
console.log(arr);
|
||
this.$refs.refReturnCart.open(arr, this.detail);
|
||
},
|
||
|
||
// 获取订单详情
|
||
async tbOrderInfoDetail(id) {
|
||
try {
|
||
this.loading = true;
|
||
const res = await orderApi.get({ orderId: id });
|
||
if (res.userId) {
|
||
shopUserApi.get({ userId: res.userId }).then((res1) => {
|
||
this.user = res1;
|
||
});
|
||
}
|
||
for (let i in res.detailMap) {
|
||
res.detailMap[i] = res.detailMap[i].map((v) => {
|
||
console.log(v.num - (res.status == "unpaid" ? v.returnNum : v.refundNum));
|
||
return {
|
||
...v,
|
||
checked: false,
|
||
selNumber: v.num - (res.status == "unpaid" ? v.returnNum : v.refundNum),
|
||
};
|
||
});
|
||
}
|
||
this.detail = res;
|
||
this.loading = false;
|
||
} catch (error) {
|
||
console.log(error);
|
||
}
|
||
},
|
||
show(obj) {
|
||
this.drawer = true;
|
||
this.type = "1";
|
||
this.detail = "";
|
||
this.tbOrderInfoDetail(obj.id);
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.packeFee {
|
||
width: 40px;
|
||
box-sizing: border-box;
|
||
height: 40px;
|
||
background: #3f9eff;
|
||
color: #fff;
|
||
font-size: 12px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
white-space: nowrap;
|
||
}
|
||
.shop_info {
|
||
display: flex;
|
||
|
||
.info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding-left: 6px;
|
||
}
|
||
}
|
||
|
||
.header {
|
||
padding: 0 20px 0;
|
||
|
||
.title {
|
||
font-size: 20px;
|
||
color: #ff9731;
|
||
}
|
||
|
||
.table {
|
||
display: flex;
|
||
padding: 20px 0;
|
||
|
||
.item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
|
||
.b {
|
||
padding-top: 20px;
|
||
border: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.line-th {
|
||
text-decoration: line-through;
|
||
}
|
||
.container {
|
||
padding: 0 20px;
|
||
font-size: 14px;
|
||
|
||
.info_content {
|
||
padding: 20px 0;
|
||
|
||
.item {
|
||
border-bottom: 1px dashed #ececec;
|
||
padding-bottom: 20px;
|
||
|
||
&:not(:first-child) {
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.label {
|
||
position: relative;
|
||
padding-left: 20px;
|
||
color: #333;
|
||
|
||
&::after {
|
||
content: "";
|
||
width: 4px;
|
||
height: 100%;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
background-color: #1890ff;
|
||
}
|
||
}
|
||
|
||
.row {
|
||
display: flex;
|
||
color: #555;
|
||
padding-top: 20px;
|
||
|
||
div {
|
||
width: 25%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.refund_wrap {
|
||
.row {
|
||
border-bottom: 1px dashed #ececec;
|
||
padding-bottom: 20px;
|
||
|
||
&:not(:first-child) {
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.time {
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.list {
|
||
.list_row {
|
||
display: flex;
|
||
padding-top: 10px;
|
||
|
||
.item {
|
||
flex: 1;
|
||
display: flex;
|
||
color: #555;
|
||
|
||
.name {
|
||
margin-left: 6px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.foot {
|
||
color: #333;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.colorStyle {
|
||
color: #ffc315;
|
||
}
|
||
</style>
|