Files
cashier_desktop/src/views/order/index.vue
2025-12-29 17:35:12 +08:00

416 lines
13 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 class="container">
<div class="query_wrap">
<el-input v-model="queryForm.orderNo" placeholder="请输入订单编号" style="width: 240px"></el-input>
<!-- <el-input v-model="queryForm.productName" placeholder="请输入商品名称" style="width: 200px;"></el-input> -->
<el-select v-model="queryForm.status" placeholder="订单状态" style="width: 140px" @change="queryFormHandle">
<el-option label="全部" value=""></el-option>
<el-option :label="item.label" :value="item.type" v-for="item in globalStore.orderStatus"
:key="item.type"></el-option>
</el-select>
<DateRange ref="DateRangeRef" @success="dateSucess" />
<div class="flex">
<el-button type="primary" @click="queryFormHandle">查询</el-button>
<el-button @click="resetHandle">重置</el-button>
</div>
</div>
<div class="table_wrap">
<div class="table">
<el-table ref="tableRef" :data="tableData.list" v-loading="tableData.loading" border strip height="100%">
<el-table-column label="台桌" prop="tableName" align="center">
<template v-slot="scope">
<span v-if="scope.row.tableName">{{ scope.row.tableName }}</span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="商品信息" width="320">
<template v-slot="scope">
<div class="goods_wrap">
<div class="row" v-for="item in scope.row.goods.slice(0, 2)" :key="item.id">
<div class="cover">
<el-image :src="item.productImg" fit="cover" style="width: 40px;height: 40px;"></el-image>
</div>
<div class="info">
<div class="name">
<span>{{ item.productName }}</span>
<span class="amount">{{ formatDecimal(+item.payAmount) }}</span>
</div>
<div class="num">
<span>出菜时间{{ item.dishOutTime }}</span>
</div>
<div class="num">
<span>上菜时间{{ item.foodServeTime }}</span>
</div>
<div class="num">
备注: {{ item.remark || "无" }}
</div>
<div class="num">
<span>{{ formatDecimal(+item.unitPrice) }}</span>
<span>x{{ item.num }}</span>
</div>
<div class="num" v-if="item.returnNum">
<span>退菜数量{{ item.returnNum }}</span>
</div>
<div class="num" v-if="item.refundNum">
<span>退单数量{{ item.refundNum }}</span>
</div>
</div>
</div>
<div class="row" v-if="scope.row.goods.length > 2">
<el-button type="primary" @click="showMoreGoodsHandle(scope.row.goods)">
查看全部{{ scope.row.goods.length }}
</el-button>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="状态" width="150">
<template v-slot="scope">
{{ filterLable("orderStatus", scope.row.status) }}
<span v-if="scope.row.status == 'refund'" class="refund">
({{ filterLable("refundType", scope.row.refundType) }})
</span>
</template>
</el-table-column>
<el-table-column label="订单信息" width="340">
<template v-slot="scope">
<div class="column">
<div class="row">订单号{{ scope.row.orderNo }}</div>
<div class="row">下单时间{{ scope.row.createTime }}</div>
<div class="row">
订单类型{{ filterLable("orderType", scope.row.orderType) }}
</div>
<div class="row">
平台类型{{
filterLable("platformType", scope.row.platformType)
}}
</div>
<div class="row">
用餐模式{{ filterLable("dineMode", scope.row.dineMode) }}
</div>
<div class="row">订单备注{{ scope.row.remark }}</div>
<div class="row">打印状态
<span v-if="scope.row.printStatus.length > 0" style="color: var(--el-color-danger)">
打印失败{{scope.row.printStatus.map(item => item.name).join('、')}}
</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="支付信息" width="280">
<template v-slot="scope">
<div class="column">
<div class="row">
支付类型{{ filterLable("payType", scope.row.payType) }}
</div>
<!-- <div class="row">支付单号{{ scope.row.payOrderNo }}</div> -->
<div class="row">支付金额{{ scope.row.payAmount }}</div>
<div class="row">支付时间{{ scope.row.paidTime }}</div>
<div class="row">
订单金额含折扣{{ scope.row.orderAmount }}
</div>
<div class="row">
订单原金额含折扣{{ scope.row.originAmount }}
</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template v-slot="scope">
<div class="column">
<div class="row">
<el-button type="warning" :disabled="scope.row.status != 'unpaid'" :loading="scope.row.payLoading"
@click="orderDoneHandle(scope.row)">
<template v-if="scope.row.status == 'unpaid'">
结算订单
</template>
<template v-else>
订单完成
</template>
</el-button>
</div>
<div class="row">
<el-button type="primary" :disabled="refundState(scope.row)" @click="RefundDrawerRef.show(scope.row)">
<template v-if="scope.row.status == 'done'">
订单退款
</template>
<template
v-else-if="scope.row.status == 'part_refund' || (scope.row.status == 'refund' && scope.row.refundAmount < scope.row.payAmount)">
部分退单
</template>
<template v-else-if="scope.row.status == 'refund'">
已退订单
</template>
<template v-else>
不可退单
</template>
</el-button>
</div>
<div class="row">
<el-button type="success" @click="PrintDrawerRef.show(scope.row)">
订单打印
</el-button>
</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination">
<el-pagination background v-model:current-page="queryForm.page" v-model:page-size="queryForm.size"
:page-sizes="[10, 30, 50, 100]" layout="sizes, pager, jumper, total" :total="tableData.total"
@size-change="orderListAjax" @current-change="orderListAjax"></el-pagination>
</div>
</div>
</div>
<!-- 退款操作 -->
<RefundDrawer ref="RefundDrawerRef" @success="queryFormHandle" />
<!-- 打印操作 -->
<PrintDrawer ref="PrintDrawerRef" />
<!-- 结算订单 -->
<SettleAccount ref="SettleAccountRef" @success="orderListAjax" />
<!-- 全部商品 -->
<allGoodsDialog ref="allGoodsDialogRef" />
</template>
<script setup>
import { onMounted, ref, reactive } from "vue";
import { orderList } from "@/api/order.js";
import { useGlobal } from "@/store/global.js";
import { useGoods } from '@/store/goods.js'
import { formatDecimal } from '@/utils/index.js'
import DateRange from "./components/dateRange.vue";
import RefundDrawer from "./components/refundDrawer.vue";
import PrintDrawer from "./components/printDrawer.vue";
import SettleAccount from '@/views/home/components/settleAccount.vue'
import allGoodsDialog from './components/allGoodsDialog.vue'
const RefundDrawerRef = ref(null);
const PrintDrawerRef = ref(null);
const DateRangeRef = ref(null);
const SettleAccountRef = ref(null)
const tableRef = ref(null);
const allGoodsDialogRef = ref(null)
const goodsStore = useGoods()
const globalStore = useGlobal();
const queryForm = ref({
orderNo: "", // 订单编号
userId: "", // 用户Id
tableCode: "", // 台桌台桌编号
tableName: "", // 台桌名称
orderType: "", // 订单类型-cash收银-miniapp小程序-offline线下
platformType: "", // 平台类型
sendType: "", // 发货类型post快递takeaway外卖,takeself,自提table---堂食
payType: "", // 支付类型
status: "", // 状态: unpaid-待支付;in-production 制作中;wait-out 待取餐;;done-订单完成;refunding-申请退单;refund-退单;part-refund 部分退单;cancelled-取消订单
isDel: 0, // 是否回收站 0-否1回收站 默认查未删除,
productName: "", // 查询包含该商品的 所有订单
startTime: "",
endTime: "",
page: 1,
size: 10,
});
const resetQueryForm = ref("");
// 重置筛选条件
function resetHandle() {
queryForm.value = { ...resetQueryForm.value };
DateRangeRef.value.reset();
orderListAjax();
}
function queryFormHandle() {
queryForm.value.page = 1;
orderListAjax();
}
const tableData = reactive({
total: 0,
loading: false,
list: [],
});
// 筛选类型
function filterLable(key, type) {
let item = globalStore[key].find((item) => item.type == type);
if (item && item.type) {
return item.label;
} else {
return type;
}
}
// 过滤退款条件
function refundState(row) {
switch (row.status) {
case 'unpaid':
return true;
case 'in-production':
return false;
case 'wait-out':
return false;
case 'done':
return false;
case 'refunding':
return false;
case 'refund':
if (row.refundAmount < row.payAmount) {
return false
} else {
return true;
}
case 'part-refund':
return false;
case 'cancelled':
return true;
default:
break;
}
}
// 结算订单
async function orderDoneHandle(row) {
try {
row.payLoading = true
await goodsStore.historyOrderAjax('', row.id)
row.payLoading = false
goodsStore.calcCartInfo()
SettleAccountRef.value.show()
} catch (error) {
console.log(error);
}
}
// 获取订单列表
async function orderListAjax() {
try {
tableData.loading = true;
const res = await orderList(queryForm.value);
res.records.map(item => {
item.payLoading = false
item.printStatus = JSON.parse(item.printStatus || '[]')
})
tableData.list = [];
tableData.list = res.records;
tableData.total = +res.totalRow;
tableRef.value.setScrollTop(0);
tableRef.value.setScrollLeft(0);
console.log("订单列表:", res);
} catch (error) {
console.log(error);
}
tableData.loading = false;
}
// 时间筛选
function dateSucess(e) {
queryForm.value.startTime = e[0];
queryForm.value.endTime = e[1];
queryFormHandle();
}
// 精简订单商品名字
function goodsNameFilter(goods) {
return goods.map((item) => item.productName).join("、");
}
// 查看全部订单商品
function showMoreGoodsHandle(goods) {
allGoodsDialogRef.value.show(goods)
}
onMounted(() => {
resetQueryForm.value = { ...queryForm.value };
queryFormHandle();
});
</script>
<style scoped lang="scss">
.refund {
color: var(--el-color-danger);
}
.flex {
display: flex;
}
.container {
height: 100%;
background-color: #fff;
border-radius: var(--el-font-size-base);
padding: var(--el-font-size-base);
flex-direction: column;
}
.query_wrap {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.table_wrap {
flex: 1;
width: calc(100vw - 125px);
padding-top: var(--el-font-size-base);
.table {
height: calc(100vh - 175px);
}
}
.column {
display: flex;
flex-direction: column;
gap: 10px;
.row {
width: 100%;
font-size: 14px;
}
}
.pagination {
display: flex;
justify-content: flex-end;
padding-top: var(--el-font-size-base);
}
.goods_wrap {
.row {
display: flex;
padding: 10px 0;
&:not(:last-child) {
border-bottom: 1px solid #ececec;
}
.info {
padding-left: 10px;
.name {
width: 160px;
display: flex;
gap: 10px;
justify-content: space-between;
.amount {
color: var(--el-color-danger);
}
}
.num {
color: #999;
font-size: 14px;
display: flex;
gap: 10px;
}
}
}
}
</style>