cashier-ipad/pagesCreateOrder/index/components/car.vue

536 lines
11 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="mask" @tap="hideGoods" v-if="switchGoods">
</view>
<view class="fixed goods-box u-flex u-flex-col" :class="{active:switchGoods}" @tap.stop="nullFun">
<view class="u-row-between top u-flex">
<view class="u-flex">
<view>
<up-icon name="shopping-cart-fill" size="20" color="rgb(102,102,102)"></up-icon>
</view>
<view class="u-m-l-10">
已选菜品({{goodsNumber}})
</view>
</view>
<view class="u-flex" @click="setModalShow('clear',true)">
<view>
<up-icon name="trash-fill" size="20" color="rgb(102,102,102)"></up-icon>
</view>
<view class="u-m-l-10">
清空点餐
</view>
</view>
<view class="u-flex">
<view>合计:</view>
<view class="u-m-l-10 color-red font-bold allPrice">{{allPrice}}</view>
<view class="">元</view>
</view>
</view>
<scroll-view scroll-y="true" class=" u-flex-1 ">
<view class=" ">
<view class="color-333item border-bottom u-p-l-20 u-p-r-20 u-p-b-10 u-p-t-20 u-flex u-row-center u-row-between"
v-for="(item,index) in data" :key="index">
<view class="u-flex u-col-top">
<view class="u-p-r-20">
{{index+1}}
</view>
<view class="">
<view>{{item.name}}</view>
<view class="u-m-t-10 u-font-24 color-666">{{item.specSnap||''}}</view>
<view class="u-flex u-m-t-14">
<up-icon name="edit-pen" @click="showModel('remark',index)" color="#333" size="16"></up-icon>
<view class="color-666 u-font-24">
{{item.note}}
</view>
</view>
</view>
</view>
<view class="u-flex">
<view class="font-bold red u-m-r-32">{{formatPrice(item.salePrice*item.number) }}</view>
<view class="u-flex" @tap="updateNumber(false,index,item)">
<image src="/pagesCreateOrder/static/images/icon-reduce-black.svg" class="icon" mode="">
</image>
</view>
<view class="u-p-l-30 u-p-r-30 color-333" style="">
{{item.number}}
</view>
<view class="u-flex" @tap="updateNumber(true,index,item)">
<image src="/pagesCreateOrder/static/images/icon-add-black.svg" class="icon" mode="">
</image>
</view>
</view>
</view>
<my-empty v-if="!data.length" text="暂未有添加商品"></my-empty>
</view>
</scroll-view>
<view class="u-row-between bottom u-flex">
<view class="u-flex" @click="hideGoods">
<view>
<up-icon name="arrow-left" size="14" color="#333"></up-icon>
</view>
<view class="u-m-l-10">
返回
</view>
</view>
<view class="u-flex luodan" @click="toConfimOrder">
<view>落单</view>
</view>
</view>
</view>
<view class="car u-flex u-row-between u-col-bottom u-relative" @touchmove.stop.prevent="moveHandle"
:style="{transform: 'translateY(' + offset.y + 'px)'}" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend">
<view class="u-absolute goods bg-fff">
<view
class="u-p-t-32 color-666 border-bottom bg-fff u-absolute total u-p-r-28 u-p-b-32 u-p-l-28 u-flex u-row-between">
<view>已添加{{goodsNumber}}件商品</view>
<view class="color-666" @tap="setModalShow('clear',true)">
<uni-icons color="#666" type="trash"></uni-icons>
<text class="u-m-l-10">清空</text>
</view>
</view>
</view>
<view class="icon-car-box" @tap="toggleGoods">
<image src="/pagesCreateOrder/static/images/icon-car.svg" class="icon-car" />
<view class="dot">{{goodsNumber}}</view>
</view>
<!-- <view class="price font-bold u-flex">
<view>¥</view>
<view>{{allPrice}}</view>
</view> -->
<!-- <my-button shape="circle" height="80" width="220" @tap="toConfimOrder">
<text class="u-font-32 font-bold">{{table.type=='add'?'确认加菜':'去下单'}} </text>
</my-button> -->
</view>
<up-modal title="提示" content="是否清空全部已添加的商品?" :show="modal.clear" showCancelButton closeOnClickOverlay
@confirm="confirmModelConfirm" @cancel="setModalShow('clear',false)" @close="setModalShow('clear',false)"
width="300px"></up-modal>
<one-remark width="400px" @confirm="goodsOneRemarkConfirm" title="单品备注" :ref="setModel" name="remark"></one-remark>
</template>
<script setup>
import go from '@/commons/utils/go.js';
import infoBox from '@/commons/utils/infoBox.js';
import oneRemark from '/pagesCreateOrder/confirm-order/components/remark'
import {
formatPrice
} from '@/commons/utils/format.js';
import {
getElRect
} from '@/commons/utils/safe-bottom.js'
import * as Api from '@/http/yskApi/Instead.js'
import {
computed,
ref,
onMounted,
reactive,
watch
} from 'vue';
const props = defineProps({
sysInfo:{
type: Object,
default:()=>{
return {
windowWidth: 0,
windowHeight: 0,
statusBarHeight:0
}
}
},
instance: {
type: Object,
default: {
}
},
data: {
type: Array,
default: () => {
return []
}
},
isCreateOrderToDetail: {
type: Boolean,
default: false
},
user: {
type: Object,
default: () => {
return {
id: ""
}
}
},
table: {
type: Object,
default: () => {
return {
tableId: ''
}
}
},
masterId: {
type: [String, Number],
default: ''
}
})
const edmits = defineEmits(['clear', 'updateNumber', 'updateSafeBottom','updateCart'])
const modal = reactive({
key: '',
clear: false
})
const models = new Map();
const modelData = reactive({
data: {},
selIndex: -1
})
//备注
let note = ref('')
function setModel(el) {
if (el && el.$attrs['name']) {
models.set(el.$attrs['name'], el);
}
}
function showModel(key, index) {
modelData.data = props.data[index]
modelData.selIndex = index
const model = models.get(key)
model && model.open({
remark: modelData.data.note||''
})
}
function confirmModelConfirm() {
if (modal.key == 'clear') {
clear()
}
}
//单品备注确认
async function goodsOneRemarkConfirm(e) {
const cart = props.data[modelData.selIndex]
await Api.$updateCart({
cartId: cart.id,
productId: cart.productId,
skuId: cart.skuId,
tableId: props.table.tableId,
note: e.remark,
num: cart.number // 0会删除此商品
})
edmits('updateCart')
}
function setModalShow(key = 'show', show = true) {
if (key == 'clear' && show && props.data.length <= 0) {
return infoBox.showToast('购物车是空的!')
}
modal.key = key
modal[key] = show
console.log(modal);
}
function nullFun() {
}
// mask
let switchGoods = ref(false)
function hideGoods() {
switchGoods.value = false
}
function showGoods() {
switchGoods.value = true
}
function toggleGoods() {
switchGoods.value = !switchGoods.value
}
function toConfimOrder() {
console.log(props.user);
if (props.data.length <= 0) {
return infoBox.showToast('还没有选择商品')
}
const {
tableId,
name,
maxCapacity,
status,
type
} = props.table
if (props.table.tableId == '') {
go.to('PAGES_CONFIRM_ORDER', {
masterId: props.masterId,
isCreateOrderToDetail: props.isCreateOrderToDetail ? 1 : 0
})
}else{
go.to('PAGES_CONFIRM_ORDER', {
masterId: props.masterId,
type,
tableId,
name,
maxCapacity,
status,
isCreateOrderToDetail: props.isCreateOrderToDetail ? 1 : 0
})
}
hideGoods()
}
const allPrice = computed(() => {
return props.data.reduce((prve, cur) => {
return prve + cur.salePrice * cur.number
}, 0).toFixed(2)
})
const goodsNumber = computed(() => {
let result = 0
result = props.data.reduce((prve, cur) => {
return prve + cur.number
}, 0)
return result >= 99 ? 99 : result
})
function updateNumber(isAdd, index, goods) {
const step = isAdd ? 1 : -1
const newval = goods.number + step
const par = {
num: newval,
index: index,
goods: goods
}
edmits('updateNumber', par)
}
const offset = ref({
x: 0,
y: (props.sysInfo.windowHeight-70-40)/2
})
const startPoint = ref({
x: 0,
y: 0
})
watch(()=>props.sysInfo.windowHeight,(newval)=>{
console.log('---------');
console.log(newval);
offset.value.y=(newval-70-40)/2
})
function touchstart(event) {
startPoint.value = {
x: event.touches[0].clientX,
y: event.touches[0].clientY
};
}
function touchmove(event) {
const currentPoint = {
x: event.touches[0].clientX,
y: event.touches[0].clientY
};
const delta = {
x: currentPoint.x - startPoint.value.x,
y: currentPoint.y - startPoint.value.y
};
const minY=props.sysInfo.statusBarHeight||0 ,maxY=props.sysInfo.windowHeight-70-40;
let newY=offset.value.y + delta.y
if(newY>maxY){
newY=maxY
}
if(newY<minY){
newY=minY
}
offset.value = {
// x: offset.value.x + delta.x,
y: newY
};
startPoint.value = currentPoint;
}
function moveHandle() {
return false
}
function touchend(e) {
// 触摸结束时重置起始坐标
}
function clear() {
setModalShow('clear', false)
edmits('clear')
hideGoods()
}
onMounted(() => {
getElRect('car', props.instance).then(res => {
console.log(res);
edmits('updateSafeBottom', res)
}).catch(err=>{
console.log(err);
})
})
</script>
<style lang="scss" scoped>
$car-size: 70px;
$car-top: -16rpx;
.luodan {
background-color: $my-main-color;
padding: 10px 30px;
border-radius: 4px;
color: #fff;
font-size: 16px;
font-weight: bold;
}
.allPrice {
font-size: 24px;
}
.goods-box {
position: fixed;
right: 0;
top: 80px;
bottom: 80px;
left: 30%;
right: 0;
background-color: #fff;
border-radius: 12px 0 0 12px;
overflow: hidden;
transition: all .2s ease-in-out;
transform: translateX(100%);
z-index: 10;
&.active {
transform: translateX(0);
}
.top {
width: 100%;
color: rgb(102, 102, 102);
font-size: 16px;
background-color: rgb(233, 233, 238);
padding: 14px 20px;
}
.bottom {
padding: 14px 20px;
border-top: 1px solid #eee;
width: 100%;
font-size: 16px;
}
}
@mixin fixedAll {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.total {
left: 0;
right: 0;
top: 0;
z-index: 1;
}
.icon {
width: 40rpx;
height: 40rpx
}
.mask {
@include fixedAll;
background: rgba(51, 51, 51, 0.5);
}
.goods {
position: fixed;
width: 50vh;
bottom: 0;
right: 0;
transition: all .2s ease-in-out;
overflow: hidden;
z-index: 3;
.item {
padding: 32rpx 28rpx;
}
}
.border-bottom {
// border-bottom: 1px solid #E5E5E5;
}
.border-top {
// border-top: 1px solid #E5E5E5;
}
.red {
color: #EB4F4F;
}
.car {
position: fixed;
right: 20px;
top: 40px;
// top: 50%;
// transform: translateY(-50%);
.icon-car-box {
position: relative;
display: flex;
width: $car-size;
height: $car-size;
justify-content: center;
align-items: center;
z-index: 2;
.dot {
position: absolute;
right: 0;
top: 0;
width: 28rpx;
height: 28rpx;
background: #EB4F4F;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 20rpx;
font-weight: bold;
color: #FFFFFF;
}
}
.price {
color: #EB4F4F;
margin-left: calc(38rpx + $car-size);
transform: translateY(calc($car-top / 2));
}
.icon-car {
width: $car-size;
height: $car-size;
}
}
</style>