cashier_app/pagesCreateOrder/index/index.vue

1496 lines
36 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.tableId">选择桌台</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="u-flex u-row-between choose-user" @tap="chooseUser">
<view>
<view v-if="!data.vipUser.id">选择用户</view>
<view class="u-flex" v-else>
<view class="headeimg">
<image class="img" :src="data.vipUser.headImg" mode=""></image>
</view>
<view class="u-m-l-20">{{data.vipUser.nickName}}</view>
<view class="color-main u-m-l-10 u-font-24">{{data.vipUser.isVip?'会员':'' }}</view>
<view class="u-font-24 u-m-l-30"><text>余额:</text><text
class="color-main">{{data.vipUser.amount}}</text></view>
<view class="u-font-24 u-m-l-30"><text>积分:</text><text
class="color-main">{{data.vipUser.accountPoints}}</text></view>
</view>
</view>
<view class="u-flex">
<uni-icons type="right" size="20" color="#999"></uni-icons>
</view>
</view> -->
<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>
<!-- <template v-if="item.name==='附加费'">
<view class="addCai" @tap="surchargeShow">
<uni-icons type="plus-filled" size="24" :color="color.ColorMain"></uni-icons>
<view class="u-m-t-24 color-main">自定义添加</view>
</view>
</template> -->
</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"
:masterId="data.masterId" :table="data.table" :data="cars" @clear="onClearCart"></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>
<up-modal title="提示" content="该台桌购物车里有商品,是否清除该台桌里的商品?" :show="modal.clear" showCancelButton closeOnClickOverlay
@confirm="confirmModelConfirm" @cancel="confirmModelConfirm('cancel')" @close="setModalShow('clear',false)"
width="300px">
</up-modal>
</template>
<script setup>
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 {
onLoad,
onReady,
onShow,
onPageScroll,
onPullDownRefresh
} from '@dcloudio/uni-app';
import {
onBeforeUnmount,
computed,
reactive,
ref,
nextTick,
watch,
getCurrentInstance
} from 'vue';
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 {
tbShopInfo
} from '@/http/yskApi/user.js'
import {
hasPermission
} from '@/commons/utils/hasPermission.js'
const modal = reactive({
key: '',
clear: false,
data: ''
})
async function confirmModelConfirm(isCancel = false) {
if (modal.key == 'clear') {
try {
await $choseTable({
masterId: data.masterId,
tableId: modal.data.tableId,
isClear: !isCancel ? true : false,
});
} catch (e) {
console.log(e)
//TODO handle the exception
}
data.table = modal.data;
setModalShow('clear', false, '')
}
}
function setModalShow(key = 'show', show = true, data) {
modal.key = key
modal[key] = show
modal.data = data
}
const instance = getCurrentInstance();
let canXiadan = ref(false)
async function xiadanClick() {
canXiadan.value = await hasPermission('允许下单')
}
xiadanClick()
//临时菜
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: "",
},
//餐桌号
masterId: "",
table: {
tableId: ""
},
})
// 获取账号信息
let $shop = ref({})
async function getTbShopInfo() {
const res = await tbShopInfo()
$shop.value = res
const useType = data.table.status == 'using' ? data.table.useType : $returnUseType(res)
uni.setStorageSync('useType', useType)
console.log(res);
return res
}
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
}
// 添加套餐
async function taocanConfirm(d, item) {
const cartGoods = await addCart({
num: 1,
groupProductIdList: d,
productId: item.id,
skuId: item.specList[0].id
})
infoBox.showToast('添加成功')
// guigeConfirm(item, 1)
// updateCartGoods({
// productId: item.id,
// skuId: item.specList[0].id,
// cartId: cartGoods.id
// })
cars.push({
...cartGoods,
specSnap: item.specSnap
})
}
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
console.log('par');
console.log(par);
onChooseTable({
tableId
})
} else {
uni.showToast({
icon: 'error',
title: '请扫描正确的桌台码'
})
}
// uni.showModal({
// title:'',
// content:res.result
// })
}
});
}
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,
isDan: fgoods.typeEnum !== 'sku'
}
})
}
})
// tabbar.push({
// name: '附加费',
// foods: [{
// name: "餐位费",
// price:$shop.value.tableFee,
// chooseNumber: 0,
// isSeatFee:true,
// isDan: true
// }
// ]
// })
tabbar = tabbar.filter(v => {
return v.foods.length
})
data.tabbar = tabbar
nextTick(() => {
getMenuItemTop()
})
storageManage.cacheGoods(data.tabbar)
}
//request类
//获取分类
function getCategory(par = {
page: 0,
size: 300
}) {
return $tbShopCategory(par)
}
//获取商品列表
function getGoods(par = {
page: 0,
size: 300
}) {
const showLoading = data.tabbar.length <= 0 ? true : false
return Api.getGoodsLists(par, showLoading)
}
//获取购物车数据
async function getCart(par = {
page: 0,
size: 300,
masterId: data.masterId,
tableId: data.table.tableId
}) {
const res = await Api.getCart(par)
return res
}
//获取取餐码
function getMasterId() {
return Api.$getMasterId({
tableId: data.table.tableId
})
}
//清空购物车
function clearCart() {
return Api.$clearCart({
masterId: data.masterId,
tableId: data.table.tableId
})
}
//加入购物车
function addCart(par) {
// if (!data.table.tableId) {
// return infoBox.showToast('请先选择桌台!')
// }
const submitPar = {
masterId: data.masterId,
tableId: data.table.tableId,
isPack: false,
num: 1,
productId: '',
skuId: '',
vipUserId: data.vipUser.id
}
Object.assign(submitPar, par)
return Api.addCart(submitPar)
}
//更新购物车
function updateCartGoods(par) {
const submitPar = {
cartId: '',
masterId: data.masterId,
tableId: data.table.tableId,
isPack: false,
num: 1,
productId: '',
skuId: '',
vipUserId: data.vipUser.id
}
Object.assign(submitPar, par)
return Api.$updateCart(submitPar)
}
//删除购物车某商品
function removeCartGoods(par) {
const submitPar = {
cartId: '',
masterId: data.masterId,
tableId: data.table.tableId,
}
Object.assign(submitPar, par)
return Api.$removeCart(submitPar)
}
//更新选择用户
function setUser(par) {
const submitPar = {
masterId: data.masterId,
tableId: data.table.tableId,
vipUserId: data.vipUser.id ? data.vipUser.id : '',
type: data.vipUser.id ? 0 : 1 //0 设置 1 取消
}
Object.assign(submitPar, par)
return Api.$setUser(submitPar)
}
//点击清空购物车
async function onClearCart() {
await clearCart()
cars.length = 0
for (let i in data.tabbar) {
for (let k in data.tabbar[i].foods) {
data.tabbar[i].foods[k].chooseNumber = 0
}
}
}
//获取桌台信息
async function getTableInfo() {
if (data.table.tableId) {
const res = await $table.get({
qrcode: data.table.tableId
})
console.log(res);
if (res && res.content[0]) {
data.table = {
...res.content[0],
...data.table
}
}
}
}
let $originGoods = []
let $category = []
async function init() {
if (option.type == 'add') {
data.masterId = option.masterId
setTabBar($category, $originGoods, [])
} else {
const masterRes = await getMasterId()
data.masterId = masterRes.masterId
}
const shopInfo = await tbShopInfo()
$shop.value = shopInfo
const useType = data.table.status == 'using' ? data.table.useType : $returnUseType(shopInfo)
uni.setStorageSync('useType', useType)
console.log(shopInfo);
await getTableInfo()
const categoryRes = await getCategory()
const category = categoryRes.content.reduce((prve, cur) => {
prve.push({
...cur,
childrenList: null
});
return [...prve, ...cur.childrenList];
}, []);
console.log(category);
$category = category
const goodsRes = await getGoods()
const goods = goodsRes.records.filter((v) => {
let isShow = true;
if (v.typeEnum !== "sku") {
isShow = v.specList.length >= 1;
}
return isShow;
});
$originGoods = goods
console.log(option);
if (option.type == 'add') {
cars.length = 0
setTabBar(category, goods, [])
return
}
if (!data.table.tableId) {
//无桌台
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)
}
// 监听选择用户事件
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 chooseTable() {
go.to('PAGES_CHOOSE_TABLE', {
...data.table
})
}
async function onChooseTable(item) {
console.log('onChooseTable');
const res = await $returnTableDetail({
tableId: item.tableId,
});
if (!res) {
// #ifdef MP-WEIXIN
uni.showModal({
title: '提示',
content: '桌台不存在或不是该店铺的桌台'
})
// #endif
// #ifndef MP-WEIXIN
infoBox.showToast('桌台不存在或不是该店铺的桌台')
// #endif
return
}
console.log('---table:detail-----');
console.log(res);
if (data.table.tableId || cars.length <= 0) {
data.table = {
...res,
...item
}
return;
}
if (res.status == "unbind") {
return infoBox.showToast('该台桌未绑定,清先去桌台管理里绑定码牌')
}
if (res.status != "idle") {
return infoBox.showToast('该台桌已在使用中')
}
if (res.cartCount > 0) {
setModalShow('clear', true, item)
} else {
await $choseTable({
masterId: data.masterId,
tableId: item.tableId,
isClear: false
});
data.table = item
}
}
function watchChooseTable() {
uni.$off('choose-table')
uni.$on('choose-table', (item) => {
onChooseTable(item)
})
}
function toLinshi() {
go.to('PAGES_CHOOSE_ADD_TEMP_CUISINE', {
masterId: data.masterId,
tableId: data.table.tableId,
vipUserId: option.vipUserId ? option.vipUserId : '',
useType: uni.getStorageSync('useType')
})
}
const chooseGuigeModel = ref(null)
const guigeModelData = reactive({
title: '',
chooseGoods: {
skuMap: {},
item: '',
skus: []
}
})
// 返回当前选中商品skuList
function returnSelGoodsSkuList(skuList, specSnap) {
const specSnapArr = specSnap ? specSnap.split(",") : [];
const result = skuList.map((v, index) => {
const values = v.value.split(",");
return {
...v,
valueArr: values,
sel: specSnap ? specSnapArr[index] : "",
values: values.map((name) => {
return {
name,
disabled: false
};
}),
};
});
return result
}
//返回当前选中商品skuMap
function returnSelGoodsSkuMap(specList) {
const skuMap = {}
for (let i in specList) {
skuMap[specList[i].specSnap] = specList[i];
}
return skuMap
}
//多规格商品弹窗时,找到默认可以下单的规格商品
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];
}
//设置商品默认选中,规格禁止以及选中
function setSkugoodsDefaultInit(goods, skuList, skuMap, specList) {
guigeModelData.chooseGoods.item = goods
guigeModelData.chooseGoods.skus = skuList
guigeModelData.chooseGoods.skuMap = skuMap
const skuGoods = findGoods(skuList, skuMap, specList);
console.log(skuList, skuMap);
console.log(skuGoods);
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);
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();
// const canChooseGoods = skuList.every((v) => v.sel);
// if (canChooseGoods) {
// const skuGoods =skuMap[specSnap];
// guigeModelData.chooseGoods.item = skuGoods
// }
}
//设置规格按钮的禁止状态
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]
}
}
}
}
let selGoods = ref({});
// 称重
const refweighitem = ref(null)
const tapweigh = (foodsindex, index) => {
const goods = data.tabbar[index].foods[foodsindex]
refweighitem.value.open(foodsindex, index, goods)
}
function chooseGuige(foodsindex, index) {
if (!canAddGoods()) {
return infoBox.showToast('请先选择桌台', 0.5).then(res => {
chooseTable()
})
}
const $goods = data.tabbar[index].foods[foodsindex]
selGoods.value = $goods
if ($goods.groupType == 1) {
instance.ctx.$refs.taocanModelRef.open()
} else {
guigeModelData.title = $goods.name
const specList = $goods.specList;
const skuMap = returnSelGoodsSkuMap(specList)
// 多规格,和套餐规格区分.groupType=1 套餐多规格
let tagSnap = JSON.parse($goods.skuResult.tagSnap)
const skuList = returnSelGoodsSkuList(tagSnap)
setSkugoodsDefaultInit($goods, skuList, skuMap, specList)
chooseGuigeModel.value.open()
}
}
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
})
}
}
//购物车商品数量改变
async function carsNumberChange(e) {
const {
num,
index,
goods
} = e
const {
productId,
categoryId,
skuId
} = goods
const cartId = goods.id
const tabbarIndex = data.tabbar.findIndex(v => v.id == categoryId)
//临时菜没有对应商品数据
const $goods = !productId ? undefined : data.tabbar[tabbarIndex].foods.find(v => v.id == productId)
//临时菜没有skuList
const $sku = !productId ? {
suit: 1
} : $goods.specList.find(v => v.id == skuId)
if (num === 0 || num < $sku.suit) {
//移除
await removeCartGoods({
cartId
})
cars.splice(index, 1)
$goods.chooseNumber = 0
return
}
await updateCartGoods({
num,
cartId,
productId,
skuId
})
cars[index].number = num
if ($goods) {
$goods.chooseNumber = num
}
}
// 找到该规格商品在购物车中是否存在并返回index值以及对应的数据
function findGoodsInCar($goods, skuId) {
const productId = $goods.id
const goodsInCarIndex = cars.findIndex((carsGoods) => {
return carsGoods.skuId == skuId && carsGoods.productId == productId;
});
const carGoods = cars[goodsInCarIndex]
return carGoods ? {
index: goodsInCarIndex,
carGoods
} : false
}
function canAddGoods() {
// return data.table.tableId
return true
}
function searchGoodsUpdate(goodsItem, goodsIndex, isAdd) {
goodsUpdate(goodsItem.goodsIndex, goodsItem.index, isAdd, goodsIndex)
}
function setSearchGoods(index, chooseNumber) {
if (index !== undefined) {
searchResult.value[index].chooseNumber = chooseNumber
}
}
async function goodsUpdate(foodsindex, index, isAdd, searchGoodsIndex, showCurrentInput) { // showCurrentInput 称重才会传的参数
// if (!canAddGoods()) {
// return infoBox.showToast('请先选择桌台', 0.5).then(res => {
// chooseTable()
// })
// }
const $goods = data.tabbar[index].foods[foodsindex]
if ($goods.isDan) {
//单规格
const goodsInCarIndex = cars.findIndex((carsGoods) => {
return carsGoods.skuId == $goods.specList[0].id && carsGoods.productId == $goods.id;
});
const productId = $goods.id
const skuId = $goods.specList[0].id
let suit = $goods.specList[0].suit || 1
if (goodsInCarIndex !== -1) {
//更新
const carGoods = cars[goodsInCarIndex]
const cartId = carGoods.id
const step = isAdd ? 1 : -1
let num = carGoods.number * 1 + step
if (num === 0 || num < suit) {
//移除
cars.splice(goodsInCarIndex, 1)
$goods.chooseNumber = 0
setSearchGoods(searchGoodsIndex, 0)
return await removeCartGoods({
cartId
})
}
// 不影响之前的代码 称重num单独处理
if ($goods.type == 'weigh' && showCurrentInput) {
num = carGoods.number * 1 + Number(showCurrentInput)
}
const {
number
} = await updateCartGoods({
num,
cartId,
productId,
skuId
})
carGoods.number = number
$goods.chooseNumber = number
setSearchGoods(searchGoodsIndex, number)
} else {
// 不影响之前的代码 称重suit单独处理
if ($goods.type == 'weigh' && showCurrentInput) {
suit = showCurrentInput
}
// 套餐和单规格
if ($goods.groupType != 1) {
//增加
const num = suit
const cartGoods = await addCart({
num,
productId,
skuId
})
infoBox.showToast('添加成功')
$goods.chooseNumber = Number(num)
cars.push(cartGoods)
}
}
return
}
}
onReady(() => {
getElRect('list-tight-top').then(res => {
data.topZhanwei = res.height
})
getMenuItemTop()
})
let isTabClickOver = true
// 点击左边的栏目切换
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);
})
}
// 获取一个目标元素的高度
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;
}
console.log(res);
if (dataVal) {
data[dataVal] = res.height;
}
resolve(res);
}).exec();
})
}
// 观测元素相交状态
async function observer() {
tabbar.map((val, index) => {
let observer = uni.createIntersectionObserver(this);
// 检测右边scroll-view的id为itemxx的元素与right-box的相交状态
// 如果跟.right-box底部相交就动态设置左边栏目的活动状态
observer.relativeTo('.right-box', {
top: 0
}).observe('#item' + index, res => {
if (res.intersectionRatio > 0) {
let id = res.id.substring(4);
leftMenuStatus(id);
}
})
})
}
// 设置左边菜单的滚动状态
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
console.log(data.arr);
resolve();
}).exec()
})
}
// 右边菜单滚动
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()
})
}
watch(() => data.table.tableId, (newval, oldval) => {
if (option.type != 'add') {
onSelTable()
}
})
async function onSelTable() {
const {
masterId
} = await getMasterId()
data.masterId = masterId
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)
}
onBeforeUnmount(() => {})
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 () => {
console.log('add:cashCai');
const cartRes = await getCart()
cars.length = 0
const cartArr = getNowCart(cartRes.records)
for (let i in cartArr) {
cars.push(cartArr[i])
}
})
uni.$on('get:table', () => {
console.log('get:table');
if (data.table.tableId) {
$table.get({
qrcode: data.table.tableId
}).then(res => {
if (res.content[0] && res.content[0].status != 'idle') {
data.table = {
tableId: ''
}
}
})
}
})
}
onShow(() => {
// watchChooseuser()
watchChooseTable()
watchUpdate()
})
let isCreateOrderToDetail = ref(false)
let option = {
type: ''
}
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()
})
</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>