cashier_app/pagesCreateOrder/index/index.vue

1535 lines
36 KiB
Vue
Raw Permalink 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="$utils.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"
:table="data.table" :data="cars" :orderInfo="data.orderInfo" :historyOrder="data.historyOrder" @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>
<!-- 称重 -->
<weigh-item ref="refweighitem" @weighgoodsUpdate='goodsUpdate'></weigh-item>
</view>
</template>
<script setup>
import { onLoad, onReady, onShow, onUnload, onHide } from '@dcloudio/uni-app';
import { inject, computed, reactive, ref, nextTick, watch, getCurrentInstance, onUnmounted, onBeforeUnmount } from 'vue';
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 myCar from './components/car'
import util from './util.js';
import go from '@/commons/utils/go.js';
import { getNowCart } from '@/pagesCreateOrder/util.js'
import storageManage from '@/commons/utils/storageManage.js'
import { hasPermission } from '@/commons/utils/hasPermission.js'
import WebsocketUtil from '@/commons/utils/websocket.js'
import { getShopTable,getShopTableDetail } from '@/http/api/table.js'
import { getProductList } from '@/http/api/product.js'
import { categoryPage } from '@/http/api/cateGory.js'
import { getShopInfo } from '@/http/api/shop.js'
import { getHistoryOrder, cancelOrder, rmPlaceOrder } from '@/http/api/order.js'
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: {
id: "",
},
socketData: {
type:'onboc',
account: uni.getStorageSync("iToken").loginId,
shop_id: uni.getStorageSync("shopInfo").id,
is_gift: 0
},
orderId: null,
isGoodsAdd: true,
goodsData: null,
orderInfo: null,
historyOrder: [],
})
const guigeModelData = reactive({
title: '',
chooseGoods: {
skuMap: {},
item: '',
skus: []
}
})
const chooseGuigeModel = ref(null)
const cartItemId = ref(null)
let isCreateOrderToDetail = ref(false)
let option = {
type: ''
}
const taocanModelRef = ref()
const websocketUtil = inject('websocketUtil'); // 注入 WebSocket 工具类实例
onLoad((opt) => {
option = opt
Object.assign(data.table, opt)
console.log(opt)
uni.setNavigationBarTitle({
title: (opt && opt.type == 'add') ? '顾客加菜' : '代客下单'
})
if (JSON.stringify(opt) == '{}') {
isCreateOrderToDetail.value = true
}
if(uni.getStorageSync("table_code")&&!opt.tableCode){
data.table.tableCode = uni.getStorageSync("table_code")
}
// init()
xiadanClick()
})
watch(() => data.table.id, (newval, oldval) => {
if (option.type != 'add') {
onSelTable()
}
})
onShow(() => {
nextTick(()=>{
uni.showLoading({
title: '购物车加载中',
mask: true
});
watchChooseTable()
watchUpdate()
watchSocketOpen()
data.isGoodsAdd = true;
init()
onMessage()
})
})
onReady(() => {
getElRect('list-tight-top').then(res => {
data.topZhanwei = res.height
})
getMenuItemTop()
})
onHide(() => {
console.log("onHide")
uni.$off('is-socket-open')
websocketUtil.offMessage()
})
onUnmounted(() => {
uni.$off('is-socket-open')
websocketUtil.offMessage()
});
/**
* 判断是否允许下单
*/
let canXiadan = ref(false)
async function xiadanClick() {
canXiadan.value = await hasPermission('允许下单')
}
let $originGoods = []
let $category = []
async function init() {
if (option.type == 'add') {
setTabBar($category, $originGoods, [])
}
let shopInfo = await getShopInfo({id:uni.getStorageSync('shopInfo').id})
uni.setStorageSync("shopInfo",shopInfo)
// 获取分类数据
let categoryRes = await categoryPage({ page: 1, size: 300 })
$category = categoryRes.records
// 获取商品数据
const goodsRes = await getGoods()
const goods = goodsRes.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
initCart()
setTabBar($category, goods, [])
return
}
setTabBar($category, goods, cars)
initCart()
}
/**
* 获取订单详情
*/
async function getHistoryOrderDetail(){
data.historyOrder = [];
let res = await getHistoryOrder({tableCode:data.table.tableCode});
data.orderInfo = res;
if( res ){
data.historyOrder = Object.entries(data.orderInfo.detailMap).map(([key, value]) => ({
info: value,
placeNum: key
}))
}
}
/**
* 监听socket是否连接正常
*/
function watchSocketOpen (){
uni.$off('is-socket-open')
uni.$on('is-socket-open', (res) => {
console.log("is-socket-open===",res)
if( res){
data.isGoodsAdd = true;
initCart()
} else {
uni.showLoading({
title: '购物车加载中',
mask: true
});
data.isGoodsAdd = false;
}
})
}
/**
* socket消息监听
*/
function onMessage (){
websocketUtil.offMessage()
websocketUtil.onMessage(async res => {
let msg = JSON.parse(res);
let cartItem;
let cartArr = [];
// console.log("onMessage===",msg)
if( msg.msg_id ){
websocketUtil.send(JSON.stringify({
type: 'receipt',
msg_id: msg.msg_id,
}))
}
if( msg.status == 0 ){
if ( msg.type == "no_suit_num") {
uni.showModal({
title: '提示',
showCancel: false,
content: msg.msg,
success: function (res) {
if (res.confirm) {
console.log(cartItemId.value)
delCart(cartItemId.value)
initCart()
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
data.isGoodsAdd = true;
return;
}
uni.$utils.showToast(msg.msg||'操作失败')
data.isGoodsAdd = true;
return;
}
if ( msg.data ) {
cartArr = data.tabbar.reduce((prve,cur)=>{
prve = [...prve,...cur.foods]
return prve
},[])
}
switch (msg.operate_type) {
case 'onboc_init':
cars.length = 0
// console.log("购物车信息onboc_init===",msg)
if( !data.table.tableCode ){
data.table.tableCode = msg.table_code
uni.setStorageSync("table_code",msg.table_code)
}
// console.log("商品信息===",cartArr)
msg.data.map(item=>{
cartItem = getNowCart(item,cartArr)
if( cartItem.isGrounding||cartItem.is_temporary == 1 ){
cartControls(cartItem,'add')
} else {
delCart(cartItem.id)
}
})
getHistoryOrderDetail()
uni.hideLoading()
break;
case 'onboc_add':
case 'add':
cartItem = getNowCart(msg.data,cartArr)
cartControls(cartItem,'add')
uni.$utils.showToast('操作成功')
break;
case 'onboc_edit':
case 'edit':
cartItem = getNowCart(msg.data,cartArr)
cartControls(cartItem,'edit')
uni.$utils.showToast('操作成功')
break;
case 'onboc_del':
case 'del':
cartItem = getNowCart(msg.data,cartArr)
cartControls(cartItem,'del')
break;
case 'onboc_cleanup':
case '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
}
}
getHistoryOrderDetail()
break;
case 'init':
case 'rottable':
if( data.table.tableCode == msg.data.new_table_code){
initCart()
} else {
data.table.tableCode = msg.data.new_table_code
let resData = await getShopTableDetail({tableCode:msg.data.new_table_code})
data.table = resData
initCart()
}
break;
case 'product_update':
init()
break;
case 'clearOrder':
getHistoryOrderDetail()
break;
}
});
}
/**
* 初始化购物车
*/
function initCart () {
let params = {
...data.socketData,
operate_type:'init',
table_code: data.table.tableCode,
}
console.log("购物车初始化参数===",params)
websocketUtil.send(JSON.stringify(params))
}
/**
* 购物车添加菜品
*/
function editCart (par,operate_type) {
cartItemId.value = par.id
if( !data.isGoodsAdd ){ return; }
let params = {
...data.socketData,
operate_type: operate_type,
table_code: data.table.tableCode,
product_id: '',
is_print: 1,
sku_id: '', //
number: 1, //数量
}
Object.assign(params, par)
console.log('购物车添加菜品参数===',params)
websocketUtil.send(JSON.stringify(params))
data.isGoodsAdd = false;
}
/**
* 删除购物车菜品
*/
function delCart (id) {
let params = {
...data.socketData,
id: id,
operate_type:'del',
table_code: data.table.tableCode,
}
console.log('购物车删除菜品参数===',params)
websocketUtil.send(JSON.stringify(params))
}
/**
* 清除购物车
*/
async function cleaCart (e) {
if( e == 'cart' ){
let params = {
...data.socketData,
operate_type:'cleanup',
table_code: data.table.tableCode,
}
console.log('购物车清空菜品参数===',params)
websocketUtil.send(JSON.stringify(params))
} else if ( e == 'allHistoryOrder' ) {
await cancelOrder({orderId: data.orderInfo.id, shopId: uni.getStorageSync("shopInfo").id })
let params = {
...data.socketData,
operate_type:'clearOrder',
table_code: data.table.tableCode,
}
websocketUtil.send(JSON.stringify(params))
initCart()
} else {
await rmPlaceOrder({orderId: data.orderInfo.id, placeNum: e, shopId: uni.getStorageSync("shopInfo").id })
let params = {
...data.socketData,
operate_type:'clearOrder',
table_code: data.table.tableCode,
}
websocketUtil.send(JSON.stringify(params))
initCart()
}
}
/**
* 获取商品列表
*/
function getGoods() {
const showLoading = data.tabbar.length <= 0 ? true : false
return getProductList({},'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) {
if (!item) {
// #ifdef MP-WEIXIN
uni.showModal({
title: '提示',
content: '桌台不存在或不是该店铺的桌台'
})
// #endif
// #ifndef MP-WEIXIN
uni.$utils.showToast('桌台不存在或不是该店铺的桌台')
// #endif
return
}
console.log('---table:detail-----',item);
console.log('---table_code-----',data.table.tableCode);
console.log('---new_table_code-----',item.tableCode);
let params = {
...data.socketData,
operate_type: 'rottable',
table_code: data.table.tableCode,
new_table_code: item.tableCode,
}
if (data.table.id || cars.length <= 0) {
data.table = {
...item
}
if( cars.length > 0){
websocketUtil.send(JSON.stringify(params))
} else{
initCart()
}
return;
}
if (item.status == "unbind") {
return uni.$utils.showToast('该台桌未绑定,清先去桌台管理里绑定码牌')
}
if (item.status != "idle") {
return uni.$utils.showToast('该台桌已在使用中')
}
data.table = item
if( cars.length > 0){
websocketUtil.send(JSON.stringify(params))
}
// initCart()
}
/**
* 菜品操作
* @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 uni.$utils.showToast('请先选择桌台', 0.5).then(res => {
// chooseTable()
// })
// }
if( !data.isGoodsAdd ){ return;}
let $goods = data.tabbar[index].foods[foodsindex]
if ($goods.type !== 'sku') {
//单规格
let goodsInCarIndex = cars.findIndex((carsGoods) => {
return carsGoods.sku_id == $goods.skuList[0].id && carsGoods.product_id == $goods.id;
});
let product_id = $goods.id
let product_type = $goods.type
let sku_id = $goods.skuList[0].id
let suitNum = $goods.skuList[0].suitNum || 1
if (goodsInCarIndex !== -1) {
//更新
let cartItem = cars[goodsInCarIndex]
let number = isAdd ? cartItem.number + 1 : + cartItem.number - 1
if( !isAdd ){
if (number === 0 || number < suitNum) {
//移除
setSearchGoods(searchGoodsIndex, 0)
delCart(cartItem.id)
}
}
// 不影响之前的代码 称重number单独处理
if ($goods.type == 'weight' && showCurrentInput) {
number = Number(showCurrentInput)
}
editCart({
id: cartItem.id,
suitNum: cartItem.suitNum || 1,
number: number,
product_id: product_id,
product_type: product_type,
sku_id: sku_id,
is_temporary: cartItem.is_temporary
},'edit')
data.isGoodsAdd = false;
setSearchGoods(searchGoodsIndex, number)
} else {
// 不影响之前的代码 称重suit单独处理
if ($goods.type == 'weight' && showCurrentInput) {
suitNum = showCurrentInput
if( $goods.skuList[0].suitNum && showCurrentInput < $goods.skuList[0].suitNum){
uni.$utils.showToast(`最小起售数量为${$goods.skuList[0].suitNum}`)
return;
}
}
// 套餐和单规格
if ($goods.groupType != 1) {
//增加
editCart({
number: suitNum,
product_id: product_id,
product_type: product_type,
sku_id: sku_id,
is_temporary: 0, //是否是临时菜
},'add')
data.isGoodsAdd = false;
}
}
return
}
}
/**
* socket通知购物车商品数量修改处理
*/
function cartControls (cartItem,type) {
if( !data.table.tableCode ){
data.table.tableCode = cartItem.table_code
}
data.isGoodsAdd = true;
let cartIndex = 0;
let product_id = cartItem.product_id
let sku_id = cartItem.sku_id
let $goods;
cars.map((item,index)=>{
if(item.id == cartItem.id) {
cartIndex = index;
product_id = item.product_id
sku_id = item.sku_id
}
})
data.tabbar.map(tabbarItem=>{
if(tabbarItem.foods.find(v => v.id == product_id)){
$goods = product_id < 0 ? {} : tabbarItem.foods.find(v => v.id == product_id)
}
})
if( type == 'del' ) {
cars.splice(cartIndex, 1)
if($goods)$goods.chooseNumber = 0;
return;
}
if( type == 'add' ){
cars.push(cartItem)
if($goods)$goods.chooseNumber = cartItem.number
}
if( type == 'edit' ){
cars[cartIndex].number = cartItem.number
if ($goods) {
$goods.chooseNumber = cartItem.number
}
}
}
/**
* 购物车商品数量改变处理
* @param {Object} e
*/
async function carsNumberChange(e) {
if( !data.isGoodsAdd ){ return; }
let $sku;
let $goods;
let params = {
number: e.num,
id: e.goods.id,
product_id: e.goods.product_id,
sku_id: e.goods.sku_id,
is_temporary: e.goods.is_temporary
}
if( e.goods.is_temporary != 1){
data.tabbar.map(tabbarItem=>{
if(tabbarItem.foods.find(v => v.id == e.goods.product_id)){
$goods = !e.goods.product_id ? undefined : tabbarItem.foods.find(v => v.id == e.goods.product_id)
}
})
$sku = !e.goods.product_id ? { suitNum: 1 } : $goods.skuList.find(v => v.id == e.goods.sku_id)
params.suitNum = $sku.suitNum || 1
if (e.num === 0 || e.num < $sku.suitNum) {
//移除
delCart(e.goods.id)
return
}
} else {
if (e.num === 0) {
//移除
delCart(e.goods.id)
return
}
params.product_name = e.goods.name
params.sku_name = e.goods.sku_name
}
editCart(params,'edit')
data.isGoodsAdd = false;
}
/**
* 添加套餐
* @param {Object} d
* @param {Object} item
*/
async function taocanConfirm(d, item) {
editCart({
number: item.skuList[0].suitNum,
product_id: item.id,
product_type: item.type,
sku_id: item.skuList[0].id,
pro_group_info: JSON.stringify(d),
is_temporary: 0, //是否是临时菜
},'add')
data.isGoodsAdd = false;
}
const instance = getCurrentInstance();
let selGoods = ref({});
/**
* 打开规格弹窗
* @param {Object} foodsindex
* @param {Object} index
*/
function chooseGuige(foodsindex, index) {
const $goods = data.tabbar[index].foods[foodsindex]
selGoods.value = $goods
if ($goods.groupType == 1) {
data.goodsData = $goods
taocanModelRef.value.open()
} else {
guigeModelData.title = $goods.name
const skuMap = returnSelGoodsSkuMap($goods.skuList)
// 多规格,和套餐规格区分.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
*/
function returnSelGoodsSkuList(selectSpecInfo) {
let specInfo = []
for (var key in selectSpecInfo) {
specInfo.push({
name: key,
value: selectSpecInfo[key]
})
}
let result = specInfo.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, suitNum) {
if( !data.isGoodsAdd ){ return; }
let goods = guigeModelData.chooseGoods.item
let sku_id = sku.id
let product_id = goods.id
let product_type = goods.type
let res = findGoodsInCar(goods, sku_id)
if (res) {
//更新
let { index } = res
let carGoods = cars[index]
let cartId = carGoods.id
let newNumber = carGoods.number * 1 + suitNum
editCart({
id: cartId,
number: newNumber,
suitNum: carGoods.suitNum || 1,
product_id: product_id,
sku_id: sku_id,
is_temporary: carGoods.is_temporary, //是否是临时菜
},'edit')
data.isGoodsAdd = false;
} else {
//添加
editCart({
number: suitNum,
product_id: product_id,
product_type: product_type,
sku_id: sku_id,
is_temporary: 0, //是否是临时菜
},'add')
data.isGoodsAdd = false;
}
}
/**
* 找到该规格商品在购物车中是否存在并返回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(selectSpecInfo = [], goodsListMap = {}, skuList) {
let skuMapNumber = selectSpecInfo.reduce((prve, cur) => {
for (let i in cur.valueArr) {
prve[cur.valueArr[i]] = i;
}
return prve;
}, {});
let canBudyGoods = skuList.filter((v) => util.isCanBuy(v, guigeModelData.chooseGoods.item))
return canBudyGoods[0];
}
/**
* 设置商品默认选中,规格禁止以及选中
* @param {Object} goods
* @param {Object} selectSpecInfo
* @param {Object} skuMap
* @param {Object} skuList
*/
function setSkugoodsDefaultInit(goods, selectSpecInfo, skuMap, skuList) {
guigeModelData.chooseGoods.item = goods
guigeModelData.chooseGoods.skus = selectSpecInfo
guigeModelData.chooseGoods.skuMap = skuMap
const skuGoods = findGoods(selectSpecInfo, skuMap, skuList);
if (skuGoods) {
skuGoods.specInfo.split(",").map((v, index) => {
guigeModelData.chooseGoods.skus[index].sel = v;
});
}
setTagDisabled();
}
//更新选中规格
function updateSkuSel(skusIndex, skdName) {
const skuList = guigeModelData.chooseGoods.skus
const skuMap = guigeModelData.chooseGoods.skuMap
guigeModelData.chooseGoods.skus[skusIndex].sel = skdName
const specInfo = 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;
}, []);
let selArrAllGroup = util.generateCombinations(selArr, selArr.length - 1);
const matchArr = [];
for (let key in skuMap) {
let goods = skuMap[key];
let 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.specInfo.split(",");
for (let i of speArr) {
if (!prve.hasOwnProperty("i")) {
prve[i] = matchArr
.filter((v) => v.specInfo.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]
}
}
}
}
/**
* 扫桌台码
*/
function scanCode() {
uni.scanCode({
onlyFromCamera: true,
success: async function(res) {
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
if (res.result.includes('codeplate?code=')) {
const par = returnUrlPar(res.result)
const tableCode = par.code
let resData = await getShopTableDetail({tableCode:tableCode})
onChooseTable(resData)
} else {
uni.showToast({
icon: 'error',
title: '请扫描正确的桌台码'
})
}
}
});
}
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
}
/**
* 商品数据处理
* @param {Object} category
* @param {Object} goods
* @param {Object} cars
*/
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)
}
let searchValue = ref('')
let isSearch = ref(false)
let searchResult = ref([])
/**
* 搜索
*/
function search() {
if (searchValue.value === '') {
isSearch.value = false
return
}
isSearch.value = true
searchResult.value = returnSearchGoods()
}
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 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)
}
/**
* 台桌切换
*/
async function onSelTable() {
setTabBar($category, $originGoods, cars)
}
function watchUpdate() {
uni.$off('update:createOrderIndex')
uni.$off('add:cashCai')
uni.$on('update:createOrderIndex', () => {
cars.length = 0
init()
})
// 添加临时菜到购物车
uni.$on('add:cashCai', async (data) => {
console.log('add:cashCai',data);
$originGoods.push(data)
data.isGoodsAdd = false;
})
}
</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>