|
|
@@ -3,7 +3,10 @@
|
|
|
<view class="page-wrap">
|
|
|
<view class="top-fixed">
|
|
|
<NavBar :title="navTitle" only-home />
|
|
|
- <view class="top-info">桌号:{{ displayTableNumber }}</view>
|
|
|
+ <view class="top-info">
|
|
|
+ <text class="top-info__item">桌号:{{ displayTableNumber }}</text>
|
|
|
+ <text class="top-info__item">就餐人数:{{ displayDinersCount }}</text>
|
|
|
+ </view>
|
|
|
<view class="search-box">
|
|
|
<view class="search-box-inner">
|
|
|
<image :src="getFileUrl('img/personal/search.png')" mode="widthFix" class="search-icon"></image>
|
|
|
@@ -25,9 +28,13 @@
|
|
|
</scroll-view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 右侧菜品长列表:按分类分段展示,每段标题 + 该分类下菜品 -->
|
|
|
+ <!-- 右侧菜品长列表:按分类分段展示,每段标题 + 该分类下菜品;搜索无结果时展示空状态 -->
|
|
|
<view class="food-list-wrap">
|
|
|
+ <view v-if="showSearchEmptyState" class="food-search-empty">
|
|
|
+ <image src="/static/no.png" mode="widthFix" class="food-search-empty__img" />
|
|
|
+ </view>
|
|
|
<scroll-view
|
|
|
+ v-else
|
|
|
class="food-list"
|
|
|
scroll-y
|
|
|
:scroll-into-view="scrollIntoViewId"
|
|
|
@@ -70,7 +77,7 @@
|
|
|
<script setup>
|
|
|
import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
|
|
|
import NavBar from "@/components/NavBar/index.vue";
|
|
|
-import { ref, computed, nextTick, getCurrentInstance } from "vue";
|
|
|
+import { ref, computed, watch, nextTick, getCurrentInstance } from "vue";
|
|
|
import FoodCard from "./components/FoodCard.vue";
|
|
|
import BottomActionBar from "./components/BottomActionBar.vue";
|
|
|
import CouponModal from "./components/CouponModal.vue";
|
|
|
@@ -78,7 +85,7 @@ import CartModal from "./components/CartModal.vue";
|
|
|
import SelectCouponModal from "./components/SelectCouponModal.vue";
|
|
|
import { go } from "@/utils/utils.js";
|
|
|
import { getFileUrl } from "@/utils/file.js";
|
|
|
-import { DiningOrderFood, GetCategoriesWithCuisines, GetStoreDetail, getOrderSseConfig, GetOrderCart, PostOrderCartAdd, PostOrderCartUpdate, PostOrderCartClear, PutOrderCartUpdateTableware, GetUserOwnedCouponList } from "@/api/dining.js";
|
|
|
+import { DiningOrderFood, GetCategoriesWithCuisines, GetStoreDetail, getOrderSseConfig, GetOrderCart, PostOrderCartAdd, PostOrderCartUpdate, PostOrderCartClear, GetUserOwnedCouponList } from "@/api/dining.js";
|
|
|
import { createSSEConnection } from "@/utils/sse.js";
|
|
|
|
|
|
// 商品图片:取第一张,若为逗号分隔字符串则截取逗号前的第一张
|
|
|
@@ -103,6 +110,13 @@ const displayTableNumber = computed(() => {
|
|
|
if (tableNumberFetched.value && tableId.value) return tableId.value;
|
|
|
return '—';
|
|
|
});
|
|
|
+
|
|
|
+/** 桌号右侧:就餐人数(与选人数页传入 / currentDiners 缓存一致) */
|
|
|
+const displayDinersCount = computed(() => {
|
|
|
+ const d = String(currentDiners.value ?? '').trim();
|
|
|
+ if (!d) return '—';
|
|
|
+ return /人\s*$/.test(d) ? d : `${d}人`;
|
|
|
+});
|
|
|
let sseRequestTask = null; // 订单 SSE 连接(封装后兼容小程序),页面卸载时需 abort()
|
|
|
const currentCategoryIndex = ref(0);
|
|
|
const foodListScrollTop = ref(0);
|
|
|
@@ -115,19 +129,25 @@ const couponModalOpen = ref(false);
|
|
|
const cartModalOpen = ref(false);
|
|
|
const selectCouponModalOpen = ref(false);
|
|
|
const selectCouponViewOnly = ref(false); // true=左下角仅查看,false=购物车内可选
|
|
|
-const fromNumberOfDiners = ref(false); // 是否从选座页(就餐人数页)进入,仅此时才调用 update-tableware 接口
|
|
|
const discountAmount = ref(12); // 优惠金额,示例数据
|
|
|
const selectedCouponId = ref(null); // 选中的优惠券ID
|
|
|
|
|
|
// 分类列表(由接口 /store/info/categories 返回后赋值)
|
|
|
const categories = ref([]);
|
|
|
+/** 无关键词拉菜单成功时的分类快照;搜索无结果时用来保留左侧标签 */
|
|
|
+const lastCategoriesForSidebar = ref([]);
|
|
|
|
|
|
// 菜品列表(由接口 /store/info/cuisines 按分类拉取并合并,每项含 quantity、categoryId)
|
|
|
const foodList = ref([]);
|
|
|
// SSE 连接建立后拉取的购物车数据,在 foodList 就绪后合并
|
|
|
let pendingCartData = null;
|
|
|
-// 购物车接口返回的完整数据:{ items, totalAmount, totalQuantity, tablewareFee },用于按接口格式展示
|
|
|
-const cartData = ref({ items: [], totalAmount: 0, totalQuantity: 0, tablewareFee: 0 });
|
|
|
+// 购物车接口返回的完整数据:{ items, totalAmount, totalQuantity, serviceFee }(已过滤特殊占位项 cuisineId=-1)
|
|
|
+const cartData = ref({ items: [], totalAmount: 0, totalQuantity: 0, serviceFee: 0 });
|
|
|
+
|
|
|
+function filterDishCartItems(arr) {
|
|
|
+ if (!Array.isArray(arr)) return [];
|
|
|
+ return arr.filter((it) => Number(it?.cuisineId ?? it?.id) !== -1);
|
|
|
+}
|
|
|
|
|
|
// 右侧长列表:按分类分段,每段为 { category, cuisines },支持一菜多分类(categoryIds)
|
|
|
const sectionList = computed(() => {
|
|
|
@@ -144,6 +164,13 @@ const sectionList = computed(() => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+// 已输入搜索关键词且当前无菜品:右侧展示空状态(与接口返回空列表一致)
|
|
|
+const showSearchEmptyState = computed(() => {
|
|
|
+ const kw = (searchKeyword.value ?? '').trim();
|
|
|
+ if (!kw) return false;
|
|
|
+ return (foodList.value?.length ?? 0) === 0;
|
|
|
+});
|
|
|
+
|
|
|
// 点击左侧分类时滚动到右侧对应段(scroll-into-view 用)
|
|
|
const scrollIntoViewId = ref('');
|
|
|
|
|
|
@@ -159,20 +186,15 @@ const cartList = computed(() => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
-// 用于展示的购物车列表:数量>0 的项展示;餐具(id=-1)始终展示(含数量为 0);若接口未返回餐具则补默认项
|
|
|
+// 用于展示的购物车列表:仅菜品(排除 cuisineId/id=-1);数量>0 的项展示
|
|
|
const displayCartList = computed(() => {
|
|
|
const apiItems = cartData.value?.items;
|
|
|
let base = [];
|
|
|
if (Array.isArray(apiItems) && apiItems.length > 0) {
|
|
|
- base = apiItems.filter((it) => (Number(it?.quantity) || 0) > 0 || Number(it?.cuisineId ?? it?.id) === -1);
|
|
|
+ base = filterDishCartItems(apiItems).filter((it) => (Number(it?.quantity) || 0) > 0);
|
|
|
} else {
|
|
|
base = cartList.value;
|
|
|
}
|
|
|
- const hasTableware = base.some((it) => Number(it?.cuisineId ?? it?.id) === -1);
|
|
|
- if (!hasTableware) {
|
|
|
- const fee = Number(cartData.value?.tablewareFee) || 0;
|
|
|
- return [...base, { cuisineId: -1, cuisineName: '餐具费', quantity: 0, unitPrice: fee || 0, subtotalAmount: 0 }];
|
|
|
- }
|
|
|
return base;
|
|
|
});
|
|
|
|
|
|
@@ -283,7 +305,8 @@ const sameCategory = (a, b) => String(a ?? '') === String(b ?? '');
|
|
|
|
|
|
// 将购物车数量同步到菜品列表:用购物车接口的 items 按 cuisineId 匹配 foodList 中的菜品并更新 quantity;items 为空时清空所有菜品数量
|
|
|
const mergeCartIntoFoodList = () => {
|
|
|
- const cartItems = pendingCartData ?? cartData.value?.items ?? [];
|
|
|
+ const raw = pendingCartData ?? cartData.value?.items ?? [];
|
|
|
+ const cartItems = filterDishCartItems(raw);
|
|
|
if (!Array.isArray(cartItems)) return;
|
|
|
if (!foodList.value.length) {
|
|
|
if (cartItems.length > 0) console.log('购物车已缓存,等 foodList 加载后再同步到菜品列表');
|
|
|
@@ -335,14 +358,13 @@ const fetchAndMergeCart = async (tableid) => {
|
|
|
if (!tableid) return;
|
|
|
try {
|
|
|
const cartRes = await GetOrderCart(tableid);
|
|
|
- const list = parseCartListFromResponse(cartRes);
|
|
|
+ const list = filterDishCartItems(parseCartListFromResponse(cartRes));
|
|
|
pendingCartData = list;
|
|
|
- // 按接口格式绑定:data.items / totalAmount / totalQuantity / tablewareFee
|
|
|
cartData.value = {
|
|
|
items: list,
|
|
|
totalAmount: Number(cartRes?.totalAmount) || 0,
|
|
|
totalQuantity: Number(cartRes?.totalQuantity) || 0,
|
|
|
- tablewareFee: Number(cartRes?.tablewareFee ?? cartRes?.tablewareAmount ?? 0) || 0
|
|
|
+ serviceFee: Number(cartRes?.serviceFee ?? cartRes?.serviceCharge ?? 0) || 0
|
|
|
};
|
|
|
mergeCartIntoFoodList();
|
|
|
console.log('购物车接口返回(data 层):', cartRes, '解析条数:', list.length);
|
|
|
@@ -408,7 +430,9 @@ const fetchCategoriesWithCuisines = async (storeId, keyword = '') => {
|
|
|
const cuisinesRaw = raw?.cuisines ?? raw?.cuisineList ?? [];
|
|
|
cuisines = Array.isArray(cuisinesRaw) ? cuisinesRaw : [];
|
|
|
}
|
|
|
- categories.value = Array.isArray(cats) ? cats : [];
|
|
|
+ const keywordTrim = params.keyword != null && String(params.keyword).trim() !== '' ? String(params.keyword).trim() : '';
|
|
|
+ const nextCats = Array.isArray(cats) ? cats : [];
|
|
|
+ categories.value = nextCats;
|
|
|
const normalized = cuisines.map((item) => {
|
|
|
const categoryId = item.categoryId ?? (categories.value[0]?.id ?? categories.value[0]?.categoryId);
|
|
|
const rawImg = item.images ?? item.cuisineImage ?? item.image ?? item.imageUrl ?? item.pic ?? item.cover ?? '';
|
|
|
@@ -429,6 +453,14 @@ const fetchCategoriesWithCuisines = async (storeId, keyword = '') => {
|
|
|
});
|
|
|
foodList.value = Array.from(byId.values());
|
|
|
mergeCartIntoFoodList();
|
|
|
+ // 全量菜单(无搜索词)成功时更新左侧分类快照
|
|
|
+ if (!keywordTrim && nextCats.length > 0) {
|
|
|
+ lastCategoriesForSidebar.value = nextCats.map((c) => ({ ...c }));
|
|
|
+ }
|
|
|
+ // 搜索无菜品时:接口常把分类滤空,左侧仍展示上次全量分类
|
|
|
+ if (keywordTrim && foodList.value.length === 0 && lastCategoriesForSidebar.value.length > 0) {
|
|
|
+ categories.value = lastCategoriesForSidebar.value.map((c) => ({ ...c }));
|
|
|
+ }
|
|
|
return true;
|
|
|
} catch (err) {
|
|
|
console.error('获取分类与菜品失败:', err);
|
|
|
@@ -506,11 +538,26 @@ const doSearch = async () => {
|
|
|
if (!storeId) return;
|
|
|
const keyword = searchKeyword.value?.trim() ?? '';
|
|
|
const ok = await fetchCategoriesWithCuisines(storeId, keyword);
|
|
|
- if (ok) {
|
|
|
+ if (ok && foodList.value.length > 0) {
|
|
|
nextTick(() => scrollToSection(0));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 搜索框从有内容变为空时,自动拉全量菜单(无需再点键盘「搜索」)
|
|
|
+watch(
|
|
|
+ () => (searchKeyword.value ?? '').trim(),
|
|
|
+ async (trimmed, prevTrimmed) => {
|
|
|
+ if (trimmed !== '') return;
|
|
|
+ if (prevTrimmed === undefined || prevTrimmed === '') return;
|
|
|
+ const storeId = uni.getStorageSync('currentStoreId') || '';
|
|
|
+ if (!storeId) return;
|
|
|
+ const ok = await fetchCategoriesWithCuisines(storeId, '');
|
|
|
+ if (ok && foodList.value.length > 0) {
|
|
|
+ nextTick(() => scrollToSection(0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
// 根据展示项(可能来自接口 cuisineId 或 foodList 的 id)找到 foodList 中的菜品
|
|
|
const findFoodByCartItem = (item) => {
|
|
|
const id = item?.id ?? item?.cuisineId;
|
|
|
@@ -520,7 +567,7 @@ const findFoodByCartItem = (item) => {
|
|
|
|
|
|
// 同步 cartData:根据 cuisineId 更新 items 中对应项的 quantity、subtotalAmount,并重算 totalAmount、totalQuantity
|
|
|
const syncCartDataFromFoodList = () => {
|
|
|
- const items = cartData.value?.items ?? [];
|
|
|
+ const items = filterDishCartItems(cartData.value?.items ?? []);
|
|
|
if (!items.length) return;
|
|
|
let totalAmount = 0;
|
|
|
let totalQuantity = 0;
|
|
|
@@ -536,22 +583,12 @@ const syncCartDataFromFoodList = () => {
|
|
|
cartData.value = { ...cartData.value, items: nextItems, totalAmount, totalQuantity };
|
|
|
};
|
|
|
|
|
|
-// 判断是否为餐具(cuisineId 或 id 为 -1),餐具可修改数量(含减至 0)
|
|
|
-const isTableware = (item) => {
|
|
|
- if (!item) return false;
|
|
|
- const id = item.id ?? item.cuisineId;
|
|
|
- return Number(id) === -1;
|
|
|
-};
|
|
|
-
|
|
|
// 更新菜品数量:菜品 id 一致则全部同步为同一数量,触发响应式;新增加入购物车时调接口;并同步 cartData
|
|
|
-// Update 接口返回 400 时不改页面数量和金额(会回滚本地状态);餐具费为 0 元时不允许修改餐具数量
|
|
|
+// Update 接口返回 400 时不改页面数量和金额(会回滚本地状态)
|
|
|
const updateFoodQuantity = (food, delta) => {
|
|
|
if (!food) return;
|
|
|
const id = food.id ?? food.cuisineId;
|
|
|
- if (Number(id) === -1) {
|
|
|
- const unitPrice = Number(food?.unitPrice ?? food?.price ?? 0) || 0;
|
|
|
- if (unitPrice <= 0) return;
|
|
|
- }
|
|
|
+ if (Number(id) === -1) return;
|
|
|
const prevQty = food.quantity || 0;
|
|
|
const nextQty = Math.max(0, prevQty + delta);
|
|
|
const sameId = (item) =>
|
|
|
@@ -594,18 +631,7 @@ const updateFoodQuantity = (food, delta) => {
|
|
|
|
|
|
if (tableId.value && delta !== 0) {
|
|
|
const needAdd = delta > 0 && (idx < 0 || nextQty === 1);
|
|
|
- const isTablewareItem = Number(id) === -1;
|
|
|
- if (isTablewareItem && fromNumberOfDiners.value) {
|
|
|
- PutOrderCartUpdateTableware({
|
|
|
- quantity: nextQty,
|
|
|
- tableId: tableId.value
|
|
|
- }).catch((err) => {
|
|
|
- console.error('更新餐具数量失败:', err);
|
|
|
- applyQuantity(prevQty);
|
|
|
- });
|
|
|
- } else if (isTablewareItem) {
|
|
|
- // 非选座页进入:餐具仅本地更新,不调 update-tableware
|
|
|
- } else if (needAdd) {
|
|
|
+ if (needAdd) {
|
|
|
PostOrderCartAdd({
|
|
|
cuisineId: id,
|
|
|
quantity: nextQty,
|
|
|
@@ -744,32 +770,23 @@ const handleCartClose = () => {
|
|
|
// 清空购物车:调用 /store/order/cart/clear,成功后用接口返回的数据更新购物车
|
|
|
const handleCartClear = () => {
|
|
|
const items = cartData.value?.items ?? [];
|
|
|
- const dishItems = items.filter((it) => Number(it?.cuisineId ?? it?.id) !== -1);
|
|
|
+ const dishItems = filterDishCartItems(items);
|
|
|
|
|
|
const applyClearResult = (res) => {
|
|
|
- const list = parseCartListFromResponse(res) ?? [];
|
|
|
+ const list = filterDishCartItems(parseCartListFromResponse(res) ?? []);
|
|
|
pendingCartData = list;
|
|
|
const totalAmount = Number(res?.totalAmount) || 0;
|
|
|
const totalQuantity = Number(res?.totalQuantity) || 0;
|
|
|
- const tablewareFee = Number(res?.tablewareFee ?? res?.tablewareAmount ?? 0) || list.reduce((s, it) => {
|
|
|
- if (Number(it?.cuisineId ?? it?.id) !== -1) return s;
|
|
|
- const line = it?.subtotalAmount != null ? Number(it.subtotalAmount) : (Number(it?.quantity) || 0) * (Number(it?.unitPrice ?? it?.price) || 0);
|
|
|
- return s + line;
|
|
|
- }, 0);
|
|
|
- cartData.value = { items: list, totalAmount, totalQuantity, tablewareFee };
|
|
|
+ const serviceFee = Number(res?.serviceFee ?? res?.serviceCharge ?? 0) || 0;
|
|
|
+ cartData.value = { items: list, totalAmount, totalQuantity, serviceFee };
|
|
|
mergeCartIntoFoodList();
|
|
|
cartModalOpen.value = false;
|
|
|
uni.showToast({ title: '已清空购物车', icon: 'success' });
|
|
|
};
|
|
|
|
|
|
if (!tableId.value) {
|
|
|
- const tablewareItems = items.filter((it) => Number(it?.cuisineId ?? it?.id) === -1);
|
|
|
- const utensilFee = tablewareItems.reduce((sum, it) => {
|
|
|
- const line = it?.subtotalAmount != null ? Number(it.subtotalAmount) : (Number(it?.quantity) || 0) * (Number(it?.unitPrice ?? it?.price) || 0);
|
|
|
- return sum + line;
|
|
|
- }, 0);
|
|
|
- const utensilQty = tablewareItems.reduce((s, i) => s + (Number(i?.quantity) || 0), 0);
|
|
|
- applyClearResult({ items: tablewareItems, totalAmount: utensilFee, totalQuantity: utensilQty, tablewareFee: utensilFee });
|
|
|
+ foodList.value = foodList.value.map((f) => ({ ...f, quantity: 0 }));
|
|
|
+ applyClearResult({ items: [], totalAmount: 0, totalQuantity: 0, serviceFee: 0 });
|
|
|
return;
|
|
|
}
|
|
|
if (dishItems.length === 0) {
|
|
|
@@ -784,44 +801,25 @@ const handleCartClear = () => {
|
|
|
});
|
|
|
};
|
|
|
|
|
|
-// 从购物车项中计算餐具费:cuisineId/id 为 -1 的项为餐具,其金额合计为餐具费
|
|
|
-const getTablewareFeeFromCart = () => {
|
|
|
- const items = cartData.value?.items ?? displayCartList.value ?? [];
|
|
|
- return (Array.isArray(items) ? items : []).reduce((sum, it) => {
|
|
|
- const id = it?.cuisineId ?? it?.id;
|
|
|
- if (Number(id) !== -1) return sum;
|
|
|
- const line = it?.subtotalAmount != null ? Number(it.subtotalAmount) : (Number(it?.quantity) || 0) * (Number(it?.unitPrice ?? it?.price) || 0);
|
|
|
- return sum + line;
|
|
|
- }, 0);
|
|
|
-};
|
|
|
-
|
|
|
// 下单点击:先带购物车数据跳转确认订单页,创建订单在确认页点击「确认下单」时再调
|
|
|
const handleOrderClick = () => {
|
|
|
- // 仅餐具无菜品时不允许下单
|
|
|
const items = displayCartList.value ?? [];
|
|
|
- const hasDish = items.some((it) => Number(it?.cuisineId ?? it?.id) !== -1);
|
|
|
- if (!hasDish && items.length > 0) {
|
|
|
- uni.showToast({ title: '请至少选择一道菜品', icon: 'none' });
|
|
|
- return;
|
|
|
- }
|
|
|
if (items.length === 0) {
|
|
|
uni.showToast({ title: '请先选择菜品', icon: 'none' });
|
|
|
return;
|
|
|
}
|
|
|
- const fromApi = Number(cartData.value?.tablewareFee) || 0;
|
|
|
- const fromItems = getTablewareFeeFromCart();
|
|
|
- const utensilFee = fromApi > 0 ? fromApi : fromItems;
|
|
|
const totalAmount = displayTotalAmount.value;
|
|
|
- const dishTotal = Math.max(0, Number(totalAmount) - Number(utensilFee));
|
|
|
+ const serviceFeeVal = Number(cartData.value?.serviceFee) || 0;
|
|
|
const cartPayload = {
|
|
|
list: displayCartListWithTags.value,
|
|
|
totalAmount,
|
|
|
- dishTotal,
|
|
|
+ dishTotal: totalAmount,
|
|
|
+ serviceFee: serviceFeeVal,
|
|
|
totalQuantity: displayTotalQuantity.value,
|
|
|
tableId: tableId.value,
|
|
|
tableNumber: tableNumber.value,
|
|
|
diners: currentDiners.value,
|
|
|
- utensilFee: Number(utensilFee) || 0
|
|
|
+ storeId: uni.getStorageSync('currentStoreId') || ''
|
|
|
};
|
|
|
uni.setStorageSync('placeOrderCart', JSON.stringify(cartPayload));
|
|
|
const query = [];
|
|
|
@@ -837,19 +835,10 @@ onLoad(async (options) => {
|
|
|
const diners = options.diners || '';
|
|
|
tableId.value = tableid;
|
|
|
currentDiners.value = diners;
|
|
|
- fromNumberOfDiners.value = diners !== '' && diners != null; // 仅从选座页进入时带 diners 参数
|
|
|
if (tableid) uni.setStorageSync('currentTableId', tableid);
|
|
|
if (diners) uni.setStorageSync('currentDiners', diners);
|
|
|
console.log('点餐页接收参数 - 桌号(tableid):', tableid, '就餐人数(diners):', diners);
|
|
|
|
|
|
- // 更新餐具数量:仅从选座页进入时调用 update-tableware 接口
|
|
|
- if (fromNumberOfDiners.value && tableid) {
|
|
|
- PutOrderCartUpdateTableware({
|
|
|
- quantity: Number(diners) || 1,
|
|
|
- tableId: parseInt(tableid, 10) || 0
|
|
|
- }).catch((err) => console.warn('更新餐具数量失败:', err));
|
|
|
- }
|
|
|
-
|
|
|
// 先拉取购物车并缓存,再加载菜品,保证合并时 pendingCartData 已就绪,避免不返显
|
|
|
if (tableid) {
|
|
|
await fetchAndMergeCart(tableid).catch((err) => console.error('获取购物车失败:', err));
|
|
|
@@ -865,12 +854,14 @@ onLoad(async (options) => {
|
|
|
if (msg.event === 'cart_update' && msg.data) {
|
|
|
try {
|
|
|
const payload = typeof msg.data === 'string' ? JSON.parse(msg.data) : msg.data;
|
|
|
- const items = payload?.items ?? [];
|
|
|
+ const items = filterDishCartItems(payload?.items ?? []);
|
|
|
cartData.value = {
|
|
|
items: Array.isArray(items) ? items : [],
|
|
|
totalAmount: Number(payload?.totalAmount) || 0,
|
|
|
totalQuantity: Number(payload?.totalQuantity) || 0,
|
|
|
- tablewareFee: Number(payload?.tablewareFee ?? payload?.tablewareAmount ?? 0) || (cartData.value?.tablewareFee ?? 0)
|
|
|
+ serviceFee:
|
|
|
+ Number(payload?.serviceFee ?? payload?.serviceCharge ?? 0) ||
|
|
|
+ (cartData.value?.serviceFee ?? 0)
|
|
|
};
|
|
|
pendingCartData = null;
|
|
|
mergeCartIntoFoodList();
|
|
|
@@ -902,9 +893,6 @@ onLoad(async (options) => {
|
|
|
tableNumber.value = data?.tableNumber ?? data?.tableNo ?? '';
|
|
|
tableNumberFetched.value = true;
|
|
|
storeName.value = data?.storeName ?? data?.storeInfo?.storeName ?? '';
|
|
|
- // 餐具费:点餐页接口可能返回,若购物车未带则用此处兜底
|
|
|
- const fee = Number(data?.tablewareFee ?? data?.tablewareAmount ?? 0) || 0;
|
|
|
- if (fee > 0) cartData.value = { ...cartData.value, tablewareFee: fee };
|
|
|
|
|
|
// 成功后调接口获取菜品种类(storeId 取自点餐页接口返回,若无则需从别处获取)
|
|
|
const storeId = res?.storeId ?? data?.storeId ?? '';
|
|
|
@@ -979,14 +967,24 @@ onUnload(() => {
|
|
|
}
|
|
|
|
|
|
.top-info {
|
|
|
- font-size: 28rpx;
|
|
|
- color: #888888;
|
|
|
- text-align: center;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 48rpx;
|
|
|
width: 100%;
|
|
|
- padding: 20rpx 0;
|
|
|
+ padding: 16rpx 30rpx 12rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
background-color: #fff;
|
|
|
}
|
|
|
|
|
|
+.top-info__item {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #aaaaaa;
|
|
|
+ line-height: 1.4;
|
|
|
+}
|
|
|
+
|
|
|
.search-box {
|
|
|
width: 90%;
|
|
|
margin-left: 5%;
|
|
|
@@ -1079,6 +1077,32 @@ onUnload(() => {
|
|
|
overflow: hidden;
|
|
|
margin: 0 20rpx;
|
|
|
}
|
|
|
+
|
|
|
+.food-search-empty {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 48rpx 32rpx 80rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background-color: #f7f9fa;
|
|
|
+}
|
|
|
+
|
|
|
+.food-search-empty__img {
|
|
|
+ width: 360rpx;
|
|
|
+ max-width: 80%;
|
|
|
+ margin-bottom: 32rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.food-search-empty__text {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #999999;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
.food-list {
|
|
|
flex: 1;
|
|
|
min-height: 0;
|