对接购物车

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
# 正式ws
VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
# VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
#测试ws
# VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
VITE_API_WSS = 'wss://sockets.sxczgkj.com/wss'
# 阿伟本地ws
# 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_URL = 'http://192.168.2.96:10587/cashier-client'
# 鹏辉
# VITE_API_URL = 'http://192.168.1.106:10589/cashier-client'
# VITE_API_URL = 'http://192.168.1.21:9200/'
# 杰哥
# 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://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 { useSocket } from "@/store/socket.js";
import { ipcRenderer } from 'electron';
import { useGoods } from '@/store/goods.js'
const goodsStore = useGoods()
const socket = useSocket();
const global = useGlobal();
@ -165,13 +169,14 @@ async function getBarCode(e) {
}
onMounted(() => {
document.addEventListener("keydown", (e) => {
getBarCode(e);
});
//
// document.addEventListener("keydown", (e) => {
// getBarCode(e);
// });
//
if (store.userInfo && store.userInfo.shopId) {
socket.init();
if (store.userInfo && store.userInfo.id) {
goodsStore.initGoods()
}
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>
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 { useUser } from "@/store/user.js"
import { clearNoNum, formatDecimal } from '@/utils'
@ -151,7 +151,11 @@ import scanModal from '@/components/payCard/scanModal.vue'
import { ElMessage } from "element-plus";
import { useGlobal } from '@/store/global.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()
@ -304,6 +308,31 @@ async function payTypeChange(index, item) {
//
async function confirmOrder() {
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')
if (payLoading.value) return
if (payActive.value == 'buyer') {
@ -477,7 +506,7 @@ function cancelDiscount() {
onMounted(() => {
money.value = `${formatDecimal(props.amount)}`
queryPayTypeAjax()
// queryPayTypeAjax()
})
</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="info">
<template v-if="goodsInfo.id">
<span>库存{{ goodsInfo.stockNumber }}</span>
<!-- <span>库存{{ goodsInfo.stockNumber }}</span> -->
<span>{{ goodsInfo.salePrice }}</span>
</template>
</div>
@ -34,10 +34,6 @@
<script setup>
import { ref } from 'vue'
import { useUser } from "@/store/user.js"
import { queryProductSku } from '@/api/product'
const store = useUser();
const emit = defineEmits(['success'])
const type = ref('shop')
@ -56,16 +52,16 @@ const selecSkuArray = ref([])
//
function submitSku() {
dialogVisible.value = false
switch (type.value) {
case 'shop':
emit('success', goodsInfo.value)
break;
case 'cart':
emit('success', goods.value)
break;
default:
break;
}
// switch (type.value) {
// case 'shop':
// break;
// case 'cart':
// emit('success', goodsInfo.value)
// break;
// default:
// 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.groundingSpecInfo.map(val => {
goods.value.skuList.map(val => {
// console.log(val);
// console.log(`${selecSkuArray.value.join(',')},${item.name}`);
// console.log(val.specSnap.indexOf(`${selecSkuArray.value.join(',')},${item.name}`));
if (val.specSnap.indexOf(`${selecSkuArray.value.join(',')},${item.name}`) != -1 && val.isGrounding) {
// console.log(val.specInfo.indexOf(`${selecSkuArray.value.join(',')},${item.name}`));
if (val.specInfo.indexOf(`${selecSkuArray.value.join(',')},${item.name}`) != -1 && val.isGrounding) {
item.disabled = false
}
})
@ -147,80 +143,62 @@ function selectedSuccess() {
//
async function queryProductSkuAjax() {
try {
loading.value = true
const res = await queryProductSku({
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
goods.value.skuList.map(item => {
if (item.specInfo == selectedSkuTag.value) {
goodsInfo.value = item
}
setTimeout(() => {
loading.value = false
}, 100)
} catch (error) {
loading.value = false
console.log(error)
}
})
}
//
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 = {}
goods.value = {}
selectedSkuNum.value = 0
dialogVisible.value = true
goods.value = ""
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()
}

View File

@ -86,9 +86,9 @@ async function uplaodHandle() {
}
onMounted(() => {
if (store.userInfo) {
findVersionAjax()
}
// if (store.userInfo) {
// findVersionAjax()
// }
ipcRenderer.on('updateProgress', (event, 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.deviceNoteList = await bySubType({
shopId: store.userInfo.shopId,
contentType: "local",
subType: "cash",
});
// // 获取已添加的小票打印机
// this.deviceNoteList = await bySubType({
// shopId: store.userInfo.shopId,
// contentType: "local",
// subType: "cash",
// });
// 获取已添加的标签打印机
this.deviceLableList = await bySubType({
shopId: store.userInfo.shopId,
contentType: "local",
subType: "label",
});
// // 获取已添加的标签打印机
// this.deviceLableList = await bySubType({
// shopId: store.userInfo.shopId,
// contentType: "local",
// subType: "label",
// });
console.log("打印队列初始化成功");
},
// 检查本地打印机是否能正常使用

View File

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

View File

@ -1,37 +1,21 @@
import _ from "lodash";
import { dayjs } from "element-plus";
import { defineStore } from "pinia";
import { useUser } from "@/store/user.js";
import { usePrint } from "@/store/print.js";
import { v4 as uuidv4 } from "uuid";
import useStorage from "@/utils/useStorage";
import ReconnectingWebSocket from "reconnecting-websocket";
import { ipcRenderer } from "electron";
import { useGoods } from "@/store/goods.js";
import { ElMessage } from "element-plus";
export const useSocket = defineStore({
id: uuidv4(),
export const useSocket = defineStore("socket", {
state: () => ({
online: false, // 在线状态
ws: null, // websocket实例
uuid: "", // 长连接唯一id
heartbeatTimer: null, // 心跳计时器
orderList: [],
log: true,
log: false,
}),
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
close() {
if (this.log) console.log("关闭ws");
@ -49,11 +33,22 @@ export const useSocket = defineStore({
2000,
{ 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) {
this.createUUID();
const store = useUser();
const printStore = usePrint();
const goodsStore = useGoods();
printStore.init();
@ -77,44 +72,80 @@ export const useSocket = defineStore({
this.online = true;
// 清除心跳
this.clearHeartBeat();
if (this.log) console.log(this);
this.ws.send(
JSON.stringify({
type: "connect",
shopId: store.userInfo.shopId,
clientId: this.uuid,
})
);
this.cartInit();
this.startheartbeat();
});
this.ws.addEventListener("message", (e) => {
let data = JSON.parse(e.data);
if (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.type == "heartbeat") {
if (this.log) console.log("接收心跳");
if (data.operate_type == "init") {
// console.log("接收消息", data);
goodsStore.getCartList(data.data);
}
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", () => {

View File

@ -1,24 +1,34 @@
import { defineStore } from "pinia";
import { login } from "@/api/user";
import { login, shopInfo_detail } from "@/api/account.js";
import useStorage from "@/utils/useStorage";
export const useUser = defineStore({
id: "user",
export const useUser = defineStore("user", {
state: () => ({
userInfo: useStorage.get("userInfo"),
shopInfo: useStorage.get("shopInfo"),
token: useStorage.get("token"),
}),
actions: {
// 登录
userlogin(param) {
return login(param).then((res) => {
this.userInfo = res;
this.token = res.token;
return login(param).then(async (res) => {
this.userInfo = res.shopInfo;
this.token = res.tokenInfo.tokenValue;
useStorage.set("token", this.token);
// this.userInfo.shopId = "24";
useStorage.set("userInfo", this.userInfo);
await this.queryShopInfo();
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 { ElMessage } from "element-plus";
import useStorage from '@/utils/useStorage'
import router from '@/router'
import useStorage from "@/utils/useStorage";
import router from "@/router";
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
timeout: 5000, // 请求超时
});
@ -17,9 +20,12 @@ service.interceptors.request.use(
// 让每个请求携带 token
// ['X-Token'] 是自定义标题键
// 请根据实际情况修改
config.headers["platformType"] = 'PC';
config.headers["token"] = useStorage.get("token");
config.headers["loginName"] = useStorage.get("userInfo").loginName;
config.headers["clientType"] = 'pc';
if (useStorage.get("shopInfo") && useStorage.get("shopInfo").id) {
config.headers["shopId"] = useStorage.get("shopInfo").id;
}
// config.headers["loginName"] = useStorage.get("userInfo").loginName;
// config.headers['Content-Type'] = 'application/json'
}
return config;
@ -35,18 +41,18 @@ service.interceptors.response.use(
(response) => {
// 对响应数据做点什么
if (+response.status === 200) {
if (+response.data.code == '0') {
if (+response.data.code == 200) {
return response.data.data;
} else if (+response.data.code == '9999') {
ElMessage.error('登录已过期,请重新登录')
useStorage.clear()
router.replace("/login")
window.location.reload()
return Promise.reject('登录已过期,请重新登录')
} else if (+response.data.code == 501) {
ElMessage.error("登录已过期,请重新登录");
useStorage.clear();
router.replace("/login");
window.location.reload();
return Promise.reject("登录已过期,请重新登录");
} else {
// 响应错误
ElMessage.error(response.data.msg)
return Promise.reject(response.data)
ElMessage.error(response.data.msg);
return Promise.reject(response.data);
}
}
},

View File

@ -1,69 +1,86 @@
<template>
<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">
<SemiSelect />
</el-icon>
</div>
<div class="item number" @click="props.item.id && takeFoodCodeRef.show()">
<el-text class="num">{{ formatDecimal(props.item.number || 1, 2, true) }}</el-text>
<div class="item number"
: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 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">
<CloseBold />
</el-icon>
</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">
<Filter />
</el-icon>
<el-text class="t">规格</el-text>
</div> -->
<div class="item" @click="showDiscountModalHandle">
</div>
<div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_temporary }"
@click="showDiscountModalHandle">
<el-icon class="icon">
<PriceTag />
</el-icon>
<el-text class="t">打折</el-text>
<el-text class="t">改价</el-text>
</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">
<ShoppingBag />
</el-icon>
<el-text class="t">赠送</el-text>
</div>
<div class="item" :class="{ disabled: props.item.isPack == 'true' }" @click="giftPackHandle('isPack')"
v-if="JSON.parse(shopStore.info.eatModel).some(item => item == 'take-out')">
<div class="item"
: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">
<Box />
</el-icon>
<el-text class="t">打包</el-text>
</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">
<DishDot />
</el-icon>
<el-text class="t">免厨</el-text>
</div>
<div class="item" @click="props.item.id && emit('delete', props.item)">
<div class="item" @click="deleteHandle">
<el-icon class="icon">
<Delete />
</el-icon>
<el-text class="t">删除</el-text>
</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">
<Sell />
</el-icon>
<el-text class="t">挂单</el-text>
</div>
<div class="item" @click="tableMergingHandle"
v-if="shopStore.info.registerType == 'restaurant' && props.item.tableId && props.item.orderId">
</div> -->
<div class="item" @click="tableMergingHandle" v-if="goodsStore.tableInfo.tableCode">
<el-icon class="icon">
<EditPen />
</el-icon>
<el-text class="t">转桌</el-text>
</div>
<div class="item" @click="props.item.id && emit('clearCart')">
<div class="item" @click="clearCart">
<el-icon class="icon">
<RefreshRight />
</el-icon>
@ -73,15 +90,16 @@
<takeFoodCode ref="takeFoodCodeRef" title="修改商品数量" placeholder="请输入商品数量" @success="updateNumber" />
<!-- 购物车选择规格 -->
<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">
<div class="dialog">
<div class="el-popover__title content">
<el-form ref="discountFormRef" :model="discountForm" :rules="discountFormRules" label-width="100px"
label-position="left">
<el-form-item label="价格更改" prop="amount">
<el-input v-model="discountForm.amount" placeholder="减8.88元请输入8.88" @input="priceInput">
<el-form-item label="价格更改" prop="discount_sale_amount">
<el-input v-model="discountForm.discount_sale_amount" placeholder="减8.88元请输入8.88"
@input="priceInput">
<template #append></template>
</el-input>
</el-form-item>
@ -114,70 +132,96 @@ import { ElMessage } from 'element-plus'
import takeFoodCode from '@/components/takeFoodCode.vue'
import skuModal from '@/components/skuModal.vue'
import { useShop } from '@/store/shop.js'
import { useGoods } from '@/store/goods.js'
import { inputFilterFloat, formatDecimal } from '@/utils/index.js'
import { updatePrice, orderPrint } from '@/api/product.js'
const shopStore = useShop()
const goodsStore = useGoods()
const props = defineProps({
item: {
type: Object,
default: {}
}
})
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging'])
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging', 'showPackage'])
const takeFoodCodeRef = ref(null)
const skuModalRef = ref([])
//
function giftPackHandle(key) {
if (!props.item.id) return
if (props.item[key] == 'true') {
props.item[key] = false
} else {
props.item[key] = true
if (!goodsStore.cartList[goodsStore.cartActiveIndex].id) return
if (key == 'is_gift' && goodsStore.cartList[goodsStore.cartActiveIndex] == 0) {
goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_amount = 0
}
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) {
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) {
case 'sub':
if (props.item.number <= 1) return
props.item.number--
if (goodsStore.cartList[goodsStore.cartActiveIndex].number <= 1) return
goodsStore.cartList[goodsStore.cartActiveIndex].number--
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
break;
case 'add':
props.item.number++
goodsStore.cartList[goodsStore.cartActiveIndex].number++
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
break;
default:
break;
}
emit('confirm', props.item)
}
//
function updateNumber(num) {
if (!props.item.id) return
props.item.number = num
emit('confirm', props.item)
goodsStore.cartList[goodsStore.cartActiveIndex].number = num
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex] }, 'edit')
}
//
function showSkuModal() {
if (!props.item.id) return
if (props.item.tbProductSpec && props.item.tbProductSpec.specList) {
skuModalRef.value.show(props.item, 'cart')
let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 0)) return
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) {
if (!props.item.id) return
emit('confirm', e)
if (goodsStore.cartList[goodsStore.cartActiveIndex].sku_id != e.id) {
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex], sku_id: e.id, sku_name: e.specInfo }, 'edit')
}
}
/**单品打折 start */
@ -186,11 +230,8 @@ const resetDiscountForm = ref({})
const discountFormRef = ref(null)
const discountFormLoading = ref(false)
const discountForm = ref({
masterId: '',
cartId: '',
amount: '',
note: '',
shopId: ''
discount_sale_amount: '',
note: ''
})
function validateAmount(rule, value, callback) {
@ -204,7 +245,7 @@ function validateAmount(rule, value, callback) {
}
const discountFormRules = ref({
amount: [
discount_sale_amount: [
{
required: true,
validator: validateAmount,
@ -220,7 +261,8 @@ const noteList = ref([
//
function showDiscountModalHandle() {
if (props.item.id) {
if (goodsStore.cartList[goodsStore.cartActiveIndex].id && !goodsStore.cartList[goodsStore.cartActiveIndex].is_temporary) {
//
showDiscountModal.value = true
}
}
@ -254,21 +296,20 @@ function discountFormSubmit() {
if (valid) {
discountFormLoading.value = true
discountForm.value.masterId = props.item.masterId
discountForm.value.cartId = props.item.id
discountForm.value.shopId = props.item.shopId
await updatePrice(discountForm.value)
discountFormLoading.value = false
goodsStore.operateCart({
...goodsStore.cartList[goodsStore.cartActiveIndex],
discount_sale_amount: goodsStore.cartList[goodsStore.cartActiveIndex].lowPrice - discountForm.value.discount_sale_amount,
discount_sale_note: discountForm.value.note
}, 'edit')
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
ElMessage.success('操作成功')
emit('confirm', { isTemporary: true })
}
} catch (error) {
discountFormLoading.value = false
console.log(error);
}
discountFormLoading.value = false
})
}
/**单品打折 end */
@ -295,6 +336,18 @@ function tableMergingHandle() {
emit('merging')
}
}
//
function deleteHandle() {
if (goodsStore.cartList[goodsStore.cartActiveIndex].id) {
goodsStore.deleteCartItem()
}
}
//
function clearCart() {
goodsStore.clearCart()
}
</script>
<style scoped lang="scss">
@ -322,6 +375,10 @@ function tableMergingHandle() {
.icon {
color: #999;
}
.num {
color: #999;
}
}
&.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>
<div class="header">
<div class="menus scroll-x">
<div class="item" :class="{ active: categorysActive == index }" v-for="(item, index) in categorys"
:key="item.id" @click="changeCategory(index)">
<div class="item" :class="{ active: goodsStore.categoryIndex == index }"
v-for="(item, index) in goodsStore.categoryList" :key="item.id" @click="changeCategory(index)">
<el-text>{{ item.name }}</el-text>
</div>
</div>
@ -17,8 +17,8 @@
</template>
<template #default>
<div class="popover_wrap">
<el-button :plain="categorysActive != index" type="primary" v-for="(item, index) in categorys"
:key="item.id" @click="changeCategory(index)">
<el-button :plain="goodsStore.categoryIndex != index" type="primary"
v-for="(item, index) in goodsStore.categoryList" :key="item.id" @click="changeCategory(index)">
{{ item.name }}
</el-button>
</div>
@ -34,8 +34,8 @@
</div>
<div class="right">
<div class="input">
<el-input placeholder="请输入商品名称查询" v-model="commdityName" clearable @focus="
global.updateData(false)" @blur="global.updateData(true)" @input="inputChange"></el-input>
<el-input placeholder="请输入商品名称查询" v-model="commdityName" clearable @input="inputChange"
style="width:200px"></el-input>
</div>
<el-button :loading="searchLoading" :icon="Search" @click="searchHandle">搜索</el-button>
</div>
@ -44,8 +44,8 @@
</div>
<div class="shop_list" :class="{ img: shopListType == 'img' }" v-loading="loading">
<!-- <swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange"> -->
<swiper ref="swiperRef" :loop="false" class="swiper_box" direction="vertical" @slideChange="onSlideChange">
<swiper-slide class="slide_item" v-for="(goods, index) in goodsList" :key="index">
<swiper ref="swiperRef" :loop="false" class="swiper_box" direction="vertical">
<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">
<transition name="el-fade-in">
@ -63,14 +63,14 @@
</div>
</div>
</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'">
<el-image :src="`${item.coverImg}?x-oss-process=image/resize,m_lfit,w_150,h_150`"
class="el_img" fit="cover"></el-image>
<div class="sell_out" v-if="item.isPauseSale == 1">
<img class="sell_out_icon" src="../../../assets/icon_xq.png">
</div>
<div class="weight" v-if="item.type == 'weigh'">称重</div>
<div class="weight" v-if="item.type == 'weight'">称重</div>
</div>
<div class="name"><el-text line-clamp="1">{{ item.name }}</el-text></div>
<div class="item_empty" v-if="shopListType == 'text'"></div>
@ -88,7 +88,7 @@
</swiper>
</div>
<div class="empty">
<el-empty description="空空如也~" v-if="!goodsList.length" />
<el-empty description="空空如也~" v-if="!goodsStore.goodsList.length" />
</div>
<!-- 选择规格 -->
<skuModal ref="skuModalRef" @success="skuConfirm" />
@ -172,31 +172,31 @@
<div class="el-popover__title content">
<el-form ref="temporaryFormRef" :model="temporaryForm" :rules="temporaryFormRules" label-width="100px"
label-position="left">
<el-form-item label="菜品名称" prop="name">
<el-input v-model="temporaryForm.name" placeholder="请输入菜品名称" />
<el-form-item label="菜品名称" prop="product_name">
<el-input v-model="temporaryForm.product_name" placeholder="请输入菜品名称" />
</el-form-item>
<el-form-item label="菜品分类" prop="categoryId">
<!-- <el-form-item label="菜品分类" prop="categoryId">
<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>
</el-select>
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input v-model="temporaryForm.price" placeholder="请输入价格" @input="priceInput">
</el-form-item> -->
<el-form-item label="价格" prop="discount_sale_amount">
<el-input v-model="temporaryForm.discount_sale_amount" placeholder="请输入价格" @input="priceInput">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="单位" prop="unit">
<!-- <el-form-item label="单位" prop="unit">
<el-select v-model="temporaryForm.unit" placeholder="请选择单位">
<el-option v-for="item in units" :key="item.id" :label="item.name"
:value="item.name"></el-option>
</el-select>
</el-form-item>
</el-form-item> -->
<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 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="item" v-for="item in noteList" :key="item" @click="addNote(item)">
{{ item }}
@ -233,6 +233,7 @@ import WeightModal from './weightModal.vue'
import GroupModal from './groupModal.vue'
import { queryCategory, queryNewCommodityInfo, queryProductSku, productStatus, productStock, getUnitList, temporaryDishes } from '@/api/product'
import { useUser } from "@/store/user.js"
import { useGoods } from '@/store/goods.js'
import { Swiper, SwiperSlide } from 'swiper/vue'
import "swiper/swiper-bundle.css";
import { staffPermission } from '@/api/user.js'
@ -244,6 +245,7 @@ const swiperRef = ref(null)
const global = useGlobal()
const store = useUser()
const goodsStore = useGoods()
const props = defineProps({
masterId: {
@ -264,18 +266,13 @@ const categorysActive = ref(0)
const commdityName = ref('')
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 inputChange = _.debounce(function () {
searchHandle()
// updateGoods()
goodsStore.filterNameGoods(commdityName.value)
}, 500)
@ -286,16 +283,11 @@ const units = ref([]) // 单位列表
const temporaryFormRef = ref(null)
const resetTemporaryForm = ref({})
const temporaryForm = ref({
masterId: '',
shopId: '',
tableId: '',
name: '',
categoryId: '',
price: '',
unit: '',
num: 1,
note: '',
vipUserId: ''
is_temporary: 1, //
discount_sale_amount: '12', //
product_name: '西红寺', //
number: 1, //
remark: '', //
})
const temporaryFormLoading = ref(false)
@ -313,15 +305,15 @@ function priceInput(e) {
//
function addNote(str) {
if (!temporaryForm.value.note.length) {
temporaryForm.value.note += str
if (!temporaryForm.value.remark.length) {
temporaryForm.value.remark += str
} else {
temporaryForm.value.note += `${str}`
temporaryForm.value.remark += `${str}`
}
}
const temporaryFormRules = ref({
name: [
product_name: [
{
required: true,
message: '请输入菜品名称',
@ -335,7 +327,7 @@ const temporaryFormRules = ref({
trigger: 'change',
}
],
price: [
discount_sale_amount: [
{
required: true,
message: '请输入价格',
@ -383,22 +375,14 @@ function temporaryFormSubmit() {
try {
if (valid) {
temporaryFormLoading.value = true
temporaryForm.value.masterId = props.masterId
temporaryForm.value.shopId = store.userInfo.shopId
temporaryForm.value.tableId = global.tableInfo.qrcode
await temporaryDishes(temporaryForm.value)
temporaryFormLoading.value = false
goodsStore.addCart(temporaryForm.value)
showTemporaryDish.value = false
ElMessage.success('添加成功')
emit('success', { isTemporary: true })
}
} catch (error) {
temporaryFormLoading.value = false
console.log(error);
}
temporaryFormLoading.value = false
})
}
@ -411,21 +395,30 @@ const GroupModalRef = ref(null)
//
const searchLoading = ref(false)
function searchHandle() {
searchLoading.value = true
goodsList.value = []
goodsPage.value = 1
finish.value = false
currentGoodsIndex.value = 0
loopMax.value = 0
loopTimer.value = null
updataGoods()
// searchLoading.value = true
// updateGoods()
goodsStore.filterNameGoods(commdityName.value)
}
//
function skuConfirm(params) {
emit('loading')
emit('success', params)
console.log(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')
if (showEditor.value) {
showEditor.value = false
goodsList.value.map(item => {
goodsStore.goodsList.value.map(item => {
item.map(val => {
val.showMore = false
})
@ -460,7 +453,7 @@ function showSkuHandle(item) {
goodEditorItem.value = item
showCloseSell.value = true
} else {
goodsList.value.map(item => {
goodsStore.goodsList.value.map(item => {
item.map(val => {
val.showMore = false
})
@ -476,7 +469,7 @@ function showSkuHandle(item) {
})
return
}
if (categorys.value[categorysActive.value].id == '-1') {
if (goodsStore.categoryList[goodsStore.categoryIndex].id == '-1') {
ElMessage({
type: 'error',
message: '该商品已下架,请上架后操作',
@ -484,29 +477,48 @@ function showSkuHandle(item) {
})
return
}
if (item.type == 'normal') {
if (item.typeEnum == 'sku') {
//
skuModalRef.value.show({ ...item })
let goodsItem = goodsStore.cartList.find(goods => goods.product_id == item.id)
if (item.type == 'sku') {
//
skuModalRef.value.show({ ...item })
} else if (item.type == 'single') {
//
if (goodsItem && goodsItem.id) {
//
goodsStore.operateCart({ ...goodsItem, number: +goodsItem.number + 1 }, 'edit')
} else {
//
loading.value = true
emit('loading')
queryProductSkuAjax(item)
//
goodsStore.addCart({ ...item.skuList[0], lowPrice: item.skuList[0].salePrice })
}
} else if (item.type == 'weigh') {
} else if (item.type == 'weight') {
//
WeightModalRef.value.show(item)
} else if (item.type == 'package' && item.groupType == 1) {
// -
GroupModalRef.value.show(item)
} else if (item.type == 'package' && item.groupType == 0) {
//
loading.value = true
emit('loading')
queryProductSkuAjax(item)
if (goodsItem && goodsItem.id) {
//
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) {
try {
@ -546,153 +558,22 @@ function localUpdateShopListType() {
//
function changeCategory(index) {
showPopover.value = false
categorysActive.value = 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)
goodsStore.setCategoryIndex(index)
}
//
async function updateData() {
updataGoods()
async function updateGoods() {
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() {
// goodsList.value.map(item => {
// item.map(val => {
// val.orderCount = 0
// })
// })
updateData()
goodsStore.goodsList.value.map(item => {
item.map(val => {
val.orderCount = 0
})
})
updateGoods()
}
const showEditor = ref(false)
@ -744,7 +625,7 @@ async function closeSellHandle() {
message: '操作成功',
showClose: true,
})
updateData()
updateGoods()
} catch (error) {
console.log(error);
}
@ -781,7 +662,7 @@ async function putawayHandle(item) {
message: '操作成功',
showClose: true,
})
updateData()
updateGoods()
} catch (error) {
console.log(error);
}
@ -804,7 +685,7 @@ async function goodEditorConfirm() {
message: '操作成功',
showClose: true,
})
updateData()
updateGoods()
} catch (error) {
console.log(error);
}
@ -842,7 +723,7 @@ async function goodStockNumberHandle(item) {
async function goodsEditorStockConfirm() {
try {
goodsEditorStockLoading.value = true
const res = await productStock({
await productStock({
shopId: store.userInfo.shopId,
productId: goodsEditorStockItem.value.id,
stock: goodsEditorStockNumber.value
@ -854,23 +735,16 @@ async function goodsEditorStockConfirm() {
message: '操作成功',
showClose: true,
})
updateData()
updateGoods()
} catch (error) {
console.log(error);
}
}
defineExpose({
updateData,
clearDot
})
onMounted(async () => {
localUpdateShopListType()
getUnitListAjax()
await updateCategoryActive()
await queryCategoryAjax()
updataGoods()
updateGoods,
clearDot,
showPackage
})
</script>

View File

@ -1,7 +1,7 @@
<!-- 称重商品组件 -->
<template>
<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="item">规格组名{{ item.title }}</div>
<div class="item"
@ -43,6 +43,9 @@
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { inputFilterFloat, formatDecimal } from '@/utils/index.js'
import { useGoods } from '@/store/goods.js'
const goodsStore = useGoods()
const dialogVisible = ref(false);
const number = ref("");
@ -52,23 +55,55 @@ const emit = defineEmits(["success"]);
const tabRefs = ref([])
function show(item) {
disabled.value = true
const confirmType = ref('')
const cartItem = ref('')
function show(item, type = 'add') {
confirmType.value = type
dialogVisible.value = true;
goodsItem.value = { ...item }
goodsItem.value.proGroupVo.map(item => {
item.isError = false
})
setTimeout(() => {
tabRefs.value.map(item => {
item.clearSelection()
if (type == 'add') {
disabled.value = true
goodsItem.value = { ...item }
goodsItem.value.groupSnap.map(item => {
item.isError = false
})
}, 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) {
let item = goodsItem.value.proGroupVo[index]
let item = goodsItem.value.groupSnap[index]
let selectNum = tabRefs.value[index].getSelectionRows()
if (selectNum.length != item.number) {
@ -79,7 +114,7 @@ function selectChange($event, index) {
let flags = []
goodsItem.value.proGroupVo.map((item, index) => {
goodsItem.value.groupSnap.map((item, index) => {
let selectNum = tabRefs.value[index].getSelectionRows()
if (selectNum.length != item.number) {
flags.push({ flag: false })
@ -103,7 +138,7 @@ const disabled = ref(true)
function confirmHandle() {
let flags = []
goodsItem.value.proGroupVo.map((item, index) => {
goodsItem.value.groupSnap.map((item, index) => {
let selectNum = tabRefs.value[index].getSelectionRows()
if (selectNum.length != item.number) {
flags.push({ flag: false })
@ -122,17 +157,25 @@ function confirmHandle() {
disabled.value = false
let goodIds = []
goodsItem.value.proGroupVo.map((item, index) => {
goodsItem.value.groupSnap.map((item, index) => {
let selectNum = tabRefs.value[index].getSelectionRows()
goodIds.push(selectNum)
})
//
emit("success", {
...goodsItem.value,
productId: goodsItem.value.id,
groupProductIdList: goodIds.flat().map(item => item.proId)
});
if (confirmType.value == 'add') {
emit("success", {
...goodsItem.value.skuList[0],
goods_type: goodsItem.value.type,
pro_group_info: goodIds
});
} else {
//
goodsStore.operateCart({
...cartItem.value,
pro_group_info: goodIds
}, 'edit')
}
dialogVisible.value = false;
}

View File

@ -26,26 +26,72 @@
</div>
</div>
<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">
<span class="name">{{ item.name }}</span>
<span class="n">x{{ item.number }}</span>
<span class="p">{{ item.salePrice }}</span>
<div class="name">
<span v-if="item.is_temporary" style="color: #999;"> [临时菜]</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 class="gift_wrap" v-if="item.isGift == 'true'">
<span>[赠送]</span>
<span>-{{ item.salePrice }}</span>
</div>
<div class="tag_wrap" v-if="item.skuName">
<div class="tag" v-for="item in item.skuName.split(',')">
<div class="tag_wrap" v-if="item.sku_name">
<div class="tag" v-for="item in item.sku_name.split(',')">
{{ item }}
</div>
</div>
<div class="packge_Wrap" v-if="item.isPack == 'true'">
<div class="icon_item" v-if="item.isPack == 'true'" @click="giftPackHandle('isPack', item)">
<el-icon class="icon" style="color: var(--primary-color)">
<Box />
</el-icon>
<div class="gift_wrap" v-if="item.is_gift">
<div class="name">
<span v-if="item.is_gift">[赠送]</span>
</div>
<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>
@ -64,8 +110,8 @@
</div>
</div>
<div class="pay_wrap">
<payCard :amount="props.amount" :discount="propsDiscount" :orderId="props.orderInfo.id" @paySuccess="paySuccess"
@cancelDiscount="propsDiscount = 0" />
<payCard :amount="goodsStore.orderInfo.originAmount" :discount="propsDiscount" :orderId="props.orderInfo.id"
@paySuccess="paySuccess" @cancelDiscount="propsDiscount = 0" />
</div>
</div>
<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 { useGlobal } from '@/store/global.js'
import { usePrint } from '@/store/print.js'
import { useGoods } from '@/store/goods.js'
import { staffPermission } from '@/api/user.js'
const goodsStore = useGoods()
const global = useGlobal()
const printStore = usePrint()
@ -424,30 +473,42 @@ defineExpose({
padding: var(--el-font-size-base) 0;
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 {
display: flex;
padding-bottom: 6px;
.name {
flex: 1;
}
.n {
width: 50px;
color: #555;
}
.p {
width: 50px;
color: #555;
}
}
.gift_wrap {
display: flex;
justify-content: space-between;
color: #999;
font-size: 16px;
.p {
color: var(--el-color-danger);
}
}
.tag_wrap {

View File

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

View File

@ -8,20 +8,20 @@
</el-icon>
<el-text class="t">({{ pendingCartNum }})</el-text>
</div>
<div class="number" @click="takeFoodCodeRef.show()">
<el-text class="t">{{ masterId }}</el-text>
<div class="number" @click="SelectVipUserRef.show()">
<el-icon class="icon">
<UserFilled />
</el-icon>
<el-text class="t">选择会员</el-text>
</div>
<div class="select_user" @click="quickCashHandle"
v-if="!global.orderMemberInfo.telephone && !global.tableInfo.id">
<div class="left">
<el-icon class="icon">
<el-icon class="icon" style="color: var(--el-color-warning);">
<WalletFilled />
</el-icon>
<el-text class="t">快捷收银</el-text>
</div>
<el-icon class="arrow">
<ArrowRight />
</el-icon>
</div>
<div class="select_user" v-else @click="clearMember">
<div class="left">
@ -45,7 +45,89 @@
</div>
<div class="shop_operation">
<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>
<div class="item" :class="{ active: item.active }" :key="item.id" v-for="(item, i) in arr.info"
@click="selectCartItemHandle(item, index, i)">
@ -64,14 +146,14 @@
</div>
<div class="grooup_wrap" v-if="item.proGroupInfo">
{{ 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 class="num">
<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>
</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>
</div>
<div class="icon_item tui" v-if="item.status == 'return'">
@ -92,17 +174,16 @@
</div>
</template>
<div class="empty">
<el-empty description="请选择商品" v-if="!cartList.length" />
<el-empty description="请选择商品" v-if="!goodsStore.cartList.length" />
</div>
</div>
<!-- 购物车操作栏 -->
<cartOperation :item="cartListActiveItem" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle"
@pending="pendingCart" @clearCart="clearCartHandle" @merging="showTableMerging" />
<cartOperation :item="cartListActiveItem" @confirm="" @delete="delCartHandle" @pending="pendingCart"
@merging="showTableMerging" @showPackage="e => goodsRef.showPackage(e)" />
</div>
<div class="footer">
<div class="top">
<div class="left" @click="allSelectedHandle"
v-if="JSON.parse(shopStore.info.eatModel).some(item => item == 'take-out')">
<div class="left" @click="allSelectedHandle" v-if="store.shopInfo.eatModel == 'take-out'">
<div class="selected">
<div class="selected_round" v-if="!allSelected"></div>
<el-icon class="icon" v-else>
@ -113,16 +194,27 @@
</div>
<div class="left" v-else></div>
<div class="num-wrap">
<!-- {{ cartInfo.productNum || 0 }}种商品 -->
<el-text>{{
cartInfo.productSum || 0
}}</el-text>{{ formatDecimal(cartInfo.totalAmount || 0) }}
<div class="num_wrap_top">
<el-text>
{{ goodsStore.cartInfo.total }}
</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 class="btm">
<el-button icon="Edit" @click="remarkRef.show()"></el-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"
@click="createOrderHandle(0)">
<template v-if="!createOrderLoading">
@ -130,9 +222,9 @@
<template v-else>下单中...</template>
</el-button>
</div>
<div class="btn" v-if="shopStore.info.registerType != 'restaurant' || cartList.length">
<el-button type="primary" style="width: 100%;" :disabled="!cartList.length" v-loading="createOrderLoading"
@click="createOrderHandle(1)">
<div class="btn" v-if="store.shopInfo.registerType != 'restaurant' || goodsStore.cartList.length">
<el-button type="primary" style="width: 100%;" :disabled="!goodsStore.cartList.length"
v-loading="createOrderLoading" @click="createOrderHandle(1)">
<template v-if="!createOrderLoading">
去结算</template>
<template v-else>下单中...</template>
@ -144,7 +236,7 @@
</div>
<div class="shop_manage card">
<!-- 分类/商品列表 -->
<goods ref="goodsRef" :masterId="masterId" @success="addCart" @loading="cartLoading = true" />
<goods ref="goodsRef" @loading="cartLoading = true" />
<!-- ©银收客 v{{ packageData.version }} -->
</div>
</div>
@ -155,10 +247,10 @@
<el-drawer v-model="membershow" :with-header="true" size="90%" title="选择会员">
<member :membershow="'1'"></member>
</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"
:masterId="masterId" :orderInfo="orderInfo" @paySuccess="createCodeAjax(1)" />
:orderInfo="orderInfo" @paySuccess="createCodeAjax(1)" />
<!-- 快捷收银 -->
<fastCashier ref="fastCashierRef" type="0" />
<!-- 挂起订单 -->
@ -166,7 +258,9 @@
<!-- 检查版本升级 -->
<updateDialog />
<!-- 合并/转桌 -->
<tableMerging ref="tableMergingRef" @success="addCart" />
<tableMerging ref="tableMergingRef" @success="" />
<!-- 选择会员 -->
<SelectVipUser ref="SelectVipUserRef" />
</template>
<script>
@ -176,10 +270,10 @@ export default {
</script>
<script setup>
import { onMounted, ref } from "vue";
import { useRoute } from 'vue-router'
import { useUser } from "@/store/user.js";
import { useGlobal } from '@/store/global.js'
import SelectVipUser from "@/components/selectVipUser.vue";
import updateDialog from '@/components/updateDialog.vue'
import remarkModal from "@/components/remarkModal.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 useStorage from '@/utils/useStorage'
import { formatDecimal } from '@/utils/index.js'
import {
createCart,
queryCart,
createCode,
packall,
delCart,
cartStatus,
clearCart,
createOrder,
} from "@/api/product";
import { orderChoseCount } from '@/api/table.js'
import { useGoods } from '@/store/goods.js'
import { queryShopInfo, staffPermission } from '@/api/user.js'
import { createOrder } from '@/api/order.js'
//
import goods from "@/views/home/components/goods.vue";
import member from "@/views/member/index.vue";
import { ElMessage } from "element-plus";
import { useShop } from '@/store/shop.js'
import TableMerging from "./components/tableMerging.vue";
const shopStore = useShop()
const SelectVipUserRef = ref(null)
const goodsStore = useGoods()
const global = useGlobal()
const route = useRoute()
const membershow = ref(false);
const store = useUser();
@ -242,8 +326,6 @@ const cartLoading = ref(false);
const orderInfo = ref({});
const createOrderLoading = ref(false);
//
const masterId = ref("");
//
const pendingCartNum = ref(0);
@ -262,99 +344,35 @@ async function quickCashHandle() {
async function createOrderHandle(t = 0) {
try {
createOrderLoading.value = true;
await staffPermission('yun_xu_xia_dan')
const res = await createOrder({
masterId: masterId.value,
shopId: store.userInfo.shopId,
remark: remark.value,
vipUserId: global.orderMemberInfo.id || '',
tableId: global.tableInfo.qrcode || '',
type: t,
seatNum: global.tableInfo.num
});
createOrderLoading.value = false;
orderId: goodsStore.orderList.length ? goodsStore.orderList[0].id : '', // id
shopId: store.shopInfo.id, // id
seatNum: goodsStore.tableInfo.num || 0, //
packFee: 0, //
originAmount: formatDecimal(goodsStore.cartInfo.totalAmount, 2, true), // +
tableCode: goodsStore.cartList[0].table_code, //
dineMode: store.shopInfo.eatModel, //
remark: remark.value, //
placeNumplaceNum: goodsStore.orderList.length, //
waitCall: 0,//
userId: '', // id
vipPrice: 0, //
})
//
orderInfo.value = res;
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()
goodsStore.orderInfo = res
settleAccountRef.value.show()
} catch (error) {
console.log(error);
}
createOrderLoading.value = false;
}
//
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) {
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 {
cartLoading.value = true;
await delCart({
masterId: params.masterId,
cartId: params.id,
});
cartListActiveItem.value = {}
@ -388,189 +405,19 @@ const allSelectedHandle = async () => {
await packall({
shopId: store.userInfo.shopId,
status: allSelected.value,
masterId: masterId.value,
});
queryCartAjax();
//
};
//
async function takeFoodCodeSuccess(code) {
if (cartList.value.length) {
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 selectCartItemHandle(index) {
goodsStore.selectCartItemHandle(index)
}
// /
function clearMember() {
global.setOrderMember({})
global.setOrderTable({})
createCodeAjax()
}
// /
@ -578,11 +425,6 @@ function showTableMerging() {
let data = cartList.value.filter(item => item.placeNum)
tableMergingRef.value.show(data)
}
onMounted(() => {
createCodeAjax()
shopStore.queryShopInfo()
});
</script>
<style scoped lang="scss">
@ -619,15 +461,20 @@ onMounted(() => {
}
.number {
width: 50px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
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 {
font-size: var(--el-font-size-base);
margin-left: 4px;
}
}
@ -681,10 +528,47 @@ onMounted(() => {
.shop_list {
flex: 1;
height: calc(100vh - 40px - 60px - 80px);
height: calc(100vh - 40px - 60px - 90px);
overflow-y: auto;
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 {
padding: var(--el-font-size-base);
@ -803,7 +687,7 @@ onMounted(() => {
}
.footer {
padding: var(--el-font-size-base);
padding: 10px var(--el-font-size-base);
border-top: 1px solid #ececec;
.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 {
display: flex;
justify-content: space-between;
@ -846,7 +750,7 @@ onMounted(() => {
$h: 70px;
display: flex;
height: $h;
padding-top: var(--el-font-size-base);
padding-top: 10px;
gap: var(--el-font-size-base);
.editor {

View File

@ -1,5 +1,5 @@
<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">
<div class="message">
{{ updataInfo.message }}
@ -15,17 +15,19 @@
<template v-if="!isUpload">
立即更新
</template>
<template v-else>
<template v-else>
下载中...
</template>
</template>
<template v-else>
</template>
<template v-else>
立即安装
</template>
</el-button>
</div>
</template>
</el-dialog>
</el-button>
</div>
</template>
</el-dialog> -->
<el-input v-model="authCode" placeholder="请扫描支付码"></el-input>
<el-button type="primary" @click="microPayAjax">反扫支付</el-button>
</template>
<script setup>
@ -33,6 +35,7 @@ import { onMounted, ref } from 'vue'
import { findVersion } from '@/api/user.js'
import packageData from "../../../package.json";
import { ipcRenderer } from 'electron'
import { microPay } from '@/api/order.js'
const showDialog = ref(false)
const updataInfo = ref({})
@ -42,6 +45,8 @@ const uploadSucess = ref(false)
const uploadResponse = ref({})
const tempFilePath = ref('')
const authCode = ref('')
//
async function findVersionAjax() {
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(() => {
findVersionAjax()
// findVersionAjax()
ipcRenderer.on('updateProgress', (event, res) => {
// console.log('updateProgress===', event, res);
uploadPro.value = res

View File

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

View File

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

View File

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