fix: 代客下单增加转台功能,修复临时菜价格展示问题,增加就餐类型切换为打包时,加菜默认为打包

This commit is contained in:
YeMingfei666 2025-03-13 18:31:36 +08:00
parent dc5dc45893
commit a3f8c8c012
11 changed files with 268 additions and 52 deletions

View File

@ -40,12 +40,36 @@ const OrderApi = {
data
});
},
edit() { },
delete() { },
//转桌
mergeOrder(data: mergeOrderRequest) {
return request<any>({
url: `${baseURL}/mergeOrder`,
method: "post",
data
});
},
};
export default OrderApi;
/**
* MergeOrderDTO
*/
export interface mergeOrderRequest {
/**
* Id
*/
detailIds?: number[];
sourceOrderId: number;
/**
* Id
*/
targetOrderId?: number;
/**
*
*/
targetTableCode?: string;
[property: string]: any;
}
export interface refundOrderRequest {
/**

View File

@ -16,6 +16,11 @@ export const useCartsStore = defineStore("carts", () => {
vipUser.value = user;
}
//就餐类型 dine-in take-out
let dinnerType = ref<string>('dine-in');
//是否启用会员价
const useVipPrice = computed(() => {
return (shopUser.userInfo.isMemberPrice && vipUser.value.id && vipUser.value.isVip) ? true : false
@ -174,9 +179,7 @@ export const useCartsStore = defineStore("carts", () => {
const oldOrderMoney = computed(() => {
let total = 0
for (let i in oldOrder.value.detailMap) {
console.log(oldOrder.value)
total += oldOrder.value.detailMap[i].reduce((prve: number, cur: any) => {
console.log(cur)
if (cur.isGift) {
return prve + 0
}
@ -236,7 +239,11 @@ export const useCartsStore = defineStore("carts", () => {
return;
}
const newNumber = item.number * 1 + step * 1;
update({ ...item, number: item.number * 1 + step * 1, pack_number: newNumber < item.pack_number ? (item.pack_number * 1 + step * 1) : item.pack_number });
let pack_number = newNumber < item.pack_number ? (item.pack_number * 1 + step * 1) : item.pack_number;
if (dinnerType.value == 'take-out') {
pack_number = newNumber
}
update({ ...item, number: newNumber, pack_number });
}
function changeSelCart(cart: CartsState) {
@ -270,6 +277,7 @@ export const useCartsStore = defineStore("carts", () => {
}
}
const basic_msg = {
number: 1,
is_gift: 0,
@ -325,10 +333,12 @@ export const useCartsStore = defineStore("carts", () => {
function update(data: any) {
console.log(data);
if (data.number * 1 < data.skuData.suitNum * 1) {
const suitNum = data.skuData ? (data.skuData.suitNum || 1) : 1;
if (data.number * 1 < suitNum * 1) {
return sendMessage('del', data);
}
sendMessage('edit', data);
const pack_number = dinnerType.value == 'take-out' ? data.number : data.pack_number
sendMessage('edit', { ...data, pack_number });
}
function updateTag(key: string, val: any, cart: CartsState = selCart.value) {
if (cart.number * 1 < cart.skuData.suitNum * 1) {
@ -338,7 +348,16 @@ export const useCartsStore = defineStore("carts", () => {
if (key == 'discount_sale_amount' && val * 1 <= 0) {
return ElMessage.error('价格不能为0')
}
sendMessage('edit', { ...cart, [key]: val });
const msg = { ...cart, [key]: val }
if (key == 'number' && dinnerType.value == 'take-out') {
msg.pack_number == val
}
sendMessage('edit', msg);
}
// 更改全部商品打包状态
function changePack(is_pack: number | string) {
sendMessage('batch', { is_pack });
}
function clear() {
@ -358,6 +377,14 @@ export const useCartsStore = defineStore("carts", () => {
vipUser.value = {}
}
function nowCartsClear() {
if (selPlaceNum.value == 1) {
selListIndex.value = -1;
}
list.value = [];
giftList.value = [];
}
// 寻找套餐商品sku
interface GroupSnap {
goods: { [key: string]: any }[];
@ -439,6 +466,9 @@ export const useCartsStore = defineStore("carts", () => {
}
}
let $initParams = {} as ApifoxModel
/**
*
* @param initParams
@ -446,6 +476,8 @@ export const useCartsStore = defineStore("carts", () => {
* @param oldOrder
*/
function init(initParams: ApifoxModel, $goodsMap: any, $oldOrder: any) {
// 商品id对应的数据map
if ($goodsMap) {
@ -461,16 +493,22 @@ export const useCartsStore = defineStore("carts", () => {
if (initParams) {
initParams.table_code = initParams.table_code ? initParams.table_code : ''
table_code.value = initParams.table_code
$initParams = initParams;
}
console.log($initParams)
// localStorage.setItem('cache_table_code', table_code.value);
concocatSocket($initParams)
}
function concocatSocket(initParams = $initParams) {
console.log("初始化参数", initParams);
WebSocketManager.subscribeToTopic(initParams, (msg) => {
console.log("收到消息:", msg);
if (msg.hasOwnProperty('status') && msg.status != 1) {
return ElMessage.error(msg.message || '操作失败')
}
if (msg && msg.data) {
if (Array.isArray(msg.data) && msg.data.length) {
if (Array.isArray(msg.data) && msg.data.length && msg.data[0].table_code) {
table_code.value = msg.data[0].table_code
}
if (msg.data.table_code) {
@ -528,7 +566,9 @@ export const useCartsStore = defineStore("carts", () => {
return ElMessage.warning(msg.message || '该商品已存在')
}
const skuData = getProductDetails({ product_id: msg.data.product_id, sku_id: msg.data.sku_id })
list.value.push({ ...skuData, ...msg.data })
const newGoods = { ...skuData, ...msg.data }
console.log('newGoods', newGoods)
list.value.push(newGoods)
return ElMessage.success(msg.message || '添加成功')
}
@ -588,9 +628,11 @@ export const useCartsStore = defineStore("carts", () => {
}
}
if (msg.operate_type === "manage_cleanup") {
dataReset()
nowCartsClear()
}
if (msg.operate_type === "batch") {
concocatSocket({ ...$initParams, table_code: table_code.value })
}
console.log(list.value)
});
}
@ -606,6 +648,8 @@ export const useCartsStore = defineStore("carts", () => {
WebSocketManager.sendMessage(msg);
}
return {
dinnerType,
changePack,
giftMoney,
goodsTotal,
isLinkFinshed,

View File

@ -34,7 +34,6 @@ export const usePermissionStore = defineStore("permission", () => {
if (!isTest) {
const dynamicRoutes = parseDynamicRoutes(data.filter(v => v.type == 0));
routes.value = [...constantRoutes, ...dynamicRoutes];
console.log(routes.value)
isRoutesLoaded.value = true;
resolve(dynamicRoutes);
} else {

View File

@ -1,6 +1,6 @@
import qs from "qs";
import { useUserStoreHook } from "@/store";
import { ElMessage, ElMessageBox } from "element-plus";
const user = useUserStoreHook()
export interface ApifoxModel {
@ -20,7 +20,7 @@ export interface ApifoxModel {
type: string;
[property: string]: any;
}
export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable'
export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable' | 'batch'
class WebSocketManager {
private client: WebSocket | null = null;
private connected: boolean = false;
@ -80,6 +80,7 @@ class WebSocketManager {
};
this.client.onerror = (error) => {
clearTimeout(this.timer)
this.connected = false;
console.error("WebSocket 发生错误:", error);
// ElNotification({
// title: "提示",
@ -112,7 +113,7 @@ class WebSocketManager {
// 订阅主题
public subscribeToTopic(initParams: ApifoxModel, onMessage: (message: any) => void) {
console.log(`正在订阅主题: `);
console.log(`正在订阅主题: `, initParams);
this.initParams = { ...this.initParams, ...initParams }
if (this.client && this.connected) {
this.disconnect();
@ -121,7 +122,13 @@ class WebSocketManager {
this.onMessage = onMessage;
}
public sendMessage(message: any) {
if (this.client) {
if (!this.client || !this.connected) {
ElMessage.error('发送失败,已重新连接,请重新操作')
this.disconnect()
this.setupWebSocket();
return
}
if (this.client && this.connected) {
const msg = JSON.stringify({
...this.initParams,
...message,
@ -130,6 +137,7 @@ class WebSocketManager {
this.client.send(msg);
} catch (error) {
console.log('error')
ElMessage.error('发送失败')
this.disconnect()
this.setupWebSocket();
@ -146,6 +154,7 @@ class WebSocketManager {
console.log("断开 WebSocket 连接");
this.client.close();
this.client = null;
this.connected = false;
}
}
}

View File

@ -91,7 +91,11 @@
</template>
<!-- 单品改价 -->
<template
v-else-if="item.discount_sale_amount * 1 > 0 && discount_before_price != allPrice"
v-else-if="
item.discount_sale_amount * 1 > 0 &&
discount_before_price != allPrice &&
!item.is_temporary
"
>
<div>{{ to2(allPrice) }}</div>
<div class="free-price">

View File

@ -251,9 +251,6 @@ function init() {
for (let goods of props.goodsList) {
goodsMap[goods.id] = goods;
}
console.log("cartsinit");
console.log(props.oldOrder);
carts.init({ table_code: props.table.tableCode }, goodsMap, props.oldOrder);
}

View File

@ -32,8 +32,9 @@ const controls = ref([
{ label: "赠送", key: "is_gift", disabled: false, per: "gift" },
{ label: "打包", key: "is_pack", disabled: false, per: "pack" },
{ label: "删除", key: "del", disabled: false, per: "del" },
{ label: "存单", key: "", disabled: false, per: "save" },
{ label: "取单", key: "", disabled: false },
{ label: "转桌", key: "rottable", disabled: false, per: "rottable" },
// { label: "", key: "", disabled: false, per: "save" },
// { label: "", key: "", disabled: false },
{ label: "单品备注", key: "one-note", disabled: false, per: "one-note" },
{ label: "整单备注", key: "all-note", disabled: false, per: "all-note" },
{ label: "退菜", key: "return", disabled: false, per: "return" },
@ -43,7 +44,7 @@ const controls = ref([
// { label: "", key: "", disabled: false, per: "all-wating" },
]);
const emits = defineEmits(["noteClick", "changePriceClick", "packClick", "return"]);
const emits = defineEmits(["noteClick", "changePriceClick", "packClick", "return", "rottable"]);
function controlsClick(item) {
switch (item.key) {
case "is_gift":
@ -68,6 +69,9 @@ function controlsClick(item) {
case "one-note":
emits("noteClick", true);
break;
case "rottable":
emits("rottable", carts.selCart);
break;
case "all-note":
emits("noteClick", false);
break;
@ -82,18 +86,26 @@ function controlsClick(item) {
}
}
const perList = computed(() => {
// if (!carts.oldOrder.id) {
// return ["all-wating", "all-note", "rottable"];
// }
let arr = [];
if (!carts.selCart.id) {
return ["all-wating", "all-note"];
arr = ["all-wating", "all-note"];
}
if (carts.isCanSelectGroup) {
return ["all-wating", "all-note", "del", "pack", "gift", "print", "one-note"];
arr = ["all-wating", "all-note", "del", "pack", "gift", "print", "one-note"];
}
if (carts.selCart.id) {
if (carts.isOldOrder) {
return ["return"];
arr = ["return"];
}
return ["cart", "del", "pack", "gift", "save", "one-note", "print", "all-note", "all-wating"];
arr = ["cart", "del", "pack", "gift", "save", "one-note", "print", "all-note", "all-wating"];
}
if (carts.oldOrder.id) {
arr.push("rottable");
}
return arr;
});
const canEdit = computed(() => {
return !perList.value.includes("cart");

View File

@ -79,9 +79,9 @@ export default {
if (this.number > this.max) {
ElMessage.error("最多只能选择" + this.max + "位就餐人数");
}
if (!this.number) {
ElMessage.error("请选择就餐人数");
}
// if (!this.number) {
// ElMessage.error("");
// }
console.log(this.number);
this.$emit("confirm", this.number);
this.close();

View File

@ -0,0 +1,112 @@
<template>
<el-dialog title="转桌" width="700px" v-model="show" @close="reset">
<el-form :rules="rules" ref="refForm" :model="form">
<el-form-item label="转桌到" prop="targetTableCode">
<el-select v-model="form.targetTableCode" placeholder="请选择转桌到" style="width: 200px">
<el-option
v-for="item in tableList"
:key="item.id"
:label="item.name"
:value="item.tableCode"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="转入类型">
<el-radio-group v-model="rottableType">
<el-radio value="0" border>转桌(可将部分商品转入)</el-radio>
<el-radio value="1" border>并桌(并台会将全部购物车商品转入)</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="购物车商品" v-if="rottableType == 0">
<el-table border :data="cartGoods" ref="refTable">
<el-table-column type="selection" width="55" />
<el-table-column label="商品" prop="name"></el-table-column>
<el-table-column label="数量" prop="number"></el-table-column>
<el-table-column label="商品" prop="name"></el-table-column>
</el-table>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</template>
</el-dialog>
</template>
<script setup>
import tableApi from "@/api/account/table";
import orderApi from "@/api/order/order";
const props = defineProps({
cartGoods: {
type: Array,
default: () => [],
},
});
const refForm = ref();
let rottableType = ref("0");
const basicForm = {
sourceOrderId: "",
targetOrderId: "",
targetTableCode: "",
detailIds: [],
};
const form = reactive({
...basicForm,
});
const rules = {
targetTableCode: [{ required: true, message: "请选择目标桌码", trigger: "blur" }],
};
function reset() {
Object.assign(form, basicForm);
}
const show = ref(false);
function open(obj) {
Object.assign(form, obj);
show.value = true;
}
function close() {
show.value = false;
}
const refTable = ref();
const tableList = ref([]);
function getTableList() {
tableApi.getList({ page: 1, size: 999 }).then((res) => {
tableList.value = res.records.filter((v) => v.tableCode);
});
}
function confirm() {
refForm.value.validate((valid, fields) => {
if (valid) {
console.log("submit!");
const detailIds = refTable.value.getSelectionRows().map((v) => v.id);
orderApi
.mergeOrder({
...form,
detailIds,
})
.then((res) => {
ElNotification({
title: "成功",
message: "合并成功",
type: "success",
});
});
} else {
console.log("error submit!", fields);
}
});
}
onMounted(() => {
getTableList();
});
defineExpose({
open,
close,
});
</script>

View File

@ -123,6 +123,7 @@
@packClick="showPack"
@changePriceClick="showChangePrice"
@return="refReturnCartShow"
@rottable="rottableShow"
/>
</div>
<div class="right">
@ -213,6 +214,8 @@
<returnCart ref="refReturnCart" @confirm="refReturnCartConfirm"></returnCart>
<!-- 美团抖音核销 -->
<quanHexiao ref="refQuanHexiao"></quanHexiao>
<!-- 转桌 -->
<rottable ref="refRotTable" :cartGoods="carts.list"></rottable>
</div>
</template>
<script setup>
@ -228,6 +231,7 @@ import chooseUser from "./components/choose-user.vue";
import changeWeight from "./components/popup-weight-goods.vue";
import changeTaocan from "./components/popup-taocan-goods.vue";
import addLingShiCai from "./components/popup-linshiCai.vue";
import rottable from "./components/popup-rottable.vue";
import GoodsItem from "./components/goods-item.vue";
import dialogGoodsSel from "./components/dialog-goods-sel.vue";
import cartsList from "./components/carts/list.vue";
@ -247,6 +251,15 @@ const shopUser = useUserStore();
const route = useRoute();
const router = useRouter();
//
const refRotTable = ref();
function rottableShow() {
refRotTable.value.open({
sourceOrderId: carts.oldOrder.id,
});
}
//
const refQuanHexiao = ref();
function refQuanHexiaoOpen() {
@ -473,20 +486,10 @@ function showaddLingShiCai() {
refAddLingShiCai.value.open();
}
function addLingShiCaiConfirm(data) {
carts.add({
addCarts({
sku_id: "-999",
product_id: "-999",
is_temporary: 1,
sku_name: 1,
number: 1,
is_pack: 0,
is_gift: 0,
discount_sale_amount: 0,
discount_sale_note: "",
is_print: 0,
is_wait_call: 0,
product_name: "",
remark: "",
...data,
});
}
@ -537,8 +540,16 @@ const diners = reactive({
function changeDinersSel(index) {
diners.sel = index;
carts.dinnerType = diners.sel == 0 ? "dine-in" : "take-out";
}
watch(
() => diners.sel,
(newval) => {
carts.changePack(newval);
}
);
//
const category = reactive({
list: [],
@ -588,7 +599,6 @@ async function getGoods() {
goodsMapisFinish.value = true;
}
const cartsLoading = computed(() => {
console.log(goodsMapisFinish.value, carts.isLinkFinshed);
return !goodsMapisFinish.value || !carts.isLinkFinshed;
});
function goodsClick(item) {
@ -659,7 +669,7 @@ function clearCarts() {
});
}
function addCarts(item) {
carts.add(item);
carts.add({ pack_number: diners.sel ? item.number : 0, ...item });
}
watch(
@ -676,7 +686,6 @@ function init() {
onMounted(async () => {
const { id, tableCode } = route.query;
console.log(id, tableCode);
if (id) {
//
const res = await orderApi.getHistoryList({
@ -707,7 +716,9 @@ onMounted(async () => {
//
if (res.tableCode) {
const tableRes = await tableApi.get({ tableCode: res.tableCode });
table.value = tableRes || {};
if (tableRes.tableCode) {
table.value = tableRes || {};
}
}
if (res) {
oldOrder.value = res;
@ -718,13 +729,15 @@ onMounted(async () => {
}
if (tableCode) {
const tableRes = await tableApi.get({ tableCode: tableCode });
table.value = tableRes || {};
if (tableRes.tableCode) {
table.value = tableRes || {};
}
}
console.log(table.value);
init();
});
function refresh() {
console.log(refresh);
oldOrder.value = {
detailMap: [],
};
@ -777,7 +790,7 @@ $pl: 30px;
height: 100%;
max-height: calc(100vh - 256px);
.left {
flex: 1;
width: 330px;
padding-right: 14px;
box-sizing: border-box;
display: flex;
@ -790,7 +803,7 @@ $pl: 30px;
}
}
.right {
flex: 4;
flex: 1;
overflow-x: hidden;
overflow-y: scroll;
&::-webkit-scrollbar {

View File

@ -59,7 +59,9 @@
<span class="name u-line-1" style="max-width: 50px">
{{ item.name }}
</span>
<span class="u-font-14 u-line-1">{{ areaMap[item.areaId] || "" }}</span>
<span class="u-font-14 u-line-1" style="max-width: 100px">
{{ areaMap[item.areaId] || "" }}
</span>
</div>
<el-dropdown trigger="click" @command="tableComman($event, item)">
<el-icon color="#fff" class="cur-pointer"><More /></el-icon>