import { useState } from 'react' import Taro, { useDidShow } from '@tarojs/taro' import { View, Text } from '@tarojs/components' import { ConfigProvider, Empty, InfiniteLoading, Loading, PullToRefresh, Tag } from '@nutui/nutui-react-taro' import dayjs from 'dayjs' import { pageGltUserTicketRelease } from '@/api/glt/gltUserTicketRelease' import type { GltUserTicketRelease } from '@/api/glt/gltUserTicketRelease/model' import { ensureLoggedIn } from '@/utils/auth' const PAGE_SIZE = 10 const MAX_FETCH_ROUNDS = 10 export default function TicketReleasePlanPage() { const [list, setList] = useState([]) const [loading, setLoading] = useState(false) const [hasMore, setHasMore] = useState(true) const [page, setPage] = useState(1) const [total, setTotal] = useState(undefined) const router = Taro.getCurrentInstance().router const userTicketId = String(router?.params?.userTicketId || '').trim() const templateName = (() => { const raw = String(router?.params?.templateName || '') try { return decodeURIComponent(raw) } catch { return raw } })() const frozenQtyText = router?.params?.frozenQty !== undefined ? String(router?.params?.frozenQty) : undefined const releasedQtyText = router?.params?.releasedQty !== undefined ? String(router?.params?.releasedQty) : undefined const getUserId = () => { const raw = Taro.getStorageSync('UserId') const id = Number(raw) return Number.isFinite(id) && id > 0 ? id : undefined } const getStatusMeta = (item: GltUserTicketRelease) => { const status = Number(item.status) if (status === 1) return { text: '已释放', type: 'success' as const } if (status === 0) return { text: '待释放', type: 'warning' as const } return { text: `状态${Number.isFinite(status) ? status : '-'}`, type: 'primary' as const } } const formatDateTime = (v?: string) => { if (!v) return '-' const d = dayjs(v) return d.isValid() ? d.format('YYYY年MM月DD日 HH:mm:ss') : v } const reload = async (isRefresh = true) => { if (loading) return const uid = getUserId() if (!uid) { setList([]) setHasMore(false) setTotal(0) return } if (!userTicketId) { setList([]) setHasMore(false) setTotal(0) return } if (isRefresh) { setPage(1) setList([]) setHasMore(true) } setLoading(true) try { const baseList = isRefresh ? [] : list const seen = new Set(baseList.map(r => String(r.id ?? `${r.userTicketId ?? ''}:${r.periodNo ?? ''}:${r.releaseTime ?? ''}`))) let nextPage = isRefresh ? 1 : page let serverHasMore = true let added = 0 let nextList = baseList.slice() for (let round = 0; round < MAX_FETCH_ROUNDS; round++) { if (!serverHasMore) break // Only query by current logged-in userId; userTicketId is filtered on the client. const res = await pageGltUserTicketRelease({ page: nextPage, limit: PAGE_SIZE, userId: uid } as any) const incoming = Array.isArray(res?.list) ? res.list : [] const safe = incoming .filter(r => Number((r as any)?.deleted) !== 1) .filter(r => !userTicketId || String(r.userTicketId || '') === userTicketId) .filter(r => { const k = String(r.id ?? `${r.userTicketId ?? ''}:${r.periodNo ?? ''}:${r.releaseTime ?? ''}`) if (seen.has(k)) return false seen.add(k) return true }) if (safe.length) { nextList = nextList.concat(safe) added += safe.length } serverHasMore = incoming.length >= PAGE_SIZE if (!serverHasMore) break nextPage += 1 // Stop early once we got something to render for this ticket. if (added > 0) break } nextList.sort((a, b) => { const at = dayjs(a.releaseTime || a.createTime || 0).valueOf() const bt = dayjs(b.releaseTime || b.createTime || 0).valueOf() return bt - at }) setList(nextList) setTotal(nextList.length) setHasMore(serverHasMore) setPage(nextPage) } catch (e) { console.error('加载释放计划失败:', e) Taro.showToast({ title: '加载失败', icon: 'none' }) setHasMore(false) } finally { setLoading(false) } } useDidShow(() => { const redirect = userTicketId ? `/user/ticket/release/index?userTicketId=${encodeURIComponent(userTicketId)}` : '/user/ticket/index' if (!ensureLoggedIn(redirect)) return void reload(true) }) const handleRefresh = async () => { await reload(true) } const loadMore = async () => { if (!loading && hasMore) await reload(false) } return ( 释放计划明细 {typeof total === 'number' ? ( 共 {total} 条 ) : null} 票号:{userTicketId || '-'} {templateName ? ( 套票名称:{templateName} ) : null} {frozenQtyText !== undefined || releasedQtyText !== undefined ? ( {frozenQtyText !== undefined ? ( 剩余赠票:{frozenQtyText} ) : null} {releasedQtyText !== undefined ? ( 已释放:{releasedQtyText} ) : null} ) : null} {list.length === 0 && !loading && !hasMore ? ( ) : ( 加载中... } loadMoreText={ {list.length === 0 ? '暂无数据' : '没有更多了'} } > {list.map((item, index) => { const meta = getStatusMeta(item) return ( 周期:{item.periodNo ?? '-'} 释放数量:{item.releaseQty ?? 0} 释放时间:{formatDateTime(item.releaseTime)} {meta.text} ) })} )} ) }