|
|
@@ -1,27 +1,31 @@
|
|
|
<template>
|
|
|
- <!-- 点餐页:左上角永远返回主页 -->
|
|
|
+ <!-- 点餐页:左上角永远返回主页,顶部固定 -->
|
|
|
<view class="page-wrap">
|
|
|
- <NavBar title="点餐" only-home />
|
|
|
+ <view class="top-fixed">
|
|
|
+ <NavBar :title="navTitle" only-home />
|
|
|
+ <view class="top-info">桌号:{{ displayTableNumber }} 就餐人数:{{ currentDiners }}人</view>
|
|
|
+ <input type="text" placeholder="请输入菜品名称" class="search-input" />
|
|
|
+ </view>
|
|
|
<view class="content">
|
|
|
- <view class="top-info">桌号:{{ displayTableNumber }} 就餐人数:{{ currentDiners }}人</view>
|
|
|
- <!-- 搜索 -->
|
|
|
- <input type="text" placeholder="请输入菜品名称" class="search-input" />
|
|
|
-
|
|
|
<!-- 内容 -->
|
|
|
<view class="content-box">
|
|
|
<!-- 左侧分类列表 -->
|
|
|
- <scroll-view class="category-list" scroll-y>
|
|
|
- <view v-for="(category, index) in categories" :key="index" class="category-item"
|
|
|
- :class="{ active: currentCategoryIndex === index }" @click="selectCategory(index)">
|
|
|
- {{ category.categoryName }}
|
|
|
- </view>
|
|
|
- </scroll-view>
|
|
|
+ <view class="category-list-wrap">
|
|
|
+ <scroll-view class="category-list" scroll-y>
|
|
|
+ <view v-for="(category, index) in categories" :key="index" class="category-item"
|
|
|
+ :class="{ active: currentCategoryIndex === index }" @click="selectCategory(index)">
|
|
|
+ {{ category.categoryName }}
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
|
|
|
<!-- 右侧菜品列表 -->
|
|
|
- <scroll-view class="food-list" scroll-y>
|
|
|
- <FoodCard v-for="(food, index) in currentFoodList" :key="food.id || food.cuisineId || index" :food="food"
|
|
|
- :table-id="tableId" @increase="handleIncrease" @decrease="handleDecrease"/>
|
|
|
- </scroll-view>
|
|
|
+ <view class="food-list-wrap">
|
|
|
+ <scroll-view class="food-list" scroll-y>
|
|
|
+ <FoodCard v-for="(food, index) in currentFoodList" :key="food.id || food.cuisineId || index" :food="food"
|
|
|
+ :table-id="tableId" @increase="handleIncrease" @decrease="handleDecrease"/>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 底部下单:按接口格式展示 totalQuantity / totalAmount -->
|
|
|
@@ -54,14 +58,17 @@ import CouponModal from "./components/CouponModal.vue";
|
|
|
import CartModal from "./components/CartModal.vue";
|
|
|
import SelectCouponModal from "./components/SelectCouponModal.vue";
|
|
|
import { go } from "@/utils/utils.js";
|
|
|
-import { DiningOrderFood, GetStoreCategories, GetStoreCuisines, getOrderSseConfig, GetOrderCart, PostOrderCartAdd, PostOrderCartUpdate, PostOrderCartClear, PutOrderCartUpdateTableware, GetUserOwnedCouponList } from "@/api/dining.js";
|
|
|
+import { DiningOrderFood, GetStoreCategories, GetStoreCuisines, GetStoreDetail, getOrderSseConfig, GetOrderCart, PostOrderCartAdd, PostOrderCartUpdate, PostOrderCartClear, PutOrderCartUpdateTableware, GetUserOwnedCouponList } from "@/api/dining.js";
|
|
|
import { createSSEConnection } from "@/utils/sse.js";
|
|
|
|
|
|
+const storeName = ref(''); // 店铺名称,用于导航栏标题
|
|
|
const tableId = ref(''); // 桌号ID,来自上一页 url 参数 tableid,用于接口入参
|
|
|
const tableNumber = ref(''); // 桌号展示,来自 dining/page-info 接口返回的 tableNumber
|
|
|
const tableNumberFetched = ref(false); // 是否已请求过桌号(避免未返回前用 tableId 展示导致闪一下 43)
|
|
|
const currentDiners = ref(uni.getStorageSync('currentDiners') || '');
|
|
|
|
|
|
+const navTitle = computed(() => storeName.value || '点餐');
|
|
|
+
|
|
|
// 桌号展示:优先用接口返回的 tableNumber,未请求完前不显示 tableId,避免闪 43 再变 2
|
|
|
const displayTableNumber = computed(() => {
|
|
|
if (tableNumber.value) return tableNumber.value;
|
|
|
@@ -70,6 +77,7 @@ const displayTableNumber = computed(() => {
|
|
|
});
|
|
|
let sseRequestTask = null; // 订单 SSE 连接(封装后兼容小程序),页面卸载时需 abort()
|
|
|
const currentCategoryIndex = ref(0);
|
|
|
+const foodListScrollTop = ref(0);
|
|
|
const couponModalOpen = ref(false);
|
|
|
const cartModalOpen = ref(false);
|
|
|
const selectCouponModalOpen = ref(false);
|
|
|
@@ -636,6 +644,7 @@ onLoad(async (options) => {
|
|
|
const data = res?.data ?? res ?? {};
|
|
|
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 };
|
|
|
@@ -643,6 +652,13 @@ onLoad(async (options) => {
|
|
|
// 成功后调接口获取菜品种类(storeId 取自点餐页接口返回,若无则需从别处获取)
|
|
|
const storeId = res?.storeId ?? data?.storeId ?? '';
|
|
|
if (storeId) uni.setStorageSync('currentStoreId', storeId);
|
|
|
+ if (storeId && !storeName.value) {
|
|
|
+ try {
|
|
|
+ const storeRes = await GetStoreDetail(storeId);
|
|
|
+ const storeData = storeRes?.data ?? storeRes;
|
|
|
+ storeName.value = storeData?.storeInfo?.storeName ?? storeData?.storeName ?? '';
|
|
|
+ } catch (_) {}
|
|
|
+ }
|
|
|
if (storeId) {
|
|
|
try {
|
|
|
const categoriesRes = await GetStoreCategories({ storeId });
|
|
|
@@ -675,6 +691,14 @@ onLoad(async (options) => {
|
|
|
}
|
|
|
} else {
|
|
|
tableNumberFetched.value = true;
|
|
|
+ const storeId = uni.getStorageSync('currentStoreId') || '';
|
|
|
+ if (storeId && !storeName.value) {
|
|
|
+ try {
|
|
|
+ const storeRes = await GetStoreDetail(storeId);
|
|
|
+ const storeData = storeRes?.data ?? storeRes;
|
|
|
+ storeName.value = storeData?.storeInfo?.storeName ?? storeData?.storeName ?? '';
|
|
|
+ } catch (_) {}
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
|
|
|
@@ -695,12 +719,28 @@ onUnload(() => {
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.content {
|
|
|
+.page-wrap {
|
|
|
+ height: 100vh;
|
|
|
+ overflow: hidden;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- height: 100vh;
|
|
|
background-color: #f7f9fa;
|
|
|
- padding-bottom: 100rpx;
|
|
|
+}
|
|
|
+.top-fixed {
|
|
|
+ flex-shrink: 0;
|
|
|
+ z-index: 100;
|
|
|
+ background-color: #fff;
|
|
|
+ padding-bottom: 20rpx;
|
|
|
+}
|
|
|
+.content {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ /* 底部预留:BottomActionBar 高度(100rpx) + 内边距(20rpx) + 安全区 */
|
|
|
+ padding-bottom: calc(120rpx + constant(safe-area-inset-bottom));
|
|
|
+ padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
@@ -727,17 +767,29 @@ onUnload(() => {
|
|
|
}
|
|
|
|
|
|
.content-box {
|
|
|
- display: flex;
|
|
|
flex: 1;
|
|
|
+ min-height: 0;
|
|
|
overflow: hidden;
|
|
|
+ display: flex;
|
|
|
margin-top: 20rpx;
|
|
|
}
|
|
|
|
|
|
-// 左侧分类列表
|
|
|
-.category-list {
|
|
|
+// 左侧分类列表容器(给 scroll-view 提供固定高度)
|
|
|
+.category-list-wrap {
|
|
|
width: 180rpx;
|
|
|
- background-color: #fff;
|
|
|
+ flex-shrink: 0;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+ align-self: stretch;
|
|
|
+}
|
|
|
+.category-list {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
height: 100%;
|
|
|
+ background-color: #fff;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.category-item {
|
|
|
@@ -757,11 +809,19 @@ onUnload(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 右侧菜品列表
|
|
|
-.food-list {
|
|
|
+// 右侧菜品列表容器(给 scroll-view 提供固定高度)
|
|
|
+.food-list-wrap {
|
|
|
flex: 1;
|
|
|
- // background-color: #fff;
|
|
|
- // padding: 0 20rpx;
|
|
|
+ min-width: 0;
|
|
|
+ min-height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
margin: 0 20rpx;
|
|
|
}
|
|
|
+.food-list {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
</style>
|