对接订单列表接口

This commit is contained in:
gyq 2025-03-01 14:08:24 +08:00
parent d3ed4ec8e6
commit 573dd88b24
21 changed files with 2769 additions and 1674 deletions

View File

@ -338,7 +338,7 @@ html {
.empty {
display: flex;
justify-content: center;
padding-top: 100px;
padding-top: var(--el-font-size-base);
}
/*

View File

@ -77,3 +77,16 @@ export function shopTable(params) {
params,
});
}
/**
* 支付方式列表
* @param {*} params
* @returns
*/
export function getPayType(params) {
return request({
method: "get",
url: "/account/admin/payType",
params,
});
}

View File

@ -31,11 +31,11 @@ export function cashPay(data) {
* @param {*} data
* @returns
*/
export function orderList(data) {
export function orderList(params) {
return request({
method: "post",
url: "/order/admin/order",
data,
method: "get",
url: `/order/admin/order`,
params,
});
}
@ -64,3 +64,16 @@ export function historyOrder(params) {
params,
});
}
/**
* 订单退款
* @param {*} data
* @returns
*/
export function refundOrder(data) {
return request({
method: "post",
url: "/order/admin/order/refundOrder",
data,
});
}

View File

@ -25,7 +25,7 @@
</div>
<span class="title">{{ item.payName }}</span>
</div>
<div class="item" :class="{ active: payActive == 'buyer' }"
<!-- <div class="item" :class="{ active: payActive == 'buyer' }"
@click="payTypeChange('buyer', { payType: 'buyer' })">
<div class="icon">
<div class="img"
@ -34,7 +34,7 @@
</div>
</div>
<span class="title">挂账</span>
</div>
</div> -->
</div>
<div class="input_wrap">
<div class="input" style="flex: 1;">储值:{{ money }}</div>
@ -62,7 +62,7 @@
</div>
</div>
<scanModal ref="scanModalRef" :amount="props.amount" :money="money" :orderId="props.orderId"
:selecttype="props.selecttype" :payType="payType" @success="scanCodeSuccess" />
:selecttype="props.selecttype" :payType="payType" :payData="payData" @success="scanCodeSuccess" />
<el-dialog :title="`选择会员`" top="3vh" v-model="showDialog" width="80%">
<el-form inline>
<el-form-item>
@ -147,6 +147,8 @@ import { queryMembermember, createMembermember, membermemberScanPay, accountPaym
import { useUser } from "@/store/user.js"
import { clearNoNum, formatDecimal } from '@/utils'
import { getPayType } from '@/api/account.js'
import scanModal from '@/components/payCard/scanModal.vue'
import { ElMessage } from "element-plus";
import { useGlobal } from '@/store/global.js'
@ -202,6 +204,7 @@ const payActive = ref(0)
const payType = ref('')
const payList = ref([])
const payLoading = ref(false)
const payData = ref({})
// start
const showBuyer = ref(false)
@ -281,8 +284,8 @@ function scanCodeSuccess() {
//
async function payTypeChange(index, item) {
try {
await staffPermission('yun_xu_shou_kuan')
if (item.disabled) return
// await staffPermission('yun_xu_shou_kuan')
// if (item.disabled) return
payActive.value = index
payType.value = item.payType
if (item.payType == 'scanCode') {
@ -310,27 +313,11 @@ async function confirmOrder() {
try {
payLoading.value = true
// 使
await cashPay({
shopId: store.shopInfo.id,
checkOrderPay: {
orderId: goodsStore.orderInfo.id,
userId: '',
seatNum: 0, //
originAmount: goodsStore.orderInfo.originAmount, // +
discountRatio: 1, // ( )
discountAmount: 0, //
productCouponDiscountAmount: 0, //
fullCouponDiscountAmount: 0, //
couponList: [], // 使
orderAmount: goodsStore.orderInfo.originAmount, //
roundAmount: 0, //
pointsDiscountAmount: 0, // (tb_points_basic_setting)
pointsNum: 0 // 使 ( enable_deduction使)
}
})
await cashPay(payData.value)
payLoading.value = false
ElMessage.success('支付成功')
goodsStore.successDeleteCartItem()
emit('paySuccess')
return
await staffPermission('yun_xu_shou_kuan')
@ -418,9 +405,7 @@ function delHandle() {
//
async function queryPayTypeAjax() {
try {
const res = await queryPayType({
shopId: store.userInfo.shopId
})
const res = await getPayType()
res.map(item => {
if (props.amount <= 0 && item.payType == 'scanCode') {
@ -431,7 +416,7 @@ async function queryPayTypeAjax() {
})
payList.value = res
if ((res[0].payType == 'scanCode' && !res[0].disabled) || res[0].payType == 'deposit') {
if (res[0].payType == 'scanCode' && !res[0].disabled) {
scanModalRef.value.show()
payType.value = res[0].payType
}
@ -506,7 +491,28 @@ function cancelDiscount() {
onMounted(() => {
money.value = `${formatDecimal(props.amount)}`
// queryPayTypeAjax()
payData.value = {
shopId: store.shopInfo.id,
buyerRemark: '', //
checkOrderPay: {
orderId: goodsStore.orderListInfo.id,
userId: '',
seatNum: goodsStore.tableInfo.num, //
originAmount: goodsStore.orderListInfo.originAmount, // +
discountRatio: 1, // ( )
discountAmount: 0, //
productCouponDiscountAmount: 0, //
fullCouponDiscountAmount: 0, //
couponList: [], // 使
orderAmount: goodsStore.orderListInfo.originAmount, //
roundAmount: 0, //
pointsDiscountAmount: 0, // (tb_points_basic_setting)
pointsNum: 0 // 使 ( enable_deduction使)
}
}
queryPayTypeAjax()
})
</script>

View File

@ -58,6 +58,8 @@ import { scanpay, queryOrder, quickPay, queryQuickPayStatus, accountPay, querySc
import { useUser } from "@/store/user.js";
import { useGlobal } from '@/store/global.js'
import { formatDecimal } from '@/utils'
import { microPay } from '@/api/order.js'
const store = useUser();
const global = useGlobal()
import {
@ -93,6 +95,10 @@ const props = defineProps({
money: {
type: [Number, String],
default: 0,
},
payData: {
type: Object,
default: {}
}
});
@ -112,14 +118,7 @@ async function submitHandle() {
if (!scanCode.value) return;
loading.value = true;
if (props.selecttype == 1) {
await membermemberScanPay({
shopId: store.userInfo.shopId,
memberId: props.orderId,
amount: props.amount,
authCode: scanCode.value,
// payAmount: props.money < props.amount ? props.money : '',
// discountAmount: props.money < props.amount ? formatDecimal(props.amount - props.money) : ''
});
await microPay(props.payData);
} else {
if (props.fast) {
await quickPay({
@ -129,11 +128,10 @@ async function submitHandle() {
});
} else {
if (props.payType == 'scanCode') {
await scanpay({
orderId: props.orderId,
authCode: scanCode.value,
payAmount: props.money < props.amount ? props.money : '',
discountAmount: props.money < props.amount ? formatDecimal(props.amount - props.money) : ''
//
await microPay({
...props.payData,
authCode: scanCode.value
});
}
if (props.payType == 'deposit') {

View File

@ -1,25 +1,120 @@
import { defineStore } from "pinia";
export const useGlobal = defineStore({
id: "global",
export const useGlobal = defineStore("global", {
state: () => ({
// 是否监听叫号
isCallNumber: true,
orderMemberInfo: {},
tableInfo: {},
orderStatus: [
{
type: "unpaid",
label: "待支付",
},
{
type: "in-production",
label: "制作中",
},
{
type: "wait-out",
label: "待取餐",
},
{
type: "done",
label: "订单完成",
},
{
type: "refunding",
label: "申请退单",
},
{
type: "refund",
label: "退单",
},
{
type: "part-refund",
label: "部分退单",
},
{
type: "cancelled",
label: "取消订单",
},
],
orderType: [
{
type: "cash",
label: "收银",
},
{
type: "miniapp",
label: "小程序",
},
],
platformType: [
{
type: "WX",
label: "微信小程序",
},
{
type: "ALI",
label: "支付宝小程序",
},
{
type: "PC",
label: "收银机客户端",
},
{
type: "APC",
label: "PC管理端",
},
{
type: "APP",
label: "APP管理端",
},
],
dineMode: [
{
type: "dine-in",
label: "堂食",
},
{
type: "take-out",
label: "外带",
},
{
type: "take-away",
label: "外卖",
},
],
payType: [
{
type: "main-scan",
label: "主扫",
},
{
type: "back-scan",
label: "被扫",
},
{
type: "wechat-mini",
label: "微信小程序",
},
{
type: "alipay-mini",
label: "支付宝小程序",
},
{
type: "vip-pay",
label: "会员支付",
},
{
type: "cash-pay",
label: "现金支付",
},
],
}),
actions: {
// 更新状态
updateData(state) {
this.isCallNumber = state;
},
// 设置订单会员信息
setOrderMember(obj) {
this.orderMemberInfo = obj;
},
// 设置订单台桌信息
setOrderTable(obj) {
this.tableInfo = obj;
},
},
});

View File

@ -5,13 +5,23 @@ import { historyOrder } from "@/api/order.js";
import { useUser } from "@/store/user.js";
import { useSocket } from "@/store/socket.js";
import useStorage from "@/utils/useStorage.js";
import { formatDecimal } from "@/utils/index.js";
import { ElMessage } from "element-plus";
// 商品store + 购物车store
export const useGoods = defineStore("goods", {
state: () => ({
vipUserInfo: {}, // 会员信息
tableInfo: {}, // 台桌信息
tableInfo: {
name: "A1",
num: 4,
tableCode: "66666666",
}, // 台桌信息
// tableInfo: {
// name: "",
// num: "",
// tableCode: "",
// }, // 台桌信息
cartActiveIndex: 0, // 购物车激活索引,
isCartInit: false,
cartList: [], // 购物车列表
@ -22,6 +32,7 @@ export const useGoods = defineStore("goods", {
gifNumberAmount: 0,
saleNumber: 0,
saleNumberAmount: 0,
tableFee: 0,
}, // 购物车信息,
goodsName: "", // 商品名称,
categoryIndex: useStorage.get("categoryIndex") || 0, // 商品分类索引,
@ -30,16 +41,26 @@ export const useGoods = defineStore("goods", {
goodsList: [], // 商品列表
originGoodsList: [], // 原始商品列表
orderList: [], // 订单列表
orderInfo: {}, // 生成的订单信息
orderListInfo: "", // 历史订单信息
}),
actions: {
// 手动选择台桌
selectTable(tableInfo = {}) {
const socket = useSocket();
const store = useUser();
this.tableInfo = tableInfo;
this.isCartInit = false;
// 选择台桌后将购物车初始化
socket.cartInit(this.tableInfo.tableCode || "");
// this.historyOrderAjax(this.tableInfo.tableCode);
socket.cartInit();
if (store.shopInfo.registerType == "after" && this.tableInfo.tableCode) {
this.historyOrderAjax(this.tableInfo.tableCode);
}
if (!this.tableInfo.tableCode) {
this.orderList = [];
this.orderListInfo = "";
}
},
// 获取订单列表
async historyOrderAjax(tableCode) {
@ -48,8 +69,22 @@ export const useGoods = defineStore("goods", {
tableCode: tableCode,
});
if (res) {
this.orderListInfo = res;
let arr = [];
for (let key in res.detailMap) {
arr.push({
orderNum: key,
goods: res.detailMap[key].map((item) => {
return this.comleteOrderInfo(item);
}),
});
}
// val = this.completeGoodsInfo(val);
// this.orderList = res.records;
this.orderList = arr;
console.log(this.orderList);
}
} catch (error) {
console.log(error);
}
@ -145,6 +180,8 @@ export const useGoods = defineStore("goods", {
},
// 获取购物车列表,数据必须由长链接返回
async getCartList(arr) {
const store = useUser();
arr.map((val, index) => {
val = this.completeGoodsInfo(val);
val.active = false;
@ -157,9 +194,9 @@ export const useGoods = defineStore("goods", {
this.isCartInit = true;
this.calcCartInfo();
// if (arr.length && arr[0].table_code) {
// this.historyOrderAjax(arr[0].table_code);
// }
if (this.tableInfo.tableCode && store.shopInfo.registerType == "after") {
this.historyOrderAjax(this.tableInfo.tableCode);
}
console.log("getCartList.cartList===", this.cartList);
},
// 更新商品列表的角标
@ -250,13 +287,48 @@ export const useGoods = defineStore("goods", {
let sku = val.skuList.find((sku) => sku.id == item.sku_id);
let group_text = "";
if (val.type == "package") {
if (val.type == "package" && item.pro_group_info) {
group_text = JSON.parse(item.pro_group_info)
.flat()
.map((item) => item.proName)
.join("、");
}
item.lowPrice = val.lowPrice;
item.product_name = val.name;
item.sku_name = sku && sku.specInfo;
item.suitNum = sku.suitNum;
item.group_type = val.groupType;
item.goods_type = val.type;
item.skuList = val.skuList;
item.selectSpecInfo = val.selectSpecInfo;
item.group_text = group_text;
item.packFee = val.packFee;
item.unitName = val.unitName;
}
});
if (!flag) {
console.log("该商品不存在,已删除", item);
this.operateCart(item, "del");
}
return item;
}
},
// 补全订单列表商品信息
comleteOrderInfo(item) {
this.originGoodsList.map((val) => {
if (val.id == item.productId) {
let sku = val.skuList.find((sku) => sku.id == item.skuId);
let group_text = "";
if (val.type == "package") {
group_text = JSON.parse(item.proGroupInfo)
.flat()
.map((item) => item.proName)
.join("、");
}
item.lowPrice = val.lowPrice;
item.product_name = val.name;
item.sku_name = sku && sku.specInfo;
@ -265,15 +337,12 @@ export const useGoods = defineStore("goods", {
item.skuList = val.skuList;
item.selectSpecInfo = val.selectSpecInfo;
item.group_text = group_text;
item.packFee = val.packFee;
item.unitName = val.unitName;
item.number = item.num;
}
});
if (!flag) {
console.log("该商品不存在,已删除", item);
this.operateCart(item, "del");
}
return item;
}
},
// 删除购物车商品
deleteCartItem() {
@ -322,6 +391,8 @@ export const useGoods = defineStore("goods", {
},
// 计算购物车信息
calcCartInfo() {
const store = useUser();
this.updateGoodsNumber();
let total = 0; // 总数量
@ -330,10 +401,17 @@ export const useGoods = defineStore("goods", {
let gifNumberAmount = 0; // 赠送总金额
let saleNumber = 0; // 打折总数量
let saleNumberAmount = 0; // 打折总金额
let packFee = 0; // 打包费
let packFeeNumber = 0; // 打包数量
this.cartList.map((val, index) => {
total += +val.number;
if (+val.pack_number && !store.shopInfo.isTableFee) {
packFeeNumber += +val.pack_number;
packFee += +val.pack_number * +val.packFee;
}
if (val.is_temporary) {
if (val.is_gift) {
gifNumber += +val.number;
@ -380,10 +458,44 @@ export const useGoods = defineStore("goods", {
this.cartInfo.saleNumber = saleNumber;
this.cartInfo.saleNumberAmount = saleNumberAmount;
this.cartInfo.packFee = packFee;
this.cartInfo.packFeeNumber = packFeeNumber;
this.cartInfo.total = total;
this.cartInfo.totalAmount = totalAmount;
let tableFee = 0;
if (this.tableInfo.name) {
tableFee = this.tableInfo.num * store.shopInfo.tableFee;
this.tableInfo.tableFee = tableFee;
}
this.cartInfo.totalAmount = totalAmount + packFee;
console.log("this.cartInfo===", this.cartInfo);
const discountInfo = [];
if (this.cartInfo.gifNumberAmount) {
discountInfo.push(
`赠送:${formatDecimal(this.cartInfo.gifNumberAmount, 2, true)}`
);
}
if (this.cartInfo.saleNumberAmount) {
discountInfo.push(
`改价优惠:${formatDecimal(
this.cartInfo.saleNumberAmount,
2,
true
)}`
);
}
if (this.cartInfo.packFee) {
discountInfo.push(
`打包费:${formatDecimal(this.cartInfo.packFee, 2, true)}`
);
}
this.cartInfo.discountInfo = discountInfo.join("");
},
// 购物车操作
async operateCart(data, operate_type = "add") {

View File

@ -35,13 +35,14 @@ export const useSocket = defineStore("socket", {
),
cartInit(tableCode = "") {
const store = useUser();
const goodsStore = useGoods()
this.ws.send(
JSON.stringify({
type: "cashier",
account: `cashier_${store.shopInfo.id}`,
operate_type: "init",
shop_id: store.shopInfo.id,
table_code: tableCode, // 后期选台桌号
table_code: goodsStore.tableInfo.tableCode,
})
);
},

View File

@ -9,7 +9,7 @@ const service = axios.create({
? "/api/"
: import.meta.env.VITE_API_URL,
// withCredentials: true, // 跨域请求时发送 cookies
timeout: 5000, // 请求超时
timeout: 10000, // 请求超时
});
// 请求拦截器

View File

@ -0,0 +1,231 @@
<template>
<div class="cart_item" :class="{ active: props.item.active, border: props.border }"
@click="selectCartItemHandle(index)">
<div class="name_wrap">
<span>{{ props.item.product_name }}</span>
<template v-if="props.item.is_gift">
<div class="price">
<span class="dis" v-if="props.item.is_temporary">
{{ formatDecimal(+props.item.discount_sale_amount, 2, true) }}
</span>
<span class="dis" v-else>
{{ formatDecimal(+props.item.lowPrice, 2, true) }}
</span>
<span v-if="props.item.discount_sale_amount">
0.00
</span>
</div>
</template>
<template v-else>
<div class="price" v-if="props.item.is_temporary">
<span>
{{ formatDecimal(+props.item.discount_sale_amount, 2, true) }}
</span>
</div>
<div class="price" v-else>
<template v-if="+props.item.discount_sale_amount">
<span class="dis">
{{ formatDecimal(props.item.lowPrice, 2, true) }}
</span>
<span>
{{ formatDecimal(+props.item.discount_sale_amount, 2, true) }}
</span>
</template>
<span v-else>
{{ formatDecimal(+props.item.lowPrice, 2, true) }}
</span>
</div>
</template>
</div>
<div class="sku_list" v-if="props.item.sku_name">
<div class="tag" v-for="item in item.sku_name.split(',')">
{{ item }}
</div>
</div>
<div class="grooup_wrap" v-if="props.item.goods_type == 'package' && props.item.group_text">
{{ props.item.group_type == 0 ? '固定套餐:' : '自选套餐:' }}
<span>{{ props.item.group_text }}</span>
</div>
<div class="num">
<div class="left">
<div class="icon_item zen" v-if="props.item.is_gift">
<span class="t"></span>
</div>
<div class="icon_item bao" v-if="+props.item.pack_number">
<span class="t">打包({{ +props.item.pack_number }})</span>
</div>
<div class="icon_item tui" v-if="props.item.status == 'return'">
<span class="t">退</span>
</div>
<div class="icon_item lin" v-if="props.item.is_temporary == 1">
<span class="t"></span>
</div>
<div class="icon_item zhe" v-if="props.item.discount_sale_amount > 0 && !props.item.is_temporary">
<span class="t"></span>
</div>
<div class="icon_item chu" v-if="props.item.is_print == 0">
<span class="t">免厨打印</span>
</div>
</div>
<el-text class="t">x{{ formatDecimal(+props.item.number, 2, true) }}</el-text>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useGoods } from '@/store/goods.js'
import { formatDecimal } from '@/utils/index.js'
const goodsStore = useGoods()
const props = defineProps({
type: {
type: String,
default: 'cart'
},
item: {
type: Object,
default: {}
},
index: {
type: [String, Number],
default: 0
},
i: {
type: [String, Number],
default: 0
},
border: {
type: Boolean,
default: true
}
})
//
function selectCartItemHandle() {
if (props.type == 'cart') {
goodsStore.selectCartItemHandle(props.index)
} else {
}
}
</script>
<style scoped lang="scss">
.cart_item {
padding: var(--el-font-size-base);
&.active {
background-color: var(--primary-color-hover);
}
&.border {
&:not(:last-child) {
border-bottom: 1px solid #ececec;
}
}
.name_wrap {
display: flex;
justify-content: space-between;
font-size: var(--el-font-size-base);
.dis {
color: #999;
font-size: 12px;
text-decoration: line-through;
margin-right: 4px;
}
}
.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;
}
}
.grooup_wrap {
padding-top: 10px;
font-size: 12px;
color: #555;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
}
.num {
padding-top: var(--el-font-size-base);
display: flex;
align-items: center;
justify-content: space-between;
.left {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10px;
padding-right: 10px;
.icon_item {
$size: 20px;
height: $size;
padding: 0 6px;
border-radius: 2px;
background-color: #e2e2e2;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 10px;
&.zen {
background-color: #FFB0B1;
color: #FF4D4F;
}
&.bao {
background-color: #52C41A;
}
&.tui {
background-color: var(--el-color-danger);
}
&.lin {
background-color: var(--el-color-warning);
}
&.zhe {
background-color: var(--primary-color);
}
&.chu {
background-color: #ffe7ba;
color: #e69f1c;
}
span {
font-size: inherit;
color: inherit;
}
}
}
.t {
font-size: var(--el-font-size-base);
}
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="operation_wrap">
<div class="item"
:class="{ disabled: goodsStore.cartList.length && (goodsStore.cartList[goodsStore.cartActiveIndex].number <= 1 || !goodsStore.cartList[goodsStore.cartActiveIndex].id || (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1)) }"
: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 />
@ -46,9 +46,7 @@
</el-icon>
<el-text class="t">赠送</el-text>
</div>
<div class="item"
:class="{ disabled: goodsStore.cartList.length && goodsStore.cartList[goodsStore.cartActiveIndex].is_pack }"
@click="giftPackHandle('is_pack')" v-if="shopStore.info.eatModel == 'take-out'">
<div class="item" @click="packHandle">
<el-icon class="icon">
<Box />
</el-icon>
@ -74,7 +72,7 @@
</el-icon>
<el-text class="t">挂单</el-text>
</div> -->
<div class="item" @click="tableMergingHandle" v-if="goodsStore.tableInfo.tableCode">
<div class="item" @click="tableMergingRef.show()">
<el-icon class="icon">
<EditPen />
</el-icon>
@ -124,12 +122,39 @@
</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="60px"
label-position="left">
<el-form-item label="数量" prop="number">
<el-input v-model="packNumberForm.number"
:placeholder="`最多输入${+packItem.number}${packItem.unitName}`" @input="packNumberInput">
<template #append>{{ packItem.unitName }}</template>
</el-input>
</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="" />
</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 { useShop } from '@/store/shop.js'
import { useGoods } from '@/store/goods.js'
@ -139,6 +164,8 @@ import { updatePrice, orderPrint } from '@/api/product.js'
const shopStore = useShop()
const goodsStore = useGoods()
const tableMergingRef = ref(null)
const props = defineProps({
item: {
type: Object,
@ -150,6 +177,20 @@ const emit = defineEmits(['confirm', 'delete', 'pending', 'clearCart', 'merging'
const takeFoodCodeRef = ref(null)
const skuModalRef = ref([])
//
function packHandle() {
let item = goodsStore.cartList[goodsStore.cartActiveIndex]
if (item && item.id) {
if (item.number > 1) {
// 1
showPackModal.value = true
} else {
// 1
goodsStore.operateCart({ ...item, pack_number: item.number }, 'edit')
}
}
}
//
function giftPackHandle(key) {
if (!goodsStore.cartList[goodsStore.cartActiveIndex].id) return
@ -178,12 +219,14 @@ function numberChange(t) {
let item = goodsStore.cartList.length ? goodsStore.cartList[goodsStore.cartActiveIndex] : ''
if (!item || (item.goods_type == 'package' && item.group_type == 1)) return
// if (!goodsStore.cartList[goodsStore.cartActiveIndex].id || (goodsStore.cartList[goodsStore.cartActiveIndex].goods_type == 'package' && goodsStore.cartList[goodsStore.cartActiveIndex].group_type == 1)) return
switch (t) {
case 'sub':
if (goodsStore.cartList[goodsStore.cartActiveIndex].number <= 1) return
goodsStore.cartList[goodsStore.cartActiveIndex].number--
if (item.number < item.suitNum) {
goodsStore.deleteCartItem()
} else {
goodsStore.operateCart(goodsStore.cartList[goodsStore.cartActiveIndex], 'edit')
}
break;
case 'add':
goodsStore.cartList[goodsStore.cartActiveIndex].number++
@ -329,14 +372,6 @@ async function kitchenPrint() {
}
/**免厨打印 end */
//
function tableMergingHandle() {
if (props.item.id) {
emit('merging')
}
}
//
function deleteHandle() {
if (goodsStore.cartList[goodsStore.cartActiveIndex].id) {
@ -348,6 +383,59 @@ function deleteHandle() {
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()
}
}
function packNumberInput(e) {
setTimeout(() => {
packNumberForm.value.number = inputFilterFloat(e)
}, 50)
}
// modal
function packModalOpen() {
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">

View File

@ -71,6 +71,8 @@
<img class="sell_out_icon" src="../../../assets/icon_xq.png">
</div>
<div class="weight" v-if="item.type == 'weight'">称重</div>
<div class="weight" v-if="item.type == 'package' && item.groupType == 1">可选套餐</div>
<div class="weight" v-if="item.type == 'package' && item.groupType == 0">固定套餐</div>
</div>
<div class="name"><el-text line-clamp="1">{{ item.name }}</el-text></div>
<div class="item_empty" v-if="shopListType == 'text'"></div>
@ -411,13 +413,13 @@ function skuConfirm(params) {
goodsStore.operateCart({ ...goodsItem, number: params.number }, 'edit')
} else if (params.type && params.type == 'package') {
//
goodsStore.addCart(params)
goodsStore.addCart({ ...params })
} else {
goodsStore.operateCart({ ...goodsItem, number: +goodsItem.number + 1 }, 'edit')
}
} else {
//
goodsStore.addCart(params)
goodsStore.addCart({ ...params, number: params.suitNum })
}
}
@ -489,7 +491,7 @@ function showSkuHandle(item) {
goodsStore.operateCart({ ...goodsItem, number: +goodsItem.number + 1 }, 'edit')
} else {
//
goodsStore.addCart({ ...item.skuList[0], lowPrice: item.skuList[0].salePrice })
goodsStore.addCart({ ...item.skuList[0], lowPrice: item.skuList[0].salePrice, number: item.skuList[0].suitNum })
}
} else if (item.type == 'weight') {
//
@ -507,7 +509,8 @@ function showSkuHandle(item) {
goodsStore.addCart({
...item.skuList[0], lowPrice: item.skuList[0].salePrice, type: item.type,
goods_type: 'package',
pro_group_info: item.groupSnap.map((item) => item.goods)
pro_group_info: item.groupSnap.map((item) => item.goods),
number: item.skuList[0].suitNum
})
}
}
@ -942,8 +945,8 @@ defineExpose({
color: #fff;
border-radius: 20px;
position: absolute;
top: 4px;
right: 4px;
top: 2px;
right: 2px;
z-index: 1;
font-size: 12px;
}
@ -955,12 +958,13 @@ defineExpose({
.weight {
position: absolute;
left: 5px;
bottom: 5px;
left: 2px;
bottom: 2px;
color: #fff;
font-size: 12px;
padding: 2px 6px;
background-color: var(--el-color-danger);
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
border-radius: 4px;
}

View File

@ -9,7 +9,7 @@
<ArrowLeftBold />
</el-icon>
</div>
<div class="info">
<!-- <div class="info">
<div class="master_id">
<span>{{ props.masterId }}</span>
<span class="member_info" v-if="global.orderMemberInfo.telephone">
@ -23,78 +23,11 @@
dayjs(props.orderInfo.createdAt).format("MM-DD HH:mm")
}}</span>
</div>
</div>
</div> -->
</div>
<div class="list_wrap card" style="margin-top: var(--el-font-size-base)">
<div class="item" v-for="item in goodsStore.cartList" :key="item.id">
<div class="top">
<div class="name">
<span v-if="item.is_temporary" style="color: #999;"> [临时菜]</span>
{{ item.product_name }}
</div>
<div class="n">x{{ formatDecimal(+item.number, 2, true) }}</div>
<div class="p">
<template v-if="item.is_temporary">
<template v-if="item.is_gift">
<span class="t_line">{{ formatDecimal(+item.discount_sale_amount) }}</span>
0.00
</template>
<template v-else>
<span>{{ formatDecimal(item.discount_sale_amount * item.number) }}</span>
</template>
</template>
<template v-else>
<template v-if="item.is_gift">
<span class="t_line">{{ formatDecimal(+item.lowPrice) }}</span>
0.00
</template>
<template v-else>
<template v-if="+item.discount_sale_amount">
<span class="t_line">
{{ formatDecimal(+item.lowPrice) }}
</span>
<span>
{{ formatDecimal(+item.discount_sale_amount) }}
</span>
</template>
<template v-else>
{{ formatDecimal(+item.lowPrice) }}
</template>
</template>
</template>
</div>
</div>
<div class="tag_wrap" v-if="item.sku_name">
<div class="tag" v-for="item in item.sku_name.split(',')">
{{ item }}
</div>
</div>
<div class="gift_wrap" v-if="item.is_gift">
<div class="name">
<span v-if="item.is_gift">[赠送]</span>
</div>
<div class="n"></div>
<div class="p">
<span>
-<template v-if="item.is_temporary || +item.discount_sale_amount">
{{ formatDecimal(+item.discount_sale_amount) }}
</template>
<template v-else>{{ formatDecimal(+item.lowPrice) }}</template>
</span>
</div>
</div>
<div class="gift_wrap" v-if="!item.is_temporary && !item.is_gift && item.discount_sale_amount">
<div class="name">
<span>[改价优惠]</span>
</div>
<div class="n"></div>
<div class="p">
<span>
-{{ formatDecimal(item.lowPrice - item.discount_sale_amount) }}
</span>
</div>
</div>
</div>
<SettleItem :list="cartList" />
<SettleItem :list="goodsStore.orderList.map(item => item.goods).flat()" />
</div>
<div class="footer">
<!-- <el-button icon="Edit"></el-button> -->
@ -110,8 +43,8 @@
</div>
</div>
<div class="pay_wrap">
<payCard :amount="goodsStore.orderInfo.originAmount" :discount="propsDiscount" :orderId="props.orderInfo.id"
@paySuccess="paySuccess" @cancelDiscount="propsDiscount = 0" />
<payCard :amount="goodsStore.orderListInfo.orderAmount" :discount="propsDiscount"
:orderId="goodsStore.orderListInfo.id" @paySuccess="paySuccess" @cancelDiscount="propsDiscount = 0" />
</div>
</div>
<el-dialog v-model="showStaffDiscount" title="员工折扣" @close="global.updateData(true)">
@ -141,6 +74,7 @@ import _ from 'lodash'
import { onMounted, ref } from "vue";
import { useUser } from "@/store/user.js";
import payCard from "@/components/payCard/payCard.vue";
import SettleItem from './settleItem.vue'
import { print } from "@/api/pay";
import { orderfindOrder, getStaffDiscount } from '@/api/order/index.js'
import { ElMessage } from "element-plus";
@ -173,10 +107,6 @@ const propsDiscount = ref(0)
const dialogVisible = ref(false);
const props = defineProps({
cart: {
type: Array,
default: [],
},
amount: {
type: [Number, String],
default: 0,
@ -200,11 +130,9 @@ const props = defineProps({
});
const cartList = ref([])
const isPrint = ref(true);
const discountLoading = ref(false)
//
async function showStaffDiscountHandle() {
try {
@ -356,25 +284,13 @@ async function printOrderLable() {
function paySuccess() {
propsDiscount.value = 0
dialogVisible.value = false;
global.setOrderMember({})
global.setOrderTable({})
printOrderLable()
emit("paySuccess");
// printOrderLable()
// emit("paySuccess");
}
function show() {
function show(t) {
dialogVisible.value = true;
cartList.value = []
props.cart.map(item => {
if (item.info && item.info.length) {
item.info.map(item => {
cartList.value.push({ ...item })
})
} else {
cartList.value.push({ ...item })
}
})
if (t = 1) cartList.value = [...goodsStore.cartList];
}
defineExpose({
@ -468,78 +384,6 @@ defineExpose({
padding: 0 var(--el-font-size-base);
height: calc(100vh - 200px);
overflow-y: auto;
.item {
padding: var(--el-font-size-base) 0;
border-bottom: 1px solid #ececec;
.name {
flex: 1.5;
}
.n {
width: 30px;
color: #555;
}
.p {
flex: 1;
color: #555;
display: flex;
justify-content: flex-end;
}
.t_line {
text-decoration: line-through;
color: #999;
margin-right: 4px;
}
.top {
display: flex;
padding-bottom: 6px;
}
.gift_wrap {
display: flex;
color: #999;
font-size: 16px;
.p {
color: var(--el-color-danger);
}
}
.tag_wrap {
display: flex;
flex-wrap: wrap;
.tag {
padding: 2px 6px;
background-color: var(--el-color-danger);
color: #fff;
margin-right: 10px;
margin-bottom: 10px;
}
}
.packge_Wrap {
display: flex;
align-items: center;
.icon_item {
$size: 40px;
width: $size;
height: $size;
background-color: #e2e2e2;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
}
}
}
.footer {

View File

@ -0,0 +1,172 @@
<template>
<div class="item" v-for="item in props.list" :key="item.id">
<div class="top">
<div class="name">
<span v-if="item.is_temporary" style="color: #999;"> [临时菜]</span>
{{ item.product_name }}
</div>
<div class="n">x{{ formatDecimal(+item.number, 2, true) }}</div>
<div class="p">
<template v-if="item.is_temporary">
<template v-if="item.is_gift">
<span class="t_line">{{ formatDecimal(+item.discount_sale_amount) }}</span>
0.00
</template>
<template v-else>
<span>{{ formatDecimal(item.discount_sale_amount * item.number) }}</span>
</template>
</template>
<template v-else>
<template v-if="item.is_gift">
<span class="t_line">{{ formatDecimal(+item.lowPrice) }}</span>
0.00
</template>
<template v-else>
<template v-if="+item.discount_sale_amount">
<span class="t_line">
{{ formatDecimal(+item.lowPrice) }}
</span>
<span>
{{ formatDecimal(+item.discount_sale_amount) }}
</span>
</template>
<template v-else>
{{ formatDecimal(+item.lowPrice) }}
</template>
</template>
</template>
</div>
</div>
<div class="tag_wrap" v-if="item.sku_name">
<div class="tag" v-for="item in item.sku_name.split(',')">
{{ item }}
</div>
</div>
<div class="gift_wrap" v-if="item.is_gift">
<div class="name">
<span v-if="item.is_gift">[赠送]</span>
</div>
<div class="n"></div>
<div class="p">
<span>
-<template v-if="item.is_temporary || +item.discount_sale_amount">
{{ formatDecimal(+item.discount_sale_amount) }}
</template>
<template v-else>{{ formatDecimal(+item.lowPrice) }}</template>
</span>
</div>
</div>
<div class="gift_wrap" v-if="!item.is_temporary && !item.is_gift && +item.discount_sale_amount">
<div class="name">
<span>[改价优惠]</span>
</div>
<div class="n"></div>
<div class="p">
<span>
-{{ formatDecimal(item.lowPrice - item.discount_sale_amount) }}
</span>
</div>
</div>
<div class="gift_wrap" v-if="+item.pack_number">
<div class="name">
<span>[打包费]</span>
</div>
<div class="n"></div>
<div class="p">
<span>
+{{ formatDecimal(item.pack_number * item.packFee) }}
</span>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted } from 'vue'
import { formatDecimal } from '@/utils/index.js'
const props = defineProps({
list: {
type: [Array],
default: []
}
})
onMounted(() => {
console.log('SettleItem===', props.list);
})
</script>
<style scoped lang="scss">
.item {
padding: var(--el-font-size-base) 0;
border-bottom: 1px solid #ececec;
.name {
flex: 1.5;
}
.n {
width: 30px;
color: #555;
}
.p {
flex: 1;
color: #555;
display: flex;
justify-content: flex-end;
}
.t_line {
text-decoration: line-through;
color: #999;
margin-right: 4px;
}
.top {
display: flex;
padding-bottom: 6px;
}
.gift_wrap {
display: flex;
color: #999;
font-size: 16px;
.p {
color: var(--el-color-danger);
}
}
.tag_wrap {
display: flex;
flex-wrap: wrap;
.tag {
padding: 2px 6px;
background-color: var(--el-color-danger);
color: #fff;
margin-right: 10px;
margin-bottom: 10px;
}
}
.packge_Wrap {
display: flex;
align-items: center;
.icon_item {
$size: 40px;
width: $size;
height: $size;
background-color: #e2e2e2;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
}
}
</style>

View File

@ -42,6 +42,7 @@
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { shopTable } from '@/api/account.js'
import { queryShopTable } from '@/api/table.js'
import { orderSwitcht } from '@/api/product.js'
import { useUser } from "@/store/user.js"
@ -109,14 +110,13 @@ const tableList = ref([])
//
async function queryShopTableAjax() {
try {
const res = await queryShopTable({
shopId: store.userInfo.shopId,
areaId: '',
status: '',
page: 1,
pageSize: 100
const res = await shopTable({
areaId: store.userInfo.shopId,
tableCode: '',
status: 'using',
name: ''
})
tableList.value = res.list.filter(item => item.qrcode != props.data[0].info[0].tableId && item.status == 'using')
tableList.value = res.records
} catch (error) {
console.log(error)
}

View File

@ -14,8 +14,7 @@
</el-icon>
<el-text class="t">选择会员</el-text>
</div>
<div class="select_user" @click="quickCashHandle"
v-if="!global.orderMemberInfo.telephone && !global.tableInfo.id">
<div class="select_user" @click="quickCashHandle">
<div class="left">
<el-icon class="icon" style="color: var(--el-color-warning);">
<WalletFilled />
@ -23,7 +22,7 @@
<el-text class="t">快捷收银</el-text>
</div>
</div>
<div class="select_user" v-else @click="clearMember">
<!-- <div class="select_user">
<div class="left">
<el-icon class="icon">
<UserFilled />
@ -41,7 +40,7 @@
<el-icon class="arrow">
<Close />
</el-icon>
</div>
</div> -->
</div>
<div class="shop_operation">
<div class="shop_list">
@ -56,125 +55,19 @@
</el-icon>
</div>
</div>
<div class="item" :class="{ active: item.active }" v-for="(item, index) in goodsStore.cartList" :key="item.id"
@click="selectCartItemHandle(index)">
<div class="name_wrap">
<span>{{ item.product_name }}</span>
<template v-if="item.is_gift">
<div class="price">
<span class="dis" v-if="item.is_temporary">
{{ formatDecimal(+item.discount_sale_amount, 2, true) }}
</span>
<span class="dis" v-else>
{{ formatDecimal(+item.lowPrice, 2, true) }}
</span>
<span v-if="item.discount_sale_amount">
0.00
</span>
<div>
<CartItem :item="item" :index="index" v-for="(item, index) in goodsStore.cartList" :key="item.id" />
</div>
</template>
<template v-else>
<div class="price" v-if="item.is_temporary">
<span>
{{ formatDecimal(+item.discount_sale_amount, 2, true) }}
</span>
<div class="empty" v-if="!goodsStore.cartList.length">
<el-empty description="请选择商品" />
</div>
<div class="price" v-else>
<template v-if="+item.discount_sale_amount">
<span class="dis">
{{ formatDecimal(item.lowPrice, 2, true) }}
</span>
<span>
{{ formatDecimal(+item.discount_sale_amount, 2, true) }}
</span>
</template>
<span v-else>
{{ formatDecimal(+item.lowPrice, 2, true) }}
</span>
<div class="order_list_wrap">
<div class="order_title" v-if="goodsStore.orderList.length">历史下单</div>
<div class="order_list_item" v-for="(arr, index) in goodsStore.orderList" :key="index">
<div class="order_num">{{ `${arr.orderNum}次下单` }}</div>
<CartItem type="order" :border="false" :item="item" :index="index" :i="i" :key="item.id"
v-for="(item, i) in arr.goods" />
</div>
</template>
</div>
<div class="sku_list" v-if="item.sku_name">
<div class="tag" v-for="item in item.sku_name.split(',')">
{{ item }}
</div>
</div>
<div class="grooup_wrap" v-if="item.goods_type == 'package'">
{{ item.group_type == 0 ? '固定套餐:' : '自选套餐:' }}
<span>{{ item.group_text }}</span>
</div>
<div class="num">
<div class="left">
<div class="icon_item zen" v-if="item.is_gift">
<span class="t"></span>
</div>
<div class="icon_item bao" v-if="item.is_pack">
<span class="t"></span>
</div>
<!-- <div class="icon_item tui" v-if="item.status == 'return'">
<span class="t">退</span>
</div> -->
<div class="icon_item lin" v-if="item.is_temporary == 1">
<span class="t"></span>
</div>
<div class="icon_item zhe" v-if="item.discount_sale_amount > 0 && !item.is_temporary">
<span class="t"></span>
</div>
<div class="icon_item chu" v-if="item.is_print == 0">
<span class="t">免厨打印</span>
</div>
</div>
<el-text class="t">x{{ formatDecimal(+item.number, 2, true) }}</el-text>
</div>
</div>
<template v-for="(arr, index) in goodsStore.orderList" :key="index">
<el-divider v-if="arr.placeNum">{{ `${arr.placeNum}次下单` }}</el-divider>
<div class="item" :class="{ active: item.active }" :key="item.id" v-for="(item, i) in arr.info"
@click="selectCartItemHandle(item, index, i)">
<div class="name_wrap">
<span>{{ item.name }}</span>
<div class="price">
<span :class="{ dis: item.discountSaleAmount }">{{ item.salePrice }}</span>
<span v-if="item.discountSaleAmount">
{{ formatDecimal(item.salePrice - item.discountSaleAmount, 2, true) }}</span>
</div>
</div>
<div class="sku_list" v-if="item.skuName">
<div class="tag" v-for="item in item.skuName.split(',')">
{{ item }}
</div>
</div>
<div class="grooup_wrap" v-if="item.proGroupInfo">
{{ item.groupType == 0 ? '固定套餐:' : '自选套餐:' }}
<span>{{JSON.parse(item.proGroupInfo).map(item => item.proName).join('、')}}</span>
</div>
<div class="num">
<div class="left">
<div class="icon_item zen" v-if="item.is_gift" @click="giftPackHandle('isGift', item)">
<span class="t"></span>
</div>
<div class="icon_item bao" v-if="item.is_pack" @click="giftPackHandle('isPack', item)">
<span class="t"></span>
</div>
<div class="icon_item tui" v-if="item.status == 'return'">
<span class="t">退</span>
</div>
<div class="icon_item lin" v-if="item.isTemporary == 1">
<span class="t"></span>
</div>
<div class="icon_item zhe" v-if="item.discountSaleAmount">
<span class="t"></span>
</div>
<div class="icon_item chu" v-if="item.isPrint == 0">
<span class="t">免厨打印</span>
</div>
</div>
<el-text class="t">X{{ formatDecimal(item.number, 2, true) }}</el-text>
</div>
</div>
</template>
<div class="empty">
<el-empty description="请选择商品" v-if="!goodsStore.cartList.length" />
</div>
</div>
<!-- 购物车操作栏 -->
@ -183,48 +76,44 @@
</div>
<div class="footer">
<div class="top">
<div class="left" @click="allSelectedHandle" v-if="store.shopInfo.eatModel == 'take-out'">
<div class="num-wrap">
<div class="num_wrap_top">
<div class="left" @click="allSelectedHandle" v-if="store.shopInfo.eatModel.includes('take-out')">
<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>
<el-text class="t">外带</el-text>
</div>
<div class="left" v-else></div>
<div class="num-wrap">
<div class="num_wrap_top">
<div class="right">
<el-text>
{{ goodsStore.cartInfo.total }}
</el-text>{{ formatDecimal(goodsStore.cartInfo.totalAmount || 0) }}
</div>
</div>
<div class="num_wrap_btm">
<span v-if="goodsStore.cartInfo.gifNumberAmount">赠送{{ formatDecimal(goodsStore.cartInfo.gifNumberAmount
|| 0, 2, true)
}}</span>
<span v-if="goodsStore.cartInfo.gifNumberAmount && goodsStore.cartInfo.saleNumberAmount"></span>
<span v-if="goodsStore.cartInfo.saleNumberAmount">改价优惠{{
formatDecimal(goodsStore.cartInfo.saleNumberAmount
|| 0, 2, true)
}}</span>
{{ goodsStore.cartInfo.discountInfo }}
</div>
</div>
</div>
<div class="btm">
<el-button icon="Edit" @click="remarkRef.show()"></el-button>
<div class="button">
<div class="btn" v-if="store.shopInfo.registerType == 'restaurant'">
<el-button type="primary" style="width: 100%;" :disabled="!cartList.length" v-loading="createOrderLoading"
@click="createOrderHandle(0)">
<div class="btn" v-if="store.shopInfo.registerType == 'after'">
<el-button type="primary" style="width: 100%;" :disabled="!goodsStore.cartList.length"
v-loading="createOrderLoading" @click="createOrderHandle(0)">
<template v-if="!createOrderLoading">
仅下单</template>
<template v-else>下单中...</template>
</el-button>
</div>
<div class="btn" v-if="store.shopInfo.registerType != 'restaurant' || goodsStore.cartList.length">
<el-button type="primary" style="width: 100%;" :disabled="!goodsStore.cartList.length"
v-loading="createOrderLoading" @click="createOrderHandle(1)">
<div class="btn">
<el-button type="primary" style="width: 100%;"
:disabled="!goodsStore.cartList.length && !goodsStore.orderList.length" v-loading="createOrderLoading"
@click="createOrderHandle(1)">
<template v-if="!createOrderLoading">
去结算</template>
<template v-else>下单中...</template>
@ -257,8 +146,6 @@
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
<!-- 检查版本升级 -->
<updateDialog />
<!-- 合并/转桌 -->
<tableMerging ref="tableMergingRef" @success="" />
<!-- 选择会员 -->
<SelectVipUser ref="SelectVipUserRef" />
</template>
@ -282,6 +169,7 @@ 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 tableMerging from '@/views/home/components/tableMerging.vue'
import CartItem from './components/cartItem.vue'
import useStorage from '@/utils/useStorage'
import { formatDecimal } from '@/utils/index.js'
import { useGoods } from '@/store/goods.js'
@ -294,8 +182,6 @@ import goods from "@/views/home/components/goods.vue";
import member from "@/views/member/index.vue";
import { ElMessage } from "element-plus";
import TableMerging from "./components/tableMerging.vue";
const SelectVipUserRef = ref(null)
@ -340,27 +226,42 @@ async function quickCashHandle() {
}
}
//
// t=0 t=1
async function createOrderHandle(t = 0) {
try {
createOrderLoading.value = true;
const res = await createOrder({
orderId: goodsStore.orderList.length ? goodsStore.orderList[0].id : '', // id
if (goodsStore.cartList.length) {
const data = {
orderId: goodsStore.orderListInfo.id || '', // id
shopId: store.shopInfo.id, // id
seatNum: goodsStore.tableInfo.num || 0, //
packFee: 0, //
originAmount: formatDecimal(goodsStore.cartInfo.totalAmount, 2, true), // +
seatAmount: goodsStore.cartInfo.tableFee, //
packFee: goodsStore.cartInfo.packFee, //
originAmount: formatDecimal(+goodsStore.cartInfo.totalAmount, 2, true), // +
tableCode: goodsStore.cartList[0].table_code, //
dineMode: store.shopInfo.eatModel, //
dineMode: allSelected.value ? store.shopInfo.eatModel.split(',')[1] : store.shopInfo.eatModel.split(',')[0], //
remark: remark.value, //
placeNumplaceNum: goodsStore.orderList.length, //
placeNum: (goodsStore.orderListInfo.placeNum || 0) + 1, //
waitCall: 0,//
userId: '', // id
vipPrice: 0, //
})
}
goodsStore.orderInfo = res
settleAccountRef.value.show()
createOrderLoading.value = true;
const res = await createOrder(data)
//
goodsStore.orderListInfo = res
if (t == 1) {
settleAccountRef.value.show(t)
} else {
goodsStore.historyOrderAjax(res.tableCode)
}
//
goodsStore.clearCart()
} else {
settleAccountRef.value.show(t)
}
} catch (error) {
console.log(error);
}
@ -400,13 +301,7 @@ function giftPackHandle(key, item) {
//
const allSelectedHandle = async () => {
if (!cartList.value.length) return;
allSelected.value = !allSelected.value;
await packall({
shopId: store.userInfo.shopId,
status: allSelected.value,
});
//
};
//
@ -428,6 +323,29 @@ function showTableMerging() {
</script>
<style scoped lang="scss">
.order_list_wrap {
.order_list_item {
&:not(:last-child) {
border-bottom: 1px solid #ececec;
}
}
.order_title {
display: flex;
justify-content: center;
font-size: 14px;
color: #999;
padding: 10px 0;
border-top: 1px solid #ececec;
}
.order_num {
font-size: 12px;
color: #999;
padding: var(--el-font-size-base) var(--el-font-size-base) 0;
}
}
.cart_wrap {
flex: 1.5;
height: 100%;
@ -460,6 +378,7 @@ function showTableMerging() {
}
}
.number {
flex: 1;
display: flex;
@ -690,6 +609,17 @@ function showTableMerging() {
padding: 10px var(--el-font-size-base);
border-top: 1px solid #ececec;
.num-wrap {
height: 40px;
display: flex;
flex-direction: column;
.num_wrap_top {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
.left {
display: flex;
align-items: center;
@ -720,16 +650,6 @@ function showTableMerging() {
margin-left: 6px;
}
}
.num-wrap {
height: 40px;
display: flex;
flex-direction: column;
.num_wrap_top {
flex: 1;
display: flex;
justify-content: flex-end;
}
.num_wrap_btm {
@ -741,11 +661,6 @@ function showTableMerging() {
}
}
.top {
display: flex;
justify-content: space-between;
}
.btm {
$h: 70px;
display: flex;

View File

@ -1,12 +1,20 @@
<template>
<el-date-picker v-model="dateVlaue" type="daterange" :editable="false" :shortcuts="shortcuts" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" :clearable="false" @change="dateConfirm" />
start-placeholder="开始时间" end-placeholder="结束时间" :clearable="false" :style="{ width: `${props.width}px` }"
@change="dateConfirm" />
</template>
<script setup>
import { onMounted, ref } from 'vue'
import { ref } from 'vue'
import { dayjs } from 'element-plus'
const props = defineProps({
width: {
type: [String, Number],
default: 200
}
})
const emits = defineEmits(['success'])
const shortcuts = [
@ -56,7 +64,7 @@ const shortcuts = [
},
]
const dateVlaue = ref([dayjs(), dayjs()])
const dateVlaue = ref([])
const format = ["YYYY-MM-DD 00:00:00", "YYYY-MM-DD 23:59:59"];
//
@ -68,11 +76,20 @@ function dateConfirm(value) {
])
}
onMounted(() => {
//
emits('success', [
dayjs(dateVlaue[0]).format(format[0]),
dayjs(dateVlaue[1]).format(format[1]),
])
//
function reset() {
dateVlaue.value = []
}
defineExpose({
reset
})
// onMounted(() => {
// //
// emits('success', [
// dayjs(dateVlaue[0]).format(format[0]),
// dayjs(dateVlaue[1]).format(format[1]),
// ])
// })
</script>

View File

@ -0,0 +1,372 @@
<template>
<el-drawer v-model="isShow" direction="rtl" size="60%">
<template #header>
<h4>订单号{{ item.orderNo }}</h4>
</template>
<template #default>
<div class="order_info">
<!-- <div class="row"><span>订单类型</span>{{ filterLable('orderType', item.orderType) }}</div>
<div class="row"><span>平台类型</span>{{ filterLable('platformType', item.platformType) }}</div>
<div class="row"><span>用餐模式</span>{{ filterLable('dineMode', item.dineMode) }}</div>
<div class="row"><span>订单备注</span>{{ item.remark }}</div> -->
<!-- <div class="row"><span>支付类型</span>{{ filterLable('payType', item.payType) }}</div>
<div class="row"><span>支付单号</span>{{ item.payOrderNo }}</div>
<div class="row"><span>支付金额</span>{{ item.payAmount }}</div>
<div class="row"><span>支付时间</span>{{ item.paidTime }}</div>
<div class="row"><span>订单金额含折扣</span>{{ item.orderAmount }}</div>
<div class="row"><span>订单原金额不含折扣</span>{{ item.originAmount }}</div> -->
</div>
<div class="table">
<div class="tab_head">
<el-radio-group v-model="refundType" @change="refundTypeChange">
<el-radio-button label="整单退" :value="1" />
<el-radio-button label="部分退" :value="2" />
<el-radio-button label="自定义" :value="3" />
</el-radio-group>
<div class="amount">
<el-input v-model="customAmount" v-if="refundType == 3" style="width: 250px;"
placeholder="请输入退款金额" @input="inputChange">
<template #prepend></template>
</el-input>
<template v-else>
退款金额{{ formatDecimal(refundType == 1 ? item.originAmount : amount) }}
</template>
</div>
</div>
<el-table ref="tableRef" :data="item.goods" brder stripe @selection-change="tabSelectChange">
<el-table-column type="selection" width="35" :selectable="selectable"></el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
<div class="goods_info">
<el-image :src="scope.row.productImg" style="width: 50px;height: 50px;"></el-image>
<div class="info">
<div class="name">
<span>{{ scope.row.productName }}</span>
</div>
<div class="sku" v-if="scope.row.skuName">{{ scope.row.skuName }}</div>
<div class="sku">{{ formatDecimal(+scope.row.price) }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="订单数量" prop="num" width="100"></el-table-column>
<el-table-column label="支付金额" width="100">
<template v-slot="scope">
{{ formatDecimal(+scope.row.payAmount) }}
</template>
</el-table-column>
<el-table-column label="退款数量" width="170">
<template v-slot="scope">
<el-input-number v-model="scope.row.refundNum" :min="1" :max="+scope.row.num"
style="width: 130px;" @change="numberChange">
</el-input-number>
</template>
</el-table-column>
</el-table>
<div class="ipt">
<el-input type="textarea" v-model="remark" placeholder="请输入退单原因" />
</div>
<div class="remark_tag">
<div class="item" v-for="(item, index) in remarkTagList" :key="index" @click="remark = item">
{{ item }}
</div>
</div>
</div>
</template>
<template #footer>
<div class="drawer_footer">
<div class="btn">
<el-button style="width: 100%;" @click="refundHandle(true)">手动退款</el-button>
</div>
<div class="btn">
<el-button type="primary" style="width: 100%;" @click="refundHandle()">原路退回</el-button>
</div>
</div>
</template>
</el-drawer>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useGlobal } from '@/store/global.js'
import { formatDecimal, inputFilterFloat } from "@/utils/index.js";
import { refundOrder } from '@/api/order.js'
import { ElNotification } from 'element-plus'
const emits = defineEmits(['success'])
const globalStore = useGlobal()
const isShow = ref(false)
const item = ref({})
const tableRef = ref(null)
const modify = ref(false)
const amount = ref(0)
const customAmount = ref('')
const refundType = ref(1)
const remark = ref('')
const remarkTagList = ref([
'顾客取消',
'等待时间长',
'支付错误',
'商品不满意',
'服务态度不满意'
])
// 退
async function refundHandle(cash = false) {
try {
let rows = tableRef.value.getSelectionRows()
if (refundType.value == 1) {
tableRef.value.clearSelection()
tableRef.value.toggleAllSelection()
} else if (refundType.value == 2) {
if (!rows.length) {
ElNotification({
title: '错误',
message: '请选择退款商品',
type: 'error',
})
return
}
} else if (refundType.value == 3) {
if (!customAmount.value) {
ElNotification({
title: '错误',
message: '请请输入退款金额',
type: 'error',
})
return
}
}
let refundDetails = []
if (refundType.value != 1) {
refundDetails = tableRef.value.getSelectionRows().map(val => {
return {
id: item.value.id,
returnAmount: val.payAmount,
num: val.refundNum
}
})
}
let refundAmount = ''
switch (refundType.value) {
case 1:
refundAmount = item.value.orderAmount
break;
case 2:
refundAmount = amount.value
break;
case 3:
refundAmount = customAmount.value
break;
default:
break;
}
let data = {
orderId: item.value.id,
refundAmount: refundAmount,
modify: modify.value,
cash: cash,
refundReason: remark.value,
refundDetails: refundDetails
};
// console.log(data);
// return
await refundOrder(data)
ElNotification({
title: '提示',
message: '退款成功',
type: 'success',
})
isShow.value = false
emits('success')
} catch (error) {
console.log(error);
}
}
//
function numberChange() {
let rows = tableRef.value.getSelectionRows()
tabSelectChange(rows)
}
// 退
function tabSelectChange(val) {
amount.value = 0
val.map(item => {
amount.value += item.refundNum * item.price
})
}
//
const selectable = (row, index) => {
return refundType.value != 1;
};
//
function resetDrawer() {
modify.value = false
amount.value = 0
customAmount.value = ''
refundType.value = 1
remark.value = ''
}
function show(row) {
isShow.value = true
item.value = { ...row }
item.value.goods.map(item => {
item.refundNum = item.num
})
resetDrawer()
setTimeout(() => {
tableRef.value.clearSelection()
refundTypeChange(1)
}, 100);
}
//
function filterLable(key, type) {
let item = globalStore[key].find(item => item.type == type)
if (item && item.type) {
return item.label
} else {
return type
}
}
// 退
function refundTypeChange(val) {
switch (val) {
case 1:
modify.value = false
// tableRef.value.toggleAllSelection()
//
item.value.goods.forEach((row) => {
tableRef.value.toggleRowSelection(row, true);
});
break;
case 2:
modify.value = false
tableRef.value.clearSelection()
break;
case 3:
modify.value = true
break;
default:
break;
}
}
// 退
function inputChange(n) {
setTimeout(() => {
if (n > item.value.payAmount - item.value.refundAmount) {
customAmount.value = formatDecimal(item.value.payAmount - item.value.refundAmount, 2, true)
} else {
customAmount.value = inputFilterFloat(n)
}
}, 100)
}
defineExpose({
show
})
// onMounted(() => {
// setTimeout(() => {
// refundTypeChange(1)
// }, 100)
// })
</script>
<style scoped lang="scss">
.drawer_footer {
display: flex;
gap: var(--el-font-size-base);
.btn {
flex: 1;
}
}
.order_info {
.row {
margin-bottom: 4px;
span {
color: #555;
}
}
}
.table {
padding: var(--el-font-size-base) 0;
.ipt {
padding: var(--el-font-size-base) 0;
}
.tab_head {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: var(--el-font-size-base);
.amount {
color: var(--el-color-danger);
font-weight: bold;
}
}
.remark_tag {
display: flex;
flex-wrap: wrap;
gap: 10px;
.item {
padding: 6px 12px;
border: 1px solid #ddd;
background-color: #fff;
border-radius: 4px;
color: #555;
}
}
}
.goods_info {
display: flex;
align-items: center;
.info {
flex: 1;
display: flex;
flex-direction: column;
padding-left: 6px;
.name {
display: flex;
justify-content: space-between;
.n {
color: #999;
}
}
.sku {
color: #999;
font-size: 14px;
}
}
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -244,7 +244,7 @@ onMounted(() => {
}
.overflow_y {
height: calc(100vh - 225px);
height: calc(100vh - 160px);
overflow-y: auto;
}