shinnosuke
5 天以前 e52934f6527027bd6008c2ade61c3083159efd4a
rencaika_merchant/pages/orders/orders.uvue
@@ -19,11 +19,11 @@
         <view v-if="listLoadState == 'success'" class="order-list">
            <view v-for="order in orders" :key="order.id" class="order-card" :class="order.category == 'stay' ? 'stay-order-card' : (order.category == 'store' ? 'store-order-card' : '')" @tap="openOrderItem(order)">
               <view class="customer-row"><view class="customer-info"><image class="customer-icon" src="/static/icons/lucide/circle-user-round.svg" mode="aspectFit"></image><text class="customer-name">{{order.customerName}}</text><text class="customer-phone">{{order.customerMobile}}</text></view><text class="status" :class="order.status == 'completed' ? 'verified' : 'pending'">{{order.statusText}}</text></view>
               <text v-if="order.category != 'stay'" class="order-name">{{order.title}}</text>
               <view v-if="order.category == 'stay'" class="stay-title-row"><text class="stay-order-name">{{order.title}}</text><text class="card-tag">{{order.cardLevel}}</text></view>
               <view class="customer-row"><view class="customer-info"><image class="customer-icon" src="/static/icons/lucide/circle-user-round.svg" mode="aspectFit"></image><text class="customer-name">{{order.customerName}}</text><text class="customer-phone">{{order.customerMobile}}</text></view><text class="status" :class="order.status == 'completed' ? 'verified' : ((order.status == 'cancelled' || order.status == 'refunded') ? 'closed' : 'pending')">{{order.statusText}}</text></view>
               <text v-if="order.category != 'stay' && !isTicketOrder(order)" class="order-name">{{order.title}}</text>
               <view v-if="order.category == 'stay' || isTicketOrder(order)" class="stay-title-row"><text class="stay-order-name">{{order.title}}</text><text class="card-tag">{{order.cardLevel}}</text></view>
               <view v-else class="price-row" :class="order.category == 'store' ? 'store-price-row' : ''"><view class="price-group"><text class="price">¥{{formatAmount(order.payAmount)}}</text><text v-if="order.orderAmount > order.payAmount" class="original-price">¥{{formatAmount(order.orderAmount)}}</text></view><text class="card-tag">{{order.cardLevel}}</text></view>
               <text class="time-text">{{order.status == 'completed' && order.verifyTime.length > 0 ? '核销时间:' + formatDateTime(order.verifyTime) : '下单时间:' + formatDateTime(order.createdAt)}}</text>
               <text class="time-text">{{orderTimeText(order)}}</text>
            </view>
         </view>
@@ -123,6 +123,7 @@
            <view class="status-option" :class="statusFilter == 'all' ? 'selected' : ''" @tap="selectStatus('all')"><text class="status-option-text">全部</text><text v-if="statusFilter == 'all'" class="status-selected-mark">已选</text></view>
            <view class="status-option" :class="statusFilter == pendingStatus ? 'selected' : ''" @tap="selectStatus(pendingStatus)"><text class="status-option-text">{{pendingStatusText}}</text><text v-if="statusFilter == pendingStatus" class="status-selected-mark">已选</text></view>
            <view class="status-option" :class="statusFilter == 'completed' ? 'selected' : ''" @tap="selectStatus('completed')"><text class="status-option-text">已完成</text><text v-if="statusFilter == 'completed'" class="status-selected-mark">已选</text></view>
            <view class="status-option" :class="statusFilter == 'closed' ? 'selected' : ''" @tap="selectStatus('closed')"><text class="status-option-text">已取消/已退款</text><text v-if="statusFilter == 'closed'" class="status-selected-mark">已选</text></view>
         </view>
         <view class="status-cancel" @tap="closeStatusFilter"><text class="status-cancel-text">取消</text></view>
      </view>
