fix: 修复订单列表不能查看的问题

This commit is contained in:
richarjiang
2026-04-10 23:07:56 +08:00
parent 54e30da003
commit 0810f71250
4 changed files with 142 additions and 37 deletions

View File

@@ -1,5 +1,5 @@
<template>
<view class="page" :style="{ paddingTop: navBarHeight }">
<view class="page" :style="{ '--status-bar': statusBarHeight + 'px' }">
<CustomNavBar title="订单管理" show-back />
<!-- Summary stats bar -->
@@ -106,14 +106,14 @@
</view>
<view class="info-right">
<text class="info-label">下单时间</text>
<text class="info-value">{{ formatDate(order.createdAt) }}</text>
<text class="info-value">{{ formatDateTime(order.createdAt) }}</text>
</view>
</view>
<!-- Paid time if available -->
<view v-if="order.paidAt && order.status === OrderStatus.PAID" class="info-row">
<text class="info-label">支付时间</text>
<text class="info-value">{{ formatDate(order.paidAt) }}</text>
<text class="info-value">{{ formatDateTime(order.paidAt) }}</text>
</view>
</view>
</view>
@@ -133,19 +133,21 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, computed, onMounted } from 'vue'
import CustomNavBar from '../../components/CustomNavBar.vue'
import { getSystemLayout } from '../../utils/system'
import { useAdminStore } from '../../stores/admin'
import { formatPrice, formatDate } from '../../utils/format'
import { formatPrice, formatDateTime } from '../../utils/format'
import { OrderStatus } from '@mp-pilates/shared'
import type { OrderWithDetails } from '@mp-pilates/shared'
const adminStore = useAdminStore()
const navBarHeight = ref('64px')
// 动态计算顶部模块高度
const statusBarHeight = ref(0)
onMounted(() => {
navBarHeight.value = `${getSystemLayout().navBarHeight}px`
const windowInfo = uni.getWindowInfo()
statusBarHeight.value = windowInfo.statusBarHeight ?? 20
})
const filters = [
@@ -165,6 +167,21 @@ const totalCount = ref<number | null>(null)
const paidCount = ref<number | null>(null)
const pendingCount = ref<number | null>(null)
// 每个 tab 单独缓存数据
const orderCache: Record<string, { items: OrderWithDetails[]; total: number; page: number; hasMore: boolean }> = {}
function getCacheKey(filter: string): string {
return filter || 'all'
}
function getCachedData(filter: string) {
return orderCache[getCacheKey(filter)]
}
function setCachedData(filter: string, data: { items: OrderWithDetails[]; total: number; page: number; hasMore: boolean }) {
orderCache[getCacheKey(filter)] = data
}
const LIMIT = 20
function statusLabel(s: string) {
@@ -191,23 +208,45 @@ function statusAccentClass(s: string) {
}
async function loadOrders(reset = false) {
const filter = activeFilter.value
// 如果有缓存且是重置切换tab直接用缓存数据
if (reset) {
const cached = getCachedData(filter)
if (cached) {
orders.value = [...cached.items]
hasMore.value = cached.hasMore
page.value = cached.page
return
}
}
// 初始加载或下拉刷新,需要请求接口
if (loading.value) return
if (reset) page.value = 1
loading.value = true
try {
const params: { page: number; limit: number; status?: string } = {
page: page.value,
limit: LIMIT,
}
if (activeFilter.value) params.status = activeFilter.value
if (filter) params.status = filter
const result = await adminStore.fetchAdminOrders(params)
if (reset) {
orders.value = [...result.items]
} else {
orders.value.push(...result.items)
}
hasMore.value = orders.value.length < result.total
totalCount.value = result.total
const newItems = reset ? [...result.items] : [...orders.value, ...result.items]
const newHasMore = newItems.length < result.total
// 缓存数据
setCachedData(filter, {
items: newItems,
total: result.total,
page: page.value,
hasMore: newHasMore,
})
orders.value = newItems
hasMore.value = newHasMore
} catch {
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
@@ -216,30 +255,79 @@ async function loadOrders(reset = false) {
}
}
async function loadSummaryCounts() {
// 初始加载所有分类的数据
async function loadAllFiltersData() {
loading.value = true
try {
const [allResult, paidResult, pendingResult] = await Promise.all([
adminStore.fetchAdminOrders({ page: 1, limit: 1 }),
adminStore.fetchAdminOrders({ page: 1, limit: 1, status: OrderStatus.PAID }),
adminStore.fetchAdminOrders({ page: 1, limit: 1, status: OrderStatus.PENDING }),
// 并行请求所有分类(第一页数据)
const [allResult, paidResult, pendingResult, refundedResult] = await Promise.all([
adminStore.fetchAdminOrders({ page: 1, limit: LIMIT }),
adminStore.fetchAdminOrders({ page: 1, limit: LIMIT, status: OrderStatus.PAID }),
adminStore.fetchAdminOrders({ page: 1, limit: LIMIT, status: OrderStatus.PENDING }),
adminStore.fetchAdminOrders({ page: 1, limit: LIMIT, status: OrderStatus.REFUNDED }),
])
// 缓存全部
setCachedData('', {
items: [...allResult.items],
total: allResult.total,
page: 1,
hasMore: allResult.items.length < allResult.total,
})
totalCount.value = allResult.total
// 缓存已支付
setCachedData(OrderStatus.PAID, {
items: [...paidResult.items],
total: paidResult.total,
page: 1,
hasMore: paidResult.items.length < paidResult.total,
})
paidCount.value = paidResult.total
// 缓存待支付
setCachedData(OrderStatus.PENDING, {
items: [...pendingResult.items],
total: pendingResult.total,
page: 1,
hasMore: pendingResult.items.length < pendingResult.total,
})
pendingCount.value = pendingResult.total
// 缓存已退款
setCachedData(OrderStatus.REFUNDED, {
items: [...refundedResult.items],
total: refundedResult.total,
page: 1,
hasMore: refundedResult.items.length < refundedResult.total,
})
// 设置当前 tab 的数据
orders.value = [...allResult.items]
hasMore.value = allResult.items.length < allResult.total
} catch {
// non-critical, ignore
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
loading.value = false
refreshing.value = false
}
}
function selectFilter(value: string) {
activeFilter.value = value
totalCount.value = null
loadOrders(true)
// 切换 tab 直接从缓存读取
const cached = getCachedData(value)
if (cached) {
orders.value = [...cached.items]
hasMore.value = cached.hasMore
page.value = cached.page
}
}
async function onRefresh() {
refreshing.value = true
await Promise.all([loadOrders(true), loadSummaryCounts()])
// 下拉刷新重新请求所有分类的数据
await loadAllFiltersData()
}
function loadMore() {
@@ -249,8 +337,7 @@ function loadMore() {
}
onMounted(() => {
loadOrders(true)
loadSummaryCounts()
loadAllFiltersData()
})
</script>
@@ -266,13 +353,18 @@ onMounted(() => {
/* ── Stats bar ──────────────────────────────── */
.stats-bar {
position: fixed;
top: calc(var(--status-bar) + 44px);
left: 0;
right: 0;
display: flex;
align-items: center;
height: 96rpx;
background: #FFFFFF;
padding: 28rpx 0;
margin: 0;
padding: 0;
border-bottom: 1rpx solid rgba(180, 160, 130, 0.2);
box-shadow: 0 2rpx 12rpx rgba(180, 160, 130, 0.08);
z-index: 100;
}
.stat-item {
@@ -309,9 +401,13 @@ onMounted(() => {
/* ── Filter pills ───────────────────────────── */
.filter-wrap {
position: fixed;
top: calc(var(--status-bar) + 92px);
left: 0;
right: 0;
background: #FAF8F5;
border-bottom: 1rpx solid rgba(180, 160, 130, 0.15);
flex-shrink: 0;
z-index: 99;
}
.filter-scroll { overflow: hidden; }
@@ -364,7 +460,11 @@ onMounted(() => {
/* ── List ───────────────────────────────────── */
.list-scroll {
flex: 1;
position: fixed;
top: calc(var(--status-bar) + 144px);
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}