代客下单修改,登录页面修改,部分页面调整,请求封装调整

This commit is contained in:
2025-11-27 18:02:28 +08:00
parent f9cc02e93f
commit 3bb09ef0b1
45 changed files with 4934 additions and 1054 deletions

View File

@@ -188,7 +188,7 @@ async function getTable() {
// let state=status.list[status.active].key
// state=state?(state=='all'?'':state):''
const areaId = area.list[area.defaultCateIndex].id || "";
let { data } = await $table.get({
let data = await $table.get({
...query,
areaId,
name: searchValue.value,
@@ -203,13 +203,11 @@ async function getTable() {
tables.originList = data.records;
}
async function getArea() {
const { data } = await $tableArea.get({
const data = await $tableArea.get({
page: 0,
size: 300,
});
data.records.unshift({
name: "全部",
});
area.list = data.records.map((v) => {
return {
...v,

View File

@@ -116,7 +116,7 @@
const {
records,
totalRow
}=res.data
}=res
hasAjax.value = true
list.length = records.length
for (let i in records) {

View File

@@ -611,8 +611,8 @@ async function getDiscountActivity() {
let res = await discountActivity({
shopId: uni.getStorageSync("shopId"),
});
if (res.code == 200) {
fullReductionActivities.value = res.data?[res.data]:[];
if (res) {
fullReductionActivities.value = res?[res]:[];
}
}
const websocketUtil = inject("websocketUtil"); // 注入 WebSocket 工具类实例
@@ -620,7 +620,7 @@ const websocketUtil = inject("websocketUtil"); // 注入 WebSocket 工具类实
const limitTimeDiscountRes = ref(null);
async function getLimit() {
const res = await limitTimeDiscountApi.limitTimeDiscount();
limitTimeDiscountRes.value = res.data;
limitTimeDiscountRes.value = res;
if (pageData.table.tableCode) {
pageData.limitTimeDiscount = limitTimeDiscountRes.value;
@@ -695,7 +695,7 @@ async function getHistoryOrderDetail(tableCode) {
let res = await getHistoryOrder({
tableCode: tableCode,
});
pageData.orderInfo = res.data;
pageData.orderInfo = res;
}
//餐位费
@@ -734,7 +734,7 @@ async function init() {
});
// 获取商品列表
let res = await getProductList({}, "product", false);
$goods = res.data;
$goods = res;
// console.log("商品列表===",$goods)
getTableInfo(pageData.table);
}
@@ -896,16 +896,16 @@ async function getTbShopInfo() {
const res = await getShopInfo({
id: uni.getStorageSync("shopId"),
});
pageData.shopInfo = res.data;
seatFeeConfig.pricePerPerson = res.data.tableFee || 0;
uni.setStorageSync("shopInfo", res.data);
pageData.shopInfo = res;
seatFeeConfig.pricePerPerson = res.tableFee || 0;
uni.setStorageSync("shopInfo", res);
}
/**
* 获取桌台信息
*/
async function getTableInfo(opt) {
const { data: res } = await getShopTableDetail({
const res = await getShopTableDetail({
id: opt.id,
tableCode: opt.tableCode,
});
@@ -939,7 +939,7 @@ function watchChooseuser() {
const res = await shopUserDetail({
userId: data.userId,
});
pageData.user = res.data;
pageData.user = res;
} else {
pageData.user = data;
}
@@ -1267,11 +1267,11 @@ async function createAnOrder() {
if (pageData.orderInfo && pageData.shopInfo.registerType != "before") {
par.orderId = pageData.orderInfo.id;
}
let res = {data:{id:''}};
let res = {id:''}
if (goods.list.length) {
res = await createOrder(par);
console.log(res, "创建订单");
if (res.code != 200) {
if (!res) {
uni.showToast({
title: res.msg || "创建订单失败!",
icon: "none",
@@ -1299,14 +1299,14 @@ async function createAnOrder() {
return go.to(
"PAGES_ORDER_PAY",
{
orderId: res.data.id,
orderId: res.id,
isNowPay: true,
dinnerType: pageData.eatTypes.active,
},
"redirect"
);
} else {
if(!res.data.id&&pageData.orderInfo.id){
if(!res.id&&pageData.orderInfo.id){
return go.to(
"PAGES_ORDER_PAY",
{
@@ -1322,7 +1322,7 @@ async function createAnOrder() {
go.to(
"PAGES_ORDER_DETAIL",
{
id: res.data.id||pageData.orderInfo.id,
id: res.id||pageData.orderInfo.id,
dinnerType: pageData.eatTypes.active,
},
"redirect"

View File

@@ -11,11 +11,13 @@
<view>
<up-icon
name="shopping-cart-fill"
size="20"
color="rgb(102,102,102)"
size="50rpx"
color="#666"
></up-icon>
</view>
<view class="u-m-l-10"> 已选菜品({{ goodsNumber }}) </view>
<view class="u-m-l-10 font-700 color-333 u-font-32">
已选菜品({{ goodsNumber }})
</view>
</view>
<view
class="u-flex"
@@ -30,13 +32,6 @@
</view>
<view class="u-m-l-10"> 清空点餐 </view>
</view>
<view class="u-flex">
<view>合计:</view>
<view class="u-m-l-10 color-red font-bold allPrice">{{
allPrice
}}</view>
<view class=""></view>
</view>
</view>
<scroll-view
scroll-y="true"
@@ -54,10 +49,10 @@
{{ index + 1 }}
</view>
<view class="">
<view>
<text>{{ item.name }}</text>
<text class="limit" v-if="item.is_time_discount"></text>
</view>
<view>
<text>{{ item.name }}</text>
<text class="limit" v-if="item.is_time_discount"></text>
</view>
<view class="u-m-t-10 u-font-24 color-666">{{
item.specInfo || ""
}}</view>
@@ -182,7 +177,9 @@
v-if="v.is_time_discount || v.isTimeDiscount"
>
<view class="font-bold red u-m-r-32"
>{{ returnLimitPrice({...v,number:v.num,salePrice:v.price}) }}</view
>{{
returnLimitPrice({ ...v, number: v.num, salePrice: v.price })
}}</view
>
<view class="u-m-l-30 u-m-r-30 color-333">
X{{ v.num.toFixed(2) }}
@@ -203,18 +200,41 @@
</view>
</view>
</scroll-view>
<view
class="u-row-between bottom u-flex"
class="bottom"
style="position: absolute; left: 0; bottom: 0; background-color: #fff"
>
<view class="u-flex" @click="hideGoods">
<view>
<up-icon name="arrow-left" size="14" color="#333"></up-icon>
</view>
<view class="u-m-l-10"> 返回 </view>
<view class="u-flex u-p-32 border-bottom u-row-right u-font-32">
<view class="color-000">合计</view>
<view class="u-m-l-10 color-red font-bold allPrice"
>{{ allPrice }}</view
>
</view>
<view class="u-flex luodan" @click="toConfimOrder">
<view>落单</view>
<view
class="u-row-between u-flex"
style="padding: 32rpx 52rpx 64rpx 52rpx"
>
<view class="u-flex" @click="hideGoods">
<view>
<up-icon name="arrow-left" size="14" color="#666"></up-icon>
</view>
<view class="u-m-l-20"> 返回 </view>
</view>
<view class="u-flex">
<text class="color-333 u-m-r-20"
>上菜方式{{ returnServingStyleName(subStatus) }}</text
>
<up-icon
name="edit-pen-fill"
color="#666"
size="36rpx"
@click="servingStyleModalShow = true"
></up-icon>
</view>
<view class="u-flex luodan" @click="toConfimOrder">
<view>落单</view>
</view>
</view>
</view>
</view>
@@ -263,10 +283,41 @@
:ref="setModel"
name="remark"
></one-remark>
<ServingStyleModal
v-model="servingStyleModalShow"
@confirm="servingStyleConfirm"
></ServingStyleModal>
<!-- 下单确认 -->
<Modal
v-model="orderConfirmModalShow"
title="下单确认"
confirmText="确定"
@confirm="workerConfirm"
>
<view class="u-p-40 u-font-32 color-333">
<view class="u-flex">
<text class="font-bold">员工名称</text>
<text class="u-m-l-52 color-666">{{
accountStore.shopStaff.name
}}</text>
</view>
<view class="u-flex u-m-t-44">
<text class="font-bold u-m-r-52">员工账号</text>
<up-input
v-model="form.workerAccount"
placeholder="请输入员工账号"
></up-input>
</view>
</view>
</Modal>
</view>
</template>
<script setup>
import Modal from "@/components/my-components/modal.vue";
import ServingStyleModal from "/pagesCreateOrder/index/components/serving-style.modal.vue";
import go from "@/commons/utils/go.js";
import infoBox from "@/commons/utils/infoBox.js";
import oneRemark from "/pagesCreateOrder/confirm-order/components/remark";
@@ -280,9 +331,25 @@ import * as Api from "@/http/yskApi/Instead.js";
import { computed, ref, onMounted, reactive, watch, inject } from "vue";
import BigNumber from "bignumber.js";
import { limitTimeDiscount } from "../../../http/yskApi/limitTimeDiscount";
import { number } from "uview-plus/libs/function/test";
import { servingStyles, returnServingStyleName } from "@/data/index.js";
import { createOrder, getHistoryOrder } from "@/http/api/order.js";
const form = reactive({
workerAccount: "",
});
//下单确认
const orderConfirmModalShow = ref(false);
//上菜方式
const subStatus = ref(servingStyles[0].value);
const servingStyleModalShow = ref(false);
function servingStyleConfirm(e) {
subStatus.value = e;
servingStyleModalShow.value = false;
}
const yskUtils = inject("yskUtils");
const accountStore = inject("accountStore");
const shopInfo = uni.getStorageSync("shopInfo");
let shopList = ref();
@@ -341,6 +408,12 @@ const props = defineProps({
type: [String, Number],
default: "",
},
orderInfo: {
type: Object,
default: () => {
return {};
},
},
});
function returnLimitPrice(data) {
const price = yskUtils.limitUtils.returnPrice({
@@ -350,12 +423,12 @@ function returnLimitPrice(data) {
shopUserInfo: null,
idKey: "product_id",
});
return price
return price;
}
function returnLimitTotalPrice(data) {
console.log('returnLimitTotalPrice',data)
const price = yskUtils.limitUtils.returnPrice({
function returnLimitTotalPrice(data) {
console.log("returnLimitTotalPrice", data);
const price = yskUtils.limitUtils.returnPrice({
goods: data,
shopInfo: shopInfo,
limitTimeDiscountRes: props.limitTimeDiscount,
@@ -370,6 +443,7 @@ const edmits = defineEmits([
"updateNumber",
"updateSafeBottom",
"updateCart",
"updateCartRemark",
]);
const modal = reactive({
key: "",
@@ -380,15 +454,23 @@ const modal = reactive({
let allHistoryOrder = ref([]);
const allPrice = computed(() => {
let cartPrice = props.data.reduce((prve, cur) => {
let price = (cur.is_time_discount? returnLimitPrice(cur) : cur.lowPrice) * cur.number
let price =
(cur.is_time_discount ? returnLimitPrice(cur) : cur.lowPrice) *
cur.number;
return BigNumber(prve).plus(price);
}, 0);
let historyOrderPrice = allHistoryOrder.value.reduce((prve, cur) => {
let price = (cur.isTimeDiscount? returnLimitPrice({...cur,salePrice:cur.price}) : cur.price)* (cur.num - cur.returnNum)
return BigNumber(prve).plus(price);
let price =
(cur.isTimeDiscount
? returnLimitPrice({ ...cur, salePrice: cur.price })
: cur.price) *
(cur.num - cur.returnNum);
return BigNumber(prve).plus(price);
}, 0);
return BigNumber(cartPrice).plus(historyOrderPrice).decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber();
return BigNumber(cartPrice)
.plus(historyOrderPrice)
.decimalPlaces(2, BigNumber.ROUND_UP)
.toNumber();
});
const models = new Map();
const modelData = reactive({
@@ -432,16 +514,13 @@ function confirmModelConfirm() {
//单品备注确认
async function goodsOneRemarkConfirm(e) {
const cart = props.data[modelData.selIndex];
await Api.$updateCart({
cartId: cart.id,
productId: cart.productId,
skuId: cart.skuId,
tableId: props.table.tableId,
note: e.remark,
num: cart.number, // 0会删除此商品
edmits("updateCartRemark", {
remark: e.remark,
index: modelData.selIndex,
goods: cart,
});
edmits("updateCart");
}
// 清空购物车
function setModalShow(key = "show", show = true, type = "", title = "") {
if (title) {
@@ -496,11 +575,45 @@ function getshopsInfo() {
// const findCategory = layoutData.category.list.find(v => v.shopId == goods.shop_id)
}
function toConfimOrder() {
if (props.data.length <= 0&& props.historyOrder.length<=0) {
return infoBox.showToast("还没有选择商品");
async function workerConfirm() {
//debugger
// form.workerAccount=18888888888
if (!form.workerAccount) {
return infoBox.showToast("请输入服务员账号");
}
if (form.workerAccount != accountStore.staffUserName) {
return infoBox.showToast("请输入当前登录员工账号");
}
let newOldRes = null;
if (props.data.length >= 1) {
newOldRes = await createOrder({
shopId: uni.getStorageSync("shopId"), //店铺Id
userId: "", //用户Id
tableCode: props.table.tableCode, //台桌编码
dineMode: "dine-in", //用餐模式 堂食 dine-in 外带 take-out 外卖 take-away
remark: "", //备注
seatNum: 0, //用餐人数
packFee: 0, //打包费
originAmount: 0, //订单原金额(不包含打包费+餐位费)
placeNum: 1, //当前订单下单次数
waitCall: 0, //是否等叫 0 否 1 等叫
vipPrice: false, //是否使用会员价
limitRate: null,
subStatus: subStatus.value,
});
if (!newOldRes) {
return infoBox.showToast("创建订单失败");
}
}
form.workerAccount = "";
go.to("PAGES_TABLE_ORDER", {
orderId: newOldRes ? newOldRes.id : props.orderInfo.id,
});
orderConfirmModalShow.value = false;
hideGoods();
return;
if (props.table.id) {
const { id, name, maxCapacity, status, type } = props.table;
go.to("PAGES_CONFIRM_ORDER", {
@@ -522,6 +635,12 @@ function toConfimOrder() {
}
hideGoods();
}
function toConfimOrder() {
if (props.data.length <= 0 && props.historyOrder.length <= 0) {
return infoBox.showToast("还没有选择商品");
}
orderConfirmModalShow.value = true;
}
const goodsNumber = computed(() => {
let result = 0;
@@ -638,10 +757,10 @@ $car-top: -16rpx;
.luodan {
background-color: $my-main-color;
padding: 10px 30px;
border-radius: 4px;
padding: 18rpx 33px;
border-radius: 16rpx;
color: #fff;
font-size: 16px;
font-size: 40rpx;
font-weight: bold;
}
@@ -676,7 +795,6 @@ $car-top: -16rpx;
}
.bottom {
padding: 14px 20px;
border-top: 1px solid #eee;
width: 100%;
font-size: 16px;
@@ -783,17 +901,17 @@ $car-top: -16rpx;
color: #999;
text-decoration: line-through;
}
.limit{
background-color: #cc5617;
margin-left: 10rpx;
padding: 2rpx 10rpx;
white-space: nowrap;
text-align: center;
position: absolute;
font-weight: 400;
font-size: 24rpx;
color: #ffffff;
border-radius: 14rpx;
color: #fff;
.limit {
background-color: #cc5617;
margin-left: 10rpx;
padding: 2rpx 10rpx;
white-space: nowrap;
text-align: center;
position: absolute;
font-weight: 400;
font-size: 24rpx;
color: #ffffff;
border-radius: 14rpx;
color: #fff;
}
</style>
</style>

View File

@@ -173,16 +173,16 @@
</template>
</view>
<view class="bg-fff u-p-20 w-full">
<view class="u-flex u-row-between u-font-16">
<view>{{ data.name }}</view>
<view class="u-flex u-row-between ">
<view class="u-font-40">{{ data.name }}</view>
<view class="u-flex" v-if="is_time_discount">
<view class="font-bold u-m-t-16">
<view class="font-bold u-m-t-16 u-font-40">
¥{{ limitPrice }}
</view>
<view class="u-m-t-16 old-price"> ¥{{ data.lowPrice }} </view>
</view>
<view class="font-bold u-m-t-16" v-else> ¥{{ data.lowPrice }} </view>
<view class="font-bold u-m-t-16 u-font-40" v-else> ¥{{ data.lowPrice }} </view>
</view>
</view>
</view>
@@ -290,7 +290,6 @@ const is_time_discount = computed(() => {
null,
"id"
);
console.log("isCanuse", isCanuse,props.data);
return isCanuse;
});
@@ -375,8 +374,8 @@ function emitEvent(emitName) {
<style lang="scss" scoped>
.icon {
width: 60rpx;
height: 60rpx;
width: 94rpx;
height: 94rpx;
}
.icon-btn {
@@ -384,11 +383,12 @@ function emitEvent(emitName) {
}
.btn {
background: #eb4f4f;
border-radius: 100rpx;
background: #FE4F1E;
border-radius: 16rpx;
font-size: 32rpx;
font-weight: bold;
padding: 0 50rpx;
padding: 16rpx 44rpx;
line-height: normal;
color: #fff;
}
@@ -434,17 +434,17 @@ function emitEvent(emitName) {
z-index: 2;
}
.limit-discount {
background-color: #cc5617;
padding: 10rpx 20rpx;
background-color: #FEB41E;
padding: 16rpx 44rpx;
white-space: nowrap;
text-align: center;
position: absolute;
top: 0;
left: 0;
font-weight: 400;
font-size: 28rpx;
font-weight: 700;
font-size: 32rpx;
color: #ffffff;
border-radius: 20rpx 0rpx 20rpx 0rpx;
border-radius: 16rpx 0rpx 16rpx 0rpx;
z-index: 9;
color: #fff;
}

View File

@@ -0,0 +1,125 @@
<template>
<view>
<up-popup :show="show" mode="center">
<view class="popup-content">
<view class="top u-flex u-row-between">
<text class="font-bold u-font-32 color-333">{{ title }}</text>
<up-icon size="18" name="close" @click="show = false"></up-icon>
</view>
<up-line></up-line>
<scroll-view style="max-height: 50vh" :scroll-y="true">
<view class="u-flex servingStyles">
<view
v-for="(item, index) in servingStyles"
:key="index"
@click="servingSel = item.value"
:class="[servingSel == item.value ? 'active' : '']"
class="item tranistion"
>
<text>{{ item.name }}</text>
</view>
</view>
</scroll-view>
<up-line></up-line>
<view class="bottom u-row-right">
<view
class="btn success"
@click="confirm"
:class="[btnShape]"
>{{ confirmText }}</view
>
</view>
</view>
</up-popup>
</view>
</template>
<script setup>
import { servingStyles } from "@/data/index.js";
import { ref } from "vue";
const props = defineProps({
title: {
type: String,
default: "上菜方式",
},
confirmText: {
type: String,
default: "确定",
},
cancelText: {
type: String,
default: "取消",
},
btnShape: {
type: String,
default: "round",
},
});
const servingSel =defineModel("servingSel",{
type: String,
default: servingStyles[0].value,
});
const show = defineModel({
type: Boolean,
default: false,
});
const emits = defineEmits(["close", "confirm"]);
function close() {
show.value = false;
emits("close");
}
function confirm() {
emits("confirm", servingSel.value);
}
</script>
<style lang="scss">
.popup-content {
background: #fff;
width: 640rpx;
border-radius: 18rpx;
}
.top {
padding: 40rpx 48rpx;
}
.bottom {
padding: 48rpx 52rpx;
display: flex;
gap: 50rpx;
.btn {
text-align: center;
padding: 18rpx 60rpx;
font-size: 32rpx;
border: 2rpx solid transparent;
border-radius: 8rpx;
&.success {
background-color: $my-main-color;
color: #fff;
}
&.cancel {
border-color: #d9d9d9;
box-shadow: 0 4rpx 0 0 #00000005;
}
}
}
.servingStyles {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 38rpx;
gap: 26rpx;
.item {
padding: 14rpx 38rpx;
border-radius: 16rpx;
border: 2rpx solid $my-main-color;
color: $my-main-color;
font-size: 28rpx;
&.active {
background-color: $my-main-color;
color: #fff;
}
}
}
</style>

View File

@@ -6,6 +6,14 @@
<template v-else>
<view class="fixed top bg-fff u-flex u-flex-row">
<template v-if="true">
<view
class="u-flex u-font-32 u-p-l-58"
style="padding-right: 100rpx"
@click="uni.navigateBack()"
>
<up-icon name="arrow-left" size="32rpx" color="#333"></up-icon>
<text class="u-m-l-20">返回</text>
</view>
<view class="u-flex-1 u-flex u-flex-row" style="overflow-x: scroll">
<!-- 顶部左侧 -->
<scroll-view
@@ -33,13 +41,13 @@
</scroll-view>
</view>
<!-- 顶部右侧 选择桌台什么的 -->
<view class="search-box u-flex u-col-center color-666">
<view class="search-box u-flex u-col-center color-333 u-font-32">
<!-- <view style="display: flex;align-items: center;">
<view :class="[lvhong?'lvstyle':'hongstyle']">
</view><text style="margin: 0 6px;">状态</text>
</view> -->
<view class="u-flex u-col-center" @click="chooseTable">
<view class="u-flex u-col-center">
<view class="u-flex u-col-center u-m-r-22">
<image
src="/pagesCreateOrder/static/images/icon-table.svg"
mode=""
@@ -51,7 +59,7 @@
<text class="font-bold u-m-r-4 no-wrap">
{{ data.table.name }}
</text>
<view
<!-- <view
class="u-flex"
@click.stop="resetTable"
style="margin-left: 6px"
@@ -62,42 +70,46 @@
bold=""
:size="24"
></up-icon>
</view>
</view> -->
</view>
<text class="no-wrap" v-else>选择桌</text>
<text class="no-wrap" v-else></text>
</view>
</view>
<view
class="u-flex u-col-center"
@click="toOrder"
style="margin-left: 20px"
style="margin-left: 74rpx"
>
<view class="u-flex">
<up-icon name="order" size="24"></up-icon>
<image
src="/static/iconImg/order.svg"
style="width: 40rpx; height: 40rpx"
/>
</view>
<view class="u-m-r-12">已点订单</view>
<view class="u-m-l-22">已点订单</view>
</view>
<view
style="margin-left: 74rpx"
class="u-flex u-col-center"
@click="changePop('search', true)"
>
<view class="u-flex">
<view class="u-flex u-m-r-22">
<up-icon name="search" size="24"></up-icon>
</view>
<view class="">搜索</view>
</view>
<view class="u-flex u-col-center u-m-l-10">
<!-- <view class="u-flex u-col-center u-m-l-10" @click="loginShow"> -->
<view class="u-flex">
<up-icon name="account" size="24"></up-icon>
</view>
<view>{{ data.userInfo.shopName }}</view>
<!-- <view style="color: #aaa;font-size: 12px;">切换</view> -->
<view
class="color-333 u-font-32 font-700"
style="margin-left: 87px"
>{{ accountStore.shopStaff.name }}</view
>
</view>
<view class="u-flex u-col-center u-m-l-10" @click="loginShowOut">
<view class="u-flex u-col-center u-m-l-38" @click="loginShowOut">
<view class="u-flex">
<!-- <up-icon name="account" size="24"></up-icon> -->
</view>
@@ -226,6 +238,7 @@
@updateSafeBottom="updateSafeBottom"
:instance="instance"
@updateCart="getCart"
@updateCartRemark="updateCartRemark"
:sysInfo="sysInfo"
:isCreateOrderToDetail="isCreateOrderToDetail"
@updateNumber="carsNumberChange"
@@ -235,6 +248,7 @@
:data="cars"
:orderInfo="data.orderInfo"
:historyOrder="data.historyOrder"
:tableCode="data.table.tableCode"
@clear="cleaCart"
></my-car>
</view>
@@ -295,7 +309,9 @@
import _ from "lodash";
import * as Api from "@/http/yskApi/Instead.js";
import * as limitTimeDiscountApi from "@/http/yskApi/limitTimeDiscount.js";
import * as padApi from "@/http/yskApi/pad.js";
import {
$table,
$choseTable,
@@ -347,6 +363,13 @@ import { getNowCart } from "@/pagesCreateOrder/util.js";
// import yskUtils from "ysk-utils";
import yskUtils from "@/lib/index";
provide("yskUtils", yskUtils);
import {useAccountStore} from '@/stores/account'
const accountStore = useAccountStore()
provide("accountStore", accountStore);
import {
$productCategory,
$layoutpage,
@@ -450,6 +473,7 @@ const layoutArr = {
};
const tabsEle = reactive({
scrollWidth: 0,
scroViewllLeft: 0,
tabsItems: [],
scrollLeft: 0,
});
@@ -494,7 +518,6 @@ function onMessage() {
data.isGoodsAdd = true;
// 如果是商品库存不足起售数量
if (msg.type == "no_suit_num") {
// cartItem = getNowCart(msg.data, cartArr)
cartControls([], "del");
}
return;
@@ -602,15 +625,15 @@ function delCart(id) {
* 获取订单详情
*/
async function getHistoryOrderDetail() {
if(shopInfo.registerType=='before'){
return
if (shopInfo.registerType == "before") {
return;
}
data.historyOrder = [];
let res = await getHistoryOrder({
tableCode: data.table.tableCode,
});
data.orderInfo = res.data;
if (res.data) {
data.orderInfo = res;
if (res) {
data.historyOrder = Object.entries(data.orderInfo.detailMap).map(
([key, value]) => ({
info: value,
@@ -1018,10 +1041,13 @@ function changeCategorySel(index) {
function setTabsCurrentPosition(position = "center") {
const index = layoutData.category.sel;
console.log(tabsEle.tabsItems[index]);
console.log(tabsEle.scroViewllLeft);
tabsEle.scrollLeft =
tabsEle.tabsItems[index].left -
tabsEle.scrollWidth / 2 +
tabsEle.tabsItems[index].width / 2;
tabsEle.tabsItems[index].width / 2 -
tabsEle.scroViewllLeft;
}
const shopInfo = uni.getStorageSync("shopInfo");
@@ -1042,13 +1068,13 @@ async function getGoodsData(max = 6, isGetPrve = false) {
try {
const res2 = await $productCategory(pageData.id);
layoutData.list[layoutData.current + i * fuhao] = {
...res2.data,
padLayoutCode: res2.data.padLayoutCode
? res2.data.padLayoutCode
: res2.data.productList.length <= 4
? layoutArr[res2.data.productList.length]
...res2,
padLayoutCode: res2.padLayoutCode
? res2.padLayoutCode
: res2.productList.length <= 4
? layoutArr[res2.productList.length]
: "6-grid",
productList: res2.data.productList.map((v) => {
productList: res2.productList.map((v) => {
v.salePrice = v.lowPrice;
const findGoodsInCar = cars.find((cars) => {
return cars.productId == v.id;
@@ -1140,16 +1166,15 @@ async function init() {
if (option.type == "add") {
setTabBar($category, $originGoods, []);
}
// shopInfo.value = uni.getStorageSync('shopInfo').data
let shopInfo = await getShopInfo({
id: uni.getStorageSync("shopInfo").id,
});
uni.setStorageSync("shopInfo", shopInfo.data);
uni.setStorageSync("shopInfo", shopInfo);
// 获取布局
// const getLayoutData = await getLayout({})
// 获取分类数据-获取商品分类
const categoryRes = await getCategory();
$category = categoryRes.data;
$category = categoryRes;
let arr = [];
for (let i = 0; i < $category.length; i++) {
@@ -1166,8 +1191,8 @@ async function init() {
// }
// })
const content =
res.data.records.length > 0
? res.data.records
res.records.length > 0
? res.records
: [
{
productCategoryId: $category[i].id,
@@ -1194,7 +1219,7 @@ async function init() {
});
getLayoutGoodsInit();
// 获取商品数据
const { data: goodsRes } = await getGoods();
const goodsRes = await getGoods();
const goods = goodsRes.filter((v) => {
let isShow = true;
if (v.type != "sku") {
@@ -1218,11 +1243,13 @@ function categoryEleInit() {
rect: true,
}).then((res) => {
tabsEle.scrollWidth = res.width;
tabsEle.scroViewllLeft = res.left;
});
for (let i in layoutData.category.list) {
getElRect("u-tab-item" + i, instance.value, {
rect: true,
}).then((res) => {
console.log(res);
tabsEle.tabsItems[i] = {
width: res.width,
left: res.left,
@@ -1317,9 +1344,11 @@ function chooseTable() {
// setTimeout(() => {
// changeCategorySel(0)
// }, 500)
go.to("PAGES_CHOOSE_TABLE", {
...data.table,
});
go.to("PAGES_INDEX_CHOOSE_TABLE");
// go.to("PAGES_CHOOSE_TABLE", {
// ...data.table,
// });
}
async function confirmModelConfirm(isCancel = false) {
@@ -1682,6 +1711,21 @@ function editCart(par, operate_type) {
}
const $cacheGoods = {};
//修改购物车商品备注
function updateCartRemark(e) {
let { remark, index, goods } = e;
cars[index].note = remark;
let params = {
number: e.num,
id: e.goods.id,
product_id: e.goods.product_id,
sku_id: e.goods.sku_id,
is_temporary: e.goods.is_temporary,
remark: remark,
};
editCart(params, "edit");
}
//购物车商品数量改变
async function carsNumberChange(e) {
if (!data.isGoodsAdd) {
@@ -1909,7 +1953,7 @@ async function onSelTable() {
data.masterId = masterId;
const cartRes = await getCart();
cars.length = 0;
const cartArr = getNowCart(cartRes.data);
const cartArr = getNowCart(cartRes);
for (let i in cartArr) {
cars.push(cartArr[i]);
}
@@ -1973,7 +2017,7 @@ let sysInfo = ref({
const limitTimeDiscountRes = ref(null);
async function getLimit() {
const res = await limitTimeDiscountApi.limitTimeDiscount();
limitTimeDiscountRes.value = res.data;
limitTimeDiscountRes.value = res;
if (data.table.tableCode) {
data.limitTimeDiscount = limitTimeDiscountRes.value;
@@ -1990,11 +2034,22 @@ async function getLimit() {
console.log("limitTimeDiscount", data.limitTimeDiscount);
}
}
async function getTableDetail() {
let res = await $returnTableDetail({
tableCode: data.table.tableCode,
});
console.log(res, "getTableDetail");
if(res){
data.table = res;
}
}
onLoad(async (opt) => {
sysInfo.value = uni.getSystemInfoSync();
uni.hideTabBar();
// option = opt
Object.assign(data.table, opt);
await getTableDetail();
await getLimit();
if (opt.useType) {
uni.setStorageSync("useType", opt.useType);
@@ -2034,7 +2089,7 @@ onLoad(async (opt) => {
// right: 0;
// top: 0;
// bottom: 0;
padding-right: 30rpx;
padding-right: 58rpx;
background-color: #fff;
white-space: nowrap;
}
@@ -2109,7 +2164,7 @@ $u-main-color: $my-main-color;
}
.u-tab-item {
padding: 10px 16px;
padding: 28rpx 20rpx;
box-sizing: border-box;
display: flex;
align-items: center;
@@ -2118,6 +2173,7 @@ $u-main-color: $my-main-color;
color: #444;
font-weight: 400;
line-height: 1;
margin-right: 56rpx;
}
.u-tab-item-active {

View File

@@ -0,0 +1,213 @@
<template>
<view class="">
<view @click="show = true">
<slot v-if="$slots.default"> </slot>
<view v-else class="choose-goods u-flex u-row-between">
<text class="color-999 u-m-r-32" v-if="!modelValue">{{ nullText }}</text>
<text class="color-333 u-m-r-32 u-line-1" v-else>{{ goodsName }}</text>
<up-icon size="14" name="arrow-down"></up-icon>
</view>
</view>
<up-popup :show="show" mode="center">
<view class="" style="min-width: 400px;">
<view class="top u-flex u-row-between">
<text class="font-bold u-font-32 color-333">{{ title }}</text>
<up-icon size="18" name="close" @click="show = false"></up-icon>
</view>
<scroll-view
:scroll-y="true"
style="max-height: 50vh"
@scroll="scroll"
:scroll-top="scrollTop"
>
<view
v-for="(item, index) in list"
:key="index"
class="item"
@click="itemClick(item)"
:class="[selItem && selItem.id == item.id ? 'selected' : '']"
>
<view class="u-flex u-row-between">
<view class="u-flex gap-20">
<!-- <view class="u-flex" @click.stop="preview(item)">
<up-image
:src="item.coverImg"
width="80rpx"
height="80rpx"
></up-image>
</view> -->
<text class="u-font-32 color-333">{{ item.name }}</text>
</view>
<text class="u-font-32 color-red u-p-l-30"
></text
>
</view>
</view>
</scroll-view>
<view class="bottom">
<view class="btn cancel" @click="close">{{ cancelText }}</view>
<view class="btn success" @click="confirm">{{ confirmText }}</view>
</view>
</view>
</up-popup>
</view>
</template>
<script setup>
import { ref, onMounted, watch } from "vue";
import * as tableApi from "@/http/api/table.js";
const show = ref(false);
const modelValue = defineModel({
type: String,
default: "",
});
const goodsName = defineModel("goodsName", {
type: String,
default: "",
});
const props = defineProps({
title: {
type: String,
default: "选择台桌",
},
nullText: {
type: String,
default: "请选择",
},
confirmText: {
type: String,
default: "确认",
},
cancelText: {
type: String,
default: "取消",
},
});
const selItem = ref("");
function itemClick(item) {
if (selItem.value && selItem.value.id == item.id) {
selItem.value = "";
return;
}
selItem.value = item;
}
const list = ref([]);
const scrollTop = ref(0);
function scroll(e) {
scrollTop.value = e.detail.scrollTop;
}
function preview(item) {
uni.previewImage({
urls: item.images || [item.coverImg],
});
}
watch(
() => modelValue.value,
(newVal, oldVal) => {
console.log(newVal, oldVal);
selItem.value = list.value.find((item) => item.id == newVal);
console.log(selItem.value);
if (selItem.value) {
goodsName.value = selItem.value.name;
}
}
);
watch(
() => list.value.length,
(newVal, oldVal) => {
selItem.value = list.value.find((item) => item.id == modelValue.value);
console.log(selItem.value);
if (selItem.value) {
modelValue.value = selItem.value.id;
goodsName.value = selItem.value.name;
}
}
);
function close() {
show.value = false;
}
function confirm() {
if (!selItem.value) {
uni.showToast({
title: "请选择台桌",
icon: "none",
});
return;
}
modelValue.value = selItem.value.id;
show.value = false;
}
async function getTablelist() {
const res = await tableApi.getShopTable({ size: 999 });
list.value = res.records || [];
}
onMounted(() => {
getTablelist();
});
</script>
<style lang="scss">
.popup-content {
background: #fff;
width: 640rpx;
border-radius: 18rpx;
}
.top {
padding: 40rpx 48rpx;
border-bottom: 1px solid #d9d9d9;
}
.bottom {
padding: 48rpx 52rpx;
display: flex;
justify-content: space-between;
border-top: 1px solid #d9d9d9;
gap: 50rpx;
.btn {
flex: 1;
text-align: center;
padding: 18rpx 60rpx;
border-radius: 100rpx;
font-size: 32rpx;
border: 2rpx solid transparent;
&.success {
background-color: $my-main-color;
color: #fff;
}
&.cancel {
border-color: #d9d9d9;
box-shadow: 0 4rpx 0 0 #00000005;
}
}
}
.item {
padding: 18rpx 32rpx;
border: 1px solid #d9d9d9;
margin: 20rpx;
border-radius: 8rpx;
transition: all 0.3s ease-in-out;
box-shadow: 0 0 10px transparent;
&.selected {
border-color: $my-main-color;
box-shadow: 0 0 10px $my-main-color;
}
}
.choose-goods {
display: flex;
padding: 24rpx;
align-items: center;
border-radius: 8rpx;
border: 2rpx solid #d9d9d9;
background: #fff;
font-size: 28rpx;
font-weight: 400;
}
</style>

View File

@@ -0,0 +1,126 @@
<template>
<view class="box u-font-32">
<view class="u-flex gap-30">
<text>开单时间</text>
<text class="color-666">2025/09/22 19:43</text>
</view>
<view class="u-flex gap-30 u-m-t-50">
<text>就餐人数</text>
<text class="color-666">{{ cartStore.personCount}} </text>
<up-icon name="edit-pen" size="16" @click="editPersonCount"></up-icon>
</view>
<view class="u-flex gap-30 u-m-t-50">
<text>员工名称</text>
<text class="color-666">{{accountStore.shopStaff.name}}</text>
</view>
<view class="font-700" style="margin-top: 92rpx"> 订单操作 </view>
<view class="u-flex btns u-m-t-32">
<view
v-for="(item, index) in orderBtns"
:key="index"
@click="orderBtnClick(item)"
:class="[servingSel == item.value ? 'active' : '']"
class="item tranistion"
>
<text>{{ item.name }}</text>
</view>
</view>
<view class="font-700" style="margin-top: 60rpx"> 台桌操作 </view>
<view class="u-flex btns u-m-t-32">
<view
v-for="(item, index) in tableBtns"
:key="index"
@click="tableBtnClick(item)"
:class="[tableSel == item.value ? 'active' : '']"
class="item tranistion"
>
<text >{{ item.name }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive, toRaw, watch, computed ,inject} from "vue";
const accountStore=inject('accountStore')
const cartStore=inject('cartStore')
const orderBtns = [
{
name: "单品改价",
value: "changePrice",
},
{
name: "单品转台",
value: "transfer",
},
{
name: "赠菜",
value: "gift",
},
{
name: "单品上菜",
value: "serve",
},
{
name: "整单上菜",
value: "serveAll",
},
{
name: "起菜",
value: "startCooking",
},
];
const selCart = defineModel("selCart", {
default: null,
});
const tableBtns = [
{
name: "换台",
value: "changeTable",
},
{
name: "清台",
value: "clearTable",
},
];
const servingSel = ref("");
const tableSel = ref("");
const emits = defineEmits(["btnClick"]);
function orderBtnClick(item) {
servingSel.value = item.value;
emits("btnClick", item.value);
}
function tableBtnClick(item) {
tableSel.value = item.value;
emits("btnClick", item.value);
}
function editPersonCount(){
emits("btnClick", 'editPersonCount');
}
</script>
<style scoped lang="scss">
.box {
padding: 32rpx 50rpx;
position: fixed;
}
.gap-30 {
gap: 30rpx;
}
.btns {
display: flex;
flex-wrap: wrap;
.item {
padding: 14rpx 38rpx;
margin-right: 26rpx;
margin-bottom: 30rpx;
border-radius: 16rpx;
border: 2rpx solid $my-main-color;
color: $my-main-color;
font-size: 28rpx;
&.active {
background-color: $my-main-color;
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,256 @@
<template>
<my-model ref="model" :title="title" iconColor="#000" @close="resetForm">
<template #desc>
<view class="u-text-left u-p-30 ">
<template v-if="!current">
<view>
<view class="u-m-t-24 border discount u-relative u-flex input-box">
<view class="u-flex-1">
<input @input="discountInput" v-model="form.discount" type="digit"
placeholder-class="placeholder-class" placeholder="打八折请输入80" />
</view>
<view class="color-999 u-p-l-48 u-p-r-48 u-flex u-row-center u-col-center">
<view>%</view>
</view>
<view class="color-999 u-p-l-48 u-p-r-48 bg1 u-absolute u-flex u-row-center u-col-center">
<view>%</view>
</view>
</view>
<view class="u-flex u-m-t-24">
<view class="u-flex" v-for="(item,index) in discounts" :key="index">
<button @tap="setForm('discount',item)" class="tag u-m-r-20"
hover-class="hover-class">{{item}}%</button>
</view>
</view>
</view>
</template>
<template v-else>
<view>
<view class="u-m-t-24 border discount u-relative u-flex input-box">
<view class="u-flex-1">
<input @input="discountMoneyInput" v-model="form.discountMoney" type="digit"
placeholder-class="placeholder-class" placeholder="请输入最终优惠金额" />
</view>
<view class="color-999 u-p-l-48 u-p-r-48 u-flex u-row-center u-col-center">
<view></view>
</view>
<view class="color-999 u-p-l-48 u-p-r-48 bg1 u-absolute u-flex u-row-center u-col-center">
<view></view>
</view>
</view>
</view>
</template>
<view class="u-m-t-48">
<view class="u-font-24">
<text class="color-999">当前单品价格{{price}}</text>
</view>
<view class="u-font-24">
<text class="color-999">打折原因</text>
<text class="color-red">*</text>
</view>
<view class="u-flex u-m-t-24">
<view class="u-flex" v-for="(item,index) in causes" :key="index">
<button @tap="changeCauses(item,index)" class="tag u-m-r-20"
:class="{active:item.checked}">{{item.name}}</button>
</view>
</view>
</view>
<view class="u-m-t-32 u-flex ">
<uni-easyinput type="textarea" v-model="form.note" placeholder="自定义内容"></uni-easyinput>
</view>
</view>
</template>
<template #btn>
<view class="u-p-30">
<view class="u-m-t-10">
<my-button @tap="confirm" shape="circle" showShadow>确认</my-button>
<view style="height: 20rpx;">
</view>
<!-- <my-button type="cancel" bgColor="#fff" @tap="confirm">取消</my-button> -->
</view>
</view>
</template>
</my-model>
</template>
<script setup>
import { reactive, nextTick, ref, watch } from 'vue';
import myModel from '@/components/my-components/my-model.vue'
import myButton from '@/components/my-components/my-button.vue'
import myTabs from '@/components/my-components/my-tabs.vue'
const props = defineProps({
price: {
type: [Number, String],
default: 0
},
title: {
type: String,
default: ''
},
data: {
type: Array,
default: []
}
})
const discounts = [95, 90, 85, 80]
const causes = reactive([{
name: '顾客投诉质量问题',
checked: false
},
{
name: '友情打折',
checked: false
},
{
name: '临时活动',
checked: false
}
])
function changeCauses(item, index) {
item.checked = !item.checked
form.notes = causes
}
function discountInput(e) {
if (e.detail.value >= 100) {
nextTick(() => {
form.discount = 100
})
}
}
function discountMoneyInput(e) {
const max = 100
if (e.detail.value >= max) {
nextTick(() => {
form.discountMoney = 100
})
}
}
function setForm(key, val) {
form[key] = val
}
const tabs = ['打折', '减免']
let current = ref(1)
function tabsChange(i) {
console.log(i);
current.value = i
}
const $form = {
discountMoney: '',
discount: '',
name: '',
price: ''
}
const form = reactive({
...$form
})
watch(() => props.price, (newval) => {
form.price = newval
form.currentPrice = newval
})
function resetForm() {
Object.assign(form, {
...$form
})
}
const model = ref(null)
function open() {
model.value.open()
}
function close() {
model.value.close()
}
const emits = defineEmits(['confirm'])
function confirm() {
const {
discount,
discountMoney
} = form
if (current.value === 0 && discount === '') {
return uni.showToast({
icon: 'none',
title: '请输入有效折扣!'
})
}
if (current.value === 1 && discountMoney === '') {
return uni.showToast({
icon: 'none',
title: '请输入有效减免价格!'
})
}
emits('confirm', form)
close()
}
defineExpose({
open,
close
})
</script>
<style lang="scss">
.tag {
background-color: #fff;
border: 1px solid #E5E5E5;
line-height: inherit;
font-size: 24rpx;
color: #666666;
padding: 6rpx 20rpx;
border-radius: 8rpx;
&.active {
border-color: #E6F0FF;
color: $my-main-color;
}
}
.hover-class {
background-color: #E5E5E5;
}
.discount {
.u-absolute {
top: 0;
bottom: 0;
right: 0;
}
}
.bg1 {
background: #F7F7FA;
}
.tab {
padding: 0 80rpx;
}
.border {
border: 1px solid #E5E5E5;
border-radius: 4rpx;
}
.input-box {
padding: 22rpx 32rpx;
font-size: 28rpx;
color: #666;
}
.placeholder-class {
font-size: 28rpx;
}
</style>

View File

@@ -0,0 +1,197 @@
<template>
<my-model ref="model" :title="title" iconColor="#000" @close="resetForm">
<template #desc>
<view class="u-text-left u-p-30 ">
<view style="transform: scale(1.5);transform-origin:left;">
<uni-number-box :min="1" :max="1" :value="form.number" @change="changeValue" :width="300" />
</view>
<view class="u-m-t-48">
<view class="u-font-24">
<text class="color-999">赠菜原因</text>
<text class="color-red">*</text>
</view>
<view class="u-flex u-m-t-24">
<view class="u-flex" v-for="(item,index) in causes" :key="index">
<button @tap="changeCauses(item)" class="tag u-m-r-20"
:class="{active:item.checked}">{{item.name}}</button>
</view>
</view>
</view>
<view class="u-m-t-32 u-flex ">
<uni-easyinput type="textarea" v-model="value" placeholder="自定义内容"></uni-easyinput>
</view>
</view>
</template>
<template #btn>
<view class="u-p-30">
<view class="u-m-t-10">
<my-button @tap="confirm" shape="circle" showShadow>确认</my-button>
<my-button type="cancel" bgColor="#fff" @tap="confirm">取消</my-button>
</view>
</view>
</template>
</my-model>
</template>
<script setup>
import {
reactive,
nextTick,
ref
} from 'vue';
import myModel from '@/components/my-components/my-model.vue'
import myButton from '@/components/my-components/my-button.vue'
import myTabs from '@/components/my-components/my-tabs.vue'
const props = defineProps({
title: {
type: String,
default: ''
},
data: {
type: Array,
default: []
}
})
function changeCauses(item) {
item.checked = !item.checked
}
const discounts = [95, 90, 85, 80]
const causes = reactive([{
name: '顾客投诉质量问题',
checked: false
},
{
name: '友情打折',
checked: false
},
{
name: '临时活动',
checked: false
}
])
function discountInput(e) {
if (e.detail.value >= 100) {
nextTick(() => {
form.discount = 100
})
}
}
function discountMoneyInput(e) {
const max=100
if (e.detail.value >= max) {
nextTick(() => {
form.discountMoney = 100
})
}
}
function setForm(key, val) {
form[key] = val
}
const tabs = ['打折', '减免']
let current = ref(0)
function tabsChange(i) {
console.log(i);
current.value = i
}
const $form = {
number:1
}
function changeValue(e){
form.number=e
}
const form = reactive({
...$form
})
function resetForm() {
Object.assign(form, {
...$form
})
}
const model = ref(null)
function open() {
model.value.open()
}
function close() {
model.value.close()
}
const emits = defineEmits(['confirm'])
function confirm() {
const {number
} = form
close()
emits('confirm', {
name,
price
})
}
defineExpose({
open,
close
})
</script>
<style lang="scss">
.tag {
background-color: #fff;
border: 1px solid #E5E5E5;
line-height: inherit;
font-size: 24rpx;
color: #666666;
padding: 6rpx 20rpx;
border-radius: 8rpx;
&.active {
border-color: #E6F0FF;
color: $my-main-color;
}
}
.hover-class {
background-color: #E5E5E5;
}
.discount {
.u-absolute {
top: 0;
bottom: 0;
right: 0;
}
}
.bg1 {
background: #F7F7FA;
}
.tab {
padding: 0 80rpx;
}
.border {
border: 1px solid #E5E5E5;
border-radius: 4rpx;
}
.input-box {
padding: 22rpx 32rpx;
font-size: 28rpx;
color: #666;
}
.placeholder-class {
font-size: 28rpx;
}
</style>

View File

@@ -0,0 +1,224 @@
<template>
<view class="table">
<view class="header">
<text>商品</text>
<view class="u-flex" style="gap: 54rpx">
<text>数量</text>
<text>单价</text>
<text>小计</text>
</view>
</view>
<view class="list">
<view
v-for="(item, index) in cartStore.allCartList"
:key="index"
class="item transition"
@click="itemClick(item)"
:class="[isSelected(item) ? 'isSelected' : '']"
>
<view class="u-flex">
<text>{{ item.productName }}</text>
<view class="u-flex gap-10" style="margin-left: 40rpx">
<text class="status gift" v-if="item.isGift"></text>
<template v-if="item.subStatus">
<text
class="status "
:class="[
returnSubStatusText(item) == '已超时' ? 'timeout' : '',
returnStatusClass(item),
]"
>{{ returnSubStatusText(item) }}</text
>
</template>
</view>
</view>
<view class="u-flex" style="gap: 54rpx">
<text>{{ item.num }}</text>
<view class="u-flex u-relative">
<text class="limit-price" v-if="showOldPrice">
{{ returnPrice(item) }}
</text>
<text
class="origin-price"
:class="[showOldPrice ? 'old-price' : '']"
>{{ item.price }}</text
>
</view>
<text>{{
BigNumber(item.num).times(returnPrice(item)).toFixed(2)
}}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, inject, ref, watch } from "vue";
import dayjs from "dayjs";
import BigNumber from "bignumber.js";
const cartStore = inject("cartStore");
const yskUtils = inject("yskUtils");
function isSelected(item) {
return selCart.value && item.id === selCart.value.id;
}
function showOldPrice(item) {
return item.isTimeDiscount ||item.isGift || item.discountSaleAmount * 1 > 0;
}
const nowTime = ref(new Date().getTime());
const timer = setInterval(() => {
nowTime.value = new Date().getTime();
}, 1000);
//超时时间
const maxTime = 10 * 60 * 1000;
function returnStatusClass(item) {
if (item.subStatus == "DELIVERED") {
return "success";
}
}
/**
* 返回商品状态文本
*/
function returnSubStatusText(item) {
let a = nowTime.value;
if (item.subStatus == "PENDING_PREP") {
return "待起菜";
}
if (item.subStatus == "READY_TO_SERVE") {
if (item.startOrderTime) {
const maxWaitTime = dayjs(item.startOrderTime).add(
maxTime,
"millisecond"
);
if (dayjs(nowTime.value).isAfter(maxWaitTime)) {
return "已超时";
}
}
return "待出菜";
}
if (item.subStatus == "SENT_OUT") {
return "已出菜";
}
if (item.subStatus == "DELIVERED") {
return "已上菜";
}
return "";
}
function returnPrice(data) {
if (data.isTimeDiscount) {
return returnLimitPrice(data);
}
if (data.discountSaleAmount * 1 > 0) {
return data.discountSaleAmount;
}
if(data.isGift){
return 0
}
return data.price;
}
function returnLimitPrice(data) {
const price = yskUtils.limitUtils.returnPrice({
goods: data,
shopInfo: cartStore.shopInfo,
limitTimeDiscountRes: cartStore.limitTimeDiscount,
shopUserInfo: cartStore.shopUserInfo,
idKey: "productId",
});
return price;
}
const selCart = defineModel("selCart", {
default: null,
});
function itemClick(item) {
if (selCart.value && item.id === selCart.value.id) {
selCart.value = null;
return;
}
selCart.value = item;
console.log(item);
}
</script>
<style scoped lang="scss">
.list {
.item {
padding: 40rpx 102rpx;
display: flex;
justify-content: space-between;
background-color: #fff;
border: 1px solid transparent;
border-top-color: #e5e5e5;
font-size: 40rpx;
&:last-child {
border-top-color: transparent;
}
&.isSelected {
border-color: $my-main-color;
}
}
}
.table {
.header {
background-color: #f8f8f8;
padding: 40rpx 102rpx;
display: flex;
justify-content: space-between;
font-size: 40rpx;
}
}
.status {
padding: 10rpx 14rpx;
border-radius: 14rpx;
border: 1px solid transparent;
font-size: 28rpx;
color: #999;
border-color: #999;
background-color: rgba(153, 153, 153, 0.25);
&.default {
}
&.timeout {
color: #ff383c;
border-color: #ff383c;
background-color: rgba(255, 56, 60, 0.21);
}
&.success {
color: $my-main-color;
border-color: $my-main-color;
background-color: rgba(63, 158, 255, 0.25);
}
&.gift {
$color: rgb(255, 159, 46);
color: $color;
background-color: rgb(255, 240, 223);
border-color: $color;
}
}
.old-price {
text-decoration: line-through;
color: #999;
font-size: 28rpx;
position: relative;
}
.limit-price,
.discount-price {
position: absolute;
bottom: 100%;
text-align: center;
left: 0;
right: 0;
}
.gap-10 {
gap: 10rpx;
}
</style>

View File

@@ -0,0 +1,610 @@
<template>
<view
class="bg-fff border-r-24 u-m-t-32"
v-if="orderInfo && orderInfo.detailMap"
>
<view
class="u-m-b-20"
v-for="(goods, orderIndex) in orderInfo.detailMap"
:key="orderIndex"
>
<view class="u-p-t-24"> {{ orderIndex }}次下单 </view>
<view class="u-m-t-24 list">
<view class="item u-m-b-32" v-for="(item, index) in goods" :key="index">
<view class="u-flex u-col-top">
<view class="u-flex u-relative">
<view class="limit-discount" v-if="item.isTimeDiscount"
>限时折扣</view
>
<image
v-if="item.isTemporary == 0"
class="img"
:src="item.coverImg || item.productImg"
mode=""
></image>
<view
v-else
style="
background-color: #3f9eff;
width: 152rpx;
height: 152rpx;
line-height: 152rpx;
text-align: center;
color: #fff;
"
>
临时菜
</view>
</view>
<view class="u-p-l-32 u-flex-1">
<view class="u-flex u-row-between u-col-top">
<view class="">
<view class="u-flex">
<view class="tui" v-if="isTui(item)">
{{
item.status == "part_refund" ? "部分已退" : "全部已退"
}}
</view>
<view
:class="{
'line-th':
item.status == 'return' ||
item.status == 'refund' ||
item.status == 'refunding',
}"
>
{{ item.name || item.productName }}
</view>
</view>
<view
class="u-flex u-m-t-8"
style="flex-direction: column; align-items: flex-start"
>
<view class="u-flex u-m-b-8">
<view class="u-m-r-20 u-flex" v-if="item.isGift">
<uni-tag
text="赠送"
custom-style="background-color: #FFF0DF; border-color: #FFF0DF; color: #FF9F2E;"
>
</uni-tag>
</view>
<view class="u-m-r-20 u-flex" v-if="item.userCouponId">
<uni-tag
:text="productCouponDikou(item)"
custom-style="background-color: #FFF0DF; border-color: #FFF0DF; color: #FF9F2E;"
>
</uni-tag>
</view>
<view class="u-m-r-20 u-flex" v-if="item.packNumber > 0">
<uni-tag
custom-style="background-color: #E6F0FF; border-color: #E6F0FF; color: #318AFE;"
size="small"
text="打包"
inverted
type="success"
/>
</view>
</view>
<view class="u-flex u-m-t-8">
<view
class="u-m-r-20 u-font-24 u-flex"
v-if="item.refundNum > 0"
>
<view class="color-666">退款金额:</view>
<view class="color-999 u-m-l-6">{{
item.refundNum * item.unitPrice
}}</view>
</view>
<view
class="u-m-r-20 u-font-24 u-flex"
v-if="item.returnNum"
>
<view class="color-666">退菜数量:</view>
<view class="color-999 u-m-l-6">{{
item.returnNum
}}</view>
</view>
</view>
</view>
<view class="color-999 u-font-24 u-m-t-8">{{
item.skuName || ""
}}</view>
<view class="u-m-t-12 color-666 u-font-24" v-if="item.remark">
备注{{ item.remark }}
</view>
</view>
<view class="u-text-right u-m-t-28">
<view class="u-relative">
<template v-if="item.isGift">
<text class="line-th color-999"
>{{ toFixed(item.price * item.num, item) }}</text
>
<view class="u-absolute" style="right: 0; bottom: 100%">
<text class="font-bold">0</text>
</view>
</template>
<template v-else>
<template
v-if="
item.discountSaleAmount &&
item.discountSaleAmount * 1 > 0
"
>
<text class="line-th color-999"
>¥{{ toFixed(item.price * item.num, item) }}</text
>
<view class="u-absolute" style="right: 0; bottom: 100%">
<text class="font-bold"
>¥{{
toFixed(item.discountSaleAmount * item.num, item)
}}</text
>
</view>
</template>
<template v-else-if="item.isTimeDiscount">
<text class="line-th color-999"
>¥{{ toFixed(item.price * item.num, item) }}</text
>
<view
class="u-absolute xianshi"
style="right: 0; bottom: 100%"
>
<text class="font-bold"
>¥{{ returnLimitTotalMoney(item) }}</text
>
</view>
</template>
<template
v-else-if="
isVip &&
item.price &&
item.price * 1 != item.memberPrice * 1
"
>
<text class="line-th color-999"
>¥{{ toFixed(item.price * item.num, item) }}</text
>
<view class="u-absolute" style="right: 0; bottom: 100%">
<text class="font-bold"
>¥{{
toFixed(item.memberPrice * item.num, item)
}}</text
>
</view>
</template>
<template v-else>
<view class="font-bold">
<text>¥</text>
<text class="">{{
toFixed(item.price * item.num, item)
}}</text>
</view>
</template>
</template>
</view>
<view class="u-m-t-22 color-999 u-font-24"
>X{{ item.num || item.num }}</view
>
</view>
</view>
</view>
</view>
<!-- <template v-if="canTuicai(orderInfo, item)"> -->
<template v-if="false">
<view
class="u-flex u-row-right gap-20 u-m-t-24"
v-if="item.returnNum * item.unitPrice < item.num * item.unitPrice"
>
<my-button
:width="128"
:height="48"
plain
shape="circle"
@tap="tuicai(item, index)"
><text class="no-wrap">退菜</text></my-button
>
</view>
</template>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, reactive,inject } from "vue";
import BigNumber from "bignumber.js";
import { hasPermission } from "@/commons/utils/hasPermission.js";
import {
isTui,
isTuiCai,
isGift,
canTuiKuan,
canTuicai,
mathFloorPrice,
} from "@/commons/utils/goodsUtil.js";
const emits = defineEmits(["tuicai", "tuikuan", "printOrder"]);
const yskUtils = inject("yskUtils");
const shopInfo = inject("shopInfo");
const pageData = inject("pageData");
const pop = reactive({
youhui: false,
});
const props = defineProps({
orderInfo: {
type: Object,
default: () => {},
},
data: {
type: Array,
default: () => [],
},
seatFee: {
type: Object,
default: () => {},
},
user: {
type: Object,
default: () => {
return {
id: "",
isVip: false,
};
},
},
});
/**
* 计算菜品数量
*/
const goodsNumber = computed(() => {
let result = 0;
result = props.data.reduce((a, b) => {
const bTotal = b.info.length;
return a + bTotal;
}, 0);
return result.toFixed(0);
});
/**
* 桌位费
*/
const seatFeePrice = computed(() => {
const n =
props.orderInfo.seatNum > 0
? props.orderInfo.seatNum * uni.getStorageSync("shopInfo").tableFee
: 0;
return n.toFixed(2);
});
function toFixed(price, item) {
if (item) {
if (item.productType == "weight" || item.type == "weight") {
return (Math.floor(price * 100) / 100).toFixed(2);
} else {
return parseFloat(price).toFixed(2);
}
} else {
return parseFloat(price).toFixed(2);
}
}
/**
* 判断是否是会员
*/
const isVip = computed(() => {
return (
uni.getStorageSync("shopInfo").isMemberPrice &&
props.user &&
props.user.id &&
props.user.isVip
);
});
function returnLimitTotalMoney(data) {
const price = yskUtils.limitUtils.returnPrice({
goods: data,
shopInfo: pageData.shopInfo,
limitTimeDiscountRes: pageData.limitTimeDiscount,
shopUserInfo: pageData.user,
idKey: "product_id",
});
return BigNumber(price).times(data.number).toNumber();
}
const vipDiscountPrice = computed(() => {
if (!isVip.value) {
return 0;
}
const goodsPrice = props.data.reduce((prve, cur) => {
const curTotal = cur.info
.filter(
(v) =>
v.discountSaleAmount <= 0 &&
v.isGift != 1 &&
v.status !== "return" &&
v.price != v.unitPrice &&
v.memberPrice != v.price
)
.reduce((a, b) => {
return a + b.num * (b.price - b.memberPrice);
}, 0);
return prve + curTotal;
}, 0);
return goodsPrice.toFixed(2);
});
/**
* 单品打折优惠
*/
const discountSaleAmount = computed(() => {
const goodsPrice = props.data.reduce((prve, cur) => {
const curTotal = cur.info
.filter(
(v) =>
v.discountSaleAmount > 0 && v.isGift != 1 && v.status !== "return"
)
.reduce((a, b) => {
return a + b.num * (b.price - b.discountSaleAmount);
}, 0);
return prve + curTotal;
}, 0);
return goodsPrice.toFixed(2);
});
/**
* 打折优惠
*/
const discountAmount = computed(() => {
return props.orderInfo.discountAmount || 0;
});
/**
* 总优惠金额
*/
const discountsPrice = computed(() => {
// 满减券优惠
let fullCouponDiscountAmount =
props.orderInfo.status == "done"
? props.orderInfo.fullCouponDiscountAmount
: 0;
// 商品券优惠
let productCouponDiscountAmount =
props.orderInfo.status == "done"
? props.orderInfo.productCouponDiscountAmount
: 0;
// 积分抵扣优惠
let pointsDiscountAmount =
props.orderInfo.status == "done" ? props.orderInfo.pointsDiscountAmount : 0;
return (
parseFloat(vipDiscountPrice.value) +
parseFloat(discountSaleAmount.value) +
discountAmount.value +
fullCouponDiscountAmount +
productCouponDiscountAmount +
pointsDiscountAmount
).toFixed(2);
});
// 菜品金额
const productCoupPrice = computed(() => {
if (props.orderInfo.status == "done") {
return props.orderInfo.productCouponDiscountAmount;
}
const goodsPrice = props.data.reduce((a, b) => {
const curTotal = b.info
.filter((v) => !v.isGift)
.reduce((prve, cur) => {
let memberPrice = cur.memberPrice ? cur.memberPrice : cur.price;
let tPrice = isVip.value ? memberPrice : cur.price;
tPrice =
cur.memberPrice != cur.unitPrice && cur.price != cur.unitPrice
? cur.unitPrice
: tPrice;
let Total = Math.floor(tPrice * cur.num * 100) / 100;
return (
prve + Total - cur.returnNum * tPrice - cur.refundNum * cur.unitPrice
);
}, 0);
return a + curTotal;
}, 0);
// console.log("菜品金额==",goodsPrice)
return goodsPrice.toFixed(2);
});
const allPpackFee = computed(() => {
//不是退菜只要有打包费的都计算,包括赠送
const goodsPrice = props.data.reduce((prve, cur) => {
const curTotal = cur.info
.filter((v) => v.packNumber > 0)
.reduce((a, b) => {
return a + parseFloat(b.packAmount * b.packNumber).toFixed(2) * 1;
}, 0);
return prve + curTotal;
}, 0);
return goodsPrice.toFixed(2);
});
const packFee = computed(() => {
//不是退菜只要有打包费的都计算,包括赠送
const goodsPrice = props.data.reduce((prve, cur) => {
const curTotal = cur.info
.filter((v) => v.status !== "return" && v.returnNum + v.refundNum < v.num)
.reduce((a, b) => {
return (
a +
parseFloat(
(
b.packAmount *
(b.num - (b.returnNum + b.refundNum) > b.packNumber
? b.packNumber
: b.num - (b.returnNum + b.refundNum))
).toFixed(2)
)
);
}, 0);
return prve + curTotal;
}, 0);
return goodsPrice.toFixed(2);
});
const allPrice = computed(() => {
let seatAmount = props.orderInfo.seatAmount || 0;
const total = productCoupPrice.value * 1 + seatAmount * 1 + packFee.value * 1;
return (total <= 0 ? 0 : total).toFixed(2);
});
/**
* 已优惠金额
*/
const youhuiAllPrice = computed(() => {
const n = vipDiscountPrice.value * 1;
return (n < 0 ? 0 : n).toFixed(2);
});
function youhuiDetailShow() {
pop.youhui = true;
}
function productCouponDikou(item) {
return "商品券抵扣¥" + returnProductCoupPrice(item);
}
function youhuiDetailHide() {
pop.youhui = false;
}
/**
* 转桌/并桌
*/
function rotatingTables() {
let arr = [];
props.data.forEach((ele) => {
ele.info.forEach((res) => {
// 头像 coverImg
res.coverImg = res.productImg;
// 名字 name
res.name = res.productName;
// 金额 price
res.price = res.price;
// 数量 number
res.number = res.num;
res.masterId = props.orderInfo.masterId;
res.useType = props.orderInfo.useType;
res.tableId = props.orderInfo.tableId;
arr.push(res);
});
});
uni.navigateTo({
url:
"/pagesCreateOrder/confirm-order/rotatingTables?item=" +
JSON.stringify(arr) +
"&tableId=" +
props.orderInfo.tableId,
});
}
function returnProductCoupPrice(item) {
if (!item.isMember) {
return item.price * item.num;
}
const price = item.memberPrice ? item.memberPrice : item.price;
return price * item.num;
}
function returnCanTuiMoney(item) {
// if (props.orderInfo.status == 'unpaid') {
// return returnTotalMoney(item)
// } else {
if (
props.orderInfo.pointsDiscountAmount > 0 ||
props.orderInfo.fullCouponDiscountAmount > 0
) {
return item.canReturnAmount;
} else if (item.price != item.unitPrice) {
return item.price * item.num;
} else {
return (Math.floor(item.num * item.unitPrice * 100) / 100).toFixed(2);
}
// }
}
function tuicai(item, index) {
emits("tuicai", item, index);
}
</script>
<style lang="scss" scoped>
.img {
width: 152rpx;
height: 152rpx;
border-radius: 6px;
}
.border-top {
border-color: #f6f6f6;
}
.border-r-24 {
border-radius: 24rpx;
}
.border-bottom {
// border-color: rgb(240, 240, 240);
border-color: #f6f6f6;
}
.line-th {
text-decoration: line-through;
}
.tag {
padding: 4rpx 8rpx 2rpx 10rpx;
border-radius: 8rpx;
font-size: 24rpx;
&.no-pay {
background-color: rgb(170, 170, 170);
color: #fff;
}
&.refund {
background-color: #fce7e7;
padding: 8rpx 20rpx 6rpx 22rpx;
color: #eb4f4f;
}
}
.tui {
background-color: rgb(239, 239, 239);
border-radius: 4rpx;
margin-right: 6rpx;
color: #666;
padding: 0 4rpx;
font-size: 20rpx;
}
.limit-discount {
background-color: #cc5617;
padding: 2rpx 10rpx;
white-space: nowrap;
text-align: center;
position: absolute;
top: 0;
left: 0;
font-weight: 400;
font-size: 24rpx;
color: #ffffff;
border-radius: 20rpx 0rpx 20rpx 0rpx;
z-index: 9;
color: #fff;
}
</style>

View File

@@ -0,0 +1,131 @@
<template>
<my-model ref="model" :title="title" iconColor="#000" @close="resetForm">
<template #desc>
<view class="u-text-left u-p-l-30 u-p-r-30 u-p-t-30 ">
<view class="u-m-t-32 u-flex ">
<uni-easyinput type="number" v-model="form.pack_number" placeholder="打包数量"></uni-easyinput>
</view>
</view>
</template>
<template #btn>
<view class="u-p-l-30 u-p-r-30 u-m-t-28 u-p-b-30">
<view class="">
<my-button @tap="confirm" shape="circle" fontWeight="700">确认</my-button>
<view class="u-m-t-10">
<my-button type="cancel" bgColor="#fff" @tap="confirm">取消</my-button>
</view>
</view>
</view>
</template>
</my-model>
</template>
<script setup>
import { reactive, nextTick, ref } from 'vue';
const props = defineProps({
title: {
type: String,
default: ''
}
})
const $form = {
pack_number: 1
}
const form = reactive({
number: null,
...$form
})
function resetForm() {
Object.assign(form, {
...$form
})
}
const model = ref(null)
function open(data) {
console.log(data)
form.number = data.number
model.value.open()
}
function close() {
model.value.close()
}
const emits = defineEmits(['confirm'])
function confirm() {
const { pack_number } = form
if( pack_number > form.number){
uni.showToast({
title: '打包数量不能大于菜品数量',
icon: 'none'
})
return false;
}
emits('confirm', pack_number)
close()
}
defineExpose({
open,
close
})
</script>
<style lang="scss">
.lh34{
line-height: 34rpx;
}
.tag {
background-color: #fff;
border: 1px solid #E5E5E5;
line-height: inherit;
font-size: 24rpx;
color: #666666;
padding: 6rpx 20rpx;
border-radius: 8rpx;
&.active {
border-color: #E6F0FF;
color: $my-main-color;
}
}
.hover-class {
background-color: #E5E5E5;
}
.discount {
.u-absolute {
top: 0;
bottom: 0;
right: 0;
}
}
.bg1 {
background: #F7F7FA;
}
.tab {
padding: 0 80rpx;
}
.border {
border: 1px solid #E5E5E5;
border-radius: 4rpx;
}
.input-box {
padding: 22rpx 32rpx;
font-size: 28rpx;
color: #666;
}
.placeholder-class {
font-size: 28rpx;
}
</style>

View File

@@ -0,0 +1,169 @@
<template>
<my-model ref="model" :title="title" iconColor="#000" @close="resetForm">
<template #desc>
<view class="u-text-left u-p-l-30 u-p-r-30 u-p-t-30 ">
<view class="u-m-t-32 u-flex ">
<uni-easyinput type="textarea" v-model="form.remark" placeholder="自定义内容"></uni-easyinput>
</view>
<view class="u-flex u-m-t-24">
<view class="u-flex u-flex-wrap u-m-r-20 u-m-b-20 lh34" v-for="(item,index) in causes" :key="index">
<button @tap="changeCauses(item)" class="tag ">{{item.name}}</button>
</view>
</view>
</view>
</template>
<template #btn>
<view class="u-p-l-30 u-p-r-30 u-m-t-28 u-p-b-30">
<view class="">
<my-button @tap="confirm" shape="circle" fontWeight="700">确认</my-button>
<view class="u-m-t-10">
<my-button type="cancel" bgColor="#fff" @tap="confirm">取消</my-button>
</view>
</view>
</view>
</template>
</my-model>
</template>
<script setup>
import {
reactive,
nextTick,
ref
} from 'vue';
const props = defineProps({
title: {
type: String,
default: ''
},
data: {
type: Array,
default: []
}
})
function changeCauses(item) {
let prve=form.remark?',':''
form.remark +=prve+item.name
console.log(form.remark);
}
const causes = reactive([{
name: '免葱',
checked: false
},
{
name: '免香菜',
checked: false
},
{
name: '不要辣',
checked: false
}
])
function setForm(key, val) {
form[key] = val
}
const $form = {
remark:''
}
const form = reactive({
...$form
})
function resetForm() {
Object.assign(form, {
...$form
})
}
const model = ref(null)
function open(data) {
Object.assign(form,data)
model.value.open()
}
function close() {
model.value.close()
}
const emits = defineEmits(['confirm'])
function confirm() {
const { remark } = form
emits('confirm', {
remark
})
console.log(remark);
close()
}
defineExpose({
open,
close
})
</script>
<style lang="scss">
.lh34{
line-height: 34rpx;
}
.tag {
background-color: #fff;
border: 1px solid #E5E5E5;
line-height: inherit;
font-size: 24rpx;
color: #666666;
padding: 6rpx 20rpx;
border-radius: 8rpx;
&.active {
border-color: #E6F0FF;
color: $my-main-color;
}
}
.hover-class {
background-color: #E5E5E5;
}
.discount {
.u-absolute {
top: 0;
bottom: 0;
right: 0;
}
}
.bg1 {
background: #F7F7FA;
}
.tab {
padding: 0 80rpx;
}
.border {
border: 1px solid #E5E5E5;
border-radius: 4rpx;
}
.input-box {
padding: 22rpx 32rpx;
font-size: 28rpx;
color: #666;
}
.placeholder-class {
font-size: 28rpx;
}
</style>

View File

@@ -0,0 +1,683 @@
<template>
<view class="u-font-28">
<up-sticky offsetTop="0" customNavHeight="0">
<view class="navbar">
<view class="u-flex" style="margin-left: 100rpx" @click="back">
<up-icon name="arrow-left" size="32rpx" color="#333"></up-icon>
<text class="u-m-l-16">返回</text>
</view>
<text class="font-700 u-font-40 color-333"
>{{ returnAreaName }} {{ returnTableName }}</text
>
<view class="u-flex navbar-right" style="gap: 134rpx">
<up-icon
name="scan"
size="64rpx"
color="#999"
@click="saomaShangCai"
></up-icon>
</view>
</view>
</up-sticky>
<view class="container">
<view class="goods-list">
<goodsList v-model:selCart="selCart"></goodsList>
<view style="height: 200rpx"></view>
<view class="bottom u-flex u-row-between">
<view>
<text>合计</text>
<text class="color-red u-font-40"
>¥{{ cartStore.orderCostSummary.finalPayAmount }}</text
>
</view>
<view class="u-flex" style="gap: 94rpx">
<view class="btn" @click="back">继续加菜</view>
<view class="btn success" @click="toPay">结算</view>
</view>
</view>
</view>
<view class="controls">
<controls @btnClick="btnClick" v-model:selCart="selCart"></controls>
</view>
</view>
<model-discount
title="菜品减免"
:ref="setModel"
name="discount"
:price="modelData.data.salePrice"
@confirm="discountconfirm"
></model-discount>
<!-- 转桌 -->
<Modal
v-model="modalData.show"
:width="modalData.key != 'editPersonCount' ? '800rpx' : ''"
:title="modalData.title"
confirmText="确定"
@confirm="modalConfirm"
>
<template v-if="modalData.key == 'editPersonCount'">
<view class="u-p-40 u-font-32 color-333 u-flex u-flex-x-center">
<up-number-box
v-model="modalData.form.personCount"
integer
:min="0"
:max="100"
inputWidth="200"
></up-number-box>
</view>
</template>
<template v-if="modalData.key == 'btnClick'">
<view class="u-p-40 u-font-32 color-333">
<view class="u-flex">
<text class="font-bold u-m-r-52" style="min-width: 128rpx"
>转桌到</text
>
<view class="u-flex-1">
<chooseTables
v-model="modalData.form.targetTableCode"
></chooseTables>
</view>
</view>
<view class="u-flex u-m-t-44">
<text class="font-bold u-m-r-52">转入类型</text>
<up-radio-group v-model="modalData.form.type" placement="row">
<up-radio
:key="1"
label="转桌(部分商品转入)"
:name="1"
></up-radio>
<up-radio
:key="2"
label="并桌(全部商品转入)"
:name="2"
></up-radio>
</up-radio-group>
</view>
<template v-if="modalData.form.type == 1">
<view class="u-flex u-m-t-44">
<text class="font-bold u-m-r-52">购物车商品</text>
</view>
<view class="u-m-t-44">
<u-table2
:data="cartStore.oldCartList"
:columns="modalData.form.columns"
row-key="id"
@selection-change="handleSelectionChange"
/>
</view>
</template>
</view>
</template>
</Modal>
</view>
</template>
<script setup>
import Modal from "@/components/my-components/modal.vue";
import chooseTables from "./components/choose-tables.vue";
import { onLoad } from "@dcloudio/uni-app";
import goodsList from "./components/goods-list.vue";
import modelDiscount from "./components/discount";
import controls from "./components/controls.vue";
import { useCartStore } from "@/stores/cart.js";
import { useAccountStore } from "@/stores/account.js";
import * as orderApi from "@/http/api/order.js";
import * as tableApi from "@/http/api/table.js";
import * as areaApi from "@/http/api/area.js";
import yskUtils from "ysk-utils";
import go from "@/commons/utils/go.js";
import { reactive, ref, provide, computed } from "vue";
const cartStore = useCartStore();
const accountStore = useAccountStore();
const modalData = reactive({
show: false,
key: "",
title: "",
form: {
personCount: 0,
targetTableCode: "",
checks: [],
type: 1,
columns: [
{ type: "selection", width: "50px" },
{ title: "商品名称", key: "productName" },
{
title: "数量",
key: "num",
style: { "justify-content": "center", "text-align": "cnter" },
},
],
},
});
function handleSelectionChange(e) {
console.log(e);
modalData.form.checks = e;
}
async function transferTable() {
if (!modalData.form.targetTableCode) {
uni.showToast({
title: "请选择目标台桌",
icon: "none",
});
return;
}
if (modalData.form.type == 1 && modalData.form.checks.length <= 0) {
uni.showToast({
title: "请选择商品",
icon: "none",
});
return;
}
let detailIds = cartStore.oldCartList.map((v) => v.id);
if (modalData.form.type == 1) {
detailIds = modalData.form.checks.map((v) => v.id);
}
const res = await orderApi.mergeOrder({
sourceOrderId: cartStore.order.id,
targetOrderId: "",
targetTableCode: modalData.form.targetTableCode,
detailIds,
});
uni.showToast({
title: "转桌成功",
icon: "none",
});
const orderRes = await orderApi.getHistoryOrder({
tableCode: modalData.form.targetTableCode,
});
if (orderRes) {
options.orderId = orderRes.id;
getOrderById();
modalData.show = false;
modalData.form.targetTableCode = [];
modalData.form.checks = [];
modalData.form.type = 1;
}
}
async function editPersonCount() {
cartStore.personCount = modalData.form.personCount;
modalData.show = false;
}
async function modalConfirm(key) {
if (modalData.key == "transferTable") {
transferTable();
}
if (modalData.key == "editPersonCount") {
editPersonCount();
}
}
provide("cartStore", cartStore);
provide("yskUtils", yskUtils);
provide("accountStore", accountStore);
const selCart = ref(null);
function back() {
uni.navigateBack();
}
function toPay() {
go.to("PAGES_ORDER_PAY", {
orderId: cartStore.order.id,
isNowPay: true,
dinnerType: cartStore.currentDinnerType,
});
}
const areaList = ref([]);
async function getArea() {
const res = await areaApi.getShopArea({ size: 999 });
areaList.value = res.records;
}
async function getOrderById() {
const res = await orderApi.getOrderById({ orderId: options.orderId });
const tableRes = await tableApi.getShopTableDetail({
tableCode: res.tableCode,
});
if (tableRes) {
cartStore.table = tableRes;
} else {
cartStore.table = {
tableCode: res.tableCode,
};
}
cartStore.setOrder(res);
cartStore.sendMessage({
operate_type: "init",
});
}
const options = {};
onLoad(async (opt) => {
Object.assign(options, opt);
console.log("options", options);
getTablelist();
await getArea();
getOrderById();
});
const tableList = ref([]);
async function getTablelist() {
const res = await tableApi.getShopTable({ size: 999 });
tableList.value = res.records || [];
}
async function shopTableClear() {
const res = await tableApi.shopTableClear({
id: cartStore.table.id,
});
}
async function btnClick(type) {
if (type == "editPersonCount") {
console.log(modalData.form);
modalData.form.personCount = cartStore.personCount;
modalData.title = "就餐人数";
modalData.key = "editPersonCount";
modalData.show = true;
return;
}
modalData.key = "btnClick";
if (type == "clearTable") {
uni.showModal({
title: "提示",
content: "是否清空该桌订单",
success(res) {
if (res.confirm) {
console.log("清空该桌订单");
shopTableClear();
}
},
});
}
if (type == "transfer") {
modalData.form.type == 1;
modalData.title = "转桌";
modalData.show = true;
}
if (type == "changeTable") {
modalData.form.type == 2;
modalData.title = "转桌";
modalData.show = true;
}
if (type == "serveAll") {
await orderApi.upOrderDetail({
orderId: cartStore.order.id,
type: 1,
});
getOrderById();
return;
}
if (!selCart.value) {
return;
}
if (type == "changePrice") {
showModel("discount");
return;
}
if (type == "gift") {
updateCart({
id: selCart.value.id,
product_id: selCart.value.product_id,
sku_id: selCart.value.sku_id,
unit_price: 0,
is_gift: 1,
});
return;
}
if (type == "startCooking") {
await orderApi.upOrderDetail({
orderDetailId: selCart.value.id,
type: 0,
});
getOrderById();
return;
}
if (type == "serve") {
await orderApi.upOrderDetail({
orderDetailId: selCart.value.id,
type: 1,
});
getOrderById();
return;
}
}
const models = new Map();
const modelData = reactive({
data: {},
});
/**
* 设置弹窗信息
* @param {Object} el
*/
function setModel(el) {
if (el && el.$attrs["name"]) {
models.set(el.$attrs["name"], el);
}
}
/**
* 打开弹窗
* @param {Object} key
* @param {Object} index
*/
function showModel(key) {
modelData.data = selCart.value;
const item = selCart.value;
const model = models.get(key);
console.log("弹窗数据===", modelData.data);
if (key == "packNumber") {
if (modelData.data.type == "weight" && item.pack_number <= 0) {
let par = {
id: modelData.data.id,
product_id: modelData.data.product_id,
sku_id: modelData.data.sku_id,
pack_number: 1,
};
updateCart(par);
return false;
}
if (item.pack_number > 0) {
let par = {
id: modelData.data.id,
product_id: modelData.data.product_id,
sku_id: modelData.data.sku_id,
pack_number: 0,
};
updateCart(par);
return false;
}
model &&
model.open({
number: item.number,
});
} else {
model &&
model.open({
packNumber: modelData.data.remark || "",
});
}
}
/**
* 单品打折
* @param {Object} form
*/
async function discountconfirm(form) {
if (form.discountMoney != ".") {
let str = "";
if (form.notes) {
form.notes.forEach((ele) => {
if (ele.checked) {
str = str + ele.name + ",";
}
});
}
let discount_sale_amount = modelData.data.is_gift ? 0 : form.discountMoney;
let par = {
id: modelData.data.id,
product_id: modelData.data.product_id,
sku_id: modelData.data.sku_id,
discount_sale_amount: discount_sale_amount,
// discount_sale_note: str + form.note,
};
updateCart(par);
}
}
/**
* 购物车数据修改
* @param {Object} par
*/
function updateCart(par) {
console.log(selCart.value);
if (selCart.value.isHistory) {
cartStore.sendMessage({
type: "onboc",
operate_type: "bulk_edit",
data: {
history: [par],
cart: [],
},
});
return;
}
cartStore.sendMessage({
type: "onboc",
operate_type: "edit",
...par,
});
getCart();
}
/**
* 更新购物车和历史订单数据
*/
function uodateCartAndHistory() {
let newData = {
history: [],
cart: [],
};
websocketUtil.send(
JSON.stringify({
type: "onboc",
operate_type: "bulk_edit",
data: newData,
})
);
}
/**
* 获取购物车数据
*/
function getCart() {
// 初始化购物车
cartStore.sendMessage({
type: "onboc",
operate_type: "init",
}),
false;
}
const returnAreaName = computed(() => {
if (!cartStore.table) {
return "";
}
if (!cartStore.table.areaId) {
return "";
}
const item = areaList.value.find((v) => v.id == cartStore.table.areaId);
return item ? item.name : "";
});
const returnTableName = computed(() => {
if (!cartStore.table) {
return "";
}
return cartStore.table.name || "";
});
/**
* 扫码上传
*/
async function saomaShangCai() {
uni.scanCode({
success: async (res) => {
console.log("条码类型:" + res.scanType);
console.log("条码内容:" + res.result);
console.log("orderDetailId", res.result.split(":")[1]);
await orderApi.upOrderDetail({
orderDetailId: res.result.split(":")[1],
type: 1,
});
getOrderById();
},
});
}
</script>
<style lang="scss" scoped>
.line {
width: 1px;
height: 20rpx;
background-color: #e5e5e5;
margin-left: 8rpx;
margin-right: 16rpx;
}
.my-radio {
.circle {
background: #ffffff;
width: 18px;
height: 18px;
&.active {
background-color: $my-main-color;
border-color: $my-main-color;
}
border: 1px solid #707070;
border-radius: 50%;
overflow: hidden;
&.square {
border-radius: 8rpx;
}
}
}
.area {
padding: 2px 28rpx 24rpx 28rpx;
}
.scale7 {
transform: scale(0.7);
}
::v-deep .uni-searchbar {
padding: 0 !important;
}
.search {
padding: 20rpx 28rpx 20rpx 28rpx;
.icon-saoma {
margin-left: 20rpx;
width: 34rpx;
height: 32rpx;
}
}
.list {
padding: 38rpx 28rpx;
display: grid;
grid-template-columns: repeat(6, 1fr);
column-gap: 50rpx;
row-gap: 62rpx;
.no-choose {
padding: 36rpx 30rpx 36rpx 24rpx;
}
.item {
color: #fff;
padding: 18rpx 14rpx;
border-radius: 16rpx;
overflow: hidden;
.bottom {
padding: 26rpx 14rpx 38rpx 14rpx;
background-color: #fff;
border-radius: 6rpx;
}
.diancan {
padding: 18rpx 18rpx;
border-radius: 8rpx;
text-align: center;
}
}
}
.icon-people {
width: 30rpx;
height: 34rpx;
}
.exit {
width: 48rpx;
height: 48rpx;
margin-left: 100rpx;
}
.navbar {
background-color: #fff;
display: flex;
justify-content: space-between;
padding: 32rpx 0;
padding-top: calc(var(--status-bar-height) + 32rpx);
}
.navbar-right {
margin-right: 86rpx;
}
.status-list {
background-color: #fff;
display: flex;
padding: 32rpx 72rpx;
}
.status-list {
display: flex;
flex-wrap: wrap;
gap: 68rpx;
.circle {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
}
}
.container {
display: flex;
}
$control-width: 800rpx;
.goods-list {
flex: 1;
position: relative;
border-right: 1px solid #e5e5e5;
min-height: calc(100vh - 100px);
.bottom {
position: fixed;
border-right: 1px solid #e5e5e5;
bottom: calc(env(safe-area-inset-bottom));
left: 0;
right: $control-width;
padding: 32rpx 102rpx;
background-color: #f9f9f9;
}
}
.controls {
width: $control-width;
}
.btn {
padding: 18rpx 76rpx;
border-radius: 8rpx;
border: 1px solid $my-main-color;
color: $my-main-color;
&.success {
background-color: $my-main-color;
color: #fff;
}
}
:deep(.u-table-cell:last-child) {
justify-content: center;
}
</style>