cashier_desktop/src/views/home/components/cartOperation.vue

705 lines
24 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>
<div class="operation_wrap">
<template v-if="goodsStore.cartType == 'cart'">
<div class="item"
:class="{ disabled: goodsStore.cartList.length && (!goodsStore.cartList[goodsStore.cartActiveIndex].id || (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1)) }"
@click="numberChange('sub')">
<el-icon class="icon">
<SemiSelect />
</el-icon>
</div>
<div class="item number"
:class="{ disabled: goodsStore.cartList.length && (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1) }"
@click="showEditNumber">
<el-text class="num">
{{ formatDecimal(goodsStore.cartList.length ?
+goodsStore.cartList[goodsStore.cartActiveIndex].number :
1, 2, true) }}
</el-text>
</div>
<div class="item"
:class="{ disabled: goodsStore.cartList.length && (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1) }"
@click="numberChange('add')">
<el-icon class="icon add">
<CloseBold />
</el-icon>
</div>
<div class="item"
:class="{ disabled: (goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].id && goodsStore.cartList[goodsStore.cartActiveIndex].goods_type != 'sku' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type != 1) }"
@click="showSkuModal">
<el-icon class="icon">
<Filter />
</el-icon>
<el-text class="t">规格</el-text>
</div>
<div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_temporary || goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_gift }"
@click="showDiscountModalHandle">
<el-icon class="icon">
<PriceTag />
</el-icon>
<el-text class="t">改价</el-text>
</div>
<div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_gift }"
@click="giftPackHandle('is_gift')">
<el-icon class="icon">
<ShoppingBag />
</el-icon>
<el-text class="t">赠送</el-text>
</div>
<div class="item" :class="{ disabled: goodsStore.allSelected }" @click="packHandle">
<el-icon class="icon">
<Box />
</el-icon>
<el-text class="t">打包</el-text>
</div>
<div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_print == 0 }"
@click="giftPackHandle('is_print')">
<el-icon class="icon">
<DishDot />
</el-icon>
<el-text class="t">免厨</el-text>
</div>
<div class="item" @click="deleteHandle">
<el-icon class="icon">
<Delete />
</el-icon>
<el-text class="t">删除</el-text>
</div>
<div class="item" @click="pendingOrderHandle">
<el-icon class="icon">
<Sell />
</el-icon>
<el-text class="t">挂单</el-text>
</div>
<div class="item" @click="tableMergingRef.show()">
<el-icon class="icon">
<EditPen />
</el-icon>
<el-text class="t">转桌</el-text>
</div>
<div class="item" @click="clearCart">
<el-icon class="icon">
<RefreshRight />
</el-icon>
<el-text class="t">清空</el-text>
</div>
</template>
<template v-if="goodsStore.cartType == 'order'">
<div class="item disabled">
<el-icon class="icon">
<SemiSelect />
</el-icon>
</div>
<div class="item number disabled">
<el-text class="num">
{{ formatDecimal(goodsStore.cartList.length ?
+goodsStore.cartList[goodsStore.cartActiveIndex].number :
1, 2, true) }}
</el-text>
</div>
<div class="item disabled">
<el-icon class="icon add">
<CloseBold />
</el-icon>
</div>
<div class="item disabled">
<el-icon class="icon">
<Filter />
</el-icon>
<el-text class="t">规格</el-text>
</div>
<div class="item disabled">
<el-icon class="icon">
<PriceTag />
</el-icon>
<el-text class="t">改价</el-text>
</div>
<div class="item disabled">
<el-icon class="icon">
<ShoppingBag />
</el-icon>
<el-text class="t">赠送</el-text>
</div>
<div class="item disabled">
<el-icon class="icon">
<Box />
</el-icon>
<el-text class="t">打包</el-text>
</div>
<div class="item disabled">
<el-icon class="icon">
<DishDot />
</el-icon>
<el-text class="t">免厨</el-text>
</div>
<div class="item"
:class="{ disabled: goodsStore.cartOrderItem.returnNum >= goodsStore.cartOrderItem.number }"
@click="returnOrderItemHandle">
<el-icon class="icon">
<Delete />
</el-icon>
<el-text class="t">退菜</el-text>
</div>
<div class="item" @click="pendingOrderHandle">
<el-icon class="icon">
<Sell />
</el-icon>
<el-text class="t">挂单</el-text>
</div>
<div class="item" @click="tableMergingRef.show()">
<el-icon class="icon">
<EditPen />
</el-icon>
<el-text class="t">转桌</el-text>
</div>
<div class="item disabled">
<el-icon class="icon">
<RefreshRight />
</el-icon>
<el-text class="t">清空</el-text>
</div>
</template>
</div>
<takeFoodCode ref="takeFoodCodeRef" title="修改商品数量" placeholder="请输入商品数量" @success="updateNumber" />
<!-- 购物车选择规格 -->
<skuModal ref="skuModalRef" @success="skuConfirm" />
<!-- 单品改价 -->
<el-dialog v-model="showDiscountModal" title="单品改价" @open="resetDiscountForm = { ...discountForm }"
@closed="discountModalClose">
<div class="dialog">
<div class="el-popover__title content">
<el-form ref="discountFormRef" :model="discountForm" :rules="discountFormRules" label-width="100px"
label-position="left">
<el-form-item label="价格更改" prop="discount_sale_amount">
<el-input v-model="discountForm.discount_sale_amount" placeholder="请输入改价金额" @input="priceInput">
<template #append>元</template>
</el-input>
</el-form-item>
<el-form-item label="更改原因">
<el-input v-model="discountForm.note" type="textarea" placeholder="请输入更改原因" />
<div class="remark_list">
<div class="item" v-for="item in noteList" :key="item" @click="addNote(item)">
{{ item }}
</div>
</div>
</el-form-item>
</el-form>
</div>
<div class="footer_wrap">
<div class="btn">
<el-button style="width: 100%;" @click="showDiscountModal = false">取消</el-button>
</div>
<div class="btn">
<el-button type="primary" style="width: 100%;" :loading="discountFormLoading"
@click="discountFormSubmit">确认</el-button>
</div>
</div>
</div>
</el-dialog>
<!-- 修改打包数量 -->
<el-dialog v-model="showPackModal" title="打包数量" @open="packModalOpen" width="350">
<div class="dialog">
<div class="el-popover__title content">
<el-form ref="packNumerFormRef" :model="packNumberForm" :rules="packNumberFormRules" label-width="100px"
label-position="left">
<el-form-item :label="`数量(${packItem.unitName}`" prop="number">
<!-- <el-input v-model="packNumberForm.number"
:placeholder="`最多输入${+packItem.number}${packItem.unitName}`" @input="packNumberInput">
<template #append></template>
</el-input> -->
<el-input-number v-model="packNumberForm.number" :min="1"
:max="+packItem.number"></el-input-number>
</el-form-item>
</el-form>
</div>
<div class="footer_wrap">
<div class="btn">
<el-button style="width: 100%;" @click="showPackModal = false">取消</el-button>
</div>
<div class="btn">
<el-button type="primary" style="width: 100%;" @click="packFormSubmit">确认</el-button>
</div>
</div>
</div>
</el-dialog>
<!-- 合并/转桌 -->
<tableMerging ref="tableMergingRef" @success="" />
<!-- 退菜数量 -->
<el-dialog
:title="`退菜:${goodsStore.cartOrderItem.product_name} x ${goodsStore.cartOrderItem.number - goodsStore.cartOrderItem.returnNum}`"
v-model="showReturnForm" width="350" top="20%">
<el-form :model="returnForm" label-width="0" label-position="left">
<el-form-item prop="num">
<el-input-number v-model="returnForm.num" :min="1"
:max="goodsStore.cartOrderItem.number - goodsStore.cartOrderItem.returnNum" style="width: 100%;">
</el-input-number>
</el-form-item>
</el-form>
<div class="footer_wrap">
<div class="btn">
<el-button style="width: 100%;" @click="showReturnForm = false">取消</el-button>
</div>
<div class="btn">
<el-button type="primary" style="width: 100%;" :loading="returnFormLoading"
@click="returnFormSubmit">确认</el-button>
</div>
</div>
</el-dialog>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import takeFoodCode from '@/components/takeFoodCode.vue'
import TableMerging from './tableMerging.vue'
import skuModal from '@/components/skuModal.vue'
import { useGoods } from '@/store/goods.js'
import { inputFilterFloat, formatDecimal } from '@/utils/index.js'
import { refundOrder } from '@/api/order.js'
import { useSocket } from '@/store/socket.js'
const goodsStore = useGoods()
const socket = useSocket()
const tableMergingRef = ref(null)
const props = defineProps({
item: {
type: Object,
default: {}
}
})
const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging', 'showPackage'])
const takeFoodCodeRef = ref(null)
const skuModalRef = ref([])
const showReturnForm = ref(false)
const returnFormLoading = ref(false)
const returnForm = ref({
num: 1
})
// 挂单
function pendingOrderHandle() {
let cart = goodsStore.cartList;
let order = goodsStore.orderList;
if (cart.length || order.length) {
goodsStore.pendingCart()
goodsStore.successClearCart();
socket.cartInit();
ElMessage.success('挂单成功')
}
}
// 退菜
async function returnOrderItemHandle() {
if (goodsStore.cartOrderItem.returnNum >= goodsStore.cartOrderItem.number) return
if (goodsStore.cartOrderItem.number == 1) {
returnOrderItemAjax()
} else {
showReturnForm.value = true
}
}
// 提交自定义数量退菜
async function returnFormSubmit() {
try {
returnFormLoading.value = true
await returnOrderItemAjax(returnForm.value.num)
showReturnForm.value = false
ElMessage.success('退菜成功')
} catch (error) {
console.log('退菜失败了');
}
returnFormLoading.value = false
}
// 提交退菜
async function returnOrderItemAjax(num = 1) {
try {
let data = {
orderId: goodsStore.orderListInfo.id,
refundAmount: 0,
modify: 0,
cash: false,
refundReason: '',
refundDetails: [
{
id: goodsStore.cartOrderItem.id,
returnAmount: goodsStore.cartOrderItem.lowPrice,
num: num
}
]
}
await refundOrder(data)
goodsStore.cartOrderItem.returnNum += num
goodsStore.calcCartInfo()
// await goodsStore.historyOrderAjax('', data.orderId)
} catch (error) {
console.log(error);
}
}
// 显示打包
function packHandle() {
let item = goodsStore.cartList[goodsStore.cartActiveIndex]
if (item && item.id && !goodsStore.allSelected) {
if (!item.pack_number || item.pack_number <= 0) {
if (item.number > 1 && item.goods_type != 'weight') {
// 大于1时需要编辑
showPackModal.value = true
} else {
// 小于1时直接提交
goodsStore.operateCart({ ...item, pack_number: 1 }, 'edit')
}
} else {
// 取消打包
goodsStore.operateCart({ ...item, pack_number: 0 }, 'edit')
}
}
}
// 赠送打包操作
function giftPackHandle(key) {
let item = goodsStore.cartList[goodsStore.cartActiveIndex]
if (item && item.id) {
if (key == 'is_gift' && goodsStore.cartList[goodsStore.cartActiveIndex] == 0) {
goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_amount = 0
}
if (goodsStore.cartList[goodsStore.cartActiveIndex][key] == 0) {
goodsStore.cartList[goodsStore.cartActiveIndex][key] = 1
} else {
goodsStore.cartList[goodsStore.cartActiveIndex][key] = 0
}
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex] }, 'edit')
}
}
// 显示直接修改数量
function showEditNumber() {
let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 1)) return
takeFoodCodeRef.value.show()
}
// 加减修改数量
function numberChange(t) {
let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 1)) return
switch (t) {
case 'sub':
goodsStore.cartList[goodsStore.cartActiveIndex].number--
if (item.number < item.suitNum) {
goodsStore.deleteCartItem()
} else {
if (goodsStore.allSelected) {
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex], pack_number: goodsStore.cartList[goodsStore.cartActiveIndex].number }, 'edit')
} else {
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
}
}
break;
case 'add':
goodsStore.cartList[goodsStore.cartActiveIndex].number++
if (goodsStore.allSelected) {
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex], pack_number: goodsStore.cartList[goodsStore.cartActiveIndex].number }, 'edit')
} else {
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
}
break;
default:
break;
}
}
// 输入修改数量
function updateNumber(num) {
goodsStore.cartList[goodsStore.cartActiveIndex].number = num
if (goodsStore.allSelected) {
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex], pack_number: goodsStore.cartList[goodsStore.cartActiveIndex].number }, 'edit')
} else {
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
}
}
// 显示规格
function showSkuModal() {
let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 0)) return
switch (item.goods_type) {
case 'sku':
skuModalRef.value.show({ ...goodsStore.cartList[goodsStore.cartActiveIndex] }, 'cart')
break;
case 'package':
emit('showPackage', item)
break;
default:
break;
}
}
// 修改规格
function skuConfirm(e) {
if (goodsStore.cartList[goodsStore.cartActiveIndex].sku_id != e.id) {
goodsStore.operateCart({ ...goodsStore.cartList[goodsStore.cartActiveIndex], sku_id: e.id, sku_name: e.specInfo }, 'edit')
}
}
/**单品改价 start */
const showDiscountModal = ref(false)
const resetDiscountForm = ref({})
const discountFormRef = ref(null)
const discountFormLoading = ref(false)
const discountForm = ref({
discount_sale_amount: '',
note: ''
})
function validateAmount(rule, value, callback) {
let item = goodsStore.cartList[goodsStore.cartActiveIndex]
let lowPrice = 0
if (goodsStore.showVipPrice) {
lowPrice = +item.memberPrice
} else {
lowPrice = +item.discount_sale_amount || +item.lowPrice
}
if (value == '') {
callback(new Error('请输入折扣价格'))
} else if (value <= 0 || value >= lowPrice) {
callback(new Error(`输入大于0小于${lowPrice}的数字`))
} else {
callback()
}
}
const discountFormRules = ref({
discount_sale_amount: [
{
required: true,
validator: validateAmount,
trigger: 'blur',
}
]
})
const noteList = ref([
'顾客投诉质量...',
'友情打折',
'临时活动',
])
// 显示
function showDiscountModalHandle() {
let item = goodsStore.cartList[goodsStore.cartActiveIndex]
if ((item && item.id) && (!item.is_temporary && !item.is_gift)) {
// 存在商品并且不能为临时菜或者赠送
showDiscountModal.value = true
}
}
// 过滤价格输入
function priceInput(e) {
setTimeout(() => {
discountForm.value.amount = inputFilterFloat(e)
}, 50)
}
// 关闭
function discountModalClose() {
discountForm.value = { ...resetDiscountForm.value }
discountFormRef.value.resetFields()
}
// 添加快捷备注
function addNote(str) {
if (!discountForm.value.note.length) {
discountForm.value.note += str
} else {
discountForm.value.note += `${str}`
}
}
// 提交
function discountFormSubmit() {
discountFormRef.value.validate(async valid => {
try {
if (valid) {
discountFormLoading.value = true
goodsStore.operateCart({
...goodsStore.cartList[goodsStore.cartActiveIndex],
discount_sale_amount: discountForm.value.discount_sale_amount,
discount_sale_note: discountForm.value.note
}, 'edit')
goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_amount = discountForm.value.discount_sale_amount
goodsStore.cartList[goodsStore.cartActiveIndex].discount_sale_note = discountForm.value.note
showDiscountModal.value = false
}
} catch (error) {
console.log(error);
}
discountFormLoading.value = false
})
}
/**单品打折 end */
// 删除
function deleteHandle() {
let item = goodsStore.cartList[goodsStore.cartActiveIndex]
if (item && item.id) {
goodsStore.deleteCartItem()
}
}
// 清空购物车
function clearCart() {
goodsStore.clearCart()
}
/** 修改打包数量 start */
const showPackModal = ref(false)
const packNumerFormRef = ref(null)
const packItem = ref('')
const packNumberForm = ref({
number: 1
})
const packNumberFormRules = {
number: [
{
required: true,
validator: validatePackNumber,
trigger: 'blur',
}
]
}
// 校验数量是否合法
function validatePackNumber(rule, value, callback) {
if (!packNumberForm.value.number) {
callback(new Error('请输入打包数量'))
} else if (packNumberForm.value.number < 1) {
callback(new Error('输入有误'))
} else if (packNumberForm.value.number > packItem.value.number) {
callback(new Error(`最多输入${+packItem.value.number}${packItem.value.unitName}`))
} else {
callback()
}
}
// modal打开时
function packModalOpen() {
packNumberForm.value.number = 1
packItem.value = goodsStore.cartList[goodsStore.cartActiveIndex]
}
// 提交
function packFormSubmit() {
packNumerFormRef.value.validate(valid => {
if (valid) {
showPackModal.value = false
goodsStore.operateCart({ ...packItem.value, pack_number: packNumberForm.value.number }, 'edit')
}
})
}
/** 修改打包数量 end */
</script>
<style scoped lang="scss">
.operation_wrap {
padding: 10px;
display: flex;
flex-direction: column;
gap: 8px;
.item {
width: 70px;
height: 34px;
display: flex;
align-items: center;
justify-content: center;
background-color: #efefef;
border-radius: 6px;
&:active {
background-color: #d3d3d3;
}
&.disabled {
.t {
color: #999;
}
.icon {
color: #999;
}
.num {
color: #999;
}
}
&.number {
background-color: transparent;
height: auto;
}
.num {
color: #333;
font-size: 18px;
}
.icon {
color: #333;
}
.add {
transform: rotate(-45deg);
}
.t {
margin-left: 4px;
}
}
}
.footer_wrap {
display: flex;
gap: 20px;
.btn {
flex: 1;
}
}
.dialog {
.content {
padding-bottom: 20px;
}
}
.remark_list {
display: flex;
gap: 10px;
margin-top: 10px;
.item {
padding: 0 10px;
border: 1px solid #ddd;
color: #999;
border-radius: 4px;
}
}
</style>