对接购物车

This commit is contained in:
gyq 2025-02-26 18:06:37 +08:00
parent 44144c5ac7
commit d3ed4ec8e6
27 changed files with 2589 additions and 1629 deletions

View File

@ -2,10 +2,10 @@
ENV = development ENV = development
# 正式ws # 正式ws
VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client' # VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
#测试ws #测试ws
# VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client' VITE_API_WSS = 'wss://sockets.sxczgkj.com/wss'
# 阿伟本地ws # 阿伟本地ws
# VITE_API_WSS = 'ws://192.168.2.17:9998/client' # VITE_API_WSS = 'ws://192.168.2.17:9998/client'
@ -20,10 +20,7 @@ VITE_API_PHP_URL = 'https://czgdoumei.sxczgkj.com/index.php/api'
VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api' VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# 阿伟 # 阿伟
# VITE_API_URL = 'http://192.168.2.96:10587/cashier-client' # VITE_API_URL = 'http://192.168.1.21:9200/'
# 鹏辉
# 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.1.34:10589/cashier-client'
@ -38,4 +35,8 @@ VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# VITE_API_URL = 'https://36z1017t45.goho.co/cashier-client' # VITE_API_URL = 'https://36z1017t45.goho.co/cashier-client'
# 正式 # 正式
VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client' # VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client'
# 正式
VITE_API_URL = 'https://tapi.cashier.sxczgkj.cn'

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,10 @@ import { scanSendMessage } from "@/api/order/index";
import { useGlobal } from "@/store/global.js"; import { useGlobal } from "@/store/global.js";
import { useSocket } from "@/store/socket.js"; import { useSocket } from "@/store/socket.js";
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import { useGoods } from '@/store/goods.js'
const goodsStore = useGoods()
const socket = useSocket(); const socket = useSocket();
const global = useGlobal(); const global = useGlobal();
@ -165,13 +169,14 @@ async function getBarCode(e) {
} }
onMounted(() => { onMounted(() => {
document.addEventListener("keydown", (e) => { //
getBarCode(e); // document.addEventListener("keydown", (e) => {
}); // getBarCode(e);
// });
// //
if (store.userInfo && store.userInfo.shopId) { if (store.userInfo && store.userInfo.id) {
socket.init(); goodsStore.initGoods()
} }
ipcRenderer.on('showCloseDialog', (event, arg) => { ipcRenderer.on('showCloseDialog', (event, arg) => {

79
src/api/account.js Normal file
View File

@ -0,0 +1,79 @@
import request from "@/utils/request.js";
/**
* 商户登录
* @param {*} data
* @returns
*/
export function login(data) {
return request({
method: "post",
url: "/account/admin/auth/login",
data,
});
}
/**
* 验证码获取
* @param {*} params
* @returns
*/
export function captcha(params) {
return request({
method: "get",
url: "/account/admin/auth/captcha",
params,
});
}
/**
* 店铺详情
* @param {*} params
* @returns
*/
export function shopInfo_detail(params) {
return request({
method: "get",
url: "/account/admin/shopInfo/detail",
params,
});
}
/**
* 获取店铺用户列表
* @param {*} params
* @returns
*/
export function shopUserList(params) {
return request({
method: "get",
url: "/account/admin/shopUser",
params,
});
}
/**
* 获取台桌区域
* @param {*} params
* @returns
*/
export function shopArea(params) {
return request({
method: "get",
url: "/account/admin/shopArea",
params,
});
}
/**
* 获取台桌列表
* @param {*} params
* @returns
*/
export function shopTable(params) {
return request({
method: "get",
url: "/account/admin/shopTable",
params,
});
}

66
src/api/order.js Normal file
View File

@ -0,0 +1,66 @@
import request from "@/utils/request.js";
/**
* 反扫
* @param {*} data
* @returns
*/
export function microPay(data) {
return request({
method: "post",
url: "/order/pay/microPay",
data,
});
}
/**
* 现金支付订单
* @param {*} data
* @returns
*/
export function cashPay(data) {
return request({
method: "post",
url: "/order/pay/cashPay",
data,
});
}
/**
* 查询订单列表
* @param {*} data
* @returns
*/
export function orderList(data) {
return request({
method: "post",
url: "/order/admin/order",
data,
});
}
/**
* 新增订单
* @param {*} data
* @returns
*/
export function createOrder(data) {
return request({
method: "post",
url: "/order/admin/order/createOrder",
data,
});
}
/**
* 历史订单(多次下单使用)
* @param {*} data
* @returns
*/
export function historyOrder(params) {
return request({
method: "get",
url: "/order/admin/order/historyOrder",
params,
});
}

27
src/api/product_new.js Normal file
View File

@ -0,0 +1,27 @@
import request from "@/utils/request.js";
/**
* 查询分类信息
* @param {*} params
* @returns
*/
export function categoryList(params) {
return request({
method: "get",
url: "/product/admin/prod/category/list",
params,
});
}
/**
* 查询商品列表
* @param {*} params
* @returns
*/
export function productPage(params) {
return request({
method: "get",
url: "/product/admin/product/list",
params,
});
}

View File

@ -142,7 +142,7 @@
<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, buyerPage, payCreditPay } from '@/api/pay' import { queryPayType, accountPay, 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'
@ -151,7 +151,11 @@ 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' import { cashPay } from '@/api/order.js'
import { useGoods } from '@/store/goods.js'
const goodsStore = useGoods()
const global = useGlobal() const global = useGlobal()
@ -304,6 +308,31 @@ async function payTypeChange(index, item) {
// //
async function confirmOrder() { async function confirmOrder() {
try { try {
payLoading.value = true
// 使
await cashPay({
shopId: store.shopInfo.id,
checkOrderPay: {
orderId: goodsStore.orderInfo.id,
userId: '',
seatNum: 0, //
originAmount: goodsStore.orderInfo.originAmount, // +
discountRatio: 1, // ( )
discountAmount: 0, //
productCouponDiscountAmount: 0, //
fullCouponDiscountAmount: 0, //
couponList: [], // 使
orderAmount: goodsStore.orderInfo.originAmount, //
roundAmount: 0, //
pointsDiscountAmount: 0, // (tb_points_basic_setting)
pointsNum: 0 // 使 ( enable_deduction使)
}
})
payLoading.value = false
ElMessage.success('支付成功')
emit('paySuccess')
return
await staffPermission('yun_xu_shou_kuan') await staffPermission('yun_xu_shou_kuan')
if (payLoading.value) return if (payLoading.value) return
if (payActive.value == 'buyer') { if (payActive.value == 'buyer') {
@ -477,7 +506,7 @@ function cancelDiscount() {
onMounted(() => { onMounted(() => {
money.value = `${formatDecimal(props.amount)}` money.value = `${formatDecimal(props.amount)}`
queryPayTypeAjax() // queryPayTypeAjax()
}) })
</script> </script>

View File

@ -0,0 +1,94 @@
<template>
<el-dialog :title="`选择会员`" top="3vh" v-model="showDialog" width="80%">
<el-form inline>
<el-form-item>
<el-input placeholder="请输入手机号搜索会员" v-model="tableData.phone" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getMemberList">搜索</el-button>
<el-button @click="resetTable">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData.list" height="440px" border stripe v-loading="tableData.loading">
<el-table-column prop="nickName" label="昵称" width="120px" />
<el-table-column prop="phone" label="手机" width="150px" />
<el-table-column prop="code" label="编号" width="120px" />
<el-table-column prop="level" label="等级" />
<el-table-column prop="accountPoints" label="积分" />
<el-table-column prop="amount" label="余额" width="100px">
<template v-slot="scope">
{{ formatDecimal(scope.row.amount) }}
</template>
</el-table-column>
<el-table-column label="操作" width="120px">
<template v-slot="scope">
<el-button type="primary" @click="toHomeMember(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
<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" />
</el-dialog>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { shopUserList } from "@/api/account.js";
const showDialog = ref(false)
const tableData = reactive({
phone: '',
loading: false,
list: [],
page: 1,
size: 10,
total: 0
})
//
async function toHomeMember(row) {
try {
console.log(row);
//
} catch (error) {
console.log(error);
}
showDialog.value = false
}
//
function resetTable() {
tableData.phone = ''
tableData.page = 1
getMemberList()
}
//
async function getMemberList() {
try {
tableData.loading = true
const res = await shopUserList({
key: tableData.phone,
isVips: 1,
page: tableData.page,
size: tableData.size
})
tableData.list = res.records
tableData.total = res.totalRow
} catch (error) {
console.log(error);
}
tableData.loading = false
}
//
function show() {
showDialog.value = true
getMemberList()
}
defineExpose({
show
})
</script>

View File

@ -15,7 +15,7 @@
<div class="footer"> <div class="footer">
<div class="info"> <div class="info">
<template v-if="goodsInfo.id"> <template v-if="goodsInfo.id">
<span>库存{{ goodsInfo.stockNumber }}</span> <!-- <span>库存{{ goodsInfo.stockNumber }}</span> -->
<span>{{ goodsInfo.salePrice }}</span> <span>{{ goodsInfo.salePrice }}</span>
</template> </template>
</div> </div>
@ -34,10 +34,6 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { useUser } from "@/store/user.js"
import { queryProductSku } from '@/api/product'
const store = useUser();
const emit = defineEmits(['success']) const emit = defineEmits(['success'])
const type = ref('shop') const type = ref('shop')
@ -56,16 +52,16 @@ const selecSkuArray = ref([])
// //
function submitSku() { function submitSku() {
dialogVisible.value = false dialogVisible.value = false
switch (type.value) { // switch (type.value) {
case 'shop': // case 'shop':
emit('success', goodsInfo.value) // break;
break; // case 'cart':
case 'cart': // emit('success', goodsInfo.value)
emit('success', goods.value) // break;
break; // default:
default: // break;
break; // }
} emit('success', goodsInfo.value)
} }
// //
@ -100,11 +96,11 @@ function selectedSku(index = 0, i = 0) {
}) })
goods.value.selectSpec[index + 1].selectSpecResult.map(item => { goods.value.selectSpec[index + 1].selectSpecResult.map(item => {
goods.value.groundingSpecInfo.map(val => { goods.value.skuList.map(val => {
// console.log(val); // console.log(val);
// console.log(`${selecSkuArray.value.join(',')},${item.name}`); // console.log(`${selecSkuArray.value.join(',')},${item.name}`);
// console.log(val.specSnap.indexOf(`${selecSkuArray.value.join(',')},${item.name}`)); // console.log(val.specInfo.indexOf(`${selecSkuArray.value.join(',')},${item.name}`));
if (val.specSnap.indexOf(`${selecSkuArray.value.join(',')},${item.name}`) != -1 && val.isGrounding) { if (val.specInfo.indexOf(`${selecSkuArray.value.join(',')},${item.name}`) != -1 && val.isGrounding) {
item.disabled = false item.disabled = false
} }
}) })
@ -147,80 +143,62 @@ function selectedSuccess() {
// //
async function queryProductSkuAjax() { async function queryProductSkuAjax() {
try { goods.value.skuList.map(item => {
loading.value = true if (item.specInfo == selectedSkuTag.value) {
const res = await queryProductSku({ goodsInfo.value = item
shopId: store.userInfo.shopId,
productId: type.value == 'shop' ? goods.value.id : goods.value.productId,
spec_tag: selectedSkuTag.value
})
goodsInfo.value = res
if (type.value == 'cart') {
goods.value.skuId = res.id
} }
setTimeout(() => { })
loading.value = false
}, 100)
} catch (error) {
loading.value = false
console.log(error)
}
} }
// //
function show(item, t = 'shop') { function show(item, t = 'shop') {
type.value = t
let arr = []
for (let val in item.selectSpecInfo) {
if (item.selectSpecInfo[val].length) {
switch (type.value) {
case 'shop':
arr.push({
name: val,
selectSpecResult: item.selectSpecInfo[val].map(item => {
return {
active: false,
name: item,
disabled: false
}
})
})
break;
case 'cart':
//
const skus = item.sku_name.split(',')
arr.push({
name: val,
selectSpecResult: item.selectSpecInfo[val].map(item => {
return {
active: !!skus.find(val => val === item),
name: item,
disabled: false
}
})
})
break;
default:
break;
}
}
}
item.selectSpec = arr
//
goodsInfo.value = {} goodsInfo.value = {}
goods.value = {} goods.value = {}
selectedSkuNum.value = 0 selectedSkuNum.value = 0
dialogVisible.value = true dialogVisible.value = true
goods.value = "" goods.value = ""
goods.value = item goods.value = item
type.value = t
goods.value.selectSpec = JSON.parse(goods.value.selectSpec)
goods.value.selectSpec.map((item, index) => {
let arr = []
item.selectSpecResult.map(val => {
switch (type.value) {
case 'shop':
let disabled = true
if (index == 0) {
goods.value.groundingSpecInfo.map(item => {
if (item.specSnap.indexOf(val) != -1 && item.isGrounding) {
disabled = false
}
})
}
arr.push({
active: false,
name: val,
disabled: index == 0 ? disabled : true
})
break;
case 'cart':
//
const skus = goods.value.skuName.split(',')
arr.push({
active: !!skus.find(item => item === val),
name: val,
disabled: true
})
break;
default:
break;
}
})
item.selectSpecResult = arr
})
let arr = []
goods.value.selectSpec.map(item => {
if (item.selectSpecResult.length) {
arr.push({ ...item })
}
})
goods.value.selectSpec = arr
selectedSuccess() selectedSuccess()
} }

View File

@ -86,9 +86,9 @@ async function uplaodHandle() {
} }
onMounted(() => { onMounted(() => {
if (store.userInfo) { // if (store.userInfo) {
findVersionAjax() // findVersionAjax()
} // }
ipcRenderer.on('updateProgress', (event, res) => { ipcRenderer.on('updateProgress', (event, res) => {
uploadPro.value = res uploadPro.value = res
}) })

407
src/store/goods.js Normal file
View File

@ -0,0 +1,407 @@
import _ from "lodash";
import { defineStore } from "pinia";
import { productPage, categoryList } from "@/api/product_new.js";
import { historyOrder } from "@/api/order.js";
import { useUser } from "@/store/user.js";
import { useSocket } from "@/store/socket.js";
import useStorage from "@/utils/useStorage.js";
import { ElMessage } from "element-plus";
// 商品store + 购物车store
export const useGoods = defineStore("goods", {
state: () => ({
vipUserInfo: {}, // 会员信息
tableInfo: {}, // 台桌信息
cartActiveIndex: 0, // 购物车激活索引,
isCartInit: false,
cartList: [], // 购物车列表
cartInfo: {
total: 0,
totalAmount: 0,
gifNumber: 0,
gifNumberAmount: 0,
saleNumber: 0,
saleNumberAmount: 0,
}, // 购物车信息,
goodsName: "", // 商品名称,
categoryIndex: useStorage.get("categoryIndex") || 0, // 商品分类索引,
categoryList: [], // 商品分类列表
originCategoryList: [], // 原始商品分类列表,
goodsList: [], // 商品列表
originGoodsList: [], // 原始商品列表
orderList: [], // 订单列表
orderInfo: {}, // 生成的订单信息
}),
actions: {
// 手动选择台桌
selectTable(tableInfo = {}) {
const socket = useSocket();
this.tableInfo = tableInfo;
// 选择台桌后将购物车初始化
socket.cartInit(this.tableInfo.tableCode || "");
// this.historyOrderAjax(this.tableInfo.tableCode);
},
// 获取订单列表
async historyOrderAjax(tableCode) {
try {
const res = await historyOrder({
tableCode: tableCode,
});
// val = this.completeGoodsInfo(val);
// this.orderList = res.records;
} catch (error) {
console.log(error);
}
},
// 初始化商品
async initGoods() {
await this.getCategoryList();
await this.getGoodsList();
},
// 切换商品分类
setCategoryIndex(index) {
this.categoryIndex = index;
useStorage.set("categoryIndex", index);
if (index == 0) {
// this.getGoodsList();
this.goodsList = _.chunk(this.originGoodsList, 12);
} else {
// 除了全部,其他只做本地筛选
this.goodsList = _.chunk(
this.originGoodsList.filter(
(item) =>
item.categoryId == this.categoryList[this.categoryIndex].id
),
12
);
}
this.updateGoodsNumber();
},
// 根据商品名字模糊查询商品列表
filterNameGoods(name) {
this.goodsList = _.chunk(
this.originGoodsList.filter((item) => item.name.includes(name)),
12
);
this.updateGoodsNumber();
},
// 获取商品分类列表
async getCategoryList() {
try {
const res = await categoryList();
this.originCategoryList = [...res];
this.categoryList = res;
this.categoryList.unshift({
name: "全部",
id: "",
});
// this.categoryList.push({
// name: "已下架",
// id: "-1",
// });
} catch (error) {
console.log(error);
}
},
// 获取商品列表/更新商品列表
async getGoodsList() {
try {
const res = await productPage({
categoryId: this.categoryList[this.categoryIndex].id,
name: this.goodsName,
});
const originGoodsListRes = await productPage();
this.originGoodsList = originGoodsListRes;
const socket = useSocket();
socket.init();
res.map((val, index) => {
val.showMore = false;
val.orderCount = 0;
});
// 将数组分割成每页12个
this.goodsList = _.chunk(res, 12);
} catch (error) {
console.log(error);
}
},
// 选中购物车商品
selectCartItemHandle(index) {
this.cartActiveIndex = index;
if (this.cartList.length) {
this.cartList.map((val) => {
val.active = false;
});
this.cartList[index].active = true;
}
},
// 获取购物车列表,数据必须由长链接返回
async getCartList(arr) {
arr.map((val, index) => {
val = this.completeGoodsInfo(val);
val.active = false;
if (!this.isCartInit && index == 0) {
val.active = true;
}
});
this.cartList = arr;
this.isCartInit = true;
this.calcCartInfo();
// if (arr.length && arr[0].table_code) {
// this.historyOrderAjax(arr[0].table_code);
// }
console.log("getCartList.cartList===", this.cartList);
},
// 更新商品列表的角标
updateGoodsNumber() {
this.goodsList.map((item) => {
item.map((val) => {
val.number = 0;
this.cartList.map((cart) => {
if (val.id == cart.product_id) {
val.number += +cart.number;
}
});
});
});
},
// 添加商品到购物车
addCart(params) {
let tableCode = "";
if (this.tableInfo.tableCode) {
tableCode = this.tableInfo.tableCode;
} else {
if (this.cartList.length) {
tableCode = this.cartList[0].table_code;
}
}
const sendData = {
table_code: tableCode,
product_id: params.productId || "",
sku_id: params.id || "",
number: params.number || 1,
pack_number: params.is_pack || 0,
is_gift: params.is_gift || 0,
is_temporary: params.is_temporary || 0,
discount_sale_amount: params.discount_sale_amount || 0,
discount_sale_note: params.discount_sale_note || 0,
is_print: 1,
is_wait_call: 0,
remark: params.remark || "",
product_name: params.product_name || "",
sku_name: params.sku_name || "",
pro_group_info: params.pro_group_info || [],
goods_type: params.goods_type || "",
};
this.operateCart(sendData, "add");
},
// 购物添加成功
successAddCart(goodsInfoItem) {
if (this.cartList.length) {
for (let i = 0; i < this.cartList.length; i++) {
if (
this.cartList[i].product_id == goodsInfoItem.product_id &&
this.cartList[i].id == goodsInfoItem.id
) {
this.cartList[i] = this.completeGoodsInfo({
active: this.cartList[i].active,
...goodsInfoItem,
});
this.calcCartInfo();
return;
}
}
this.cartList.push(this.completeGoodsInfo({ ...goodsInfoItem }));
} else {
this.cartList.push(this.completeGoodsInfo({ ...goodsInfoItem }));
}
// 给第一个商品添加选中效果
if (this.cartList.length == 1) {
this.selectCartItemHandle(0);
}
this.calcCartInfo();
},
// 成功编辑购物车商品
successEditCart(data) {
this.successAddCart(data);
},
// 补全商品信息
completeGoodsInfo(item) {
if (item.is_temporary) {
return item;
} else {
let flag = false;
this.originGoodsList.map((val) => {
if (val.id == item.product_id) {
flag = true;
let sku = val.skuList.find((sku) => sku.id == item.sku_id);
let group_text = "";
if (val.type == "package") {
group_text = JSON.parse(item.pro_group_info)
.flat()
.map((item) => item.proName)
.join("、");
}
item.lowPrice = val.lowPrice;
item.product_name = val.name;
item.sku_name = sku && sku.specInfo;
item.group_type = val.groupType;
item.goods_type = val.type;
item.skuList = val.skuList;
item.selectSpecInfo = val.selectSpecInfo;
item.group_text = group_text;
}
});
if (!flag) {
console.log("该商品不存在,已删除", item);
this.operateCart(item, "del");
}
return item;
}
},
// 删除购物车商品
deleteCartItem() {
let tableCode = "";
if (this.tableInfo.tableCode) {
tableCode = this.tableInfo.tableCode;
} else {
if (this.cartList.length) {
tableCode = this.cartList[0].table_code;
}
}
this.operateCart(
{
table_code: tableCode,
id: this.cartList[this.cartActiveIndex].id,
},
"del"
);
},
// 删除购物车回执操作
successDeleteCartItem() {
this.cartList.splice(this.cartActiveIndex, 1);
this.selectCartItemHandle(
this.cartActiveIndex == 0 ? 0 : this.cartActiveIndex - 1
);
this.calcCartInfo();
},
// 清空购物车
clearCart() {
let tableCode = "";
if (this.tableInfo.tableCode) {
tableCode = this.tableInfo.tableCode;
} else {
if (this.cartList.length) {
tableCode = this.cartList[0].table_code;
}
}
this.operateCart({ table_code: tableCode }, "cleanup");
},
// 清空购物车回执操作
successClearCart() {
this.cartList = [];
this.cartInfo.total = 0;
this.cartInfo.totalAmount = 0;
this.calcCartInfo();
},
// 计算购物车信息
calcCartInfo() {
this.updateGoodsNumber();
let total = 0; // 总数量
let totalAmount = 0; // 总金额
let gifNumber = 0; // 赠送总数量
let gifNumberAmount = 0; // 赠送总金额
let saleNumber = 0; // 打折总数量
let saleNumberAmount = 0; // 打折总金额
this.cartList.map((val, index) => {
total += +val.number;
if (val.is_temporary) {
if (val.is_gift) {
gifNumber += +val.number;
gifNumberAmount += +val.number * +val.discount_sale_amount;
} else {
// 临时菜使用discount_sale_amount计算价格
totalAmount += val.number * val.discount_sale_amount;
}
} else {
if (val.is_gift) {
// 赠送
if (+val.discount_sale_amount) {
// 且有折扣
gifNumber += +val.number;
gifNumberAmount += +val.number * val.discount_sale_amount;
saleNumber += +val.number;
saleNumberAmount +=
val.number * (val.lowPrice - val.discount_sale_amount);
} else {
gifNumber += +val.number;
gifNumberAmount += +val.number * +val.lowPrice;
}
} else {
if (+val.discount_sale_amount) {
// 代表打过折
saleNumber += +val.number;
saleNumberAmount +=
val.number * (val.lowPrice - val.discount_sale_amount);
// 使用正常价减去折扣价格计算
totalAmount += val.number * val.discount_sale_amount;
} else {
// 使用正常价格计算
totalAmount += val.number * val.lowPrice;
}
}
}
});
this.cartInfo.gifNumber = gifNumber;
this.cartInfo.gifNumberAmount = gifNumberAmount;
this.cartInfo.saleNumber = saleNumber;
this.cartInfo.saleNumberAmount = saleNumberAmount;
this.cartInfo.total = total;
this.cartInfo.totalAmount = totalAmount;
console.log("this.cartInfo===", this.cartInfo);
},
// 购物车操作
async operateCart(data, operate_type = "add") {
const socket = useSocket();
const store = useUser();
if (socket.online) {
socket.ws.send(
JSON.stringify({
type: "cashier",
shop_id: store.shopInfo.id,
account: store.userInfo.id,
operate_type: operate_type,
...data,
})
);
} else {
console.log("离线操作");
}
},
},
});

View File

@ -33,19 +33,19 @@ export const usePrint = defineStore({
this.localDevices = arg; this.localDevices = arg;
}); });
// 获取已添加的小票打印机 // // 获取已添加的小票打印机
this.deviceNoteList = await bySubType({ // this.deviceNoteList = await bySubType({
shopId: store.userInfo.shopId, // shopId: store.userInfo.shopId,
contentType: "local", // contentType: "local",
subType: "cash", // subType: "cash",
}); // });
// 获取已添加的标签打印机 // // 获取已添加的标签打印机
this.deviceLableList = await bySubType({ // this.deviceLableList = await bySubType({
shopId: store.userInfo.shopId, // shopId: store.userInfo.shopId,
contentType: "local", // contentType: "local",
subType: "label", // subType: "label",
}); // });
console.log("打印队列初始化成功"); console.log("打印队列初始化成功");
}, },
// 检查本地打印机是否能正常使用 // 检查本地打印机是否能正常使用

View File

@ -1,5 +1,5 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { queryShopInfo } from "@/api/user"; import { shopInfo_detail } from "@/api/account.js";
import useStorage from "@/utils/useStorage"; import useStorage from "@/utils/useStorage";
export const useShop = defineStore({ export const useShop = defineStore({
@ -11,7 +11,7 @@ export const useShop = defineStore({
// 获取店铺信息 // 获取店铺信息
async queryShopInfo() { async queryShopInfo() {
try { try {
const res = await queryShopInfo(); const res = await shopInfo_detail();
useStorage.set("shopInfo", res); useStorage.set("shopInfo", res);
this.info = useStorage.get("shopInfo"); this.info = useStorage.get("shopInfo");
} catch (error) { } catch (error) {

View File

@ -1,37 +1,21 @@
import _ from "lodash"; import _ from "lodash";
import { dayjs } from "element-plus";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import { usePrint } from "@/store/print.js"; import { usePrint } from "@/store/print.js";
import { v4 as uuidv4 } from "uuid";
import useStorage from "@/utils/useStorage"; import useStorage from "@/utils/useStorage";
import ReconnectingWebSocket from "reconnecting-websocket"; import ReconnectingWebSocket from "reconnecting-websocket";
import { ipcRenderer } from "electron"; import { useGoods } from "@/store/goods.js";
import { ElMessage } from "element-plus";
export const useSocket = defineStore({ export const useSocket = defineStore("socket", {
id: uuidv4(),
state: () => ({ state: () => ({
online: false, // 在线状态 online: false, // 在线状态
ws: null, // websocket实例 ws: null, // websocket实例
uuid: "", // 长连接唯一id
heartbeatTimer: null, // 心跳计时器 heartbeatTimer: null, // 心跳计时器
orderList: [], orderList: [],
log: true, log: false,
}), }),
actions: { actions: {
// 创建uuid
createUUID() {
if (!useStorage.get("uuid")) {
ipcRenderer.send("getOSmacSync");
// useStorage.set("uuid", uuidv4());
ipcRenderer.on("getOSmacRes", (event, arg) => {
useStorage.set("uuid", arg);
this.uuid = useStorage.get("uuid");
});
} else {
this.uuid = useStorage.get("uuid");
}
},
// 关闭ws // 关闭ws
close() { close() {
if (this.log) console.log("关闭ws"); if (this.log) console.log("关闭ws");
@ -49,11 +33,22 @@ export const useSocket = defineStore({
2000, 2000,
{ leading: true, trailing: false } { leading: true, trailing: false }
), ),
cartInit(tableCode = "") {
const store = useUser();
this.ws.send(
JSON.stringify({
type: "cashier",
account: `cashier_${store.shopInfo.id}`,
operate_type: "init",
shop_id: store.shopInfo.id,
table_code: tableCode, // 后期选台桌号
})
);
},
// 初始化 // 初始化
init(wsUrl = import.meta.env.VITE_API_WSS) { init(wsUrl = import.meta.env.VITE_API_WSS) {
this.createUUID();
const store = useUser();
const printStore = usePrint(); const printStore = usePrint();
const goodsStore = useGoods();
printStore.init(); printStore.init();
@ -77,44 +72,80 @@ export const useSocket = defineStore({
this.online = true; this.online = true;
// 清除心跳 // 清除心跳
this.clearHeartBeat(); this.clearHeartBeat();
if (this.log) console.log(this); if (this.log) console.log(this);
this.cartInit();
this.ws.send(
JSON.stringify({
type: "connect",
shopId: store.userInfo.shopId,
clientId: this.uuid,
})
);
this.startheartbeat(); this.startheartbeat();
}); });
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.operate_type == "init") {
if (this.log) console.log("接收消息", data); // console.log("接收消息", data);
this.ws.send( goodsStore.getCartList(data.data);
JSON.stringify({
type: "send",
orderNo: data.orderInfo.orderNo,
})
);
// 接收订单消息,打印小票
// printBill(data)
// 打印标签小票
if (!this.orderList.some((el) => el == data.orderInfo.orderNo)) {
// console.log("打印", data);
printStore.labelPrint(data);
printStore.pushReceiptData(data);
this.orderList.push(data.orderInfo.orderNo);
if (this.orderList.length > 30) {
this.orderList.splice(0, 1);
}
}
} else if (data.type == "heartbeat") {
if (this.log) console.log("接收心跳");
} }
this.ws.send(
JSON.stringify({
type: "receipt",
msg_id: data.msg_id,
})
);
if (data.data_type == "cart") {
if (data.status == 1) {
// 返回成功状态
switch (data.operate_type) {
case "add":
// 添加购物车商品
goodsStore.successAddCart(data.data);
break;
case "edit":
// 编辑购物车商品
goodsStore.successEditCart(data.data);
break;
case "del":
// 删除购物车商品
goodsStore.successDeleteCartItem();
break;
case "cleanup":
// 清空购物车
goodsStore.successClearCart();
break;
default:
break;
}
} else {
ElMessage.error("操作失败");
}
}
// if (data.data_type == "cart" && data.operate_type == "init") {
// // 购物车消息
// goodsStore.getCartList(data.data);
// } else if (data.data_type == "order") {
// // 接收订单消息,打印小票
// if (this.log) console.log("接收消息", data);
// this.ws.send(
// JSON.stringify({
// type: "send",
// orderNo: data.orderInfo.orderNo,
// })
// );
// // 接收订单消息,打印小票
// // printBill(data)
// // 打印标签小票
// if (!this.orderList.some((el) => el == data.orderInfo.orderNo)) {
// // console.log("打印", data);
// printStore.labelPrint(data);
// printStore.pushReceiptData(data);
// this.orderList.push(data.orderInfo.orderNo);
// if (this.orderList.length > 30) {
// this.orderList.splice(0, 1);
// }
// }
// } else if (data.data_type == "heartbeat") {
// if (this.log) console.log("接收心跳");
// }
}); });
this.ws.addEventListener("error", () => { this.ws.addEventListener("error", () => {

View File

@ -1,24 +1,34 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { login } from "@/api/user"; import { login, shopInfo_detail } from "@/api/account.js";
import useStorage from "@/utils/useStorage"; import useStorage from "@/utils/useStorage";
export const useUser = defineStore({ export const useUser = defineStore("user", {
id: "user",
state: () => ({ state: () => ({
userInfo: useStorage.get("userInfo"), userInfo: useStorage.get("userInfo"),
shopInfo: useStorage.get("shopInfo"),
token: useStorage.get("token"), token: useStorage.get("token"),
}), }),
actions: { actions: {
// 登录 // 登录
userlogin(param) { userlogin(param) {
return login(param).then((res) => { return login(param).then(async (res) => {
this.userInfo = res; this.userInfo = res.shopInfo;
this.token = res.token; this.token = res.tokenInfo.tokenValue;
useStorage.set("token", this.token); useStorage.set("token", this.token);
// this.userInfo.shopId = "24";
useStorage.set("userInfo", this.userInfo); useStorage.set("userInfo", this.userInfo);
await this.queryShopInfo();
return this.userInfo; return this.userInfo;
}); });
}, },
// 获取店铺信息
async queryShopInfo() {
try {
const res = await shopInfo_detail();
useStorage.set("shopInfo", res);
this.shopInfo = useStorage.get("shopInfo");
} catch (error) {
console.log(error);
}
},
}, },
}); });

View File

@ -1,10 +1,13 @@
import axios from "axios"; import axios from "axios";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import useStorage from '@/utils/useStorage' import useStorage from "@/utils/useStorage";
import router from '@/router' import router from "@/router";
const service = axios.create({ const service = axios.create({
baseURL: import.meta.env.MODE == 'development' ? '/api/' : import.meta.env.VITE_API_URL, baseURL:
import.meta.env.MODE == "development"
? "/api/"
: import.meta.env.VITE_API_URL,
// withCredentials: true, // 跨域请求时发送 cookies // withCredentials: true, // 跨域请求时发送 cookies
timeout: 5000, // 请求超时 timeout: 5000, // 请求超时
}); });
@ -17,9 +20,12 @@ service.interceptors.request.use(
// 让每个请求携带 token // 让每个请求携带 token
// ['X-Token'] 是自定义标题键 // ['X-Token'] 是自定义标题键
// 请根据实际情况修改 // 请根据实际情况修改
config.headers["platformType"] = 'PC';
config.headers["token"] = useStorage.get("token"); config.headers["token"] = useStorage.get("token");
config.headers["loginName"] = useStorage.get("userInfo").loginName; if (useStorage.get("shopInfo") && useStorage.get("shopInfo").id) {
config.headers["clientType"] = 'pc'; config.headers["shopId"] = useStorage.get("shopInfo").id;
}
// config.headers["loginName"] = useStorage.get("userInfo").loginName;
// config.headers['Content-Type'] = 'application/json' // config.headers['Content-Type'] = 'application/json'
} }
return config; return config;
@ -35,18 +41,18 @@ service.interceptors.response.use(
(response) => { (response) => {
// 对响应数据做点什么 // 对响应数据做点什么
if (+response.status === 200) { if (+response.status === 200) {
if (+response.data.code == '0') { if (+response.data.code == 200) {
return response.data.data; return response.data.data;
} else if (+response.data.code == '9999') { } else if (+response.data.code == 501) {
ElMessage.error('登录已过期,请重新登录') ElMessage.error("登录已过期,请重新登录");
useStorage.clear() useStorage.clear();
router.replace("/login") router.replace("/login");
window.location.reload() window.location.reload();
return Promise.reject('登录已过期,请重新登录') return Promise.reject("登录已过期,请重新登录");
} else { } else {
// 响应错误 // 响应错误
ElMessage.error(response.data.msg) ElMessage.error(response.data.msg);
return Promise.reject(response.data) return Promise.reject(response.data);
} }
} }
}, },

View File

@ -1,69 +1,86 @@
<template> <template>
<div class="operation_wrap"> <div class="operation_wrap">
<div class="item" :class="{ disabled: props.item.number <= 1 || !props.item.id }" @click="numberChange('sub')"> <div class="item"
:class="{ disabled: goodsStore.cartList.length && (goodsStore.cartList[goodsStore.cartActiveIndex].number <= 1 || !goodsStore.cartList[goodsStore.cartActiveIndex].id || (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1)) }"
@click="numberChange('sub')">
<el-icon class="icon"> <el-icon class="icon">
<SemiSelect /> <SemiSelect />
</el-icon> </el-icon>
</div> </div>
<div class="item number" @click="props.item.id && takeFoodCodeRef.show()"> <div class="item number"
<el-text class="num">{{ formatDecimal(props.item.number || 1, 2, true) }}</el-text> :class="{ disabled: goodsStore.cartList.length && (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1) }"
@click="showEditNumber">
<el-text class="num">
{{ formatDecimal(goodsStore.cartList.length ? +goodsStore.cartList[goodsStore.cartActiveIndex].number :
1, 2, true) }}
</el-text>
</div> </div>
<div class="item" @click="numberChange('add')"> <div class="item"
:class="{ disabled: goodsStore.cartList.length && (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1) }"
@click="numberChange('add')">
<el-icon class="icon add"> <el-icon class="icon add">
<CloseBold /> <CloseBold />
</el-icon> </el-icon>
</div> </div>
<!-- <div class="item" :class="{ disabled: (props.item.id && !props.item.tbProductSpec) }" @click="showSkuModal"> <div class="item"
:class="{ disabled: (goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].id && goodsStore.cartList[goodsStore.cartActiveIndex].goods_type != 'sku' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type != 1) }"
@click="showSkuModal">
<el-icon class="icon"> <el-icon class="icon">
<Filter /> <Filter />
</el-icon> </el-icon>
<el-text class="t">规格</el-text> <el-text class="t">规格</el-text>
</div> --> </div>
<div class="item" @click="showDiscountModalHandle"> <div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_temporary }"
@click="showDiscountModalHandle">
<el-icon class="icon"> <el-icon class="icon">
<PriceTag /> <PriceTag />
</el-icon> </el-icon>
<el-text class="t">打折</el-text> <el-text class="t">改价</el-text>
</div> </div>
<div class="item" :class="{ disabled: props.item.isGift == 'true' }" @click="giftPackHandle('isGift')"> <div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_gift }"
@click="giftPackHandle('is_gift')">
<el-icon class="icon"> <el-icon class="icon">
<ShoppingBag /> <ShoppingBag />
</el-icon> </el-icon>
<el-text class="t">赠送</el-text> <el-text class="t">赠送</el-text>
</div> </div>
<div class="item" :class="{ disabled: props.item.isPack == 'true' }" @click="giftPackHandle('isPack')" <div class="item"
v-if="JSON.parse(shopStore.info.eatModel).some(item => item == 'take-out')"> :class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_pack }"
@click="giftPackHandle('is_pack')" v-if="shopStore.info.eatModel == 'take-out'">
<el-icon class="icon"> <el-icon class="icon">
<Box /> <Box />
</el-icon> </el-icon>
<el-text class="t">打包</el-text> <el-text class="t">打包</el-text>
</div> </div>
<div class="item" :class="{ disabled: props.item.isPrint == 0 }" @click="kitchenPrint"> <div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_print == 0 }"
@click="giftPackHandle('is_print')">
<el-icon class="icon"> <el-icon class="icon">
<DishDot /> <DishDot />
</el-icon> </el-icon>
<el-text class="t">免厨</el-text> <el-text class="t">免厨</el-text>
</div> </div>
<div class="item" @click="props.item.id && emit('delete', props.item)"> <div class="item" @click="deleteHandle">
<el-icon class="icon"> <el-icon class="icon">
<Delete /> <Delete />
</el-icon> </el-icon>
<el-text class="t">删除</el-text> <el-text class="t">删除</el-text>
</div> </div>
<div class="item" @click="props.item.id && emit('pending', props.item)"> <!-- <div class="item" @click="props.item.id && emit('pending', props.item)">
<el-icon class="icon"> <el-icon class="icon">
<Sell /> <Sell />
</el-icon> </el-icon>
<el-text class="t">挂单</el-text> <el-text class="t">挂单</el-text>
</div> </div> -->
<div class="item" @click="tableMergingHandle" <div class="item" @click="tableMergingHandle" v-if="goodsStore.tableInfo.tableCode">
v-if="shopStore.info.registerType == 'restaurant' && props.item.tableId && props.item.orderId">
<el-icon class="icon"> <el-icon class="icon">
<EditPen /> <EditPen />
</el-icon> </el-icon>
<el-text class="t">转桌</el-text> <el-text class="t">转桌</el-text>
</div> </div>
<div class="item" @click="props.item.id && emit('clearCart')"> <div class="item" @click="clearCart">
<el-icon class="icon"> <el-icon class="icon">
<RefreshRight /> <RefreshRight />
</el-icon> </el-icon>
@ -73,15 +90,16 @@
<takeFoodCode ref="takeFoodCodeRef" title="修改商品数量" placeholder="请输入商品数量" @success="updateNumber" /> <takeFoodCode ref="takeFoodCodeRef" title="修改商品数量" placeholder="请输入商品数量" @success="updateNumber" />
<!-- 购物车选择规格 --> <!-- 购物车选择规格 -->
<skuModal ref="skuModalRef" @success="skuConfirm" /> <skuModal ref="skuModalRef" @success="skuConfirm" />
<!-- 单品打折 --> <!-- 单品改价 -->
<el-dialog v-model="showDiscountModal" title="单品打折" @open="resetDiscountForm = { ...discountForm }" <el-dialog v-model="showDiscountModal" title="单品改价" @open="resetDiscountForm = { ...discountForm }"
@closed="discountModalClose"> @closed="discountModalClose">
<div class="dialog"> <div class="dialog">
<div class="el-popover__title content"> <div class="el-popover__title content">
<el-form ref="discountFormRef" :model="discountForm" :rules="discountFormRules" label-width="100px" <el-form ref="discountFormRef" :model="discountForm" :rules="discountFormRules" label-width="100px"
label-position="left"> label-position="left">
<el-form-item label="价格更改" prop="amount"> <el-form-item label="价格更改" prop="discount_sale_amount">
<el-input v-model="discountForm.amount" placeholder="减8.88元请输入8.88" @input="priceInput"> <el-input v-model="discountForm.discount_sale_amount" placeholder="减8.88元请输入8.88"
@input="priceInput">
<template #append></template> <template #append></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@ -114,70 +132,96 @@ import { ElMessage } from 'element-plus'
import takeFoodCode from '@/components/takeFoodCode.vue' import takeFoodCode from '@/components/takeFoodCode.vue'
import skuModal from '@/components/skuModal.vue' import skuModal from '@/components/skuModal.vue'
import { useShop } from '@/store/shop.js' import { useShop } from '@/store/shop.js'
import { useGoods } from '@/store/goods.js'
import { inputFilterFloat, formatDecimal } from '@/utils/index.js' import { inputFilterFloat, formatDecimal } from '@/utils/index.js'
import { updatePrice, orderPrint } from '@/api/product.js' import { updatePrice, orderPrint } from '@/api/product.js'
const shopStore = useShop() const shopStore = useShop()
const goodsStore = useGoods()
const props = defineProps({ const props = defineProps({
item: { item: {
type: Object, type: Object,
default: {} default: {}
} }
}) })
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging']) const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging', 'showPackage'])
const takeFoodCodeRef = ref(null) const takeFoodCodeRef = ref(null)
const skuModalRef = ref([]) const skuModalRef = ref([])
// //
function giftPackHandle(key) { function giftPackHandle(key) {
if (!props.item.id) return if (!goodsStore.cartList[goodsStore.cartActiveIndex].id) return
if (props.item[key] == 'true') {
props.item[key] = false if (key == 'is_gift' && goodsStore.cartList[goodsStore.cartActiveIndex] == 0) {
} else { goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_amount = 0
props.item[key] = true
} }
emit('confirm', props.item)
if (goodsStore.cartList[goodsStore.cartActiveIndex][key] == 0) {
goodsStore.cartList[goodsStore.cartActiveIndex][key] = 1
} else {
goodsStore.cartList[goodsStore.cartActiveIndex][key] = 0
}
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex] }, 'edit')
}
//
function showEditNumber() {
let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 1)) return
takeFoodCodeRef.value.show()
} }
// //
function numberChange(t) { function numberChange(t) {
console.log(props.item); let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 1)) return
if (!props.item.id) return // if (!goodsStore.cartList[goodsStore.cartActiveIndex].id || (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1)) return
switch (t) { switch (t) {
case 'sub': case 'sub':
if (props.item.number <= 1) return if (goodsStore.cartList[goodsStore.cartActiveIndex].number <= 1) return
props.item.number-- goodsStore.cartList[goodsStore.cartActiveIndex].number--
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
break; break;
case 'add': case 'add':
props.item.number++ goodsStore.cartList[goodsStore.cartActiveIndex].number++
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
break; break;
default: default:
break; break;
} }
emit('confirm', props.item)
} }
// //
function updateNumber(num) { function updateNumber(num) {
if (!props.item.id) return goodsStore.cartList[goodsStore.cartActiveIndex].number = num
props.item.number = num goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex] }, 'edit')
emit('confirm', props.item)
} }
// //
function showSkuModal() { function showSkuModal() {
if (!props.item.id) return let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (props.item.tbProductSpec && props.item.tbProductSpec.specList) { if (!item || (item.goods_type == 'package' && item.group_type == 0)) return
skuModalRef.value.show(props.item, 'cart')
switch (item.goods_type) {
case 'sku':
skuModalRef.value.show({ ...goodsStore.cartList[goodsStore.cartActiveIndex] }, 'cart')
break;
case 'package':
emit('showPackage', item)
break;
default:
break;
} }
} }
// //
function skuConfirm(e) { function skuConfirm(e) {
if (!props.item.id) return if (goodsStore.cartList[goodsStore.cartActiveIndex].sku_id != e.id) {
emit('confirm', e) goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex], sku_id: e.id, sku_name: e.specInfo }, 'edit')
}
} }
/**单品打折 start */ /**单品打折 start */
@ -186,11 +230,8 @@ const resetDiscountForm = ref({})
const discountFormRef = ref(null) const discountFormRef = ref(null)
const discountFormLoading = ref(false) const discountFormLoading = ref(false)
const discountForm = ref({ const discountForm = ref({
masterId: '', discount_sale_amount: '',
cartId: '', note: ''
amount: '',
note: '',
shopId: ''
}) })
function validateAmount(rule, value, callback) { function validateAmount(rule, value, callback) {
@ -204,7 +245,7 @@ function validateAmount(rule, value, callback) {
} }
const discountFormRules = ref({ const discountFormRules = ref({
amount: [ discount_sale_amount: [
{ {
required: true, required: true,
validator: validateAmount, validator: validateAmount,
@ -220,7 +261,8 @@ const noteList = ref([
// //
function showDiscountModalHandle() { function showDiscountModalHandle() {
if (props.item.id) { if (goodsStore.cartList[goodsStore.cartActiveIndex].id && !goodsStore.cartList[goodsStore.cartActiveIndex].is_temporary) {
//
showDiscountModal.value = true showDiscountModal.value = true
} }
} }
@ -254,21 +296,20 @@ function discountFormSubmit() {
if (valid) { if (valid) {
discountFormLoading.value = true discountFormLoading.value = true
discountForm.value.masterId = props.item.masterId goodsStore.operateCart({
discountForm.value.cartId = props.item.id ...goodsStore.cartList[goodsStore.cartActiveIndex],
discountForm.value.shopId = props.item.shopId discount_sale_amount: goodsStore.cartList[goodsStore.cartActiveIndex].lowPrice - discountForm.value.discount_sale_amount,
discount_sale_note: discountForm.value.note
await updatePrice(discountForm.value) }, 'edit')
discountFormLoading.value = false
goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_amount = discountForm.value.discount_sale_amount
goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_note = discountForm.value.note
showDiscountModal.value = false showDiscountModal.value = false
ElMessage.success('操作成功')
emit('confirm', { isTemporary: true })
} }
} catch (error) { } catch (error) {
discountFormLoading.value = false
console.log(error); console.log(error);
} }
discountFormLoading.value = false
}) })
} }
/**单品打折 end */ /**单品打折 end */
@ -295,6 +336,18 @@ function tableMergingHandle() {
emit('merging') emit('merging')
} }
} }
//
function deleteHandle() {
if (goodsStore.cartList[goodsStore.cartActiveIndex].id) {
goodsStore.deleteCartItem()
}
}
//
function clearCart() {
goodsStore.clearCart()
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -322,6 +375,10 @@ function tableMergingHandle() {
.icon { .icon {
color: #999; color: #999;
} }
.num {
color: #999;
}
} }
&.number { &.number {

View File

@ -1,95 +0,0 @@
<!-- 分类 -->
<template>
</template>
<script setup>
import { queryCategory } from '@/api/product'
import { ref, onMounted } from 'vue'
import { useUser } from "@/store/user.js"
const store = useUser()
const categorys = ref([])
const categorysActive = ref(0)
//
async function queryCategoryAjax() {
try {
const res = await queryCategory({
shopId: store.userInfo.shopId,
page: 1,
pageSize: 100
})
categorys.value = res.list
} catch (error) {
console.log(error)
}
}
onMounted(() => {
queryCategoryAjax()
})
</script>
<style scoped lang="scss">
.header {
display: flex;
height: 80px;
justify-content: space-between;
border-bottom: 1px solid #ececec;
}
.menus {
display: flex;
padding: 0 10px;
.item {
padding: 0 10px;
display: flex;
align-items: center;
position: relative;
span {
font-size: 24px;
}
&.active {
&::after {
content: "";
width: 70%;
height: 2px;
border-radius: 4px;
position: absolute;
bottom: 0;
left: 15%;
background-color: var(--primary-color);
}
span {
color: #333;
}
}
}
}
.all {
width: 80px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&::before {
content: "";
height: 60%;
border-left: 1px solid #ececec;
position: absolute;
left: 0;
top: 20%;
}
.icon {
color: #555;
font-size: 20px;
}
}
</style>

View File

@ -2,8 +2,8 @@
<template> <template>
<div class="header"> <div class="header">
<div class="menus scroll-x"> <div class="menus scroll-x">
<div class="item" :class="{ active: categorysActive == index }" v-for="(item, index) in categorys" <div class="item" :class="{ active: goodsStore.categoryIndex == index }"
:key="item.id" @click="changeCategory(index)"> v-for="(item, index) in goodsStore.categoryList" :key="item.id" @click="changeCategory(index)">
<el-text>{{ item.name }}</el-text> <el-text>{{ item.name }}</el-text>
</div> </div>
</div> </div>
@ -17,8 +17,8 @@
</template> </template>
<template #default> <template #default>
<div class="popover_wrap"> <div class="popover_wrap">
<el-button :plain="categorysActive != index" type="primary" v-for="(item, index) in categorys" <el-button :plain="goodsStore.categoryIndex != index" type="primary"
:key="item.id" @click="changeCategory(index)"> v-for="(item, index) in goodsStore.categoryList" :key="item.id" @click="changeCategory(index)">
{{ item.name }} {{ item.name }}
</el-button> </el-button>
</div> </div>
@ -34,8 +34,8 @@
</div> </div>
<div class="right"> <div class="right">
<div class="input"> <div class="input">
<el-input placeholder="请输入商品名称查询" v-model="commdityName" clearable @focus=" <el-input placeholder="请输入商品名称查询" v-model="commdityName" clearable @input="inputChange"
global.updateData(false)" @blur="global.updateData(true)" @input="inputChange"></el-input> style="width:200px"></el-input>
</div> </div>
<el-button :loading="searchLoading" :icon="Search" @click="searchHandle">搜索</el-button> <el-button :loading="searchLoading" :icon="Search" @click="searchHandle">搜索</el-button>
</div> </div>
@ -44,8 +44,8 @@
</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 ref="swiperRef" :loop="false" class="swiper_box" direction="vertical" @slideChange="onSlideChange"> <swiper ref="swiperRef" :loop="false" class="swiper_box" direction="vertical">
<swiper-slide class="slide_item" v-for="(goods, index) in goodsList" :key="index"> <swiper-slide class="slide_item" v-for="(goods, index) in goodsStore.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">
<transition name="el-fade-in"> <transition name="el-fade-in">
@ -63,14 +63,14 @@
</div> </div>
</div> </div>
</transition> </transition>
<div class="dot" v-if="item.orderCount">{{ item.orderCount }}</div> <div class="dot" v-if="item.number">{{ item.number }}</div>
<div class="cover" v-if="shopListType == 'img'"> <div class="cover" v-if="shopListType == 'img'">
<el-image :src="`${item.coverImg}?x-oss-process=image/resize,m_lfit,w_150,h_150`" <el-image :src="`${item.coverImg}?x-oss-process=image/resize,m_lfit,w_150,h_150`"
class="el_img" fit="cover"></el-image> class="el_img" fit="cover"></el-image>
<div class="sell_out" v-if="item.isPauseSale == 1"> <div class="sell_out" v-if="item.isPauseSale == 1">
<img class="sell_out_icon" src="../../../assets/icon_xq.png"> <img class="sell_out_icon" src="../../../assets/icon_xq.png">
</div> </div>
<div class="weight" v-if="item.type == 'weigh'">称重</div> <div class="weight" v-if="item.type == 'weight'">称重</div>
</div> </div>
<div class="name"><el-text line-clamp="1">{{ item.name }}</el-text></div> <div class="name"><el-text line-clamp="1">{{ item.name }}</el-text></div>
<div class="item_empty" v-if="shopListType == 'text'"></div> <div class="item_empty" v-if="shopListType == 'text'"></div>
@ -88,7 +88,7 @@
</swiper> </swiper>
</div> </div>
<div class="empty"> <div class="empty">
<el-empty description="空空如也~" v-if="!goodsList.length" /> <el-empty description="空空如也~" v-if="!goodsStore.goodsList.length" />
</div> </div>
<!-- 选择规格 --> <!-- 选择规格 -->
<skuModal ref="skuModalRef" @success="skuConfirm" /> <skuModal ref="skuModalRef" @success="skuConfirm" />
@ -172,31 +172,31 @@
<div class="el-popover__title content"> <div class="el-popover__title content">
<el-form ref="temporaryFormRef" :model="temporaryForm" :rules="temporaryFormRules" label-width="100px" <el-form ref="temporaryFormRef" :model="temporaryForm" :rules="temporaryFormRules" label-width="100px"
label-position="left"> label-position="left">
<el-form-item label="菜品名称" prop="name"> <el-form-item label="菜品名称" prop="product_name">
<el-input v-model="temporaryForm.name" placeholder="请输入菜品名称" /> <el-input v-model="temporaryForm.product_name" placeholder="请输入菜品名称" />
</el-form-item> </el-form-item>
<el-form-item label="菜品分类" prop="categoryId"> <!-- <el-form-item label="菜品分类" prop="categoryId">
<el-select v-model="temporaryForm.categoryId" placeholder="请选择菜品分类"> <el-select v-model="temporaryForm.categoryId" placeholder="请选择菜品分类">
<el-option v-for="item in temporaryCategorys" :key="item.id" :label="item.name" <el-option v-for="item in goodsStore.originCategoryList" :key="item.id" :label="item.name"
:value="item.id"></el-option> :value="item.id"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item> -->
<el-form-item label="价格" prop="price"> <el-form-item label="价格" prop="discount_sale_amount">
<el-input v-model="temporaryForm.price" placeholder="请输入价格" @input="priceInput"> <el-input v-model="temporaryForm.discount_sale_amount" placeholder="请输入价格" @input="priceInput">
<template #append></template> <template #append></template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="单位" prop="unit"> <!-- <el-form-item label="单位" prop="unit">
<el-select v-model="temporaryForm.unit" placeholder="请选择单位"> <el-select v-model="temporaryForm.unit" placeholder="请选择单位">
<el-option v-for="item in units" :key="item.id" :label="item.name" <el-option v-for="item in units" :key="item.id" :label="item.name"
:value="item.name"></el-option> :value="item.name"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item> -->
<el-form-item label="下单数量"> <el-form-item label="下单数量">
<el-input-number v-model="temporaryForm.num" :min="1" /> <el-input-number v-model="temporaryForm.number" :min="1" />
</el-form-item> </el-form-item>
<el-form-item label="备注"> <el-form-item label="备注">
<el-input v-model="temporaryForm.note" type="textarea" placeholder="请输入自定义备注" /> <el-input v-model="temporaryForm.remark" type="textarea" placeholder="请输入自定义备注" />
<div class="remark_list"> <div class="remark_list">
<div class="item" v-for="item in noteList" :key="item" @click="addNote(item)"> <div class="item" v-for="item in noteList" :key="item" @click="addNote(item)">
{{ item }} {{ item }}
@ -233,6 +233,7 @@ import WeightModal from './weightModal.vue'
import GroupModal from './groupModal.vue' import GroupModal from './groupModal.vue'
import { queryCategory, queryNewCommodityInfo, queryProductSku, productStatus, productStock, getUnitList, temporaryDishes } from '@/api/product' import { queryCategory, queryNewCommodityInfo, queryProductSku, productStatus, productStock, getUnitList, temporaryDishes } from '@/api/product'
import { useUser } from "@/store/user.js" import { useUser } from "@/store/user.js"
import { useGoods } from '@/store/goods.js'
import { Swiper, SwiperSlide } from 'swiper/vue' import { Swiper, SwiperSlide } from 'swiper/vue'
import "swiper/swiper-bundle.css"; import "swiper/swiper-bundle.css";
import { staffPermission } from '@/api/user.js' import { staffPermission } from '@/api/user.js'
@ -244,6 +245,7 @@ const swiperRef = ref(null)
const global = useGlobal() const global = useGlobal()
const store = useUser() const store = useUser()
const goodsStore = useGoods()
const props = defineProps({ const props = defineProps({
masterId: { masterId: {
@ -264,18 +266,13 @@ const categorysActive = ref(0)
const commdityName = ref('') const commdityName = ref('')
const loading = ref(false) const loading = ref(false)
const goodsList = ref([])
const goodsPage = ref(1)
const goodsPageSize = ref(12)
const finish = ref(false) //
const currentGoodsIndex = ref(0)
const loopMax = ref(0)
const loopTimer = ref(null)
const showPopover = ref(false) const showPopover = ref(false)
//
const inputChange = _.debounce(function () { const inputChange = _.debounce(function () {
searchHandle() // updateGoods()
goodsStore.filterNameGoods(commdityName.value)
}, 500) }, 500)
@ -286,16 +283,11 @@ const units = ref([]) // 单位列表
const temporaryFormRef = ref(null) const temporaryFormRef = ref(null)
const resetTemporaryForm = ref({}) const resetTemporaryForm = ref({})
const temporaryForm = ref({ const temporaryForm = ref({
masterId: '', is_temporary: 1, //
shopId: '', discount_sale_amount: '12', //
tableId: '', product_name: '西红寺', //
name: '', number: 1, //
categoryId: '', remark: '', //
price: '',
unit: '',
num: 1,
note: '',
vipUserId: ''
}) })
const temporaryFormLoading = ref(false) const temporaryFormLoading = ref(false)
@ -313,15 +305,15 @@ function priceInput(e) {
// //
function addNote(str) { function addNote(str) {
if (!temporaryForm.value.note.length) { if (!temporaryForm.value.remark.length) {
temporaryForm.value.note += str temporaryForm.value.remark += str
} else { } else {
temporaryForm.value.note += `${str}` temporaryForm.value.remark += `${str}`
} }
} }
const temporaryFormRules = ref({ const temporaryFormRules = ref({
name: [ product_name: [
{ {
required: true, required: true,
message: '请输入菜品名称', message: '请输入菜品名称',
@ -335,7 +327,7 @@ const temporaryFormRules = ref({
trigger: 'change', trigger: 'change',
} }
], ],
price: [ discount_sale_amount: [
{ {
required: true, required: true,
message: '请输入价格', message: '请输入价格',
@ -383,22 +375,14 @@ function temporaryFormSubmit() {
try { try {
if (valid) { if (valid) {
temporaryFormLoading.value = true temporaryFormLoading.value = true
goodsStore.addCart(temporaryForm.value)
temporaryForm.value.masterId = props.masterId
temporaryForm.value.shopId = store.userInfo.shopId
temporaryForm.value.tableId = global.tableInfo.qrcode
await temporaryDishes(temporaryForm.value)
temporaryFormLoading.value = false
showTemporaryDish.value = false showTemporaryDish.value = false
ElMessage.success('添加成功')
emit('success', { isTemporary: true })
} }
} catch (error) { } catch (error) {
temporaryFormLoading.value = false temporaryFormLoading.value = false
console.log(error); console.log(error);
} }
temporaryFormLoading.value = false
}) })
} }
@ -411,21 +395,30 @@ const GroupModalRef = ref(null)
// //
const searchLoading = ref(false) const searchLoading = ref(false)
function searchHandle() { function searchHandle() {
searchLoading.value = true // searchLoading.value = true
goodsList.value = [] // updateGoods()
goodsPage.value = 1 goodsStore.filterNameGoods(commdityName.value)
finish.value = false
currentGoodsIndex.value = 0
loopMax.value = 0
loopTimer.value = null
updataGoods()
} }
// //
function skuConfirm(params) { function skuConfirm(params) {
emit('loading') console.log(params);
emit('success', params) let goodsItem = goodsStore.cartList.find(goods => goods.product_id == params.productId && goods.sku_id == params.id)
if (goodsItem && goodsItem.id) {
//
if (params.type && params.type == 'weight') {
//
goodsStore.operateCart({ ...goodsItem, number: params.number }, 'edit')
} else if (params.type && params.type == 'package') {
//
goodsStore.addCart(params)
} else {
goodsStore.operateCart({ ...goodsItem, number: +goodsItem.number + 1 }, 'edit')
}
} else {
//
goodsStore.addCart(params)
}
} }
// //
@ -439,7 +432,7 @@ async function showEditorChange() {
await staffPermission('yun_xu_xiu_gai_shang_pin') await staffPermission('yun_xu_xiu_gai_shang_pin')
if (showEditor.value) { if (showEditor.value) {
showEditor.value = false showEditor.value = false
goodsList.value.map(item => { goodsStore.goodsList.value.map(item => {
item.map(val => { item.map(val => {
val.showMore = false val.showMore = false
}) })
@ -460,7 +453,7 @@ function showSkuHandle(item) {
goodEditorItem.value = item goodEditorItem.value = item
showCloseSell.value = true showCloseSell.value = true
} else { } else {
goodsList.value.map(item => { goodsStore.goodsList.value.map(item => {
item.map(val => { item.map(val => {
val.showMore = false val.showMore = false
}) })
@ -476,7 +469,7 @@ function showSkuHandle(item) {
}) })
return return
} }
if (categorys.value[categorysActive.value].id == '-1') { if (goodsStore.categoryList[goodsStore.categoryIndex].id == '-1') {
ElMessage({ ElMessage({
type: 'error', type: 'error',
message: '该商品已下架,请上架后操作', message: '该商品已下架,请上架后操作',
@ -484,29 +477,48 @@ function showSkuHandle(item) {
}) })
return return
} }
if (item.type == 'normal') {
if (item.typeEnum == 'sku') { let goodsItem = goodsStore.cartList.find(goods => goods.product_id == item.id)
// if (item.type == 'sku') {
skuModalRef.value.show({ ...item }) //
skuModalRef.value.show({ ...item })
} else if (item.type == 'single') {
//
if (goodsItem && goodsItem.id) {
//
goodsStore.operateCart({ ...goodsItem, number: +goodsItem.number + 1 }, 'edit')
} else { } else {
// //
loading.value = true goodsStore.addCart({ ...item.skuList[0], lowPrice: item.skuList[0].salePrice })
emit('loading')
queryProductSkuAjax(item)
} }
} else if (item.type == 'weigh') { } else if (item.type == 'weight') {
//
WeightModalRef.value.show(item) WeightModalRef.value.show(item)
} else if (item.type == 'package' && item.groupType == 1) { } else if (item.type == 'package' && item.groupType == 1) {
// -
GroupModalRef.value.show(item) GroupModalRef.value.show(item)
} else if (item.type == 'package' && item.groupType == 0) { } else if (item.type == 'package' && item.groupType == 0) {
// //
loading.value = true if (goodsItem && goodsItem.id) {
emit('loading') //
queryProductSkuAjax(item) goodsStore.operateCart({ ...goodsItem, number: +goodsItem.number + 1 }, 'edit')
} else {
//
goodsStore.addCart({
...item.skuList[0], lowPrice: item.skuList[0].salePrice, type: item.type,
goods_type: 'package',
pro_group_info: item.groupSnap.map((item) => item.goods)
})
}
} }
} }
} }
//
function showPackage(item) {
GroupModalRef.value.show(item, 'edit')
}
// //
const queryProductSkuAjax = _.throttle(async function (goods) { const queryProductSkuAjax = _.throttle(async function (goods) {
try { try {
@ -546,153 +558,22 @@ function localUpdateShopListType() {
// //
function changeCategory(index) { function changeCategory(index) {
showPopover.value = false showPopover.value = false
categorysActive.value = index goodsStore.setCategoryIndex(index)
useStorage.set('categorysActive', index)
goodsList.value = []
goodsPage.value = 1
finish.value = false
currentGoodsIndex.value = 0
loopMax.value = 0
clearInterval(loopTimer.value)
loopTimer.value = null
updataGoods()
}
//
function updateCategoryActive() {
return new Promise((resolve, reject) => {
let index = useStorage.get('categorysActive')
if (index != null) {
categorysActive.value = index
}
resolve()
})
}
//
async function queryCategoryAjax() {
try {
const res = await queryCategory({
shopId: store.userInfo.shopId,
page: 1,
pageSize: 100
})
temporaryCategorys.value = [...res.list]
categorys.value = res.list
categorys.value.unshift({
name: '全部',
id: ''
})
categorys.value.push({
name: '已下架',
id: '-1'
})
} catch (error) {
console.log(error)
}
}
//
async function productqueryCommodityInfoAjax(page = goodsPage.value) {
try {
// loading.value = true
const res = await queryNewCommodityInfo({
shopId: store.userInfo.shopId,
categoryId: categorys.value[categorysActive.value].id,
commdityName: commdityName.value,
page: page,
pageSize: goodsPageSize.value,
masterId: props.masterId,
tableId: global.tableInfo.qrcode || '',
})
if (res.list.length < goodsPageSize.value) {
finish.value = true
}
// loading.value = false
// if (res.pages > 2 && loopTimer.value == null) {
// //
// // loopMax.value = parseInt(res.total / goodsPageSize.value)
// loopGetGoods()
// }
// if (goodsPage.value >= res.pages) {
// clearInterval(loopTimer.value)
// loopTimer.value = null
// }
res.list.map((val, index) => {
val.showMore = false
})
return res
} catch (error) {
loading.value = false
console.log(error)
}
}
//
function loopGetGoods() {
loopTimer.value = setInterval(async () => {
goodsPage.value++
const res = await productqueryCommodityInfoAjax()
goodsList.value.push(res.list)
}, 1000)
} }
// //
async function updateData() { async function updateGoods() {
updataGoods() goodsStore.getGoodsList()
} }
//
async function updataGoods() {
if (!goodsList.value.length) {
const res = await productqueryCommodityInfoAjax()
goodsList.value.push(res.list)
if (!res.isLastPage) {
goodsPage.value++
const res2 = await productqueryCommodityInfoAjax()
goodsList.value.push(res2.list)
}
searchLoading.value = false
} else {
const res = await productqueryCommodityInfoAjax(currentGoodsIndex.value + 1)
goodsList.value[currentGoodsIndex.value] = res.list
searchLoading.value = false
}
}
//
const onSlideChange = _.debounce(async function (e) {
if (e.activeIndex == e.previousIndex) return
if (e.activeIndex > e.previousIndex) {
{
goodsPage.value++
const res = await productqueryCommodityInfoAjax()
res.list.length && goodsList.value.push(res.list)
}
{
goodsPage.value++
const res = await productqueryCommodityInfoAjax()
res.list.length && goodsList.value.push(res.list)
}
}
currentGoodsIndex.value = e.activeIndex
}, 500)
// //
function clearDot() { function clearDot() {
// goodsList.value.map(item => { goodsStore.goodsList.value.map(item => {
// item.map(val => { item.map(val => {
// val.orderCount = 0 val.orderCount = 0
// }) })
// }) })
updateData() updateGoods()
} }
const showEditor = ref(false) const showEditor = ref(false)
@ -744,7 +625,7 @@ async function closeSellHandle() {
message: '操作成功', message: '操作成功',
showClose: true, showClose: true,
}) })
updateData() updateGoods()
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@ -781,7 +662,7 @@ async function putawayHandle(item) {
message: '操作成功', message: '操作成功',
showClose: true, showClose: true,
}) })
updateData() updateGoods()
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@ -804,7 +685,7 @@ async function goodEditorConfirm() {
message: '操作成功', message: '操作成功',
showClose: true, showClose: true,
}) })
updateData() updateGoods()
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@ -842,7 +723,7 @@ async function goodStockNumberHandle(item) {
async function goodsEditorStockConfirm() { async function goodsEditorStockConfirm() {
try { try {
goodsEditorStockLoading.value = true goodsEditorStockLoading.value = true
const res = await productStock({ await productStock({
shopId: store.userInfo.shopId, shopId: store.userInfo.shopId,
productId: goodsEditorStockItem.value.id, productId: goodsEditorStockItem.value.id,
stock: goodsEditorStockNumber.value stock: goodsEditorStockNumber.value
@ -854,23 +735,16 @@ async function goodsEditorStockConfirm() {
message: '操作成功', message: '操作成功',
showClose: true, showClose: true,
}) })
updateData() updateGoods()
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
} }
defineExpose({ defineExpose({
updateData, updateGoods,
clearDot clearDot,
}) showPackage
onMounted(async () => {
localUpdateShopListType()
getUnitListAjax()
await updateCategoryActive()
await queryCategoryAjax()
updataGoods()
}) })
</script> </script>

View File

@ -1,7 +1,7 @@
<!-- 称重商品组件 --> <!-- 称重商品组件 -->
<template> <template>
<el-dialog title="可选套餐" width="70%" :close-on-click-modal="false" v-model="dialogVisible" top="10vh"> <el-dialog title="可选套餐" width="70%" :close-on-click-modal="false" v-model="dialogVisible" top="10vh">
<div class="row" v-for="(item, index) in goodsItem.proGroupVo" :key="index"> <div class="row" v-for="(item, index) in goodsItem.groupSnap" :key="index">
<div class="title_wrap"> <div class="title_wrap">
<div class="item">规格组名{{ item.title }}</div> <div class="item">规格组名{{ item.title }}</div>
<div class="item" <div class="item"
@ -43,6 +43,9 @@
import { ref } from "vue"; import { ref } from "vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { inputFilterFloat, formatDecimal } from '@/utils/index.js' import { inputFilterFloat, formatDecimal } from '@/utils/index.js'
import { useGoods } from '@/store/goods.js'
const goodsStore = useGoods()
const dialogVisible = ref(false); const dialogVisible = ref(false);
const number = ref(""); const number = ref("");
@ -52,23 +55,55 @@ const emit = defineEmits(["success"]);
const tabRefs = ref([]) const tabRefs = ref([])
function show(item) { const confirmType = ref('')
disabled.value = true const cartItem = ref('')
function show(item, type = 'add') {
confirmType.value = type
dialogVisible.value = true; dialogVisible.value = true;
goodsItem.value = { ...item } if (type == 'add') {
goodsItem.value.proGroupVo.map(item => { disabled.value = true
item.isError = false goodsItem.value = { ...item }
}) goodsItem.value.groupSnap.map(item => {
setTimeout(() => { item.isError = false
tabRefs.value.map(item => {
item.clearSelection()
}) })
}, 100); setTimeout(() => {
tabRefs.value.map(item => {
item.clearSelection()
})
}, 100);
} else {
cartItem.value = { ...item }
disabled.value = false
goodsItem.value = goodsStore.originGoodsList.find(val => val.id == item.product_id)
// console.log('item===', item)
// console.log('goodsItem.value===', goodsItem.value);
let selectGroup = JSON.parse(item.pro_group_info)
console.log('selectGroup===', selectGroup);
setTimeout(() => {
goodsItem.value.groupSnap.map((item, index) => {
item.goods.map((val, i) => {
selectGroup[index].map(sg => {
if (val.proId == sg.proId) {
tabRefs.value[index].toggleRowSelection(val, true)
}
})
})
})
goodsItem.value.groupSnap.map(item => {
item.isError = false
})
}, 100)
}
} }
// //
function selectChange($event, index) { function selectChange($event, index) {
let item = goodsItem.value.proGroupVo[index] let item = goodsItem.value.groupSnap[index]
let selectNum = tabRefs.value[index].getSelectionRows() let selectNum = tabRefs.value[index].getSelectionRows()
if (selectNum.length != item.number) { if (selectNum.length != item.number) {
@ -79,7 +114,7 @@ function selectChange($event, index) {
let flags = [] let flags = []
goodsItem.value.proGroupVo.map((item, index) => { goodsItem.value.groupSnap.map((item, index) => {
let selectNum = tabRefs.value[index].getSelectionRows() let selectNum = tabRefs.value[index].getSelectionRows()
if (selectNum.length != item.number) { if (selectNum.length != item.number) {
flags.push({ flag: false }) flags.push({ flag: false })
@ -103,7 +138,7 @@ const disabled = ref(true)
function confirmHandle() { function confirmHandle() {
let flags = [] let flags = []
goodsItem.value.proGroupVo.map((item, index) => { goodsItem.value.groupSnap.map((item, index) => {
let selectNum = tabRefs.value[index].getSelectionRows() let selectNum = tabRefs.value[index].getSelectionRows()
if (selectNum.length != item.number) { if (selectNum.length != item.number) {
flags.push({ flag: false }) flags.push({ flag: false })
@ -122,17 +157,25 @@ function confirmHandle() {
disabled.value = false disabled.value = false
let goodIds = [] let goodIds = []
goodsItem.value.proGroupVo.map((item, index) => { goodsItem.value.groupSnap.map((item, index) => {
let selectNum = tabRefs.value[index].getSelectionRows() let selectNum = tabRefs.value[index].getSelectionRows()
goodIds.push(selectNum) goodIds.push(selectNum)
}) })
// //
emit("success", { if (confirmType.value == 'add') {
...goodsItem.value, emit("success", {
productId: goodsItem.value.id, ...goodsItem.value.skuList[0],
groupProductIdList: goodIds.flat().map(item => item.proId) goods_type: goodsItem.value.type,
}); pro_group_info: goodIds
});
} else {
//
goodsStore.operateCart({
...cartItem.value,
pro_group_info: goodIds
}, 'edit')
}
dialogVisible.value = false; dialogVisible.value = false;
} }

View File

@ -26,26 +26,72 @@
</div> </div>
</div> </div>
<div class="list_wrap card" style="margin-top: var(--el-font-size-base)"> <div class="list_wrap card" style="margin-top: var(--el-font-size-base)">
<div class="item" v-for="item in cartList" :key="item.id"> <div class="item" v-for="item in goodsStore.cartList" :key="item.id">
<div class="top"> <div class="top">
<span class="name">{{ item.name }}</span> <div class="name">
<span class="n">x{{ item.number }}</span> <span v-if="item.is_temporary" style="color: #999;"> [临时菜]</span>
<span class="p">{{ item.salePrice }}</span> {{ item.product_name }}
</div>
<div class="n">x{{ formatDecimal(+item.number, 2, true) }}</div>
<div class="p">
<template v-if="item.is_temporary">
<template v-if="item.is_gift">
<span class="t_line">{{ formatDecimal(+item.discount_sale_amount) }}</span>
0.00
</template>
<template v-else>
<span>{{ formatDecimal(item.discount_sale_amount * item.number) }}</span>
</template>
</template>
<template v-else>
<template v-if="item.is_gift">
<span class="t_line">{{ formatDecimal(+item.lowPrice) }}</span>
0.00
</template>
<template v-else>
<template v-if="+item.discount_sale_amount">
<span class="t_line">
{{ formatDecimal(+item.lowPrice) }}
</span>
<span>
{{ formatDecimal(+item.discount_sale_amount) }}
</span>
</template>
<template v-else>
{{ formatDecimal(+item.lowPrice) }}
</template>
</template>
</template>
</div>
</div> </div>
<div class="gift_wrap" v-if="item.isGift == 'true'"> <div class="tag_wrap" v-if="item.sku_name">
<span>[赠送]</span> <div class="tag" v-for="item in item.sku_name.split(',')">
<span>-{{ item.salePrice }}</span>
</div>
<div class="tag_wrap" v-if="item.skuName">
<div class="tag" v-for="item in item.skuName.split(',')">
{{ item }} {{ item }}
</div> </div>
</div> </div>
<div class="packge_Wrap" v-if="item.isPack == 'true'"> <div class="gift_wrap" v-if="item.is_gift">
<div class="icon_item" v-if="item.isPack == 'true'" @click="giftPackHandle('isPack', item)"> <div class="name">
<el-icon class="icon" style="color: var(--primary-color)"> <span v-if="item.is_gift">[赠送]</span>
<Box /> </div>
</el-icon> <div class="n"></div>
<div class="p">
<span>
-<template v-if="item.is_temporary || +item.discount_sale_amount">
{{ formatDecimal(+item.discount_sale_amount) }}
</template>
<template v-else>{{ formatDecimal(+item.lowPrice) }}</template>
</span>
</div>
</div>
<div class="gift_wrap" v-if="!item.is_temporary && !item.is_gift && item.discount_sale_amount">
<div class="name">
<span>[改价优惠]</span>
</div>
<div class="n"></div>
<div class="p">
<span>
-{{ formatDecimal(item.lowPrice - item.discount_sale_amount) }}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -64,8 +110,8 @@
</div> </div>
</div> </div>
<div class="pay_wrap"> <div class="pay_wrap">
<payCard :amount="props.amount" :discount="propsDiscount" :orderId="props.orderInfo.id" @paySuccess="paySuccess" <payCard :amount="goodsStore.orderInfo.originAmount" :discount="propsDiscount" :orderId="props.orderInfo.id"
@cancelDiscount="propsDiscount = 0" /> @paySuccess="paySuccess" @cancelDiscount="propsDiscount = 0" />
</div> </div>
</div> </div>
<el-dialog v-model="showStaffDiscount" title="员工折扣" @close="global.updateData(true)"> <el-dialog v-model="showStaffDiscount" title="员工折扣" @close="global.updateData(true)">
@ -105,9 +151,12 @@ import { formatDecimal } from '@/utils/index.js'
import receiptPrint from "@/components/lodop/receiptPrint.js"; import receiptPrint from "@/components/lodop/receiptPrint.js";
import { useGlobal } from '@/store/global.js' import { useGlobal } from '@/store/global.js'
import { usePrint } from '@/store/print.js' import { usePrint } from '@/store/print.js'
import { useGoods } from '@/store/goods.js'
import { staffPermission } from '@/api/user.js' import { staffPermission } from '@/api/user.js'
const goodsStore = useGoods()
const global = useGlobal() const global = useGlobal()
const printStore = usePrint() const printStore = usePrint()
@ -424,30 +473,42 @@ defineExpose({
padding: var(--el-font-size-base) 0; padding: var(--el-font-size-base) 0;
border-bottom: 1px solid #ececec; border-bottom: 1px solid #ececec;
.name {
flex: 1.5;
}
.n {
width: 30px;
color: #555;
}
.p {
flex: 1;
color: #555;
display: flex;
justify-content: flex-end;
}
.t_line {
text-decoration: line-through;
color: #999;
margin-right: 4px;
}
.top { .top {
display: flex; display: flex;
padding-bottom: 6px; padding-bottom: 6px;
.name {
flex: 1;
}
.n {
width: 50px;
color: #555;
}
.p {
width: 50px;
color: #555;
}
} }
.gift_wrap { .gift_wrap {
display: flex; display: flex;
justify-content: space-between;
color: #999; color: #999;
font-size: 16px; font-size: 16px;
.p {
color: var(--el-color-danger);
}
} }
.tag_wrap { .tag_wrap {

View File

@ -80,11 +80,10 @@ const loading = ref(false)
// //
function confirmHandle() { function confirmHandle() {
if (!number.value) return if (!number.value) return
goodsItem.value.productId = goodsItem.value.id // goodsItem.value.productId = goodsItem.value.id
goodsItem.value.number = number.value // goodsItem.value.number = number.value
emit("success", goodsItem.value);
dialogVisible.value = false; dialogVisible.value = false;
emit("success", { ...goodsItem.value.skuList[0], number: number.value, type: goodsItem.value.type });
} }
defineExpose({ defineExpose({

View File

@ -8,20 +8,20 @@
</el-icon> </el-icon>
<el-text class="t">({{ pendingCartNum }})</el-text> <el-text class="t">({{ pendingCartNum }})</el-text>
</div> </div>
<div class="number" @click="takeFoodCodeRef.show()"> <div class="number" @click="SelectVipUserRef.show()">
<el-text class="t">{{ masterId }}</el-text> <el-icon class="icon">
<UserFilled />
</el-icon>
<el-text class="t">选择会员</el-text>
</div> </div>
<div class="select_user" @click="quickCashHandle" <div class="select_user" @click="quickCashHandle"
v-if="!global.orderMemberInfo.telephone && !global.tableInfo.id"> v-if="!global.orderMemberInfo.telephone && !global.tableInfo.id">
<div class="left"> <div class="left">
<el-icon class="icon"> <el-icon class="icon" style="color: var(--el-color-warning);">
<WalletFilled /> <WalletFilled />
</el-icon> </el-icon>
<el-text class="t">快捷收银</el-text> <el-text class="t">快捷收银</el-text>
</div> </div>
<el-icon class="arrow">
<ArrowRight />
</el-icon>
</div> </div>
<div class="select_user" v-else @click="clearMember"> <div class="select_user" v-else @click="clearMember">
<div class="left"> <div class="left">
@ -45,7 +45,89 @@
</div> </div>
<div class="shop_operation"> <div class="shop_operation">
<div class="shop_list"> <div class="shop_list">
<template v-for="(arr, index) in cartList" :key="index"> <div class="table_info" v-if="goodsStore.tableInfo.name">
<div class="left">
<span>台桌{{ goodsStore.tableInfo.name }}</span>
<span>{{ goodsStore.tableInfo.num }}</span>
</div>
<div class="close" @click="goodsStore.selectTable()">
<el-icon class="icon">
<Close />
</el-icon>
</div>
</div>
<div class="item" :class="{ active: item.active }" v-for="(item, index) in goodsStore.cartList" :key="item.id"
@click="selectCartItemHandle(index)">
<div class="name_wrap">
<span>{{ item.product_name }}</span>
<template v-if="item.is_gift">
<div class="price">
<span class="dis" v-if="item.is_temporary">
{{ formatDecimal(+item.discount_sale_amount, 2, true) }}
</span>
<span class="dis" v-else>
{{ formatDecimal(+item.lowPrice, 2, true) }}
</span>
<span v-if="item.discount_sale_amount">
0.00
</span>
</div>
</template>
<template v-else>
<div class="price" v-if="item.is_temporary">
<span>
{{ formatDecimal(+item.discount_sale_amount, 2, true) }}
</span>
</div>
<div class="price" v-else>
<template v-if="+item.discount_sale_amount">
<span class="dis">
{{ formatDecimal(item.lowPrice, 2, true) }}
</span>
<span>
{{ formatDecimal(+item.discount_sale_amount, 2, true) }}
</span>
</template>
<span v-else>
{{ formatDecimal(+item.lowPrice, 2, true) }}
</span>
</div>
</template>
</div>
<div class="sku_list" v-if="item.sku_name">
<div class="tag" v-for="item in item.sku_name.split(',')">
{{ item }}
</div>
</div>
<div class="grooup_wrap" v-if="item.goods_type == 'package'">
{{ item.group_type == 0 ? '固定套餐:' : '自选套餐:' }}
<span>{{ item.group_text }}</span>
</div>
<div class="num">
<div class="left">
<div class="icon_item zen" v-if="item.is_gift">
<span class="t"></span>
</div>
<div class="icon_item bao" v-if="item.is_pack">
<span class="t"></span>
</div>
<!-- <div class="icon_item tui" v-if="item.status == 'return'">
<span class="t">退</span>
</div> -->
<div class="icon_item lin" v-if="item.is_temporary == 1">
<span class="t"></span>
</div>
<div class="icon_item zhe" v-if="item.discount_sale_amount > 0 && !item.is_temporary">
<span class="t"></span>
</div>
<div class="icon_item chu" v-if="item.is_print == 0">
<span class="t">免厨打印</span>
</div>
</div>
<el-text class="t">x{{ formatDecimal(+item.number, 2, true) }}</el-text>
</div>
</div>
<template v-for="(arr, index) in goodsStore.orderList" :key="index">
<el-divider v-if="arr.placeNum">{{ `${arr.placeNum}次下单` }}</el-divider> <el-divider v-if="arr.placeNum">{{ `${arr.placeNum}次下单` }}</el-divider>
<div class="item" :class="{ active: item.active }" :key="item.id" v-for="(item, i) in arr.info" <div class="item" :class="{ active: item.active }" :key="item.id" v-for="(item, i) in arr.info"
@click="selectCartItemHandle(item, index, i)"> @click="selectCartItemHandle(item, index, i)">
@ -64,14 +146,14 @@
</div> </div>
<div class="grooup_wrap" v-if="item.proGroupInfo"> <div class="grooup_wrap" v-if="item.proGroupInfo">
{{ item.groupType == 0 ? '固定套餐:' : '自选套餐:' }} {{ item.groupType == 0 ? '固定套餐:' : '自选套餐:' }}
<span>{{ JSON.parse(item.proGroupInfo).map(item => item.proName).join('、') }}</span> <span>{{JSON.parse(item.proGroupInfo).map(item => item.proName).join('、')}}</span>
</div> </div>
<div class="num"> <div class="num">
<div class="left"> <div class="left">
<div class="icon_item zen" v-if="item.isGift == 'true'" @click="giftPackHandle('isGift', item)"> <div class="icon_item zen" v-if="item.is_gift" @click="giftPackHandle('isGift', item)">
<span class="t"></span> <span class="t"></span>
</div> </div>
<div class="icon_item bao" v-if="item.isPack == 'true'" @click="giftPackHandle('isPack', item)"> <div class="icon_item bao" v-if="item.is_pack" @click="giftPackHandle('isPack', item)">
<span class="t"></span> <span class="t"></span>
</div> </div>
<div class="icon_item tui" v-if="item.status == 'return'"> <div class="icon_item tui" v-if="item.status == 'return'">
@ -92,17 +174,16 @@
</div> </div>
</template> </template>
<div class="empty"> <div class="empty">
<el-empty description="请选择商品" v-if="!cartList.length" /> <el-empty description="请选择商品" v-if="!goodsStore.cartList.length" />
</div> </div>
</div> </div>
<!-- 购物车操作栏 --> <!-- 购物车操作栏 -->
<cartOperation :item="cartListActiveItem" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle" <cartOperation :item="cartListActiveItem" @confirm="" @delete="delCartHandle" @pending="pendingCart"
@pending="pendingCart" @clearCart="clearCartHandle" @merging="showTableMerging" /> @merging="showTableMerging" @showPackage="e => goodsRef.showPackage(e)" />
</div> </div>
<div class="footer"> <div class="footer">
<div class="top"> <div class="top">
<div class="left" @click="allSelectedHandle" <div class="left" @click="allSelectedHandle" v-if="store.shopInfo.eatModel == 'take-out'">
v-if="JSON.parse(shopStore.info.eatModel).some(item => item == 'take-out')">
<div class="selected"> <div class="selected">
<div class="selected_round" v-if="!allSelected"></div> <div class="selected_round" v-if="!allSelected"></div>
<el-icon class="icon" v-else> <el-icon class="icon" v-else>
@ -113,16 +194,27 @@
</div> </div>
<div class="left" v-else></div> <div class="left" v-else></div>
<div class="num-wrap"> <div class="num-wrap">
<!-- {{ cartInfo.productNum || 0 }}种商品 --> <div class="num_wrap_top">
<el-text>{{ <el-text>
cartInfo.productSum || 0 {{ goodsStore.cartInfo.total }}
}}</el-text>{{ formatDecimal(cartInfo.totalAmount || 0) }} </el-text>{{ formatDecimal(goodsStore.cartInfo.totalAmount || 0) }}
</div>
<div class="num_wrap_btm">
<span v-if="goodsStore.cartInfo.gifNumberAmount">赠送{{ formatDecimal(goodsStore.cartInfo.gifNumberAmount
|| 0, 2, true)
}}</span>
<span v-if="goodsStore.cartInfo.gifNumberAmount && goodsStore.cartInfo.saleNumberAmount"></span>
<span v-if="goodsStore.cartInfo.saleNumberAmount">改价优惠{{
formatDecimal(goodsStore.cartInfo.saleNumberAmount
|| 0, 2, true)
}}</span>
</div>
</div> </div>
</div> </div>
<div class="btm"> <div class="btm">
<el-button icon="Edit" @click="remarkRef.show()"></el-button> <el-button icon="Edit" @click="remarkRef.show()"></el-button>
<div class="button"> <div class="button">
<div class="btn" v-if="shopStore.info.registerType == 'restaurant'"> <div class="btn" v-if="store.shopInfo.registerType == 'restaurant'">
<el-button type="primary" style="width: 100%;" :disabled="!cartList.length" v-loading="createOrderLoading" <el-button type="primary" style="width: 100%;" :disabled="!cartList.length" v-loading="createOrderLoading"
@click="createOrderHandle(0)"> @click="createOrderHandle(0)">
<template v-if="!createOrderLoading"> <template v-if="!createOrderLoading">
@ -130,9 +222,9 @@
<template v-else>下单中...</template> <template v-else>下单中...</template>
</el-button> </el-button>
</div> </div>
<div class="btn" v-if="shopStore.info.registerType != 'restaurant' || cartList.length"> <div class="btn" v-if="store.shopInfo.registerType != 'restaurant' || goodsStore.cartList.length">
<el-button type="primary" style="width: 100%;" :disabled="!cartList.length" v-loading="createOrderLoading" <el-button type="primary" style="width: 100%;" :disabled="!goodsStore.cartList.length"
@click="createOrderHandle(1)"> v-loading="createOrderLoading" @click="createOrderHandle(1)">
<template v-if="!createOrderLoading"> <template v-if="!createOrderLoading">
去结算</template> 去结算</template>
<template v-else>下单中...</template> <template v-else>下单中...</template>
@ -144,7 +236,7 @@
</div> </div>
<div class="shop_manage card"> <div class="shop_manage card">
<!-- 分类/商品列表 --> <!-- 分类/商品列表 -->
<goods ref="goodsRef" :masterId="masterId" @success="addCart" @loading="cartLoading = true" /> <goods ref="goodsRef" @loading="cartLoading = true" />
<!-- ©银收客 v{{ packageData.version }} --> <!-- ©银收客 v{{ packageData.version }} -->
</div> </div>
</div> </div>
@ -155,10 +247,10 @@
<el-drawer v-model="membershow" :with-header="true" size="90%" title="选择会员"> <el-drawer v-model="membershow" :with-header="true" size="90%" title="选择会员">
<member :membershow="'1'"></member> <member :membershow="'1'"></member>
</el-drawer> </el-drawer>
<takeFoodCode ref="takeFoodCodeRef" title="修改取餐号" placeholder="请输入取餐号" @success="takeFoodCodeSuccess" /> <!-- <takeFoodCode ref="takeFoodCodeRef" title="修改取餐号" placeholder="请输入取餐号" @success="takeFoodCodeSuccess" /> -->
<!-- 结算订单 --> <!-- 结算订单 -->
<settleAccount ref="settleAccountRef" :cart="cartList" :amount="cartInfo.totalAmount" :remark="remark" <settleAccount ref="settleAccountRef" :cart="cartList" :amount="cartInfo.totalAmount" :remark="remark"
:masterId="masterId" :orderInfo="orderInfo" @paySuccess="createCodeAjax(1)" /> :orderInfo="orderInfo" @paySuccess="createCodeAjax(1)" />
<!-- 快捷收银 --> <!-- 快捷收银 -->
<fastCashier ref="fastCashierRef" type="0" /> <fastCashier ref="fastCashierRef" type="0" />
<!-- 挂起订单 --> <!-- 挂起订单 -->
@ -166,7 +258,9 @@
<!-- 检查版本升级 --> <!-- 检查版本升级 -->
<updateDialog /> <updateDialog />
<!-- 合并/转桌 --> <!-- 合并/转桌 -->
<tableMerging ref="tableMergingRef" @success="addCart" /> <tableMerging ref="tableMergingRef" @success="" />
<!-- 选择会员 -->
<SelectVipUser ref="SelectVipUserRef" />
</template> </template>
<script> <script>
@ -176,10 +270,10 @@ export default {
</script> </script>
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useRoute } from 'vue-router'
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import { useGlobal } from '@/store/global.js' import { useGlobal } from '@/store/global.js'
import SelectVipUser from "@/components/selectVipUser.vue";
import updateDialog from '@/components/updateDialog.vue' import updateDialog from '@/components/updateDialog.vue'
import remarkModal from "@/components/remarkModal.vue"; import remarkModal from "@/components/remarkModal.vue";
import takeFoodCode from "@/components/takeFoodCode.vue"; import takeFoodCode from "@/components/takeFoodCode.vue";
@ -190,35 +284,25 @@ import pendingCartModal from "@/views/home/components/pendingCartModal.vue";
import tableMerging from '@/views/home/components/tableMerging.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'
import { useGoods } from '@/store/goods.js'
import {
createCart,
queryCart,
createCode,
packall,
delCart,
cartStatus,
clearCart,
createOrder,
} from "@/api/product";
import { orderChoseCount } from '@/api/table.js'
import { queryShopInfo, staffPermission } from '@/api/user.js' import { queryShopInfo, staffPermission } from '@/api/user.js'
import { createOrder } from '@/api/order.js'
// //
import goods from "@/views/home/components/goods.vue"; import goods from "@/views/home/components/goods.vue";
import member from "@/views/member/index.vue"; import member from "@/views/member/index.vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useShop } from '@/store/shop.js'
import TableMerging from "./components/tableMerging.vue"; import TableMerging from "./components/tableMerging.vue";
const shopStore = useShop() const SelectVipUserRef = ref(null)
const goodsStore = useGoods()
const global = useGlobal() const global = useGlobal()
const route = useRoute()
const membershow = ref(false); const membershow = ref(false);
const store = useUser(); const store = useUser();
@ -242,8 +326,6 @@ const cartLoading = ref(false);
const orderInfo = ref({}); const orderInfo = ref({});
const createOrderLoading = ref(false); const createOrderLoading = ref(false);
//
const masterId = ref("");
// //
const pendingCartNum = ref(0); const pendingCartNum = ref(0);
@ -262,99 +344,35 @@ async function quickCashHandle() {
async function createOrderHandle(t = 0) { async function createOrderHandle(t = 0) {
try { try {
createOrderLoading.value = true; createOrderLoading.value = true;
await staffPermission('yun_xu_xia_dan')
const res = await createOrder({ const res = await createOrder({
masterId: masterId.value, orderId: goodsStore.orderList.length ? goodsStore.orderList[0].id : '', // id
shopId: store.userInfo.shopId, shopId: store.shopInfo.id, // id
remark: remark.value, seatNum: goodsStore.tableInfo.num || 0, //
vipUserId: global.orderMemberInfo.id || '', packFee: 0, //
tableId: global.tableInfo.qrcode || '', originAmount: formatDecimal(goodsStore.cartInfo.totalAmount, 2, true), // +
type: t, tableCode: goodsStore.cartList[0].table_code, //
seatNum: global.tableInfo.num dineMode: store.shopInfo.eatModel, //
}); remark: remark.value, //
createOrderLoading.value = false; placeNumplaceNum: goodsStore.orderList.length, //
waitCall: 0,//
userId: '', // id
vipPrice: 0, //
})
// goodsStore.orderInfo = res
orderInfo.value = res; settleAccountRef.value.show()
if (shopStore.info.registerType == 'restaurant' && t == 0) {
ElMessage.success('下单成功')
queryCartAjax()
} else {
settleAccountRef.value.show();
}
// if (global.tableInfo.id && t == 0) {
// ElMessage.success('')
// global.setOrderTable({})
// createCodeAjax(1)
// } else {
// orderInfo.value = res;
// settleAccountRef.value.show();
// }
} catch (error) {
console.log(error);
createOrderLoading.value = false;
}
}
//
async function clearCartHandle() {
try {
await clearCart({
shopId: store.userInfo.shopId,
masterId: masterId.value,
tableId: global.tableInfo.qrcode || ''
});
cartListActiveItem.value = {}
queryCartAjax();
//
goodsRef.value.clearDot()
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
createOrderLoading.value = false;
} }
// //
async function pendingCartHandle(item) { async function pendingCartHandle(item) {
const nItem = { ...item };
if (cartList.value.length) {
//
await pendingCart({ masterId: masterId.value });
}
masterId.value = nItem.masterId;
await pendingCart(nItem, false);
await queryCartAjax();
} }
// //
async function pendingCart(params, status = true) { async function pendingCart(params, status = true) {
try {
cartLoading.value = true;
await cartStatus({
shopId: store.userInfo.shopId,
masterId: params.masterId,
status: status,
uuid: params.uuid,
vipUserId: global.orderMemberInfo.id || '',
tableId: global.tableInfo.qrcode || '',
orderId: params.orderId
});
if (status && cartList.value.length) {
await createCodeAjax();
setTimeout(() => {
cartLoading.value = false;
}, 500);
} else {
setTimeout(() => {
cartLoading.value = false;
}, 500);
}
} catch (error) {
cartLoading.value = false;
console.log(error);
}
} }
// //
@ -362,7 +380,6 @@ async function delCartHandle(params) {
try { try {
cartLoading.value = true; cartLoading.value = true;
await delCart({ await delCart({
masterId: params.masterId,
cartId: params.id, cartId: params.id,
}); });
cartListActiveItem.value = {} cartListActiveItem.value = {}
@ -388,189 +405,19 @@ const allSelectedHandle = async () => {
await packall({ await packall({
shopId: store.userInfo.shopId, shopId: store.userInfo.shopId,
status: allSelected.value, status: allSelected.value,
masterId: masterId.value,
}); });
queryCartAjax(); //
}; };
// //
async function takeFoodCodeSuccess(code) { function selectCartItemHandle(index) {
if (cartList.value.length) { goodsStore.selectCartItemHandle(index)
await pendingCart({
masterId: masterId.value,
uuid: cartList.value[0].uuid,
});
}
masterId.value = `#${code}`;
queryCartAjax();
}
//
function selectCartItemHandle(row, index, i) {
cartList.value.map(item => {
item.info.map(val => {
if (val.id == row.id) {
val.active = true
cartListActiveItem.value = val
} else {
val.active = false
}
})
})
}
//
async function addCart(params = {}, type = "add") {
console.log(params);
try {
cartLoading.value = true;
if (params.isTemporary) {
await createCodeAjax()
cartLoading.value = false;
} else {
let skuId = ''
if (params.skuList && params.skuList.length) {
skuId = params.skuList[0].id
} else {
skuId = type == "add" ? params.id : params.skuId
}
const res = await createCart({
productId: params.productId,
masterId: masterId.value,
tableId: global.tableInfo.qrcode || '',
vipUserId: global.orderMemberInfo.id || '',
shopId: store.userInfo.shopId,
// skuId: type == "add" ? params.id : params.skuId,
skuId: skuId,
number: params.number || 1,
isPack: params.isPack || "false",
isGift: params.isGift || "false",
cartId: type == "add" ? "" : params.id,
uuid: params.uuid || store.userInfo.uuid,
type: type,
groupProductIdList: params.groupProductIdList || []
});
cartLoading.value = false;
masterId.value = res;
goodsRef.value.updateData();
queryCartAjax();
}
} catch (error) {
console.log(error);
cartLoading.value = false;
}
}
//
async function queryCartAjax() {
try {
const res = await queryCart({
masterId: masterId.value,
shopId: store.userInfo.shopId,
tableId: global.tableInfo.qrcode || '',
vipUserId: global.orderMemberInfo.id || ''
});
if (!res.list.length) {
cartListActiveItem.value = {}
}
res.list.map((item, index) => {
item.info.map((val, i) => {
if (i == 0 && index == 0) {
val.active = true
if (!cartListActiveItem.value.id) {
cartListActiveItem.value = val
}
} else {
val.active = false
}
})
})
cartList.value = res.list;
if (cartListActiveItem.value.id) {
selectCartItemHandle(cartListActiveItem.value)
}
cartInfo.value = res.amount;
pendingCartNum.value = res.num;
// goodsRef.value.updateData();
let i = 0;
res.list.map((item) => {
if (item.isPack == "true") {
i++;
}
});
if (i == res.list.length) {
allSelected.value = true;
} else {
allSelected.value = false;
}
} catch (error) {
console.log("获取购物车商品", error);
}
}
//
async function addTableNum() {
try {
const res = await orderChoseCount({
masterId: masterId.value,
shopId: store.userInfo.shopId,
tableId: global.tableInfo.qrcode,
num: global.tableInfo.num
})
} catch (error) {
console.log(error);
}
}
//
async function createCodeAjax(type = "0") {
try {
// if (!process.env.VITE_DEV_SERVER_URL) {
// masterId.value = '#20'
// } else {
// const res = await createCode({
// shopId: store.userInfo.shopId
// })
// masterId.value = res.code
// }
if (global.tableInfo.masterId) {
masterId.value = global.tableInfo.masterId
} else {
const res = await createCode({
shopId: store.userInfo.shopId,
type: type,
tableId: global.tableInfo.qrcode || '',
});
masterId.value = res.code;
}
if (global.tableInfo.num) {
await addTableNum()
}
await queryCartAjax();
if (type == 1) {
//
goodsRef.value.clearDot()
}
} catch (error) {
console.log(error);
}
} }
// / // /
function clearMember() { function clearMember() {
global.setOrderMember({}) global.setOrderMember({})
global.setOrderTable({}) global.setOrderTable({})
createCodeAjax()
} }
// / // /
@ -578,11 +425,6 @@ function showTableMerging() {
let data = cartList.value.filter(item => item.placeNum) let data = cartList.value.filter(item => item.placeNum)
tableMergingRef.value.show(data) tableMergingRef.value.show(data)
} }
onMounted(() => {
createCodeAjax()
shopStore.queryShopInfo()
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -619,15 +461,20 @@ onMounted(() => {
} }
.number { .number {
width: 50px; flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: var(--el-color-info-light-7); background-color: var(--el-color-info-light-7);
// padding-left: var(--el-font-size-base);
.icon {
color: var(--el-color-primary);
font-size: 20px;
}
.t { .t {
font-size: var(--el-font-size-base); font-size: var(--el-font-size-base);
margin-left: 4px;
} }
} }
@ -681,10 +528,47 @@ onMounted(() => {
.shop_list { .shop_list {
flex: 1; flex: 1;
height: calc(100vh - 40px - 60px - 80px); height: calc(100vh - 40px - 60px - 90px);
overflow-y: auto; overflow-y: auto;
border-right: 1px solid #ececec; border-right: 1px solid #ececec;
.table_info {
height: 40px;
border-bottom: 1px solid #ececec;
font-size: 14px;
color: #999;
display: flex;
.left {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--el-font-size-base);
}
.close {
width: 40px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
.icon {
font-size: 16px;
}
&::after {
content: "";
height: 15px;
border-left: 1px solid #ddd;
position: absolute;
left: 0;
top: 12.5px;
}
}
}
.item { .item {
padding: var(--el-font-size-base); padding: var(--el-font-size-base);
@ -803,7 +687,7 @@ onMounted(() => {
} }
.footer { .footer {
padding: var(--el-font-size-base); padding: 10px var(--el-font-size-base);
border-top: 1px solid #ececec; border-top: 1px solid #ececec;
.left { .left {
@ -837,6 +721,26 @@ onMounted(() => {
} }
} }
.num-wrap {
height: 40px;
display: flex;
flex-direction: column;
.num_wrap_top {
flex: 1;
display: flex;
justify-content: flex-end;
}
.num_wrap_btm {
flex: 1;
display: flex;
justify-content: flex-end;
font-size: 12px;
color: #999;
}
}
.top { .top {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -846,7 +750,7 @@ onMounted(() => {
$h: 70px; $h: 70px;
display: flex; display: flex;
height: $h; height: $h;
padding-top: var(--el-font-size-base); padding-top: 10px;
gap: var(--el-font-size-base); gap: var(--el-font-size-base);
.editor { .editor {

View File

@ -1,5 +1,5 @@
<template> <template>
<el-dialog v-model="showDialog" title="发现新版本" width="500" :close-on-click-modal="false" <!-- <el-dialog v-model="showDialog" title="发现新版本" width="500" :close-on-click-modal="false"
:close-on-press-escape="false" :show-close="false"> :close-on-press-escape="false" :show-close="false">
<div class="message"> <div class="message">
{{ updataInfo.message }} {{ updataInfo.message }}
@ -15,17 +15,19 @@
<template v-if="!isUpload"> <template v-if="!isUpload">
立即更新 立即更新
</template> </template>
<template v-else> <template v-else>
下载中... 下载中...
</template> </template>
</template> </template>
<template v-else> <template v-else>
立即安装 立即安装
</template> </template>
</el-button> </el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog> -->
<el-input v-model="authCode" placeholder="请扫描支付码"></el-input>
<el-button type="primary" @click="microPayAjax">反扫支付</el-button>
</template> </template>
<script setup> <script setup>
@ -33,6 +35,7 @@ import { onMounted, ref } from 'vue'
import { findVersion } from '@/api/user.js' import { findVersion } from '@/api/user.js'
import packageData from "../../../package.json"; import packageData from "../../../package.json";
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import { microPay } from '@/api/order.js'
const showDialog = ref(false) const showDialog = ref(false)
const updataInfo = ref({}) const updataInfo = ref({})
@ -42,6 +45,8 @@ const uploadSucess = ref(false)
const uploadResponse = ref({}) const uploadResponse = ref({})
const tempFilePath = ref('') const tempFilePath = ref('')
const authCode = ref('')
// //
async function findVersionAjax() { async function findVersionAjax() {
try { try {
@ -73,8 +78,24 @@ async function uplaodHandle() {
} }
} }
//
async function microPayAjax() {
try {
const res = await microPay({
authCode: authCode.value,
shopId: 1,
orderId: 1,
buyerRemark: ''
})
console.log('res===', res);
} catch (error) {
console.log(error);
}
}
onMounted(() => { onMounted(() => {
findVersionAjax() // findVersionAjax()
ipcRenderer.on('updateProgress', (event, res) => { ipcRenderer.on('updateProgress', (event, res) => {
// console.log('updateProgress===', event, res); // console.log('updateProgress===', event, res);
uploadPro.value = res uploadPro.value = res

View File

@ -15,11 +15,14 @@
<span class="t2">收银库存营销支付等业务一体化解决方案</span> <span class="t2">收银库存营销支付等业务一体化解决方案</span>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" hide-required-asterisk> <el-form ref="formRef" :model="form" :rules="rules" label-position="top" hide-required-asterisk>
<el-form-item label="商户号" prop="merchantName"> <el-form-item>
<el-input v-model="form.merchantName" placeholder="请输入注册商户号"></el-input> <el-radio-group v-model="form.loginType">
<el-radio-button label="商户" :value="0"></el-radio-button>
<el-radio-button label="员工" :value="1"></el-radio-button>
</el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="手机号码" prop="loginName"> <el-form-item label="用户名" prop="username">
<el-input v-model="form.loginName" placeholder="请输入11位手机号码"></el-input> <el-input v-model="form.username" placeholder="请输入用户名"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="登录密码" prop="password"> <el-form-item label="登录密码" prop="password">
<el-input v-model="form.password" :type="passwordType" placeholder="请输入登录密码"> <el-input v-model="form.password" :type="passwordType" placeholder="请输入登录密码">
@ -33,6 +36,16 @@
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="验证码" prop="code">
<div class="code_wrap">
<div class="ipt" style="flex: 1;">
<el-input v-model="form.code" placeholder="请输入验证码" style="width: 100%;"></el-input>
</div>
<el-image :src="codeUrl" style="width: 150px;height: 40px;border-radius: 4px;background-color: #fff;"
fit="contain" @click="captchaAjax" v-loading="codeUrlLoading"
element-loading-spinner="Loading"></el-image>
</div>
</el-form-item>
<!-- <el-form-item> <!-- <el-form-item>
<div style="width: 100%; display: flex; justify-content: flex-end"> <div style="width: 100%; display: flex; justify-content: flex-end">
<router-link :to="{ name: 'register' }"> <router-link :to="{ name: 'register' }">
@ -71,38 +84,34 @@ import { RandomNumBoth } from "@/utils";
import useStorage from "@/utils/useStorage"; import useStorage from "@/utils/useStorage";
import { douyincheckIn } from "@/api/group"; import { douyincheckIn } from "@/api/group";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import { useSocket } from "@/store/socket.js";
import { useGlobal } from '@/store/global.js' import { useGlobal } from '@/store/global.js'
import { useShop } from '@/store/shop.js' import { useGoods } from '@/store/goods.js'
import { captcha } from '@/api/account.js'
const global = useGlobal() const global = useGlobal()
const shopInfo = useShop()
const store = useUser(); const store = useUser();
const socket = useSocket(); const goodsStore = useGoods()
const router = useRouter(); const router = useRouter();
const formRef = ref(null); const formRef = ref(null);
const loading = ref(false); const loading = ref(false);
const passwordType = ref('password') const passwordType = ref('password')
const codeUrl = ref('')
const codeUrlLoading = ref(false)
const form = reactive({ const form = reactive({
serialNumber: RandomNumBoth(1000, 9999), username: "18888888888",
clientType: "pc", password: "123456",
merchantName: "", code: "",
loginName: "", uuid: "",
password: "", loginType: 0, // 0: 1:
}); });
const rules = reactive({ const rules = reactive({
merchantName: [ username: [
{
required: true,
message: " ",
trigger: "blur",
},
],
loginName: [
{ {
required: true, required: true,
message: " ", message: " ",
@ -116,6 +125,13 @@ const rules = reactive({
trigger: "blur", trigger: "blur",
}, },
], ],
code: [
{
required: true,
message: " ",
trigger: "blur",
},
],
}); });
// //
@ -127,25 +143,26 @@ const submitHandle = () => {
.userlogin(form) .userlogin(form)
.then(async (res) => { .then(async (res) => {
// //
useStorage.set('merchantLoginAccount', form.merchantName) // useStorage.set('merchantLoginAccount', form.username)
ElMessage.success("登录成功"); ElMessage.success("登录成功");
socket.init(); goodsStore.initGoods()
await shopInfo.queryShopInfo()
setTimeout(() => { setTimeout(() => {
router.replace({ router.replace({
name: "home", name: "home",
}); });
}, 1000); }, 1000);
const douyin = await douyincheckIn({ // const douyin = await douyincheckIn({
token: res.token, // token: res.token,
loginName: res.loginName, // loginName: res.loginName,
clientType: 'pc' // clientType: 'pc'
}) // })
useStorage.set('douyin', douyin.userInfo) // useStorage.set('douyin', douyin.userInfo)
global.updateData(true) // global.updateData(true)
}) })
.catch((err) => { .catch((err) => {
loading.value = false; loading.value = false;
//
captchaAjax()
}); });
} }
}); });
@ -159,9 +176,27 @@ const logout = () => {
.catch(() => { }); .catch(() => { });
}; };
//
async function captchaAjax() {
try {
codeUrlLoading.value = true
const res = await captcha()
codeUrl.value = res.code
form.uuid = res.uuid
} catch (error) {
console.log(error);
}
setTimeout(() => {
codeUrlLoading.value = false
}, 500);
}
onMounted(() => { onMounted(() => {
global.updateData(false) global.updateData(false)
captchaAjax()
let merchantLoginAccount = useStorage.get('merchantLoginAccount') let merchantLoginAccount = useStorage.get('merchantLoginAccount')
if (merchantLoginAccount) { if (merchantLoginAccount) {
form.merchantName = merchantLoginAccount form.merchantName = merchantLoginAccount
@ -227,4 +262,15 @@ onMounted(() => {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.code_wrap {
width: 100%;
display: flex;
align-items: center;
gap: 10px;
.code_img {
flex: 1;
}
}
</style> </style>

View File

@ -92,10 +92,9 @@ import { formatDecimal } from '@/utils/index.js'
import settleAccount from "@/views/home/components/settleAccount.vue"; import settleAccount from "@/views/home/components/settleAccount.vue";
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { clearTable } from '@/api/table.js' import { clearTable } from '@/api/table.js'
import { useShop } from '@/store/shop.js' import { useGoods } from "@/store/goods.js";
const shopStore = useShop()
const goodsStore = useGoods()
const router = useRouter() const router = useRouter()
const global = useGlobal() const global = useGlobal()
const store = useUser() const store = useUser()
@ -146,7 +145,7 @@ function showPayHandle() {
// //
function showPeopleNumHandle() { function showPeopleNumHandle() {
if (shopStore.info.isTableFee == 1) { if (store.shopInfo.isTableFee == 1) {
orderDownHandle() orderDownHandle()
} else { } else {
showPeopleNum.value = true showPeopleNum.value = true
@ -215,8 +214,14 @@ function orderDownHandle() {
// return // return
// } // }
// } // }
//
global.setOrderTable({ if (!props.tableInfo.tableCode) {
ElMessage.error('请绑定桌码后操作')
return
}
//
goodsStore.selectTable({
...props.tableInfo, ...props.tableInfo,
num: peopleNum.value num: peopleNum.value
}) })

View File

@ -14,7 +14,7 @@
</div> </div>
<div class="tab_container"> <div class="tab_container">
<div class="tab_head"> <div class="tab_head">
<el-radio-group v-model="area" @change="queryShopTableAjax"> <el-radio-group v-model="area" @change="shopTableAjax">
<el-radio-button label="全部" value=""></el-radio-button> <el-radio-button label="全部" value=""></el-radio-button>
<el-radio-button :label="item.name" :value="item.id" v-for="item in areaList" <el-radio-button :label="item.name" :value="item.id" v-for="item in areaList"
:key="item.id"></el-radio-button> :key="item.id"></el-radio-button>
@ -62,6 +62,7 @@
<script setup> <script setup>
import { queryShopArea, queryShopTable } from '@/api/table' import { queryShopArea, queryShopTable } from '@/api/table'
import { shopArea, shopTable } from "@/api/account.js";
import countCard from '@/views/table/components/countCard.vue' import countCard from '@/views/table/components/countCard.vue'
import tableInfo from '@/views/table/components/tableInfo.vue' import tableInfo from '@/views/table/components/tableInfo.vue'
@ -107,7 +108,7 @@ const slectTable = ref('')
// //
function tabChange(item, index) { function tabChange(item, index) {
tabActive.value = index tabActive.value = index
queryShopTableAjax() shopTableAjax()
} }
// //
@ -118,7 +119,7 @@ function countTime(t) {
// //
async function paySuccess() { async function paySuccess() {
await queryShopTableAjax() await shopTableAjax()
slectTableHandle(tableItemActive.value, tableList.value[tableItemActive.value]) slectTableHandle(tableItemActive.value, tableList.value[tableItemActive.value])
} }
@ -140,29 +141,29 @@ function slectTableClose() {
} }
// //
async function queryShopAreaAjax() { async function shopAreaAjax() {
try { try {
const res = await queryShopArea({ const res = await shopArea({
shopId: store.userInfo.shopId page: 1,
size: 500
}) })
areaList.value = res areaList.value = res.records
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
} }
// //
async function queryShopTableAjax() { async function shopTableAjax() {
try { try {
loading.value = true loading.value = true
const res = await queryShopTable({ const res = await shopTable({
shopId: store.userInfo.shopId,
areaId: area.value, areaId: area.value,
tableCode: '',
name: '',
status: tabAreas.value[tabActive.value].type, status: tabAreas.value[tabActive.value].type,
page: 1,
pageSize: 500
}) })
tableList.value = res.list tableList.value = res.records
setTimeout(() => { setTimeout(() => {
loading.value = false loading.value = false
}, 500) }, 500)
@ -173,8 +174,8 @@ async function queryShopTableAjax() {
} }
onMounted(() => { onMounted(() => {
queryShopAreaAjax() shopAreaAjax()
queryShopTableAjax() shopTableAjax()
}) })
</script> </script>