|
|
@@ -51,8 +51,8 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 操作按钮 -->
|
|
|
- <view class="order-actions">
|
|
|
+ <!-- 操作按钮:已完成(3)不显示 -->
|
|
|
+ <view class="order-actions" v-if="order.orderStatus !== 3">
|
|
|
<view class="action-btn outline" @click="handleAddFood(order)">
|
|
|
去加餐
|
|
|
</view>
|
|
|
@@ -72,46 +72,179 @@
|
|
|
|
|
|
<script setup>
|
|
|
import { onLoad } from "@dcloudio/uni-app";
|
|
|
-import { ref, computed } from "vue";
|
|
|
+import { ref, computed, watch } from "vue";
|
|
|
import { getFileUrl } from "@/utils/file.js";
|
|
|
import { go } from "@/utils/utils.js";
|
|
|
+import { GetMyOrders } from "@/api/dining.js";
|
|
|
|
|
|
const activeTab = ref('current');
|
|
|
const searchKeyword = ref('');
|
|
|
|
|
|
-// 示例订单数据
|
|
|
-const currentOrders = ref([
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- orderNo: '1929065620709298441',
|
|
|
- storeName: '正旗手选海鲜烧烤(东港店)',
|
|
|
- createTime: '2025-06-01 14:40:58',
|
|
|
- totalPrice: 19.9,
|
|
|
- goodsCount: 2,
|
|
|
- statusText: '进行中',
|
|
|
- statusClass: 'status-active',
|
|
|
- goodsImages: ['/static/demo.png', '/static/demo.png']
|
|
|
- }
|
|
|
-]);
|
|
|
+// 分页参数
|
|
|
+const pageSize = 10;
|
|
|
+const currentPage = ref({ current: 1, history: 1 });
|
|
|
+const loading = ref(false);
|
|
|
+const noMore = ref({ current: false, history: false });
|
|
|
+
|
|
|
+// records 每项:order 为订单信息,cuisineItems 为菜品数组;兼容直接平铺的旧结构
|
|
|
+function normalizeOrder(record) {
|
|
|
+ const order = record?.order ?? record;
|
|
|
+ const cuisineItems = record?.cuisineItems ?? [];
|
|
|
+ const items = Array.isArray(cuisineItems) ? cuisineItems : [];
|
|
|
+
|
|
|
+ const orderStatus = order?.orderStatus ?? order?.status;
|
|
|
+ const payStatus = order?.payStatus;
|
|
|
+ const statusText = getDisplayStatusText(payStatus, orderStatus, order?.statusText ?? order?.orderStatusName);
|
|
|
+ const statusClass = getDisplayStatusClass(payStatus, orderStatus);
|
|
|
+
|
|
|
+ const goodsCount = items.reduce((sum, it) => sum + (Number(it?.quantity) || 0), 0) || order?.dinerCount || 0;
|
|
|
+ const goodsImages = items
|
|
|
+ .map((it) => it?.cuisineImage ?? it?.image ?? it?.imageUrl ?? '')
|
|
|
+ .filter((url) => url && String(url).trim());
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: order?.id,
|
|
|
+ orderNo: order?.orderNo ?? order?.orderNumber ?? order?.orderId ?? '',
|
|
|
+ storeId: order?.storeId,
|
|
|
+ storeName: order?.storeName ?? order?.store?.name ?? (order?.storeId != null ? `门店${order.storeId}` : '—'),
|
|
|
+ tableId: order?.tableId,
|
|
|
+ tableNumber: order?.tableNumber ?? order?.tableId ?? '—',
|
|
|
+ contactPhone: order?.contactPhone ?? '',
|
|
|
+ createTime: order?.createdTime ?? order?.createTime ?? order?.orderTime ?? '—',
|
|
|
+ totalPrice: order?.payAmount ?? order?.totalPrice ?? order?.totalAmount ?? 0,
|
|
|
+ goodsCount,
|
|
|
+ statusText,
|
|
|
+ statusClass,
|
|
|
+ orderStatus,
|
|
|
+ payStatus,
|
|
|
+ dinerCount: order?.dinerCount,
|
|
|
+ discountAmount: order?.discountAmount ?? 0,
|
|
|
+ remark: order?.remark,
|
|
|
+ goodsImages,
|
|
|
+ cuisineItems: items
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+// orderStatus 订单状态:0 待支付,1 已支付,2 已取消,3 已完成
|
|
|
+function getDisplayStatusText(payStatus, orderStatus, fallback) {
|
|
|
+ if (fallback) return fallback;
|
|
|
+ return getOrderStatusText(orderStatus);
|
|
|
+}
|
|
|
+
|
|
|
+function getOrderStatusText(status) {
|
|
|
+ if (status == null && status !== 0) return '—';
|
|
|
+ const n = Number(status);
|
|
|
+ if (n === 0) return '待支付';
|
|
|
+ if (n === 1) return '已支付';
|
|
|
+ if (n === 2) return '已取消';
|
|
|
+ if (n === 3) return '已完成';
|
|
|
+ return String(status);
|
|
|
+}
|
|
|
+
|
|
|
+function getDisplayStatusClass(payStatus, orderStatus) {
|
|
|
+ return getStatusClass(orderStatus);
|
|
|
+}
|
|
|
|
|
|
+function getStatusClass(status) {
|
|
|
+ if (status == null && status !== 0) return '';
|
|
|
+ const n = Number(status);
|
|
|
+ if (n === 0) return 'status-unpaid'; // 待支付
|
|
|
+ if (n === 1) return 'status-paid'; // 已支付
|
|
|
+ if (n === 2) return 'status-cancelled'; // 已取消
|
|
|
+ if (n === 3) return 'status-completed'; // 已完成
|
|
|
+ return 'status-unpaid';
|
|
|
+}
|
|
|
+
|
|
|
+const currentOrders = ref([]);
|
|
|
const historyOrders = ref([]);
|
|
|
|
|
|
-// 当前显示的订单列表
|
|
|
+// 当前显示的订单列表(含搜索过滤)
|
|
|
const currentOrderList = computed(() => {
|
|
|
const orders = activeTab.value === 'current' ? currentOrders.value : historyOrders.value;
|
|
|
- if (!searchKeyword.value) {
|
|
|
- return orders;
|
|
|
- }
|
|
|
+ if (!searchKeyword.value) return orders;
|
|
|
return orders.filter(order =>
|
|
|
- order.orderNo.includes(searchKeyword.value) ||
|
|
|
- order.storeName.includes(searchKeyword.value)
|
|
|
+ (order.orderNo && order.orderNo.includes(searchKeyword.value)) ||
|
|
|
+ (order.storeName && order.storeName.includes(searchKeyword.value))
|
|
|
);
|
|
|
});
|
|
|
|
|
|
-// 处理订单详情
|
|
|
+// type:0 未支付订单,1 历史订单
|
|
|
+const getOrderTypeByTab = (tab) => (tab === 'current' ? 0 : 1);
|
|
|
+
|
|
|
+async function loadOrderList(tab, append = false) {
|
|
|
+ const pageKey = tab === 'current' ? 'current' : 'history';
|
|
|
+ if (loading.value) return;
|
|
|
+ if (append && noMore.value[pageKey]) return;
|
|
|
+ if (!append) {
|
|
|
+ currentPage.value[pageKey] = 1;
|
|
|
+ noMore.value[pageKey] = false;
|
|
|
+ }
|
|
|
+ const page = currentPage.value[pageKey];
|
|
|
+ if (append && page === 1) return;
|
|
|
+
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const params = {
|
|
|
+ current: page,
|
|
|
+ size: pageSize,
|
|
|
+ type: getOrderTypeByTab(tab)
|
|
|
+ };
|
|
|
+ const res = await GetMyOrders(params);
|
|
|
+ // /store/order/my-orders:返回 data,可能为 { records, total } 或 { data: { records, total } }
|
|
|
+ const raw = res && typeof res === 'object' ? res : {};
|
|
|
+ const list = Array.isArray(raw.records)
|
|
|
+ ? raw.records
|
|
|
+ : Array.isArray(raw.data?.records)
|
|
|
+ ? raw.data.records
|
|
|
+ : Array.isArray(raw.list)
|
|
|
+ ? raw.list
|
|
|
+ : [];
|
|
|
+ const normalized = list.map(normalizeOrder);
|
|
|
+
|
|
|
+ if (tab === 'current') {
|
|
|
+ currentOrders.value = append ? [...currentOrders.value, ...normalized] : normalized;
|
|
|
+ } else {
|
|
|
+ historyOrders.value = append ? [...historyOrders.value, ...normalized] : normalized;
|
|
|
+ }
|
|
|
+
|
|
|
+ const total =
|
|
|
+ raw.total != null ? Number(raw.total) : (raw.data?.total != null ? Number(raw.data.total) : 0);
|
|
|
+ if (normalized.length < pageSize || (page * pageSize >= total)) {
|
|
|
+ noMore.value[pageKey] = true;
|
|
|
+ } else {
|
|
|
+ currentPage.value[pageKey] = page + 1;
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: e?.message || '加载失败', icon: 'none' });
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const storeIdRef = ref('');
|
|
|
+const tableIdRef = ref('');
|
|
|
+const STORAGE_STORE_ID = 'currentStoreId';
|
|
|
+const STORAGE_TABLE_ID = 'currentTableId';
|
|
|
+
|
|
|
+function doLoad() {
|
|
|
+ currentPage.value = { current: 1, history: 1 };
|
|
|
+ noMore.value = { current: false, history: false };
|
|
|
+ loadOrderList(activeTab.value, false);
|
|
|
+}
|
|
|
+
|
|
|
+watch(activeTab, (tab) => {
|
|
|
+ // 每次切换标签都重新拉取该 tab 的数据,保证来回切换时列表会更新
|
|
|
+ loadOrderList(tab, false);
|
|
|
+});
|
|
|
+
|
|
|
+// 处理订单详情(须传 orderId 详情页才会请求接口)
|
|
|
const handleOrderDetail = (order) => {
|
|
|
- console.log('订单详情');
|
|
|
- go('/pages/orderInfo/orderDetail');
|
|
|
+ const orderId = order?.id ?? order?.orderId ?? '';
|
|
|
+ if (!orderId) {
|
|
|
+ uni.showToast({ title: '订单ID缺失', icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ go(`/pages/orderInfo/orderDetail?orderId=${encodeURIComponent(String(orderId))}`);
|
|
|
};
|
|
|
|
|
|
// 切换标签页
|
|
|
@@ -125,24 +258,36 @@ const handleStoreClick = (order) => {
|
|
|
// TODO: 跳转到店铺详情
|
|
|
};
|
|
|
|
|
|
-// 处理加餐
|
|
|
+// 处理加餐:带上该订单的桌号和人数,点餐页依赖 tableid、diners 拉取列表和购物车
|
|
|
const handleAddFood = (order) => {
|
|
|
- console.log('去加餐:', order);
|
|
|
- // TODO: 跳转到点餐页面
|
|
|
- go('/pages/orderFood/index');
|
|
|
+ const tableid = order?.tableId ?? order?.tableNumber ?? uni.getStorageSync(STORAGE_TABLE_ID) ?? '';
|
|
|
+ const diners = order?.dinerCount ?? order?.diners ?? uni.getStorageSync('currentDiners') ?? '';
|
|
|
+ const q = [];
|
|
|
+ if (tableid !== '' && tableid != null) q.push(`tableid=${encodeURIComponent(String(tableid))}`);
|
|
|
+ if (diners !== '' && diners != null) q.push(`diners=${encodeURIComponent(String(diners))}`);
|
|
|
+ go(q.length ? `/pages/orderFood/index?${q.join('&')}` : '/pages/orderFood/index');
|
|
|
};
|
|
|
|
|
|
-// 处理结算
|
|
|
+// 处理结算:带上桌号、人数、订单金额、备注,确认订单页用于展示和提交
|
|
|
const handleCheckout = (order) => {
|
|
|
- console.log('去结算:', order);
|
|
|
- // TODO: 跳转到结算页面
|
|
|
- go('/pages/placeOrder/index');
|
|
|
+ const tableId = order?.tableId ?? order?.tableNumber ?? '';
|
|
|
+ const diners = order?.dinerCount ?? order?.diners ?? '';
|
|
|
+ const totalAmount = order?.totalPrice ?? order?.payAmount ?? 0;
|
|
|
+ const remark = (order?.remark ?? '').trim().slice(0, 30);
|
|
|
+ const q = [];
|
|
|
+ if (tableId !== '' && tableId != null) q.push(`tableId=${encodeURIComponent(String(tableId))}`);
|
|
|
+ if (diners !== '' && diners != null) q.push(`diners=${encodeURIComponent(String(diners))}`);
|
|
|
+ if (totalAmount != null && totalAmount !== '') q.push(`totalAmount=${encodeURIComponent(String(totalAmount))}`);
|
|
|
+ if (remark !== '') q.push(`remark=${encodeURIComponent(remark)}`);
|
|
|
+ go(q.length ? `/pages/placeOrder/index?${q.join('&')}` : '/pages/placeOrder/index');
|
|
|
};
|
|
|
|
|
|
-onLoad((e) => {
|
|
|
- uni.setNavigationBarTitle({
|
|
|
- title: '我的订单'
|
|
|
- });
|
|
|
+onLoad((options) => {
|
|
|
+ uni.setNavigationBarTitle({ title: '我的订单' });
|
|
|
+ // 优先用 URL 参数,否则用本地缓存(点餐/下单流程会写入)
|
|
|
+ storeIdRef.value = options?.storeId ?? uni.getStorageSync(STORAGE_STORE_ID) ?? '';
|
|
|
+ tableIdRef.value = options?.tableId ?? uni.getStorageSync(STORAGE_TABLE_ID) ?? '';
|
|
|
+ doLoad();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
@@ -275,6 +420,14 @@ onLoad((e) => {
|
|
|
color: #008844;
|
|
|
}
|
|
|
|
|
|
+ &.status-unpaid {
|
|
|
+ color: #008844;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.status-paid {
|
|
|
+ color: #008844;
|
|
|
+ }
|
|
|
+
|
|
|
&.status-completed {
|
|
|
color: #999;
|
|
|
}
|