11 Commits

Author SHA1 Message Date
gyq
806a98aabd 更改地址 2025-03-26 17:02:18 +08:00
gyq
64ec515c01 优化 2025-02-10 10:27:28 +08:00
gyq
44144c5ac7 更改api 2025-02-08 17:10:10 +08:00
gyq
5e4bce25fb 优化台桌样式 2024-12-21 11:48:27 +08:00
gyq
5abb43cc49 优化转桌 2024-12-20 11:26:04 +08:00
gyq
bbd99a1942 取消限制 2024-12-19 15:35:29 +08:00
gyq
00172f75e7 新增支付类型挂账 2024-12-19 13:46:57 +08:00
gyq
608c41de4f 更新优化问题 2024-12-18 09:05:10 +08:00
gyq
ddd67d0c0a 将排队放出来 2024-12-17 15:11:34 +08:00
gyq
75f32c7b3d Merge branch 'gyq' of e.coding.net:g-cphe0354/pczhuomianduan/cashierdesktop into gyq_zhuan_zhuo 2024-12-17 15:10:35 +08:00
gyq
8dfa5b7aac 1.修复购物车清空已下单商品的问题
2.转桌/并桌只显示已下单商品
2024-12-17 09:59:41 +08:00
17 changed files with 16346 additions and 104 deletions

View File

@@ -26,10 +26,10 @@ VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# VITE_API_URL = 'http://192.168.1.106:10589/cashier-client' # VITE_API_URL = 'http://192.168.1.106:10589/cashier-client'
# 杰哥 # 杰哥
# VITE_API_URL = 'http://192.168.1.34:10589/cashier-client' VITE_API_URL = 'http://192.168.2.181:10587/cashier-client'
# 测试 # 测试
VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client' # VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client'
# 预发布 # 预发布
# VITE_API_URL = 'https://pre-cashierclient.sxczgkj.cn/cashier-client' # VITE_API_URL = 'https://pre-cashierclient.sxczgkj.cn/cashier-client'

View File

@@ -2,10 +2,10 @@
ENV = test ENV = test
#测试ws #测试ws
VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client' # VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
# 正式ws # 正式ws
# VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client' VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
# 正式 php # 正式 php
VITE_API_PHP_URL = 'https://czgdoumei.sxczgkj.com/index.php/api' VITE_API_PHP_URL = 'https://czgdoumei.sxczgkj.com/index.php/api'

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
{ {
"name": "vite-electron", "name": "vite-electron",
"private": true, "private": true,
"version": "1.4.26", "version": "1.4.27",
"main": "dist-electron/main.js", "main": "dist-electron/main.js",
"scripts": { "scripts": {
"dev": "chcp 65001 && vite", "dev": "chcp 65001 && vite",

View File

@@ -142,3 +142,29 @@ export function vipPay(data) {
data, data,
}); });
} }
/**
* 挂账人-分页
* @param {*} params
* @returns
*/
export function buyerPage(params) {
return request({
method: "get",
url: "/credit/buyer/page",
params,
});
}
/**
* 挂账支付
* @param {*} data
* @returns
*/
export function payCreditPay(data) {
return request({
method: "post",
url: "/pay/creditPay",
data,
});
}

View File

@@ -246,3 +246,16 @@ export function orderPrint(data) {
data, data,
}); });
} }
/**
* 转台/并台
* @param {*} data
* @returns
*/
export function orderSwitcht(data) {
return request({
method: "PUT",
url: "/order/switch",
data,
});
}

View File

@@ -87,11 +87,11 @@ const menus = ref([
path: '/member', path: '/member',
icon: 'User' icon: 'User'
}, },
// { {
// label: '排队', label: '排队',
// path: '/queue', path: '/queue',
// icon: 'Timer' icon: 'Timer'
// }, },
// { // {
// label: '交班', // label: '交班',
// path: '/work', // path: '/work',

View File

@@ -25,6 +25,9 @@ export default (data) => {
data.orderInfo.masterId ? data.orderInfo.masterId : "" data.orderInfo.masterId ? data.orderInfo.masterId : ""
} }
</div> </div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
桌号:${data.orderInfo && data.orderInfo.tableName || ''}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:20px;"> <div style="font-size: 16px;display: flex; justify-content:center;margin-top:20px;">
${data.orderInfo.outNumber ? data.orderInfo.outNumber : ""} ${data.orderInfo.outNumber ? data.orderInfo.outNumber : ""}
</div> </div>

