Files
cashierdesktop/src/views/home/index.vue
2024-04-03 17:25:22 +08:00

625 lines
15 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="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="membershow = true">
<el-icon class="icon">
<UserFilled />
</el-icon>
<el-text class="t">选择会员</el-text>
<el-icon class="arrow">
<ArrowRight />
</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"
@paySuccess="createCodeAjax(1)"
/>
<!-- 挂起订单 -->
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
</template>
<script>
export default {
name: "home",
};
</script>
<script setup>
import { onMounted, ref } from "vue";
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 pendingCartModal from "@/views/home/components/pendingCartModal.vue";
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 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 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 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();
} 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();
} catch (error) {
console.log(error);
}
}
onMounted(() => {
createCodeAjax();
});
</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: 100px;
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 {
flex: 1;
display: flex;
align-items: 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 {
display: flex;
align-items: center;
background-color: var(--el-color-info-light-8);
padding: 0 var(--el-font-size-base);
.icon {
color: var(--el-color-primary);
font-size: 24px;
}
.t {
font-size: var(--el-font-size-base);
padding: 0 10px;
}
.arrow {
color: #999;
font-size: 20px;
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>