cashier_desktop/src/views/home/index.vue

638 lines
16 KiB
Vue

<template>
<div class="content">
<div class="cart_wrap card">
<div class="menu_top">
<div class="menu" @click="pendingCartModalRef.show()">
<el-icon class="icon">
<TakeawayBox />
</el-icon>
<el-text class="t">({{ pendingCartNum }})</el-text>
</div>
<div class="number" @click="takeFoodCodeRef.show()">
<el-text class="t">{{ masterId }}</el-text>
</div>
<div class="select_user" @click="fastCashierRef.show()" v-if="!memberInfo.telephone">
<div class="left">
<el-icon class="icon">
<WalletFilled />
</el-icon>
<el-text class="t">快捷收银</el-text>
</div>
<el-icon class="arrow">
<ArrowRight />
</el-icon>
</div>
<div class="select_user" v-else @click="clearMember">
<div class="left">
<el-icon class="icon">
<UserFilled />
</el-icon>
<el-text class="t">{{ memberInfo.telephone }}</el-text>
</div>
<el-icon class="arrow">
<Close />
</el-icon>
</div>
</div>
<div class="shop_operation" v-loading="cartLoading">
<div class="shop_list">
<div class="item" :class="{ active: cartListActive == index }" v-for="(item, index) in cartList"
:key="item.id" @click="selectCartItemHandle(item, index)">
<div class="name_wrap">
<span>{{ item.name }}</span>
<span>¥{{ item.salePrice }}</span>
</div>
<div class="sku_list" v-if="item.skuName">
<div class="tag" v-for="item in item.skuName.split(',')">
{{ item }}
</div>
</div>
<div class="num">
<div class="left">
<div class="icon_item" v-if="item.isGift == 'true'" @click="giftPackHandle('isGift', item)">
<el-icon class="icon">
<ShoppingBag />
</el-icon>
</div>
<div class="icon_item" v-if="item.isPack == 'true'" @click="giftPackHandle('isPack', item)">
<el-icon class="icon" style="color: var(--primary-color)">
<Box />
</el-icon>
</div>
</div>
<el-text class="t">X{{ item.number }}</el-text>
</div>
</div>
<div class="empty">
<el-empty description="请选择商品" v-if="!cartList.length" />
</div>
</div>
<!-- 购物车操作栏 -->
<cartOperation :item="cartList[cartListActive]" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle"
@pending="pendingCart" @clearCart="clearCartHandle" />
</div>
<div class="footer">
<div class="top">
<div class="left" @click="allSelectedHandle">
<div class="selected">
<div class="selected_round" v-if="!allSelected"></div>
<el-icon class="icon" v-else>
<CircleCheckFilled />
</el-icon>
</div>
<el-text class="t">打包(¥{{ cartInfo.packAmount || 0 }})</el-text>
</div>
<div class="num-wrap">
<el-text>共{{ cartInfo.productNum || 0 }}种商品,{{
cartInfo.productSum || 0
}}件</el-text>
</div>
</div>
<div class="btm">
<el-button icon="Edit" @click="remarkRef.show()"></el-button>
<div class="button">
<el-button type="primary" style="width: 100%" :disabled="!cartList.length" v-loading="createOrderLoading"
@click="createOrderHandle">
<span v-if="!createOrderLoading">结算(¥{{ cartInfo.totalAmount || 0 }})</span>
<span v-else>下单中...</span>
</el-button>
</div>
</div>
</div>
</div>
<div class="shop_manage card">
<!-- 分类/商品列表 -->
<goods ref="goodsRef" :masterId="masterId" @success="addCart" />
<!-- ©银收客 v{{ packageData.version }} -->
</div>
</div>
<!-- 备注 -->
<remarkModal ref="remarkRef" @success="(e) => (remark = e)" />
<!-- 修改取餐号 -->
<takeFoodCode />
<el-drawer v-model="membershow" :with-header="true" size="90%" title="选择会员">
<member :membershow="'1'"></member>
</el-drawer>
<takeFoodCode ref="takeFoodCodeRef" title="修改取餐号" placeholder="请输入取餐号" @success="takeFoodCodeSuccess" />
<!-- 结算订单 -->
<settleAccount ref="settleAccountRef" :cart="cartList" :amount="cartInfo.totalAmount" :remark="remark"
:masterId="masterId" :orderInfo="orderInfo" :member="memberInfo" @paySuccess="createCodeAjax(1)" />
<!-- 快捷收银 -->
<fastCashier ref="fastCashierRef" type="0" />
<!-- 挂起订单 -->
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
</template>
<script>
export default {
name: "home",
};
</script>
<script setup>
import { onMounted, ref } from "vue";
import { useRoute } from 'vue-router'
import { useUser } from "@/store/user.js";
import remarkModal from "@/components/remarkModal.vue";
import takeFoodCode from "@/components/takeFoodCode.vue";
import cartOperation from "@/views/home/components/cartOperation.vue";
import settleAccount from "@/views/home/components/settleAccount.vue";
import fastCashier from "@/views/home/components/fastCashier.vue";
import pendingCartModal from "@/views/home/components/pendingCartModal.vue";
import useStorage from '@/utils/useStorage'
import {
createCart,
queryCart,
createCode,
packall,
delCart,
cartStatus,
clearCart,
createOrder,
} from "@/api/product";
// 商品列表
import goods from "@/views/home/components/goods.vue";
import member from "@/views/member/index.vue";
const route = useRoute()
const membershow = ref(false);
const store = useUser();
const remarkRef = ref(null);
const takeFoodCodeRef = ref(null);
const goodsRef = ref(null);
const pendingCartModalRef = ref(null);
const settleAccountRef = ref(null);
const fastCashierRef = ref(null);
const allSelected = ref(false);
const remark = ref("");
const cartListActive = ref(0);
const cartList = ref([]);
const cartInfo = ref({});
const cartLoading = ref(false);
const orderInfo = ref({});
const createOrderLoading = ref(false);
const memberInfo = ref({})
// 取餐码
const masterId = ref("");
// 挂单量
const pendingCartNum = ref(0);
// 生成订单
async function createOrderHandle() {
try {
createOrderLoading.value = true;
const res = await createOrder({
masterId: masterId.value,
shopId: store.userInfo.shopId,
remark: remark.value,
});
orderInfo.value = res;
settleAccountRef.value.show();
createOrderLoading.value = false;
} catch (error) {
console.log(error);
createOrderLoading.value = false;
}
}
// 清空购物车
async function clearCartHandle() {
try {
await clearCart({
shopId: store.userInfo.shopId,
masterId: masterId.value,
});
queryCartAjax();
// 清除商品所有红点
goodsRef.value.clearDot()
} catch (error) {
console.log(error);
}
}
// 恢复挂单
async function pendingCartHandle(item) {
const nItem = { ...item };
if (cartList.value.length) {
// 当购物车有数据时,先挂起当前购物车
await pendingCart({ masterId: masterId.value });
}
masterId.value = nItem.masterId;
await pendingCart(nItem, false);
await queryCartAjax();
}
// 挂单
async function pendingCart(params, status = true) {
try {
cartLoading.value = true;
await cartStatus({
shopId: store.userInfo.shopId,
masterId: params.masterId,
status: status,
uuid: params.uuid,
});
if (status && cartList.value.length) {
await createCodeAjax();
cartLoading.value = false;
} else {
cartLoading.value = false;
}
} catch (error) {
console.log(error);
}
}
// 删除购物车
async function delCartHandle(params) {
try {
cartLoading.value = true;
await delCart({
masterId: params.masterId,
cartId: params.id,
});
await queryCartAjax();
cartLoading.value = false;
cartListActive.value = 0;
} catch (error) {
console.log(error);
}
}
// 赠送打包操作
function giftPackHandle(key, item) {
item[key] = false;
addCart(item, "edit");
}
// 打包全选
const allSelectedHandle = async () => {
if (!cartList.value.length) return;
allSelected.value = !allSelected.value;
await packall({
shopId: store.userInfo.shopId,
status: allSelected.value,
masterId: masterId.value,
});
queryCartAjax();
};
// 确认取餐号
async function takeFoodCodeSuccess(code) {
if (cartList.value.length) {
await pendingCart({
masterId: masterId.value,
uuid: cartList.value[0].uuid,
});
}
masterId.value = `#${code}`;
queryCartAjax();
}
// 从购物车选择商品
function selectCartItemHandle(item, index) {
cartListActive.value = index;
}
// 选择完规格开始添加购物车
async function addCart(params, type = "add") {
try {
cartLoading.value = true;
const res = await createCart({
productId: params.productId,
masterId: masterId.value,
shopId: store.userInfo.shopId,
skuId: type == "add" ? params.id : params.skuId,
number: params.number || 1,
isPack: params.isPack || "false",
isGift: params.isGift || "false",
cartId: type == "add" ? "" : params.id,
uuid: params.uuid || store.userInfo.uuid,
type: type,
});
cartLoading.value = false;
masterId.value = res;
goodsRef.value.updateData();
queryCartAjax();
} catch (error) {
console.log(error);
cartLoading.value = false;
}
}
// 获取购物车商品
async function queryCartAjax() {
try {
const res = await queryCart({
masterId: masterId.value,
shopId: store.userInfo.shopId,
});
cartList.value = res.list;
cartInfo.value = res.amount;
pendingCartNum.value = res.num;
goodsRef.value.updateData();
let i = 0;
res.list.map((item) => {
if (item.isPack == "true") {
i++;
}
});
if (i == res.list.length) {
allSelected.value = true;
} else {
allSelected.value = false;
}
} catch (error) {
console.log("获取购物车商品", error);
}
}
// 获取取餐码
async function createCodeAjax(type = "0") {
try {
// if (!process.env.VITE_DEV_SERVER_URL) {
// masterId.value = '#20'
// } else {
// const res = await createCode({
// shopId: store.userInfo.shopId
// })
// masterId.value = res.code
// }
const res = await createCode({
shopId: store.userInfo.shopId,
type: type,
});
masterId.value = res.code;
queryCartAjax();
getLocalMemberInfo()
if (type == 1) {
// 结算订单 清楚商品所有红点
goodsRef.value.clearDot()
}
} catch (error) {
console.log(error);
}
}
// 从本地获取会员信息
function getLocalMemberInfo() {
let localMemberInfo = useStorage.get('memberInfo')
if (localMemberInfo && localMemberInfo.telephone) {
memberInfo.value = localMemberInfo
} else {
memberInfo.value = {}
}
}
// 清除本地会员
function clearMember() {
useStorage.del('memberInfo')
getLocalMemberInfo()
}
onMounted(() => {
createCodeAjax();
getLocalMemberInfo()
});
</script>
<style scoped lang="scss">
.cart_wrap {
flex: 1.5;
height: 100%;
display: flex;
flex-direction: column;
.menu_top {
flex-shrink: 0;
display: flex;
height: var(--el-component-size-large);
.menu {
background-color: var(--el-color-warning);
color: #fff;
width: 60px;
display: flex;
align-items: center;
justify-content: center;
.icon {
font-size: var(--el-font-size-base);
position: relative;
top: 2px;
}
.t {
color: #fff;
margin-left: 4px;
font-size: var(--el-font-size-base);
}
}
.number {
width: 50px;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--el-color-info-light-7);
// padding-left: var(--el-font-size-base);
.t {
font-size: var(--el-font-size-base);
}
}
.select_user {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--el-color-info-light-8);
padding: 0 var(--el-font-size-base);
.left {
display: flex;
align-items: center;
.icon {
color: var(--el-color-primary);
font-size: 20px;
}
.t {
font-size: var(--el-font-size-base);
margin-left: 4px;
}
}
.arrow {
color: #999;
font-size: 16px;
position: relative;
top: 2px;
}
}
}
.shop_operation {
flex: 1;
display: flex;
.shop_list {
flex: 1;
height: calc(100vh - 40px - 60px - 80px);
overflow-y: auto;
border-right: 1px solid #ececec;
.item {
padding: var(--el-font-size-base);
&.active {
background-color: var(--primary-color-hover);
}
&:not(:last-child) {
border-bottom: 1px solid #ececec;
}
.name_wrap {
display: flex;
justify-content: space-between;
font-size: var(--el-font-size-base);
}
.sku_list {
display: flex;
flex-wrap: wrap;
padding-top: 10px;
.tag {
padding: 2px 6px;
background-color: var(--el-color-danger);
color: #fff;
margin-right: 10px;
margin-bottom: 10px;
}
}
.num {
padding-top: var(--el-font-size-base);
display: flex;
align-items: center;
justify-content: space-between;
.left {
display: flex;
align-items: center;
.icon_item {
$size: 30px;
width: $size;
height: $size;
border-radius: 4px;
background-color: #e2e2e2;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
}
.t {
font-size: var(--el-font-size-base);
}
}
}
}
}
}
.footer {
padding: var(--el-font-size-base);
border-top: 1px solid #ececec;
.left {
display: flex;
align-items: center;
.selected {
width: 16px;
height: 16px;
display: flex;
align-items: center;
position: relative;
top: 1px;
.icon {
display: block;
font-size: var(--el-font-size-base);
color: var(--primary-color);
}
.selected_round {
width: 100%;
height: 100%;
border-radius: 50%;
border: 1px solid #ddd;
}
}
.t {
margin-left: 6px;
}
}
.top {
display: flex;
justify-content: space-between;
}
.btm {
$h: 70px;
display: flex;
height: $h;
padding-top: var(--el-font-size-base);
gap: var(--el-font-size-base);
.editor {
width: $h;
border: 1px solid #ececec;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
color: #555;
font-size: var(--el-font-size-base);
}
.button {
flex: 1;
.js {
.t {
color: #fff;
font-size: var(--el-font-size-base);
}
}
}
}
}
.shop_manage {
flex: 3;
margin-left: var(--el-font-size-base);
height: 100%;
}
</style>