View File

@@ -19,6 +19,9 @@ export default (data) => {
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;"> <div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
退款单【${data.orderInfo.masterId ? data.orderInfo.masterId : ""} 退款单【${data.orderInfo.masterId ? data.orderInfo.masterId : ""}
</div> </div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
桌号:${data.orderInfo && data.orderInfo.tableName || ''}
</div>
<div style="margin-top: 30px;font-size: 12px;"> <div style="margin-top: 30px;font-size: 12px;">
订单号:${data.orderInfo && data.orderInfo.orderNo} 订单号:${data.orderInfo && data.orderInfo.orderNo}
</div> </div>

View File

@@ -3,10 +3,13 @@
<el-drawer size="60%" :with-header="false" direction="rtl" v-model="dialogVisible" style="padding: 0"> <el-drawer size="60%" :with-header="false" direction="rtl" v-model="dialogVisible" style="padding: 0">
<div class="drawerbox_box"> <div class="drawerbox_box">
<div class="drawerbox_bo_top"> <div class="drawerbox_bo_top">
<div class="drawerbox_bo_top_left"> <div class="drawerbox_bo_top_left" @click="computeExpired">
<div class="drawerbox_bo_top_left_one" style="font-size: 24px;"> <div class="drawerbox_bo_top_left_one" style="font-size: 24px;">
{{ store.userInfo.shopName }} {{ store.userInfo.shopName }}
</div> </div>
<div class="tips" style="margin-top: 4px; color: var(--el-color-warning);"
v-if="!showTips && store.userInfo.expireDate">注意您的账号将于{{
store.userInfo.expireDate }}后过期请尽快续期</div>
<div class="drawerbox_bo_top_left_tow" style="margin-top: 10px"> <div class="drawerbox_bo_top_left_tow" style="margin-top: 10px">
收银员{{ store.userInfo.loginAccount }} 收银员{{ store.userInfo.loginAccount }}
</div> </div>
@@ -109,8 +112,21 @@ const screenref = ref(null);
const dialogVisible = ref(false); const dialogVisible = ref(false);
const showTips = ref(false)
function show() { function show() {
dialogVisible.value = true; dialogVisible.value = true;
computeExpired()
}
// 计算是否小于过期时间30天
function computeExpired() {
// 当前日期
let now = dayjs()
// 到期时间
let expired = dayjs(store.userInfo.expireDate).subtract(30, 'day')
// 判断当前时间是否大于到期时间30天
showTips.value = now.isBefore(expired)
} }
// 打开叫号弹窗 // 打开叫号弹窗

View File

@@ -25,6 +25,16 @@
</div> </div>
<span class="title">{{ item.payName }}</span> <span class="title">{{ item.payName }}</span>
</div> </div>
<div class="item" :class="{ active: payActive == 'buyer' }"
@click="payTypeChange('buyer', { payType: 'buyer' })">
<div class="icon">
<div class="img"
style="display: flex;align-items: center;justify-content: center;background-color: var(--el-color-danger);color: #fff;font-size: 24px;border-radius: 11px;">
</div>
</div>
<span class="title">挂账</span>
</div>
</div> </div>
<div class="input_wrap"> <div class="input_wrap">
<div class="input" style="flex: 1;">储值:{{ money }}</div> <div class="input" style="flex: 1;">储值:{{ money }}</div>
@@ -83,11 +93,56 @@
<el-pagination layout="prev, pager, next, total" background style="margin-top: 20px;" <el-pagination layout="prev, pager, next, total" background style="margin-top: 20px;"
:total="Number(tableData.total)" v-model:current-page="tableData.page" @current-change="getMemberList" /> :total="Number(tableData.total)" v-model:current-page="tableData.page" @current-change="getMemberList" />
</el-dialog> </el-dialog>
<!-- 选择挂账人员 -->
<el-dialog title="挂账" top="3vh" v-model="showBuyer" width="90%" @closed="resetBuyerTable">
<el-form inline>
<el-form-item>
<el-input placeholder="请输入挂账人或手机号搜索" v-model="buyerTable.keywords" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getBuyerList">搜索</el-button>
<el-button @click="resetBuyerTable">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="buyerTable.list" height="440px" border stripe v-loading="buyerTable.loading">
<el-table-column prop="debtor" label="挂账人" />
<el-table-column prop="mobile" label="手机" width="150px" />
<el-table-column prop="position" label="职位" width="120px" />
<el-table-column prop="repaymentMethod" label="还款方式" width="160px">
<template v-slot="scope">
<template v-if="scope.row.repaymentMethod == 'total'">按总金额还款</template>
<template v-if="scope.row.repaymentMethod == 'order'">按订单还款</template>
</template>
</el-table-column>
<el-table-column prop="creditAmount" label="挂账额度" width="160px">
<template v-slot="scope">
{{ formatDecimal(scope.row.creditAmount) }}
</template>
</el-table-column>
<el-table-column prop="remainingAmount" label="剩余挂账额度" width="160px">
<template v-slot="scope">
{{ formatDecimal(scope.row.remainingAmount) }}
</template>
</el-table-column>
<el-table-column prop="accumulateAmount" label="累计挂账金额" width="160px">
<template v-slot="scope">
{{ formatDecimal(scope.row.accumulateAmount) }}
</template>
</el-table-column>
<el-table-column label="操作" width="120px" fixed="right">
<template v-slot="scope">
<el-button type="primary" @click="payCreditPayHandle(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination layout="prev, pager, next, total" background style="margin-top: 20px;"
:total="Number(buyerTable.total)" v-model:current-page="buyerTable.page" @current-change="getBuyerList" />
</el-dialog>
</template> </template>
<script setup> <script setup>
import { onMounted, ref, computed, watch, reactive } from 'vue' import { onMounted, ref, computed, watch, reactive } from 'vue'
import { queryPayType, accountPay, cashPay, vipPay } from '@/api/pay' import { queryPayType, accountPay, cashPay, vipPay, buyerPage, payCreditPay } from '@/api/pay'
import { queryMembermember, createMembermember, membermemberScanPay, accountPaymember } from '@/api/member/index.js' import { queryMembermember, createMembermember, membermemberScanPay, accountPaymember } from '@/api/member/index.js'
import { useUser } from "@/store/user.js" import { useUser } from "@/store/user.js"
import { clearNoNum, formatDecimal } from '@/utils' import { clearNoNum, formatDecimal } from '@/utils'
@@ -96,6 +151,7 @@ import scanModal from '@/components/payCard/scanModal.vue'
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useGlobal } from '@/store/global.js' import { useGlobal } from '@/store/global.js'
import { staffPermission } from '@/api/user.js' import { staffPermission } from '@/api/user.js'
import { fa } from 'element-plus/es/locale/index.mjs'
const global = useGlobal() const global = useGlobal()
@@ -143,6 +199,76 @@ const payType = ref('')
const payList = ref([]) const payList = ref([])
const payLoading = ref(false) const payLoading = ref(false)
// 挂账人 start
const showBuyer = ref(false)
const buyerTable = reactive({
keywords: '',
loading: false,
page: 1,
size: 10,
total: 0,
list: []
})
// 显示挂账人
function showBuyerHandle() {
showBuyer.value = true
getBuyerList()
}
//
function resetBuyerTable() {
buyerTable.keywords = ''
buyerTable.page = 1
getBuyerList()
}
// 获取挂账人列表
async function getBuyerList() {
try {
buyerTable.loading = true
const res = await buyerPage({
page: buyerTable.page,
size: buyerTable.size,
shopId: store.userInfo.shopId,
keywords: buyerTable.keywords,
status: 1,
responsiblePerson: '',
repaymentStatus: ''
})
buyerTable.loading = false
buyerTable.list = res.list
buyerTable.total = res.total
} catch (error) {
buyerTable.loading = false
console.log(error);
}
}
// 选择挂账人支付
async function payCreditPayHandle(row) {
try {
payLoading.value = true
buyerTable.loading = true
const res = await payCreditPay({
creditBuyerId: row.id,
orderId: props.orderId,
payAmount: props.discount > 0 ? money.value : '',
discountAmount: props.discount > 0 ? formatDecimal(props.amount - money.value) : ''
})
showBuyer.value = false
payLoading.value = false
buyerTable.loading = false
ElMessage.success('支付成功')
emit('paySuccess')
} catch (error) {
buyerTable.loading = false
payLoading.value = false
console.log(error);
}
}
// 显示选择挂账人 end
// 获得扫码值 // 获得扫码值
function scanCodeSuccess() { function scanCodeSuccess() {
emit('paySuccess') emit('paySuccess')
@@ -162,9 +288,14 @@ async function payTypeChange(index, item) {
showDialog.value = true showDialog.value = true
getMemberList() getMemberList()
} }
if (item.payType == 'buyer') {
showBuyerHandle()
}
if (payActive.value != 'buyer') {
if (payList.value[payActive.value].payType == 'deposit' && !global.orderMemberInfo.id) { if (payList.value[payActive.value].payType == 'deposit' && !global.orderMemberInfo.id) {
scanModalRef.value.show() scanModalRef.value.show()
} }
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@@ -174,9 +305,10 @@ async function payTypeChange(index, item) {
async function confirmOrder() { async function confirmOrder() {
try { try {
await staffPermission('yun_xu_shou_kuan') await staffPermission('yun_xu_shou_kuan')
if (payLoading.value) return if (payLoading.value) return
if (payList.value[payActive.value].payType == 'scanCode') { if (payActive.value == 'buyer') {
showBuyerHandle()
} else if (payList.value[payActive.value].payType == 'scanCode') {
scanModalRef.value.show() scanModalRef.value.show()
} else { } else {
// if (money.value < props.amount) return // if (money.value < props.amount) return

View File

@@ -16,6 +16,7 @@ export const useSocket = defineStore({
uuid: "", // 长连接唯一id uuid: "", // 长连接唯一id
heartbeatTimer: null, // 心跳计时器 heartbeatTimer: null, // 心跳计时器
orderList: [], orderList: [],
log: true,
}), }),
actions: { actions: {
// 创建uuid // 创建uuid
@@ -33,7 +34,7 @@ export const useSocket = defineStore({
}, },
// 关闭ws // 关闭ws
close() { close() {
console.log("关闭ws"); if (this.log) console.log("关闭ws");
this.online = false; this.online = false;
this.ws.close(1000); this.ws.close(1000);
this.ws = null; this.ws = null;
@@ -57,7 +58,7 @@ export const useSocket = defineStore({
printStore.init(); printStore.init();
if (this.ws == null) { if (this.ws == null) {
console.log("创建新的ws连接"); if (this.log) console.log("创建新的ws连接");
const protocols = []; // 可选的子协议数组 const protocols = []; // 可选的子协议数组
const options = { const options = {
@@ -67,17 +68,17 @@ export const useSocket = defineStore({
}; };
this.ws = new ReconnectingWebSocket(wsUrl, protocols, options); this.ws = new ReconnectingWebSocket(wsUrl, protocols, options);
} else { } else {
console.log("重新连接ws"); if (this.log) console.log("重新连接ws");
this.wsReconnect(); this.wsReconnect();
} }
this.ws.addEventListener("open", (event) => { this.ws.addEventListener("open", (event) => {
console.log("wss连接成功"); if (this.log) console.log("wss连接成功");
this.online = true; this.online = true;
// 清除心跳 // 清除心跳
this.clearHeartBeat(); this.clearHeartBeat();
console.log(this); if (this.log) console.log(this);
this.ws.send( this.ws.send(
JSON.stringify({ JSON.stringify({
@@ -92,7 +93,7 @@ export const useSocket = defineStore({
this.ws.addEventListener("message", (e) => { this.ws.addEventListener("message", (e) => {
let data = JSON.parse(e.data); let data = JSON.parse(e.data);
if (data.type == "order") { if (data.type == "order") {
console.log("接收消息", data); if (this.log) console.log("接收消息", data);
this.ws.send( this.ws.send(
JSON.stringify({ JSON.stringify({
type: "send", type: "send",
@@ -112,18 +113,18 @@ export const useSocket = defineStore({
} }
} }
} else if (data.type == "heartbeat") { } else if (data.type == "heartbeat") {
console.log("接收心跳"); if (this.log) console.log("接收心跳");
} }
}); });
this.ws.addEventListener("error", () => { this.ws.addEventListener("error", () => {
console.log("WebSocket连接发生错误"); if (this.log) console.log("WebSocket连接发生错误");
this.online = false; this.online = false;
this.clearHeartBeat(); this.clearHeartBeat();
}); });
this.ws.addEventListener("error", (e) => { this.ws.addEventListener("error", (e) => {
console.log("ws关闭了", e); if (this.log) console.log("ws关闭了", e);
this.online = false; this.online = false;
this.clearHeartBeat(); this.clearHeartBeat();
}); });
@@ -131,7 +132,7 @@ export const useSocket = defineStore({
// 启动心跳连接 // 启动心跳连接
startheartbeat() { startheartbeat() {
this.heartbeatTimer = setInterval(() => { this.heartbeatTimer = setInterval(() => {
console.log("发送心跳"); if (this.log) console.log("发送心跳");
this.ws.send(JSON.stringify({ type: "heartbeat" })); this.ws.send(JSON.stringify({ type: "heartbeat" }));
}, 10000); }, 10000);
}, },

View File

@@ -56,6 +56,13 @@
</el-icon> </el-icon>
<el-text class="t">挂单</el-text> <el-text class="t">挂单</el-text>
</div> </div>
<div class="item" @click="tableMergingHandle"
v-if="shopStore.info.registerType == 'restaurant' && props.item.tableId && props.item.orderId">
<el-icon class="icon">
<EditPen />
</el-icon>
<el-text class="t">转桌</el-text>
</div>
<div class="item" @click="props.item.id && emit('clearCart')"> <div class="item" @click="props.item.id && emit('clearCart')">
<el-icon class="icon"> <el-icon class="icon">
<RefreshRight /> <RefreshRight />
@@ -117,7 +124,7 @@ const props = defineProps({
default: {} default: {}
} }
}) })
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart']) const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging'])
const takeFoodCodeRef = ref(null) const takeFoodCodeRef = ref(null)
const skuModalRef = ref([]) const skuModalRef = ref([])
@@ -280,6 +287,14 @@ async function kitchenPrint() {
} }
} }
/**免厨打印 end */ /**免厨打印 end */
// 显示合并转桌
function tableMergingHandle() {
if (props.item.id) {
emit('merging')
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -287,7 +302,7 @@ async function kitchenPrint() {
padding: 10px; padding: 10px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 15px; gap: 10px;
.item { .item {
width: 70px; width: 70px;

View File

@@ -44,7 +44,7 @@
</div> </div>
<div class="shop_list" :class="{ img: shopListType == 'img' }" v-loading="loading"> <div class="shop_list" :class="{ img: shopListType == 'img' }" v-loading="loading">
<!-- <swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange"> --> <!-- <swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange"> -->
<swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange"> <swiper ref="swiperRef" :loop="false" class="swiper_box" direction="vertical" @slideChange="onSlideChange">
<swiper-slide class="slide_item" v-for="(goods, index) in goodsList" :key="index"> <swiper-slide class="slide_item" v-for="(goods, index) in goodsList" :key="index">
<div class="item_wrap" v-for="item in goods" :key="item.id" @click="showSkuHandle(item)"> <div class="item_wrap" v-for="item in goods" :key="item.id" @click="showSkuHandle(item)">
<div class="item"> <div class="item">
@@ -225,7 +225,7 @@
<script setup> <script setup>
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import { onMounted, ref } from 'vue' import { nextTick, onMounted, ref } from 'vue'
import _ from 'lodash' import _ from 'lodash'
import useStorage from "@/utils/useStorage"; import useStorage from "@/utils/useStorage";
import skuModal from '@/components/skuModal.vue' import skuModal from '@/components/skuModal.vue'
@@ -239,6 +239,8 @@ import { staffPermission } from '@/api/user.js'
import { useGlobal } from '@/store/global.js' import { useGlobal } from '@/store/global.js'
import { inputFilterFloat } from '@/utils/index.js' import { inputFilterFloat } from '@/utils/index.js'
const swiperRef = ref(null)
const global = useGlobal() const global = useGlobal()
const store = useUser() const store = useUser()
@@ -594,14 +596,14 @@ async function queryCategoryAjax() {
} }
// 查询商品信息 // 查询商品信息
async function productqueryCommodityInfoAjax() { async function productqueryCommodityInfoAjax(page = goodsPage.value) {
try { try {
// loading.value = true // loading.value = true
const res = await queryNewCommodityInfo({ const res = await queryNewCommodityInfo({
shopId: store.userInfo.shopId, shopId: store.userInfo.shopId,
categoryId: categorys.value[categorysActive.value].id, categoryId: categorys.value[categorysActive.value].id,
commdityName: commdityName.value, commdityName: commdityName.value,
page: goodsPage.value, page: page,
pageSize: goodsPageSize.value, pageSize: goodsPageSize.value,
masterId: props.masterId, masterId: props.masterId,
tableId: global.tableInfo.qrcode || '', tableId: global.tableInfo.qrcode || '',
@@ -657,9 +659,7 @@ async function updataGoods() {
} }
searchLoading.value = false searchLoading.value = false
} else { } else {
goodsPage.value = currentGoodsIndex.value + 1 const res = await productqueryCommodityInfoAjax(currentGoodsIndex.value + 1)
// console.log('更新第二页数据', goodsPage.value);
const res = await productqueryCommodityInfoAjax()
goodsList.value[currentGoodsIndex.value] = res.list goodsList.value[currentGoodsIndex.value] = res.list
searchLoading.value = false searchLoading.value = false
} }
@@ -669,7 +669,6 @@ async function updataGoods() {
const onSlideChange = _.debounce(async function (e) { const onSlideChange = _.debounce(async function (e) {
if (e.activeIndex == e.previousIndex) return if (e.activeIndex == e.previousIndex) return
if (e.activeIndex > e.previousIndex) { if (e.activeIndex > e.previousIndex) {
// console.log('向下滑动');
{ {
goodsPage.value++ goodsPage.value++
const res = await productqueryCommodityInfoAjax() const res = await productqueryCommodityInfoAjax()
@@ -681,24 +680,19 @@ const onSlideChange = _.debounce(async function (e) {
const res = await productqueryCommodityInfoAjax() const res = await productqueryCommodityInfoAjax()
res.list.length && goodsList.value.push(res.list) res.list.length && goodsList.value.push(res.list)
} }
// goodsList.value.shift()
} else {
// console.log('向上滑动');
// goodsPage.value--
// const res = await productqueryCommodityInfoAjax()
// goodsList.value.unshift(res)
// goodsList.value.pop()
} }
currentGoodsIndex.value = e.activeIndex currentGoodsIndex.value = e.activeIndex
}, 500) }, 500)
// 订单已结算,清商品所有数字 // 订单已结算,清商品所有数字
function clearDot() { function clearDot() {
goodsList.value.map(item => { // goodsList.value.map(item => {
item.map(val => { // item.map(val => {
val.orderCount = 0 // val.orderCount = 0
}) // })
}) // })
updateData()
} }
const showEditor = ref(false) const showEditor = ref(false)
@@ -770,6 +764,7 @@ async function showPutawayHandle(item) {
} }
} }
// 确认上架操作
async function putawayHandle(item) { async function putawayHandle(item) {
try { try {
showPutawayLoading.value = true showPutawayLoading.value = true
@@ -875,6 +870,7 @@ onMounted(async () => {
getUnitListAjax() getUnitListAjax()
await updateCategoryActive() await updateCategoryActive()
await queryCategoryAjax() await queryCategoryAjax()
updataGoods()
}) })
</script> </script>

View File

@@ -0,0 +1,203 @@
<!-- 合并/转桌 -->
<template>
<el-dialog title="转桌/并桌" width="700px" v-model="visible" @closed="onClose" top="10vh">
<div class="scroll_y">
<el-form :model="form" ref="formRef" :rules="rules" label-position="top">
<el-form-item label="转入台桌" prop="targetTableId">
<el-select v-model="form.targetTableId" style="width: 200px;" placeholder="请选择目标台桌">
<el-option :label="item.name" :value="item.qrcode" v-for="item in tableList"
:key="item.qrcode"></el-option>
</el-select>
</el-form-item>
<el-form-item label="转入类型">
<el-radio-group v-model="form.isFull">
<el-radio :value="false" border>转桌可将部分商品转入</el-radio>
<el-radio :value="true" border>并桌并台会将全部购物车商品转入</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="转入商品" prop="cartIds" v-if="!form.isFull">
<div v-for="item in props.data" style="width: 100%;">
<div>{{ `${item.placeNum}次下单` }}</div>
<el-table ref="tableRefs" :data="item.info" border>
<el-table-column type="selection" align="center" width="50px"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="数量" prop="number"></el-table-column>
<el-table-column label="规格" prop="skuName"></el-table-column>
<el-table-column label="价格" prop="salePrice"></el-table-column>
</el-table>
</div>
</el-form-item>
</el-form>
</div>
<div class="footer" style="display: flex;">
<el-button style="width: 100%" @click="visible = false">
取消
</el-button>
<el-button type="primary" style="width: 100%" :loading="loading" @click="confirmHandle">
确认
</el-button>
</div>
</el-dialog>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { queryShopTable } from '@/api/table.js'
import { orderSwitcht } from '@/api/product.js'
import { useUser } from "@/store/user.js"
import { useGlobal } from '@/store/global.js'
import { ElMessage } from 'element-plus'
const store = useUser()
const global = useGlobal()
const visible = ref(false)
const props = reactive({
data: []
})
const emits = defineEmits(['success'])
const tableRefs = ref([])
const list = ref([])
const loading = ref(false)
const formRef = ref(null)
const resetForm = ref({})
const form = ref({
shopId: store.userInfo.shopId,
masterId: '',
orderId: '',
cartIds: [],
isFull: false,
currentTableId: '',
targetTableId: '',
})
const rules = ref({
targetTableId: [
{
required: true,
message: ' ',
trigger: 'change',
}
],
cartIds: [
{
required: true,
validator: (rule, value, callback) => {
let arr = []
props.data.map((item, index) => {
arr.push(...tableRefs.value[index].getSelectionRows())
})
if (!arr.length) {
ElMessage.error('至少选择一个商品')
callback(new Error('至少选择一个商品'))
} else {
callback()
}
},
trigger: 'blur',
}
]
})
const tableList = ref([])
// 获取台桌列表
async function queryShopTableAjax() {
try {
const res = await queryShopTable({
shopId: store.userInfo.shopId,
areaId: '',
status: '',
page: 1,
pageSize: 100
})
tableList.value = res.list.filter(item => item.qrcode != props.data[0].info[0].tableId && item.status == 'using')
} catch (error) {
console.log(error)
}
}
// 提交
function confirmHandle() {
formRef.value.validate(async valid => {
try {
if (valid) {
loading.value = true
form.value.masterId = props.data[0].info[0].masterId
form.value.orderId = props.data[0].info[0].orderId
form.value.currentTableId = props.data[0].info[0].tableId
if (!form.value.isFull) {
let arr = []
props.data.map((item, index) => {
arr.push(...tableRefs.value[index].getSelectionRows())
})
form.value.cartIds = arr.map(item => item.id)
}
await orderSwitcht(form.value)
loading.value = false
// 更新台桌信息
global.setOrderTable(tableList.value.find(item => item.qrcode == form.value.targetTableId))
visible.value = false
emits('success', { isTemporary: true })
}
} catch (error) {
loading.value = false
console.log(error);
}
})
}
function onClose() {
form.value = { ...resetForm.value }
formRef.value.resetFields()
}
function show(data) {
props.data = data
visible.value = true
queryShopTableAjax()
}
defineExpose({
show
})
onMounted(() => {
resetForm.value = { ...form.value }
})
</script>
<style scoped lang="scss">
$btmH: 50px;
.scroll_y {
height: 50vh;
overflow-y: auto;
padding-bottom: $btmH;
}
.footer {
position: relative;
&::before {
content: "";
height: $btmH;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
width: 100%;
position: absolute;
top: $btmH*-1;
left: 0;
z-index: 10;
}
}
</style>

View File

@@ -97,7 +97,7 @@
</div> </div>
<!-- 购物车操作栏 --> <!-- 购物车操作栏 -->
<cartOperation :item="cartListActiveItem" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle" <cartOperation :item="cartListActiveItem" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle"
@pending="pendingCart" @clearCart="clearCartHandle" /> @pending="pendingCart" @clearCart="clearCartHandle" @merging="showTableMerging" />
</div> </div>
<div class="footer"> <div class="footer">
<div class="top"> <div class="top">
@@ -165,6 +165,8 @@
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" /> <pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
<!-- 检查版本升级 --> <!-- 检查版本升级 -->
<updateDialog /> <updateDialog />
<!-- 合并/转桌 -->
<tableMerging ref="tableMergingRef" @success="addCart" />
</template> </template>
<script> <script>
@@ -185,6 +187,7 @@ import cartOperation from "@/views/home/components/cartOperation.vue";
import settleAccount from "@/views/home/components/settleAccount.vue"; import settleAccount from "@/views/home/components/settleAccount.vue";
import fastCashier from "@/views/home/components/fastCashier.vue"; import fastCashier from "@/views/home/components/fastCashier.vue";
import pendingCartModal from "@/views/home/components/pendingCartModal.vue"; import pendingCartModal from "@/views/home/components/pendingCartModal.vue";
import tableMerging from '@/views/home/components/tableMerging.vue'
import useStorage from '@/utils/useStorage' import useStorage from '@/utils/useStorage'
import { formatDecimal } from '@/utils/index.js' import { formatDecimal } from '@/utils/index.js'
@@ -209,6 +212,7 @@ import member from "@/views/member/index.vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useShop } from '@/store/shop.js' import { useShop } from '@/store/shop.js'
import TableMerging from "./components/tableMerging.vue";
const shopStore = useShop() const shopStore = useShop()
@@ -224,6 +228,7 @@ const goodsRef = ref(null);
const pendingCartModalRef = ref(null); const pendingCartModalRef = ref(null);
const settleAccountRef = ref(null); const settleAccountRef = ref(null);
const fastCashierRef = ref(null); const fastCashierRef = ref(null);
const tableMergingRef = ref(null)
const allSelected = ref(false); const allSelected = ref(false);
@@ -493,7 +498,7 @@ async function queryCartAjax() {
cartInfo.value = res.amount; cartInfo.value = res.amount;
pendingCartNum.value = res.num; pendingCartNum.value = res.num;
goodsRef.value.updateData(); // goodsRef.value.updateData();
let i = 0; let i = 0;
res.list.map((item) => { res.list.map((item) => {
@@ -568,6 +573,12 @@ function clearMember() {
createCodeAjax() createCodeAjax()
} }
// 显示转桌/并桌
function showTableMerging() {
let data = cartList.value.filter(item => item.placeNum)
tableMergingRef.value.show(data)
}
onMounted(() => { onMounted(() => {
createCodeAjax() createCodeAjax()
shopStore.queryShopInfo() shopStore.queryShopInfo()
@@ -721,6 +732,7 @@ onMounted(() => {
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
line-clamp: 2;
} }
.num { .num {

View File

@@ -254,31 +254,51 @@ onMounted(() => {
gap: var(--el-font-size-base); gap: var(--el-font-size-base);
.item { .item {
$usingColor: #D2441F;
$subColor: #3274D5;
$closedColor: #aeb8c9; $closedColor: #aeb8c9;
background-color: #efefef;
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden;
border: 2px solid #fff; padding: 2px;
background-color: var(--primary-color);
&.active { &.active {
border-color: $subColor; background-color: var(--primary-color);
.tab_cont {
.icon {
color: var(--primary-color);
}
.t1 {
color: var(--primary-color);
}
}
} }
&.using { &.using {
&.active { background-color: var(--el-color-success);
border-color: $usingColor;
.tab_cont {
.icon {
color: var(--el-color-success);
}
.t1 {
color: var(--el-color-success);
}
} }
} }
&.closed { &.closed {
.tab_title { background-color: $closedColor;
color: #555;
.tab_cont {
.icon {
color: $closedColor;
} }
&.active { .t1 {
border-color: $closedColor; color: $closedColor;
}
} }
} }
@@ -293,31 +313,6 @@ onMounted(() => {
justify-content: space-between; justify-content: space-between;
padding: 0 10px; padding: 0 10px;
color: #fff; color: #fff;
background-color: #999;
&.subscribe {
background-color: $subColor;
}
&.closed {
background-color: $closedColor;
}
&.idle {
background-color: $subColor;
}
&.using {
background-color: $usingColor;
}
&.opening {
background-color: var(--primary-color);
}
&.cleaning {
background-color: #999;
}
} }
.tab_cont { .tab_cont {
@@ -325,9 +320,11 @@ onMounted(() => {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: #efefef;
border-radius: 4px;
.icon { .icon {
color: #555; color: var(--primary-color);
font-size: 30px; font-size: 30px;
transform: rotate(45deg); transform: rotate(45deg);
} }
@@ -341,6 +338,10 @@ onMounted(() => {
align-items: center; align-items: center;
padding-bottom: 10px; padding-bottom: 10px;
.t1 {
font-weight: bold;
}
.t2 { .t2 {
font-size: 12px; font-size: 12px;
display: flex; display: flex;