Files
cashier-web/src/views/order/index/components/detail.vue

622 lines
19 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>
<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.dineMode) }}
</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.createTime) }}</div>
</div>
<div class="item">
<div class="t">支付时间</div>
<div class="b">
{{ timeFilter(detail.paidTime) }}
</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.originAmount }}</div>
<div>打包费{{ detail.packFee || "-" }}</div>
<div>餐位费{{ detail.seatAmount || "-" }}</div>
<div>商品券抵扣{{ detail.productCouponDiscountAmount }}</div>
<div>优惠券抵扣{{ detail.fullCouponDiscountAmount }}</div>
</div>
<div class="row">
<div>满减活动{{ detail.discountActAmount || '-' }}</div>
<div>新客立减{{ detail.newCustomerDiscountAmount || '-' }}</div>
<div>会员折扣{{ detail.vipDiscountAmount || '-' }}</div>
</div>
<div class="row">
<div>退单金额{{ detail.refundAmount }}</div>
<div>整单改价{{ detail.discountAmount }}</div>
<div>积分抵扣{{ detail.pointsDiscountAmount }}</div>
<div>抹零{{ detail.roundAmount }}</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>支付方式{{ returnPayType(detail.payType) }}</div>
<div>
退款金额{{ detail.refundAmount }}
<!-- <span
style="color: #ff9731; cursor: pointer"
v-if="detail.isRefund"
@click="type = '3'"
>
退款详情>
</span> -->
</div>
<div class="color-red">退款方式{{ detail.refundType }}</div>
<div></div>
<div></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="商品" width="150">
<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>
<el-tag v-if="scope.row.isTimeDiscount" type="danger" disable-transitions>限时折扣</el-tag>
</div>
</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="备注" prop="remark"></el-table-column>
<el-table-column label="出菜时间" prop="dishOutTime" width="180"></el-table-column>
<el-table-column label="上菜时间" prop="foodServeTime" width="180"></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="操作" fixed="right">
<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' &&
detail.status !== 'cancelled'
">
<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>