@@ -282,10 +283,28 @@
   const formatAmount = (amount: number): string => (amount / 100).toFixed(2)
   const formatDateTime = (value: string): string => value.length > 0 ? value.replace('T', ' ') : '—'
   /** 观影券没有金额,列表里按「标题 + 人才卡」一行展示,和免费入住同一套排版。 */
   const isTicketOrder = (order: MerchantOrder): boolean => order.sourceType == 'TICKET_PACKAGE'
   const orderTimeText = (order: MerchantOrder): string => {
      if (order.status == 'completed' && order.verifyTime.length > 0) return '核销时间:' + formatDateTime(order.verifyTime)
      return (isTicketOrder(order) ? '领取时间:' : '下单时间:') + formatDateTime(order.createdAt)
   }
   const openOrderItem = (order: MerchantOrder) => {
      const query = 'id=' + encodeURIComponent(order.id) + '&orderNo=' + encodeURIComponent(order.orderNo)
      if (isTicketOrder(order)) {
         const rawClaimId = order.claimId != null ? order.claimId as string : ''
         const claimId = rawClaimId.length > 0 ? rawClaimId : order.id.replace('TP', '')
         uni.navigateTo({ url: '/pages/ticket-package-detail/ticket-package-detail?claimId=' + encodeURIComponent(claimId) })
         return
      }
      if (order.status == 'pending_verification') {
         uni.navigateTo({ url: '/pages/verification-detail/verification-detail?' + query })
         return
      }
      // 已取消/已退款的订单进详情看状态,不能按「已完成」打开,否则会把取消说成完成。
      if (order.status == 'cancelled' || order.status == 'refunded') {
         uni.navigateTo({ url: '/pages/order-detail/order-detail?status=' + order.status + '&' + query })
         return
      }
      uni.navigateTo({ url: '/pages/order-detail/order-detail?status=completed&' + query })
@@ -384,13 +403,14 @@
      activeDateField.value = field
      if (field == 'start') {
         setPickerDate(startDateValue.value > 0 ? startDateValue.value : defaultDateValue.value)
      } else {
         if (endDateValue.value == 0) {
            endDateValue.value = startDateValue.value
            endDate.value = startDate.value
         }
         setPickerDate(endDateValue.value)
         return
      }
      // 闭区间:点截止日期时若还没选过,先用起始日期的值垫上(查同一天就不用滚两遍)。
      if (endDateValue.value == 0 && startDateValue.value > 0) {
         endDateValue.value = startDateValue.value
         endDate.value = startDate.value
      }
      setPickerDate(endDateValue.value > 0 ? endDateValue.value : (startDateValue.value > 0 ? startDateValue.value : defaultDateValue.value))
   }
   const getMaxDay = (year: number, month: number) => {
@@ -401,9 +421,12 @@
   }
   const setPickerDate = (dateValue: number) => {
      const year = Math.floor(dateValue / 10000)
      const month = Math.floor(dateValue / 100) % 100
      const day = dateValue % 100
      // dateValue 为 0 表示这一头还没选过(占位符状态)。以前直接按 0 算,滚轮会跳到"0 年 0 月 0 日"
      // 这种不存在的列上,表现为"点进来滚轮是空的"。统一回落到业务日期。
      const value = dateValue > 0 ? dateValue : defaultDateValue.value
      const year = Math.floor(value / 10000)
      const month = Math.floor(value / 100) % 100
      const day = value % 100
      const yearIndex = year - (currentYear.value - 2)
      months.value = allMonths.slice()
      days.value = allDays.slice(0, getMaxDay(year, month))
@@ -461,15 +484,29 @@
   }
   const confirmDateFilter = () => {
      if (startDateValue.value > 0 && endDateValue.value > 0 && startDateValue.value <= endDateValue.value) {
         datePickerVisible.value = false
         dateFilterText.value = '已选日期'
         dateFilterApplied.value = true
         reloadOrders()
         uni.showToast({ title: '日期区间已应用', icon: 'none' })
      } else {
         uni.showToast({ title: '请选择截止日期', icon: 'none' })
      // 闭区间:起始日期和截止日期都要选。缺哪一头就提示哪一头,并把焦点挪到那一头
      // (以前不管缺哪一头都提示"请选择截止日期":只选了截止日的人会以为系统没认下他选的那天)。
      if (startDateValue.value == 0) {
         activeDateField.value = 'start'
         setPickerDate(defaultDateValue.value)
         uni.showToast({ title: '请选择起始日期', icon: 'none' })
         return
      }
      if (endDateValue.value == 0) {
         activeDateField.value = 'end'
         setPickerDate(startDateValue.value)
         uni.showToast({ title: '请选择截止日期', icon: 'none' })
         return
      }
      if (startDateValue.value > endDateValue.value) {
         uni.showToast({ title: '起始日不能晚于截止日', icon: 'none' })
         return
      }
      datePickerVisible.value = false
      dateFilterText.value = '已选日期'
      dateFilterApplied.value = true
      reloadOrders()
      uni.showToast({ title: '日期区间已应用', icon: 'none' })
   }
   const openOrder = (orderId: string) => {
@@ -490,6 +527,11 @@
   onLoad(() => {
      if (hasActiveSession()) loadMerchantBusinessDate((value: string) => applyBusinessDate(value), () => {})
   })
   // 列表用 onShow 拉:核销成功后从结果页/详情页返回时,状态才是最新的。
   // 之前只在 onLoad 拉一次,返回列表还停在「待核销」,要切一次分类标签才刷新。
   onShow(() => {
      reloadOrders()
   })
@@ -529,6 +571,7 @@
   .status { font-size: 24rpx; line-height: 34rpx; font-weight: 600; }
   .pending { color: #FF5A42; }
   .verified { color: #98A3B4; }
   .closed { color: #98A3B4; }
   .order-name { color: #182236; font-size: 31rpx; line-height: 44rpx; font-weight: 700; margin-top: 26rpx; }
   .price-row { display: flex; flex-direction: row; justify-content: space-between; align-items: center; margin-top: 18rpx; }
   .store-price-row { margin-top: 24rpx; }