| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- <template>
- <view class="hotel-customer-theme orders-page">
- <!-- 房间信息 -->
- <view v-if="roomInfo" class="o-room-bar">
- <text>🏨 {{ roomInfo.roomNo }} {{ roomInfo.roomTypeName || '' }}</text>
- </view>
- <!-- 加载中 -->
- <view v-if="loading && orderList.length === 0" class="o-loading">
- <text>加载中...</text>
- </view>
- <!-- 空状态 -->
- <view v-else-if="orderList.length === 0" class="o-empty">
- <text class="o-empty-icon">📋</text>
- <text class="o-empty-text">暂无订单记录</text>
- <view class="o-empty-btn" @click="goMenu">去点餐</view>
- </view>
- <!-- 订单列表 -->
- <scroll-view v-else scroll-y class="o-scroll" @scrolltolower="loadMore">
- <view class="o-list">
- <view
- v-for="item in orderList"
- :key="item.id"
- class="o-card"
- @click="viewDetail(item)"
- >
- <!-- 卡片头部 -->
- <view class="o-card-header">
- <text class="o-card-no">{{ item.orderNo }}</text>
- <text class="o-card-status" :class="'o-st--' + item.status">{{ statusLabel(item.status) }}</text>
- </view>
- <!-- 菜品摘要 -->
- <view class="o-card-body">
- <view v-for="(dish, dIdx) in getItemsPreview(item)" :key="dIdx" class="o-card-dish">
- <text class="o-card-dish-name">{{ dish.dishName }} ×{{ dish.quantity }}</text>
- <text class="o-card-dish-spec" v-if="dish.specDesc">{{ dish.specDesc }}</text>
- </view>
- <text v-if="getItemCount(item) > 3" class="o-card-more">...等{{ getItemCount(item) }}件商品</text>
- </view>
- <!-- 卡片底部 -->
- <view class="o-card-footer">
- <text class="o-card-time">{{ item.createTime }}</text>
- <text class="o-card-amount">¥{{ item.totalAmount }}</text>
- </view>
- <!-- 待支付订单显示支付按钮 -->
- <view v-if="item.status === 0" class="o-card-pay">
- <text class="o-card-pay-btn" @click.stop="goPay(item)">去支付</text>
- </view>
- <!-- 退单原因 -->
- <view v-if="item.status === 9 && item.refundReason" class="o-card-refund">
- <text>↩️ {{ item.refundReason }}</text>
- </view>
- </view>
- </view>
- <!-- 加载更多 -->
- <view v-if="loading" class="o-load-more">
- <text>加载中...</text>
- </view>
- <view v-else-if="noMore" class="o-load-more o-load-more--end">
- <text>没有更多了</text>
- </view>
- </scroll-view>
- <!-- 底部 TabBar -->
- <HotelTabBar current="order" />
- </view>
- </template>
- <script setup>
- import { computed, ref } from 'vue'
- import { useHotelOrderStore } from '@/store'
- import api from '@/api'
- import HotelTabBar from '@/components/hotel/HotelTabBar.vue'
- const orderStore = useHotelOrderStore()
- const roomInfo = computed(() => orderStore.roomInfo)
- const orderList = ref([])
- const loading = ref(false)
- const noMore = ref(false)
- const pageNum = ref(1)
- const pageSize = 10
- // 页面加载时获取订单
- import { onMounted } from 'vue'
- onMounted(() => {
- loadOrders()
- })
- async function loadOrders() {
- if (loading.value) return
- loading.value = true
- try {
- const res = await api.hotelOrderPage({
- tenantId: orderStore.tenantId,
- pageNum: pageNum.value,
- pageSize: pageSize.value,
- // 按房间过滤(如果后端支持)
- roomNo: roomInfo.value?.roomNo,
- })
- const data = res?.data || res
- const list = data?.records || (Array.isArray(data) ? data : [])
- if (pageNum.value === 1) {
- orderList.value = list
- } else {
- orderList.value = orderList.value.concat(list)
- }
- if (list.length < pageSize.value) {
- noMore.value = true
- }
- } catch (e) {
- console.error('加载订单列表失败:', e)
- uni.showToast({ title: '加载失败', icon: 'none' })
- } finally {
- loading.value = false
- }
- }
- function loadMore() {
- if (noMore.value || loading.value) return
- pageNum.value++
- loadOrders()
- }
- function getItemsPreview(order) {
- if (!order.items) return []
- return order.items.slice(0, 3)
- }
- function getItemCount(order) {
- if (!order.items) return 0
- return order.items.length
- }
- function statusLabel(status) {
- const map = {
- 0: '待支付', 1: '待接单', 2: '已接单', 3: '备餐中',
- 4: '已出餐', 5: '配送中', 6: '已完成',
- 7: '已拒单', 8: '退单审核中', 9: '已退单',
- 10: '超时取消',
- }
- return map[status] || '未知'
- }
- function viewDetail(order) {
- if (order.status === 0) {
- // 待支付订单跳转到支付页
- uni.redirectTo({
- url: `/pages/hotel/customer/pay?orderId=${order.id}&tenantId=${order.tenantId}&amount=${order.totalAmount}`,
- })
- } else {
- uni.redirectTo({
- url: `/pages/hotel/customer/order-status?orderId=${order.id}`,
- })
- }
- }
- function goPay(order) {
- uni.redirectTo({
- url: `/pages/hotel/customer/pay?orderId=${order.id}&tenantId=${order.tenantId}&amount=${order.totalAmount}`,
- })
- }
- function goMenu() {
- uni.redirectTo({ url: '/pages/hotel/customer/menu' })
- }
- </script>
- <style lang="scss" scoped>
- .orders-page {
- min-height: 100vh;
- background: var(--h-bg, #F7F7F7);
- padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
- }
- /* 房间信息条 */
- .o-room-bar {
- padding: 20rpx 28rpx;
- font-size: 24rpx;
- color: var(--h-txt-sub, #666);
- }
- /* 加载/空状态 */
- .o-loading {
- display: flex;
- justify-content: center;
- align-items: center;
- min-height: 300rpx;
- color: var(--h-txt-light, #999);
- font-size: 26rpx;
- }
- .o-empty {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- min-height: 400rpx;
- }
- .o-empty-icon {
- font-size: 80rpx;
- margin-bottom: 20rpx;
- }
- .o-empty-text {
- font-size: 28rpx;
- color: var(--h-txt-light, #999);
- margin-bottom: 32rpx;
- }
- .o-empty-btn {
- padding: 20rpx 64rpx;
- border-radius: 48rpx;
- background: var(--h-pri, #2D5016);
- color: #fff;
- font-size: 28rpx;
- font-weight: 600;
- }
- /* 滚动区域 */
- .o-scroll {
- height: calc(100vh - 140rpx - env(safe-area-inset-bottom));
- }
- .o-list {
- padding: 0 28rpx;
- }
- /* 订单卡片 */
- .o-card {
- background: #fff;
- border-radius: var(--h-rad, 20rpx);
- padding: 28rpx 24rpx;
- margin-bottom: 16rpx;
- box-shadow: var(--h-shd, 0 2rpx 8rpx rgba(0, 0, 0, 0.04));
- }
- .o-card:active {
- opacity: 0.85;
- }
- .o-card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 16rpx;
- }
- .o-card-no {
- font-size: 24rpx;
- color: var(--h-txt-light, #999);
- }
- .o-card-status {
- font-size: 22rpx;
- font-weight: 600;
- padding: 4rpx 16rpx;
- border-radius: 20rpx;
- }
- /* 状态标签颜色 */
- .o-st--0 { background: #FEF3C7; color: #92400E; }
- .o-st--1 { background: #FEF3C7; color: #92400E; }
- .o-st--2 { background: #DCFCE7; color: #166534; }
- .o-st--3 { background: #FFEDD5; color: #9A3412; }
- .o-st--4 { background: #DBEAFE; color: #1E40AF; }
- .o-st--5 { background: #EDE9FE; color: #5B21B6; }
- .o-st--6 { background: #DCFCE7; color: #166534; }
- .o-st--7 { background: #FEE2E2; color: #991B1B; }
- .o-st--8 { background: #FEF9C3; color: #854D0E; }
- .o-st--9 { background: #FEF9C3; color: #854D0E; }
- .o-st--10 { background: #F3F4F6; color: #6B7280; }
- /* 菜品摘要 */
- .o-card-body {
- padding: 12rpx 0;
- border-top: 1rpx solid var(--h-bdr-lt, #F5F5F5);
- border-bottom: 1rpx solid var(--h-bdr-lt, #F5F5F5);
- }
- .o-card-dish {
- display: flex;
- align-items: center;
- gap: 12rpx;
- padding: 4rpx 0;
- }
- .o-card-dish-name {
- font-size: 26rpx;
- color: var(--h-txt, #1A1A1A);
- }
- .o-card-dish-spec {
- font-size: 22rpx;
- color: var(--h-txt-light, #999);
- }
- .o-card-more {
- font-size: 22rpx;
- color: var(--h-txt-light, #999);
- margin-top: 4rpx;
- }
- /* 卡片底部 */
- .o-card-footer {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding-top: 16rpx;
- }
- .o-card-time {
- font-size: 22rpx;
- color: var(--h-txt-light, #999);
- }
- .o-card-amount {
- font-size: 34rpx;
- font-weight: 700;
- color: var(--h-warn, #D97706);
- }
- /* 待支付按钮 */
- .o-card-pay {
- display: flex;
- justify-content: flex-end;
- padding: 12rpx 0 4rpx;
- }
- .o-card-pay-btn {
- padding: 12rpx 40rpx;
- border-radius: 32rpx;
- background: var(--h-pri, #2D5016);
- color: #fff;
- font-size: 24rpx;
- font-weight: 600;
- }
- .o-card-pay-btn:active {
- opacity: 0.8;
- }
- /* 退单原因 */
- .o-card-refund {
- margin-top: 12rpx;
- padding: 12rpx 16rpx;
- background: #FFF8E1;
- border-radius: var(--h-rad-sm, 12rpx);
- font-size: 22rpx;
- color: var(--h-txt-sub, #666);
- }
- /* 加载更多 */
- .o-load-more {
- text-align: center;
- padding: 24rpx 0;
- font-size: 24rpx;
- color: var(--h-txt-light, #999);
- }
- .o-load-more--end {
- color: var(--h-bdr, #eee);
- }
- </style>
|