cashier_admin_app/pagesCreateOrder/index/index - 副本.vue

407 lines
9.6 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-flex u-flex-col u-row-between page">
<view class="top bg-fff w-full">
<view class="u-flex u-row-between choose-user" @tap="chooseUser">
<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"
:focus="true" v-model="searchValue">
</uni-search-bar>
</view>
<view class="u-flex">
<image src="/pagesCreateOrder/static/images/icon-saoma.svg" class="icon-saoma" mode=""></image>
</view>
</view>
</view>
<view class="list u-flex w-full u-flex-1">
<view class="category u-flex" :style="computedCatrgoryStyle">
<scroll-view scroll-with-animation class="scroll-view_style menu-scroll-view" :scroll-into-view="category.intoviewId"
scroll-y="true" :scroll-top="category.scrollTop" :style="{height:listHeight+'px'}">
<view>
<view :id="'category'+index" class="item u-tab-item" @tap="changeCategoryActive(index)"
:class="{active:index==category.active}" v-for="(item,index) in category.list" :key="index">
{{item.title}}
</view>
</view>
</scroll-view>
</view>
<view class="goods-list u-flex-1 u-p-l-24">
<scroll-view @scroll="goodsScroll" scroll-with-animation class="scroll-view_style"
:scroll-top="goods.scrollTop" :scroll-into-view="goods.intoviewId" scroll-y="true"
:style="{height:listHeight+'px'}">
<view class="">
<view class="item" :class="{active:index==category.active}" v-for="(item,index) in goods.list"
:key="index">
<view class="color-main">{{item.title}}</view>
<view class="u-m-t-24 u-m-b-24 u-flex u-flex-wrap">
<view :id="'goods'+index" class="u-m-r-24 u-m-b-24 class-item"
v-for="(goodsItem,goodsIndex) in item.list" :key="goodsIndex">
<goods-item @chooseGuige="chooseGuige($event,index)" @add="goodsAdd($event,index)" @reduce="goodsReduce($event,index)"
:index="goodsIndex" :data="goodsItem"></goods-item>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<view class="bottom w-full">
<my-car :data="cars"></my-car>
</view>
<!-- 选择规格 -->
<my-model ref="guigeModel" :title="guigeModelData.title">
<template #desc>
<view v-for="(item,index) in guigeModelData.chooseGoods.skus" :key="index">
</view>
</template>
</my-model>
</view>
</template>
<script setup>
import {
onLoad,
onReady,
onShow,
onPageScroll,
onPullDownRefresh
} from '@dcloudio/uni-app';
import myModel from '@/components/my-components/my-model.vue'
import {
computed,
reactive,
ref,nextTick
} from 'vue';
import myCar from './components/car'
import goodsItem from './components/goods-item'
const guigeModel=ref(null)
const guigeModelData=reactive({
title:'',
chooseGoods:{
skus:[{
title:'',
skds:[]
}]
}
})
function chooseGuige(listindex, index){
const $goods=goods.list[index].list[listindex]
guigeModelData.title=$goods.title
guigeModel.value.open()
}
let searchValue = ref('')
const categoryArr = new Array(20).fill(1).map((v, index) => {
if (index % 2 === 0) {
return {
title: '围炉茶煮'
}
} else {
return {
title: '主食'
}
}
})
let pageHeight = ref(0)
const category = reactive({
list: categoryArr,
active: 0,
height: 0,
top: 0,
bottom: 0,
statusbarHeight: 0,
intoviewId: '',
scrollTop: 0
})
const goodslist = new Array(20).fill(1).map((v, index) => {
if (index % 2 === 0) {
return {
title: '围炉茶煮' + index,
list: new Array(10).fill(1).map((g, gIndex) => {
return {
id:gIndex,
title: '拿铁咖啡' + gIndex,
price: 28,
isDan: gIndex % 2 == 0,
chooseNumber: 0
}
})
}
} else {
return {
title: '主食' + index,
list: new Array(10).fill(1).map((g, gIndex) => {
return {
id:10000+gIndex,
title: '意大利面' + gIndex,
price: 28,
isDan: gIndex % 2 == 0,
chooseNumber: 0
}
})
}
}
})
let goods = reactive({
intoviewId: '',
scrollTop: 0,
list: goodslist
})
const cars=reactive([])
function chooseUser() {
goods.intoviewId = 'goods' + 5
}
function goodsAdd(listindex, index) {
const $goods=goods.list[index].list[listindex]
const newval =$goods.chooseNumber + 1
$goods.chooseNumber = newval
let item=cars.find(v=>v.id==$goods.id)
if(item){
item.number+=1
}else{
cars.push({...$goods,number:1})
}
}
function goodsReduce(listindex, index) {
const $goods = goods.list[index].list[listindex]
const newval = $goods.chooseNumber - 1
$goods.chooseNumber = newval <= 0 ? 0 : newval
}
async function changeCategoryActive(index) {
if(rightArr.length == 0) {
await getMenuItemTop();
}
if (index == category.active) return;
goods.scrollTop =oldScrollTop;
nextTick (function(){
goods.scrollTop = rightArr[index];
category.active = index;
leftMenuStatus(index);
})
}
let oldScrollTop=0;
let rightArr=[]
// 获取右边菜单每个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 ;
}
rects.forEach((rect) => {
// 这里减去rects[0].top是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
rightArr.push(rect.top - rects[0].top);
resolve();
})
}).exec()
})
}
let timer=null
let menuHeight=0 // 左边菜单的高度
// 获取一个目标元素的高度
function getElRect(elClass, dataVal) {
new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(this);
query.select('.' + elClass).fields({
size: true
}, res => {
// 如果节点尚未生成res值为null循环调用执行
if (!res) {
setTimeout(() => {
getElRect(elClass);
}, 10);
return;
}
if(dataVal==='menuHeight'){
menuHeight=res.height
}
if(dataVal==='menuItemHeight'){
menuItemHeight=res.height
}
resolve();
}).exec();
})
}
let menuItemHeight=0
// 设置左边菜单的滚动状态
async function leftMenuStatus(index) {
category.active = index;
// 如果为0意味着尚未初始化
if (menuHeight == 0 || menuItemHeight == 0) {
await getElRect('menu-scroll-view', 'menuHeight');
await getElRect('u-tab-item', 'menuItemHeight');
}
// 将菜单活动item垂直居中
category.scrollTop = index * menuItemHeight + menuItemHeight / 2 - menuHeight / 2;
}
async function goodsScroll(e) {
oldScrollTop = e.detail.scrollTop;
if (rightArr.length == 0) {
await getMenuItemTop();
}
if (timer) return;
if (!menuHeight) {
await getElRect('menu-scroll-view', 'menuHeight');
}
setTimeout(() => { // 节流
timer = null;
// scrollHeight为右边菜单垂直中点位置
let scrollHeight = e.detail.scrollTop + menuHeight / 2;
for (let i = 0; i < rightArr.length; i++) {
let height1 = rightArr[i];
let height2 = rightArr[i + 1];
// 如果不存在height2意味着数据循环已经到了最后一个设置左边菜单为最后一项即可
if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
leftMenuStatus(i);
return;
}
}
}, 10)
}
onReady(() => {
initCategory()
getMenuItemTop()
})
function initCategory() {
uni.getSystemInfo({
success: (res) => {
pageHeight.value = res.windowHeight
const screenHeight = res.windowHeight; // 屏幕可用高度
const topinfo = uni.createSelectorQuery().select(".top");
const bottominfo = uni.createSelectorQuery().select(".bottom");
topinfo.boundingClientRect(function(data) { //data - 各种参数
category.top = data.height + category.statusbarHeight
}).exec()
bottominfo.boundingClientRect(function(data) { //data - 各种参数
category.bottom = data.height
}).exec()
}
});
}
const listHeight = computed(() => {
return pageHeight.value - category.bottom - category.top
})
const computedCatrgoryStyle = computed(() => {
return `
top:${category.top}px;
bottom:${category.bottom}px;
`
})
function search() {
}
</script>
<style lang="scss" scoped>
/* 针对微信小程序的滚动条样式 */
::v-deep.scroll-view_style::-webkit-scrollbar {
width: 8rpx;
}
::v-deep.scroll-view_style::-webkit-scrollbar-thumb {
background: #90BDF6;
border-radius: 5px;
/* 设置滚动条圆角 */
}
::v-deep.scroll-view_style::-webkit-scrollbar-track {
background-color: #f1f1f1;
/* 设置滚动条轨道颜色 */
}
.page {
height: calc(100vh - 44px);
}
.goods-list {
box-sizing: border-box;
width: 572rpx;
}
.category {
box-sizing: border-box;
// position: fixed;
width: 178rpx;
// left: 0;
.item {
padding: 36rpx 32rpx;
position: relative;
background: #F9F9F9;
transition: all .2s ease-in-out;
&.active {
background: #fff;
}
&.active::after {
background-color: $my-main-color;
}
&::after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 8rpx;
}
}
}
.choose-user {
background: #F9F9F9;
padding: 22rpx 28rpx;
}
.search {
padding-right: 28rpx;
}
.icon-saoma {
margin-left: 20rpx;
width: 34rpx;
height: 32rpx;
}
</style>