Files
cashier_app/pagesCreateOrder/index/index.vue
2025-02-26 19:46:20 +08:00

1516 lines
34 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="u-wrap">
<view class="u-fixed position-all" style="z-index: 999;" v-if="!canXiadan" @click="xiadanClick"></view>
<view class="top bg-fff w-full">
<template v-if="option.type!='add'">
<view class="u-flex u-row-between choose-user" @tap="chooseTable">
<view>
<view v-if="!data.table.id">选择桌台</view>
<view class="u-flex" v-else>
<view class="u-m-l-20">{{data.table.name}}</view>
</view>
</view>
<view class="u-flex">
<uni-icons type="right" size="20" color="#999"></uni-icons>
</view>
</view>
</template>
<view class="search u-flex u-col-center ">
<view class="u-flex-1">
<uni-search-bar bgColor="#F9F9F9" cancelButton="none" placeholder="搜索店内商品" @confirm="search"
@clear="clearSearch" v-model="searchValue">
</uni-search-bar>
</view>
<view class="u-flex" @click="scanCode">
<image src="/pagesCreateOrder/static/images/icon-saoma.svg" class="icon-saoma" mode=""></image>
</view>
</view>
</view>
<template v-if="!isSearch">
<view class="u-menu-wrap">
<scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view"
:scroll-top="data.scrollTop" :scroll-into-view="data.itemId">
<view v-for="(item,index) in data.tabbar" :key="index" class="u-tab-item"
:class="[data.current == index ? 'u-tab-item-active' : '']" @tap.stop="swichMenu(index)">
<text class="u-line-3">{{item.name}}</text>
</view>
</scroll-view>
<scroll-view :scroll-top="data.scrollRightTop" scroll-y scroll-with-animation class="right-box"
@scroll="rightScroll">
<view class="page-view u-p-l-24">
<view class="list-tight-top">
<template v-if="lingshi.show">
<view id="lingshi" class="lingshi u-m-b-32" @tap="toLinshi">
<uni-icons type="plus-filled" size="24" :color="color.ColorMain"></uni-icons>
<view class="u-m-t-24 color-main">临时菜</view>
</view>
</template>
<template v-else>
<view style="height: 24px;"></view>
</template>
</view>
<view class="class-item" :id="'item' + index" v-for="(item , index) in data.tabbar"
:key="index">
<view class="item-title" :class="{active:data.current == index}">
<text>{{item.name}}</text>
</view>
<view class="item-container">
<view class="thumb-box" v-for="(goodsItem, goodsIndex) in item.foods" :key="goodsIndex">
<list-goods-item
@chooseGuige="chooseGuige($event,index)"
@add="goodsUpdate($event,index,true)"
@reduce="goodsUpdate($event,index,false)"
@tapweigh="tapweigh($event,index)"
:index="goodsIndex"
:data="goodsItem"></list-goods-item>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<template v-else>
<view class="u-menu-wrap">
<scroll-view class=" u-flex-1" scroll-y scroll-with-animation>
<view class="u-p-l-30 u-p-r-30">
<view class="u-font-28 color-666 ">搜索</view>
<view class="u-flex u-m-t-20 u-flex-wrap u-row-between">
<view class="u-m-b-30" v-for="(goodsItem, goodsIndex) in searchResult" :key="goodsIndex">
<list-goods-item
:img="{width:'330rpx',height:'330rpx'}"
@chooseGuige="chooseGuige(goodsItem.goodsIndex,goodsItem.index)"
@add="searchGoodsUpdate(goodsItem,goodsIndex,true)"
@reduce="searchGoodsUpdate(goodsItem,goodsIndex,false)"
@tapweigh="tapweigh(goodsItem.goodsIndex,goodsItem.index)"
:index="goodsItem.goodsIndex" :data="goodsItem"></list-goods-item>
</view>
</view>
<my-img-empty v-if="!searchResult.length" tips="未搜索到相关商品"></my-img-empty>
</view>
</scroll-view>
</view>
</template>
<view class="bottom w-full">
<my-car :isCreateOrderToDetail="isCreateOrderToDetail" @updateNumber="carsNumberChange" :user="data.vipUser"
:table="data.table" :data="cars" @clear="cleaCart"></my-car>
</view>
<!-- 套餐选择规格 -->
<taocanModel ref="taocanModelRef" @confirm="taocanConfirm" :goodsData="selGoods"></taocanModel>
<!-- 选择规格 -->
<guige-model @update-sku="updateSkuSel" @confirm="guigeConfirm" ref="chooseGuigeModel" :goodsData="selGoods"
:title="guigeModelData.title" :sku-map="guigeModelData.chooseGoods.skuMap"
:skus="guigeModelData.chooseGoods.skus"></guige-model>
<!-- 添加附加费 -->
<my-surcharge @confirm="surchargeConfirm" ref="surcharge" title="添加附加费"></my-surcharge>
<!-- 称重 -->
<weigh-item ref="refweighitem" @weighgoodsUpdate='goodsUpdate'></weigh-item>
</view>
</template>
<script setup>
import {
onLoad,
onReady,
onShow,
onPageScroll,
onPullDownRefresh
} from '@dcloudio/uni-app';
import {
computed,
reactive,
ref,
nextTick,
watch,
getCurrentInstance,
onUnmounted,
onBeforeUnmount,
} from 'vue';
import _ from 'lodash';
import * as Api from '@/http/yskApi/Instead.js'
import {
$table,
$choseTable,
$returnTableDetail
} from '@/http/yskApi/table.js'
import {
$tbShopCategory
} from '@/http/yskApi/goods.js'
import util from './util.js';
import color from '@/commons/color.js';
import guigeModel from './components/guige'
import taocanModel from './components/taocanModel.vue'
import weighItem from './components/weigh.vue'
import listGoodsItem from './components/list-goods-item.vue'
import mySurcharge from './components/surcharge'
import myCar from './components/car'
import go from '@/commons/utils/go.js';
import infoBox from '@/commons/utils/infoBox.js';
import { getNowCart } from '@/pagesCreateOrder/util.js'
import storageManage from '@/commons/utils/storageManage.js'
import {
$returnUseType
} from './util.js'
import {
hasPermission
} from '@/commons/utils/hasPermission.js'
import appConfig from '@/config/appConfig.js';
import WebsocketUtil from '@/commons/utils/websocket.js'
import { getShopTable } from '@/api/table.js'
import { getProductList } from '@/api/product.js'
import { categoryPage } from '@/api/cateGory.js'
import { inject } from 'vue';
const modal = reactive({
key: '',
clear: false,
data: ''
})
//临时菜
const lingshi = reactive({
show: true
})
//附加费
const extraFee = reactive({
show: false
})
const cars = reactive([])
const data = reactive({
scrollTop: 0, //tab标题的滚动条位置
oldScrollTop: 0,
current: 0, // 预设当前项的值
menuHeight: 0, // 左边菜单的高度
menuItemHeight: 0, // 左边菜单item的高度
itemId: '', // 栏目右边scroll-view用于滚动的id
tabbar: storageManage.cacheGoods() || [],
menuItemPos: [],
arr: [], //左右联动布局节点信息
scrollRightTop: 0, // 右边栏目scroll-view的滚动条高度
timer: null, // 定时器
topZhanwei: 136 + 24,
// 选择用户
vipUser: {
id: "",
},
table: {
tableId: ""
},
socketData: {
type:'onboc',
account: uni.getStorageSync("iToken").loginId,
shop_id: uni.getStorageSync("shopInfo").id,
is_gift: 0
},
orderId: null,
})
const guigeModelData = reactive({
title: '',
chooseGoods: {
skuMap: {},
item: '',
skus: []
}
})
const chooseGuigeModel = ref(null)
let isCreateOrderToDetail = ref(false)
let option = {
type: ''
}
const websocket = ref(null);
onLoad((opt) => {
// console.log(opt)
option = opt
Object.assign(data.table, opt)
if (opt.useType) {
uni.setStorageSync('useType', opt.useType)
}
uni.setNavigationBarTitle({
title: (opt && opt.type == 'add') ? '顾客加菜' : '代客下单'
})
if (JSON.stringify(opt) == '{}') {
isCreateOrderToDetail.value = true
}
// if (!opt.tableId) {
// infoBox.showErrorToast('暂不支持不选择桌台下载,请从桌台点餐')
// return setTimeout(() => {
// go.back()
// }, 1500)
// }
init()
})
watch(() => data.table.id, (newval, oldval) => {
if (option.type != 'add') {
onSelTable()
}
})
onShow(() => {
// watchChooseuser()
watchChooseTable()
watchUpdate()
})
onReady(() => {
getElRect('list-tight-top').then(res => {
data.topZhanwei = res.height
})
getMenuItemTop()
})
onBeforeUnmount(() => {
if (websocket.value) {
// websocket.value.destroy();
}
})
// 组件卸载时清理WebSocket
onUnmounted(() => {
if (websocket.value) {
websocket.value.destroy();
}
});
let $originGoods = []
let $category = []
async function init() {
// console.log(option.type)
if (option.type == 'add') {
setTabBar($category, $originGoods, [])
}
const useType = data.table.status == 'using' ? data.table.useType : $returnUseType(uni.getStorageSync("shopInfo"))
uni.setStorageSync('useType', useType)
await getTableInfo()
// 获取分类数据
const categoryRes = await categoryPage({ page: 1, size: 300 })
const category = categoryRes.records;
$category = category
const goodsRes = await getGoods()
const goods = goodsRes.records.filter((v) => {
let isShow = true;
if (v.type !== "sku") {
isShow = v.skuList.length >= 1;
}
return isShow;
});
$originGoods = goods
if (option.type == 'add') {
cars.length = 0
setTabBar(category, goods, [])
return
}
if (!data.table.id) {
//无桌台
// const cartRes = await getCart()
// cars.length = 0
// const cartArr = getNowCart(cartRes.records)
// for (let i in cartArr) {
// cars.push(cartArr[i])
// }
// setTabBar(category, goods, cars)
// return
}
// const cartRes = await getCart()
// cars.length = 0
// const cartArr = getNowCart(cartRes.records)
// for (let i in cartArr) {
// cars.push(cartArr[i])
// }
setTabBar(category, goods, cars)
initCart()
}
const websocketUtil = inject('websocketUtil'); // 注入 WebSocket 工具类实例
/**
* socket消息监听
*/
websocketUtil.onMessage(res => {
let msg = JSON.parse(res);
let cartItem;
if( msg.msg_id ){
// console.log('Received data:', msg);
websocketUtil.send(JSON.stringify({
type: 'receipt',
msg_id: msg.msg_id,
}))
}
if( msg.status == 0 ){
infoBox.showToast('添加失败')
return false;
}
switch (msg.operate_type) {
case 'onboc_init':
cars.length = 0
msg.data.map(item=>{
cartItem = getNowCart(item,$originGoods)
cars.push(cartItem)
})
break;
case 'onboc_add':
console.log("onboc_add")
cartItem = getNowCart(msg.data,$originGoods)
cars.push(cartItem)
break;
case 'onboc_cleanup':
cars.length = 0
for (let i in data.tabbar) {
for (let k in data.tabbar[i].foods) {
data.tabbar[i].foods[k].chooseNumber = 0
}
}
console.log(data.tabbar)
break;
}
});
/**
* 获取商品列表
*/
function getGoods() {
const showLoading = data.tabbar.length <= 0 ? true : false
return getProductList({
page: 1,
size: 300
},'product', showLoading)
}
/**
* 获取桌台信息
*/
async function getTableInfo() {
const res = await getShopTable({
status: 'idle',
})
if (res && res.records[0]) {
data.table = {
...res.records[0],
}
}
}
/**
* 前往选择桌台
*/
function chooseTable() {
go.to('PAGES_CHOOSE_TABLE', {
...data.table
})
}
/**
* 选择桌台完成
*/
function watchChooseTable() {
uni.$off('choose-table')
uni.$on('choose-table', (item) => {
onChooseTable(item)
})
}
/**
* 选择桌台完成
* @param {Object} item
*/
async function onChooseTable(item) {
console.log('onChooseTable');
if (!item) {
// #ifdef MP-WEIXIN
uni.showModal({
title: '提示',
content: '桌台不存在或不是该店铺的桌台'
})
// #endif
// #ifndef MP-WEIXIN
infoBox.showToast('桌台不存在或不是该店铺的桌台')
// #endif
return
}
console.log('---table:detail-----',item);
if (data.table.id || cars.length <= 0) {
data.table = {
...item
}
return;
}
if (item.status == "unbind") {
return infoBox.showToast('该台桌未绑定,清先去桌台管理里绑定码牌')
}
if (item.status != "idle") {
return infoBox.showToast('该台桌已在使用中')
}
data.table = item
}
/**
* 初始化购物车
*/
function initCart () {
let params = {
...data.socketData,
operate_type:'init',
table_code: data.table.tableCode,
}
websocketUtil.send(JSON.stringify(params))
}
/**
* 购物车添加菜品
*/
function editCart (par,operate_type) {
console.log('购物车添加菜品',par)
let params = {
...data.socketData,
operate_type: operate_type,
table_code: data.table.tableCode,
product_id: '',
sku_id: '', //
number: 1, //数量
is_temporary: 0, //是否是临时菜
}
Object.assign(params, par)
websocketUtil.send(JSON.stringify(params))
}
/**
* 删除购物车菜品
*/
function delCart (id) {
let params = {
...data.socketData,
id: id,
operate_type:'del',
table_code: data.table.tableCode,
}
websocketUtil.send(JSON.stringify(params))
}
/**
* 清除购物车
*/
function cleaCart () {
let params = {
...data.socketData,
operate_type:'cleanup',
table_code: data.table.tableCode,
}
websocketUtil.send(JSON.stringify(params))
}
/**
* 菜品操作
* @param {Object} foodsindex
* @param {Object} index
* @param {Object} isAdd
* @param {Object} searchGoodsIndex
* @param {Object} showCurrentInput
*/
async function goodsUpdate(foodsindex, index, isAdd, searchGoodsIndex, showCurrentInput) { // showCurrentInput 称重才会传的参数
if (!data.table.id) {
return infoBox.showToast('请先选择桌台', 0.5).then(res => {
chooseTable()
})
}
const $goods = data.tabbar[index].foods[foodsindex]
if ($goods.type !== 'sku') {
//单规格
console.log($goods)
const goodsInCarIndex = cars.findIndex((carsGoods) => {
return carsGoods.sku_id == $goods.skuList[0].id && carsGoods.product_id == $goods.id;
});
const product_id = $goods.id
const sku_id = $goods.skuList[0].id
let suitNum = $goods.skuList[0].suitNum || 1
if (goodsInCarIndex !== -1) {
//更新
const carGoods = cars[goodsInCarIndex]
const cartId = carGoods.id
// const step = isAdd ? 1 : -1
// $sku = !product_id ? { suitNum: 1 } : $goods.skuList.find(v => v.id == sku_id)
let num = isAdd ? carGoods.number + 1 : + carGoods.number - 1
if( !isAdd ){
if (num === 0 || num < suitNum) {
//移除
cars.splice(goodsInCarIndex, 1)
$goods.chooseNumber = 0
setSearchGoods(searchGoodsIndex, 0)
delCart(cartId)
}
}
// 不影响之前的代码 称重num单独处理
if ($goods.type == 'weigh' && showCurrentInput) {
num = carGoods.number * 1 + Number(showCurrentInput)
}
editCart({
id: cartId,
number: num,
product_id: product_id,
sku_id: sku_id,
},'edit')
carGoods.number = num
$goods.chooseNumber = num
setSearchGoods(searchGoodsIndex, num)
} else {
console.log(suitNum)
// 不影响之前的代码 称重suit单独处理
if ($goods.type == 'weigh' && showCurrentInput) {
suitNum = showCurrentInput
}
// 套餐和单规格
if ($goods.groupType != 1) {
//增加
editCart({
number: suitNum,
product_id: product_id,
sku_id: sku_id,
discount_sale_amount: $goods.lowPrice
},'add')
infoBox.showToast('添加成功')
$goods.chooseNumber = Number(suitNum)
}
}
return
}
}
/**
* 添加套餐
* @param {Object} d
* @param {Object} item
*/
async function taocanConfirm(d, item) {
console.log(d)
editCart({
number: item.skuList[0].suitNum,
product_id: item.id,
sku_id: item.skuList[0].id,
pro_group_info: JSON.stringify(d),
discount_sale_amount: item.lowPrice
},'add')
}
let selGoods = ref({});
/**
* 打开规格弹窗
* @param {Object} foodsindex
* @param {Object} index
*/
function chooseGuige(foodsindex, index) {
if (!data.table.id) {
return infoBox.showToast('请先选择桌台', 0.5).then(res => {
chooseTable()
})
}
const $goods = data.tabbar[index].foods[foodsindex]
console.log($goods)
selGoods.value = $goods
if ($goods.groupType == 1) {
instance.ctx.$refs.taocanModelRef.open()
} else {
console.log($goods)
guigeModelData.title = $goods.name
const skuMap = returnSelGoodsSkuMap($goods.skuList)
console.log(skuMap)
// 多规格,和套餐规格区分.groupType=1 套餐多规格
const selectSpecInfo = returnSelGoodsSkuList($goods.selectSpecInfo)
setSkugoodsDefaultInit($goods, selectSpecInfo, skuMap, $goods.skuList)
chooseGuigeModel.value.open()
}
}
//返回当前选中商品skuMap
function returnSelGoodsSkuMap(specList) {
const skuMap = {}
for (let i in specList) {
skuMap[specList[i].specInfo] = specList[i];
}
return skuMap
}
/**
* 多规格选择
* @param {Object} skuList
* @param {Object} specSnap
*/
function returnSelGoodsSkuList(selectSpecInfo) {
let specSnap = []
for (var key in selectSpecInfo) {
specSnap.push({
name: key,
value: selectSpecInfo[key]
})
}
let result = specSnap.map((v, index) => {
return {
...v,
valueArr: v.value,
sel: "",
values: v.value.map((name) => {
return {
name: name,
disabled: false
};
}),
};
});
return result
}
/**
* 多规格选择确认
* @param {Object} sku
* @param {Object} num
*/
async function guigeConfirm(sku, num) {
const goods = guigeModelData.chooseGoods.item
const skuId = sku.id
const productId = goods.id
const res = findGoodsInCar(goods, skuId)
if (res) {
//更新
const {
index
} = res
const carGoods = cars[index]
const cartId = carGoods.id
const newNumber = carGoods.number * 1 + num
const {
number
} = await updateCartGoods({
num: newNumber,
cartId,
productId,
skuId
})
carGoods.number = number
} else {
//添加
const cartGoods = await addCart({
num,
productId,
skuId
})
infoBox.showToast('添加成功')
cars.push({
...cartGoods,
specSnap: sku.specSnap
})
}
}
/**
* 找到该规格商品在购物车中是否存在并返回index值以及对应的数据
* @param {Object} $goods
* @param {Object} skuId
*/
function findGoodsInCar($goods, sku_id) {
const product_id = $goods.id
const goodsInCarIndex = cars.findIndex((carsGoods) => {
return carsGoods.sku_id == sku_id && carsGoods.product_id == product_id;
});
const carGoods = cars[goodsInCarIndex]
return carGoods ? {
index: goodsInCarIndex,
carGoods
} : false
}
//多规格商品弹窗时,找到默认可以下单的规格商品
function findGoods(skuList = [], goodsListMap = {}, specList) {
const skuMapNumber = skuList.reduce((prve, cur) => {
for (let i in cur.valueArr) {
prve[cur.valueArr[i]] = i;
}
return prve;
}, {});
const canBudyGoods = specList
.filter((v) => util.isCanBuy(v, guigeModelData.chooseGoods.item))
.sort((a, b) => {
const aNumber = a.specSnap.split(",").reduce((prve, cur) => {
return prve + skuMapNumber[cur];
}, 0);
const bNumber = b.specSnap.split(",").reduce((prve, cur) => {
return prve + skuMapNumber[cur];
}, 0);
return aNumber - bNumber;
});
return canBudyGoods[0];
}
/**
* 设置商品默认选中,规格禁止以及选中
* @param {Object} goods
* @param {Object} selectSpecInfo
* @param {Object} skuMap
* @param {Object} specList
*/
function setSkugoodsDefaultInit(goods, selectSpecInfo, skuMap, specList) {
guigeModelData.chooseGoods.item = goods
guigeModelData.chooseGoods.skus = selectSpecInfo
guigeModelData.chooseGoods.skuMap = skuMap
const skuGoods = findGoods(selectSpecInfo, skuMap, specList);
if (skuGoods) {
// this.skuGoods.data = skuGoods;
// this.skuGoods.number = skuGoods.suit || 1;
skuGoods.specSnap.split(",").map((v, index) => {
guigeModelData.chooseGoods.skus[index].sel = v;
});
}
console.log("guigeModelData.chooseGoods.skus===",guigeModelData.chooseGoods.skus);
setTagDisabled();
}
//更新选中规格
function updateSkuSel(skusIndex, skdName) {
const skuList = guigeModelData.chooseGoods.skus
const skuMap = guigeModelData.chooseGoods.skuMap
guigeModelData.chooseGoods.skus[skusIndex].sel = skdName
const specSnap = guigeModelData.chooseGoods.skus.reduce((prve, cur) => {
prve.push(cur.sel)
return prve
}, []).join()
setTagDisabled();
}
//设置规格按钮的禁止状态
function setTagDisabled() {
const skuList = guigeModelData.chooseGoods.skus
const skuMap = guigeModelData.chooseGoods.skuMap
const selArr = skuList.reduce((prve, cur) => {
if (cur.sel) {
prve.push(cur.sel);
} else {}
return prve;
}, []);
console.log(selArr);
let selArrAllGroup = util.generateCombinations(selArr, selArr.length - 1);
console.log(selArrAllGroup);
const matchArr = [];
for (let key in skuMap) {
const goods = skuMap[key];
const keyArr = key.split(",");
for (let spe of selArrAllGroup) {
if (util.arrayContainsAll(keyArr, spe)) {
matchArr.push(goods);
break;
}
}
}
//全部规格都已下架
if (!matchArr.length) {
for (let k in skuList) {
for (let i in skuList[k].values) {
skuList[k].values[i].disabled = true
}
}
return;
}
const includeSkuMap = matchArr.reduce((prve, cur) => {
const speArr = cur.specSnap.split(",");
for (let i of speArr) {
if (!prve.hasOwnProperty("i")) {
prve[i] = matchArr
.filter((v) => v.specSnap.match(i))
.every((v) => {
return !util.isCanBuy(v, guigeModelData.chooseGoods.item)
});
}
}
return prve;
}, {});
for (let i in includeSkuMap) {
for (let k in skuList) {
const index = skuList[k].valueArr.findIndex((val) => val === i);
if (index !== -1) {
skuList[k].values[index].disabled = includeSkuMap[i]
}
}
}
}
/**
* 购物车商品数量改变
* @param {Object} e
*/
async function carsNumberChange(e) {
const { num, index, goods } = e
const { product_id, categoryId, sku_id } = goods
const cartId = goods.id
//临时菜没有对应商品数据
let $goods;
data.tabbar.map(tabbarItem=>{
if(tabbarItem.foods.find(v => v.id == product_id)){
$goods = !product_id ? undefined : tabbarItem.foods.find(v => v.id == product_id)
}
})
let $sku;
if( $goods.type != 'package'){
//临时菜没有skuList
$sku = !product_id ? { suitNum: 1 } : $goods.skuList.find(v => v.id == sku_id)
} else {
$sku = !product_id ? { suitNum: 1 } : $goods.skuList.find(v => v.id == sku_id)
}
console.log(num)
console.log($sku.suitNum)
if (num === 0 || num < $sku.suitNum) {
//移除
delCart(cartId)
cars.splice(index, 1)
$goods.chooseNumber = 0
return
}
editCart({
number: num,
id: cartId,
product_id: product_id,
sku_id: sku_id
},'edit')
cars[index].number = num
if ($goods) {
$goods.chooseNumber = num
}
}
const instance = getCurrentInstance();
let canXiadan = ref(false)
async function xiadanClick() {
canXiadan.value = await hasPermission('允许下单')
}
// xiadanClick()
/**
* 扫桌台码
*/
function scanCode() {
// 只允许通过相机扫码
console.log('scanCode');
uni.scanCode({
onlyFromCamera: true,
success: function(res) {
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
if (res.result.includes('codeplate?code=')) {
const par = returnUrlPar(res.result)
const tableId = par.code
onChooseTable({
tableId
})
} else {
uni.showToast({
icon: 'error',
title: '请扫描正确的桌台码'
})
}
// uni.showModal({
// title:'',
// content:res.result
// })
}
});
}
function returnUrlPar(str) {
let arr = str.split("?")[1].split("&"); //先通过?分解得到?后面的所需字符串,再将其通过&分解开存放在数组里
let obj = {};
for (let i of arr) {
obj[i.split("=")[0]] = i.split("=")[1]; //对数组每项用=分解开,=前为对象属性名,=后为属性值
}
return obj
}
function setTabBar(category, goods, cars) {
const goodsCategoryMap = goods.reduce((prve, cur) => {
if (!prve.hasOwnProperty(cur.categoryId)) {
prve[cur.categoryId] = []
}
prve[cur.categoryId].push(cur)
return prve
}, {})
const chooseGoodsNumberMap = cars.reduce((prve, cur) => {
if (!prve.hasOwnProperty(cur.productId)) {
prve[cur.productId] = 0
}
prve[cur.productId] += cur.number
return prve
}, {})
let tabbar = category.map(v => {
const foods = goodsCategoryMap[v.id] || []
return {
...v,
foods: foods.map((fgoods, index) => {
return {
...fgoods,
chooseNumber: chooseGoodsNumberMap[fgoods.id],
price: fgoods.lowPrice,
}
})
}
})
tabbar = tabbar.filter(v => {
return v.foods.length
})
data.tabbar = tabbar
nextTick(() => {
getMenuItemTop()
})
storageManage.cacheGoods(data.tabbar)
}
//更新购物车
function updateCartGoods(par) {
const submitPar = {
cartId: '',
tableId: data.table.id,
isPack: false,
num: 1,
productId: '',
skuId: '',
vipUserId: data.vipUser.id
}
Object.assign(submitPar, par)
return Api.$updateCart(submitPar)
}
//更新选择用户
function setUser(par) {
const submitPar = {
tableId: data.table.id,
vipUserId: data.vipUser.id ? data.vipUser.id : '',
type: data.vipUser.id ? 0 : 1 //0 设置 1 取消
}
Object.assign(submitPar, par)
return Api.$setUser(submitPar)
}
// 监听选择用户事件
const surcharge = ref(null)
function surchargeConfirm(e) {
data.tabbar[data.tabbar.length - 1].foods.unshift({
...e,
chooseNumber: 0
})
}
function surchargeShow() {
surcharge.value.open()
}
let searchValue = ref('')
let isSearch = ref(false)
let searchResult = ref([])
function returnSearchGoods() {
const newval = searchValue.value
let arr = []
let goods = []
for (let i in data.tabbar) {
const goodsArr = data.tabbar[i].foods || []
for (let k in goodsArr) {
goods.push({
...goodsArr[k],
index: i,
goodsIndex: k
})
}
}
if (newval == "") {
arr = goods;
} else {
arr = goods.filter((v) =>
v.name.includes(newval.trim())
);
}
return arr
}
function search() {
if (searchValue.value === '') {
isSearch.value = false
return
}
isSearch.value = true
searchResult.value = returnSearchGoods()
console.log(searchResult.value);
}
function clearSearch() {
isSearch.value = false
}
function chooseUser() {
go.to('PAGES_CHOOSE_USER')
}
/**
* 前往临时菜
*/
function toLinshi() {
go.to('PAGES_CHOOSE_ADD_TEMP_CUISINE', {
tableCode: data.table.tableCode,
})
}
// 称重
const refweighitem = ref(null)
const tapweigh = (foodsindex, index) => {
const goods = data.tabbar[index].foods[foodsindex]
refweighitem.value.open(foodsindex, index, goods)
}
/**
* 搜索商品添加减少
* @param {Object} goodsItem
* @param {Object} goodsIndex
* @param {Object} isAdd
*/
function searchGoodsUpdate(goodsItem, goodsIndex, isAdd) {
goodsUpdate(goodsItem.goodsIndex, goodsItem.index, isAdd, goodsIndex)
}
function setSearchGoods(index, chooseNumber) {
if (index !== undefined) {
searchResult.value[index].chooseNumber = chooseNumber
}
}
let isTabClickOver = true
/**
* 点击左边的栏目切换
* @param {Object} index
*/
async function swichMenu(index) {
if (data.arr.length == 0) {
await getMenuItemTop();
}
if (index == data.current) return;
isTabClickOver = false;
data.scrollRightTop = data.oldScrollTop;
nextTick(function() {
data.scrollRightTop = data.arr[index] + data.topZhanwei;
data.current = index;
leftMenuStatus(index);
})
}
/**
* 获取一个目标元素的高度
* @param {Object} elClass
* @param {Object} dataVal
*/
function getElRect(elClass, dataVal) {
return new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(instance.proxy);
query.select('.' + elClass).fields({
size: true
}, res => {
// 如果节点尚未生成res值为null循环调用执行
if (!res) {
setTimeout(() => {
getElRect(elClass);
}, 10);
return;
}
if (dataVal) {
data[dataVal] = res.height;
}
resolve(res);
}).exec();
})
}
/**
* 设置左边菜单的滚动状态
* @param {Object} index
*/
async function leftMenuStatus(index) {
if (!isTabClickOver) {
return
}
data.current = index;
// 如果为0意味着尚未初始化
if (data.menuHeight == 0 || data.menuItemHeight == 0) {
await getElRect('menu-scroll-view', 'menuHeight');
await getElRect('u-tab-item', 'menuItemHeight');
}
// 将菜单活动item垂直居中
data.scrollTop = index * data.menuItemHeight + data.menuItemHeight / 2 - data.menuHeight / 2;
}
/**
* 获取右边菜单每个item到顶部的距离
*/
function getMenuItemTop() {
new Promise(resolve => {
let selectorQuery = uni.createSelectorQuery();
selectorQuery.selectAll('.class-item').boundingClientRect((rects) => {
// 如果节点尚未生成rects值为[](因为用selectAll所以返回的是数组),循环调用执行
if (!rects.length) {
setTimeout(() => {
getMenuItemTop();
}, 10);
return;
}
let arr = []
rects.forEach((rect) => {
// 这里减去rects[0].top是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
arr.push(rect.top - rects[0].top);
})
data.arr = arr
resolve();
}).exec()
})
}
/**
* 右边菜单滚动
* @param {Object} e
*/
async function rightScroll(e) {
data.oldScrollTop = e.detail.scrollTop;
if (data.arr.length == 0) {
await getMenuItemTop();
}
if (data.timer) return;
if (!data.menuHeight) {
await getElRect('menu-scroll-view', 'menuHeight');
}
if (e.detail.scrollTop == 0) {
isTabClickOver = true
// return swichMenu(0)
}
setTimeout(() => { // 节流
data.timer = null;
// scrollHeight为右边菜单垂直中点位置
let scrollHeight = e.detail.scrollTop + data.menuHeight / 2 + data.topZhanwei / 2;
for (let i = 0; i < data.arr.length; i++) {
let height1 = data.arr[i];
let height2 = data.arr[i + 1];
// 如果不存在height2意味着数据循环已经到了最后一个设置左边菜单为最后一项即可
if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
if (isTabClickOver) {
leftMenuStatus(i);
} else {
isTabClickOver = true
}
return;
}
}
}, 100)
}
function watchChooseuser() {
uni.$off('choose-user')
uni.$on('choose-user', (user) => {
console.log(user);
data.vipUser = user ? user : {
id: ''
}
setUser()
})
}
async function onSelTable() {
// const cartRes = await getCart()
// cars.length = 0
// const cartArr = getNowCart(cartRes.records)
// for (let i in cartArr) {
// cars.push(cartArr[i])
// }
setTabBar($category, $originGoods, cars)
}
function watchUpdate() {
uni.$off('update:createOrderIndex')
uni.$off('get:table')
uni.$off('add:cashCai')
uni.$on('update:createOrderIndex', () => {
// data.table = {
// tableId: ""
// }
cars.length = 0
console.log('update:createOrderIndex');
init()
})
// 添加临时菜到购物车
uni.$on('add:cashCai', async (data) => {
console.log('add:cashCai',data);
$originGoods.push(data)
})
uni.$on('get:table', () => {
console.log('get:table');
if (data.table.id) {
$table.get({
qrcode: data.table.id
}).then(res => {
if (res.content[0] && res.content[0].status != 'idle') {
data.table = {
tableId: ''
}
}
})
}
})
}
</script>
<style lang="scss" scoped>
.choose-user {
background: #F9F9F9;
padding: 22rpx 28rpx;
}
.search {
padding-right: 28rpx;
}
.icon-saoma {
margin-left: 20rpx;
width: 34rpx;
height: 32rpx;
}
$u-tips-color: $my-main-color;
$u-primary: $my-main-color;
$u-main-color: $my-main-color;
.u-wrap {
height: calc(100vh);
/* #ifdef H5 */
height: calc(100vh - var(--window-top));
/* #endif */
display: flex;
flex-direction: column;
}
.headeimg {
width: 60rpx;
height: 60rpx;
display: flex;
background-color: #eee;
border-radius: 12rpx;
overflow: hidden;
.img {
width: 60rpx;
height: 60rpx;
}
}
.u-menu-wrap {
flex: 1;
display: flex;
overflow: hidden;
}
.u-search-inner {
// background-color: rgb(234, 234, 234);
background-color: #fff;
border-radius: 100rpx;
display: flex;
align-items: center;
padding: 10rpx 16rpx;
}
.u-search-text {
font-size: 26rpx;
color: $u-tips-color;
margin-left: 10rpx;
}
.u-tab-view {
width: 178rpx;
height: 100%;
}
.u-tab-item {
height: 110rpx;
background: #f6f6f6;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #444;
font-weight: 400;
line-height: 1;
box-sizing: border-box;
padding-left: 12rpx;
}
.u-tab-item-active {
position: relative;
color: $my-main-color;
font-size: 30rpx;
font-weight: 600;
background: #fff;
}
.u-tab-item-active::before {
content: "";
position: absolute;
border-left: 4px solid $my-main-color;
left: 0;
top: 0;
bottom: 0;
}
.u-tab-view {
height: 100%;
background-color: #f6f6f6;
}
.addCai {
width: 250rpx;
height: 272rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
box-sizing: border-box;
border: 4rpx solid #90BDF6;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.lingshi {
width: 250rpx;
height: 136px;
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 4rpx solid #90BDF6;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
::v-deep .uni-searchbar {
padding-top: 12px !important;
padding-bottom: 16px !important;
}
.right-box {
width: 572rpx;
// background-color: rgb(250, 250, 250);
background-color: rgb(255, 255, 255);
}
.page-view {
// padding: 24rpx 28rpx 24rpx 24rpx;
}
.class-item {
margin-bottom: 30rpx;
background-color: #fff;
border-radius: 8rpx;
}
.class-item:last-child {
min-height: 50vh;
}
.item-title {
font-size: 26rpx;
font-weight: bold;
&.active {
color: $my-main-color;
}
}
.item-menu-name {
font-weight: normal;
font-size: 24rpx;
color: $u-main-color;
}
.item-container {
display: flex;
flex-wrap: wrap;
margin-top: 24rpx;
}
.thumb-box {
margin-right: 24rpx;
margin-bottom: 24rpx;
}
.item-menu-image {
width: 120rpx;
height: 120rpx;
}
</style>