- 将信用模块我的订单页面从模拟数据改为真实API数据 - 添加订单详情页面及路由配置 - 集成信用客户管理API接口调用 - 实现订单列表的搜索、分页和加载更多功能 - 添加订单状态筛选和统计信息展示 - 新增订单详情的时间线展示功能 - 更新首页进度查询跳转逻辑 - 优化页面加载和错误处理机制
211 lines
7.2 KiB
TypeScript
211 lines
7.2 KiB
TypeScript
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||
import Taro, { useDidShow } from '@tarojs/taro'
|
||
import { View, Text } from '@tarojs/components'
|
||
import { Button, ConfigProvider, Empty, Input, Loading } from '@nutui/nutui-react-taro'
|
||
import { ArrowRight, Search } from '@nutui/icons-react-taro'
|
||
|
||
import { pageCreditMpCustomer } from '@/api/credit/creditMpCustomer'
|
||
import type { CreditMpCustomer } from '@/api/credit/creditMpCustomer/model'
|
||
|
||
type ListQuery = {
|
||
page: number
|
||
limit: number
|
||
keywords?: string
|
||
userId?: number
|
||
}
|
||
|
||
const getCurrentUserId = (): number | undefined => {
|
||
try {
|
||
const raw = Taro.getStorageSync('UserId')
|
||
const n = Number(raw)
|
||
return Number.isFinite(n) && n > 0 ? n : undefined
|
||
} catch {
|
||
return undefined
|
||
}
|
||
}
|
||
|
||
const buildDesc = (row: CreditMpCustomer) => {
|
||
const price = row.price ? `${row.price}元` : ''
|
||
const years = row.years ? `${row.years}年` : ''
|
||
const location = [row.province, row.city, row.region].filter(Boolean).join(' ')
|
||
return [price, years, location].filter(Boolean).join(' · ')
|
||
}
|
||
|
||
const getStatusBadgeClass = (s?: string) => {
|
||
const txt = String(s || '').trim()
|
||
if (!txt) return 'bg-gray-400'
|
||
if (txt.includes('退回')) return 'bg-red-500'
|
||
if (txt.includes('完结') || txt.includes('已办结')) return 'bg-green-600'
|
||
if (txt.includes('受理') || txt.includes('通过') || txt.includes('签订')) return 'bg-orange-500'
|
||
return 'bg-blue-500'
|
||
}
|
||
|
||
export default function CreditMyOrderPage() {
|
||
const [list, setList] = useState<CreditMpCustomer[]>([])
|
||
const [count, setCount] = useState(0)
|
||
const [loading, setLoading] = useState(false)
|
||
const [loadingMore, setLoadingMore] = useState(false)
|
||
|
||
const [keywords, setKeywords] = useState('')
|
||
const [page, setPage] = useState(1)
|
||
const limit = 10
|
||
|
||
const userId = useMemo(() => getCurrentUserId(), [])
|
||
|
||
const hasMore = useMemo(() => list.length < count, [count, list.length])
|
||
|
||
const fetchPage = useCallback(
|
||
async (opts: { nextPage: number; replace: boolean }) => {
|
||
if (!userId) {
|
||
setList([])
|
||
setCount(0)
|
||
return
|
||
}
|
||
|
||
const query: ListQuery = {
|
||
page: opts.nextPage,
|
||
limit,
|
||
keywords: keywords.trim() || undefined,
|
||
userId
|
||
}
|
||
|
||
try {
|
||
if (opts.replace) setLoading(true)
|
||
else setLoadingMore(true)
|
||
|
||
const res = await pageCreditMpCustomer(query as any)
|
||
const incoming = (res?.list || []) as CreditMpCustomer[]
|
||
const total = Number(res?.count || 0)
|
||
setCount(Number.isFinite(total) ? total : 0)
|
||
setPage(opts.nextPage)
|
||
setList(prev => (opts.replace ? incoming : prev.concat(incoming)))
|
||
} catch (e) {
|
||
console.error('获取我的需求失败:', e)
|
||
Taro.showToast({ title: (e as any)?.message || '获取数据失败', icon: 'none' })
|
||
} finally {
|
||
setLoading(false)
|
||
setLoadingMore(false)
|
||
}
|
||
},
|
||
[keywords, limit, userId]
|
||
)
|
||
|
||
const reload = useCallback(async () => {
|
||
await fetchPage({ nextPage: 1, replace: true })
|
||
}, [fetchPage])
|
||
|
||
const loadMore = useCallback(async () => {
|
||
if (loading || loadingMore || !hasMore) return
|
||
await fetchPage({ nextPage: page + 1, replace: false })
|
||
}, [fetchPage, hasMore, loading, loadingMore, page])
|
||
|
||
useDidShow(() => {
|
||
reload().then()
|
||
})
|
||
|
||
useEffect(() => {
|
||
const handler = () => reload()
|
||
Taro.eventCenter.on('credit:order:created', handler)
|
||
return () => {
|
||
Taro.eventCenter.off('credit:order:created', handler)
|
||
}
|
||
}, [reload])
|
||
|
||
const goDetail = (id?: number) => {
|
||
if (!id) return
|
||
Taro.navigateTo({ url: `/credit/my-order/detail?id=${id}` })
|
||
}
|
||
|
||
return (
|
||
<View className="bg-pink-50 min-h-screen">
|
||
<ConfigProvider>
|
||
<View className="max-w-md mx-auto">
|
||
<View className="px-4 pt-3">
|
||
<View className="bg-white rounded-full border border-pink-100 px-3 py-2 flex items-center gap-2">
|
||
<Search size={16} className="text-gray-400" />
|
||
<View className="flex-1">
|
||
<Input
|
||
value={keywords}
|
||
onChange={setKeywords}
|
||
placeholder="请输入拖欠方名称查询"
|
||
onConfirm={reload}
|
||
/>
|
||
</View>
|
||
<Button size="small" type="primary" onClick={reload}>
|
||
查询
|
||
</Button>
|
||
</View>
|
||
|
||
<View className="mt-2 text-xs text-gray-500 flex items-center justify-between">
|
||
<Text>仅展示我发布的需求</Text>
|
||
<Text>共{count}条</Text>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="px-4 mt-3 pb-6">
|
||
{loading ? (
|
||
<View className="bg-white rounded-xl border border-pink-100 py-10 flex items-center justify-center">
|
||
<Loading>加载中...</Loading>
|
||
</View>
|
||
) : !list.length ? (
|
||
<View className="bg-white rounded-xl border border-pink-100 py-10">
|
||
<Empty description={userId ? '暂无需求' : '未登录或缺少用户信息'} />
|
||
</View>
|
||
) : (
|
||
list.map(row => {
|
||
const title = String(row.toUser || '-').trim()
|
||
const desc = buildDesc(row)
|
||
const statusTxt = String(row.statusTxt || '处理中').trim()
|
||
const time = String(row.createTime || '').slice(0, 19).replace('T', ' ')
|
||
|
||
return (
|
||
<View
|
||
key={String(row.id)}
|
||
className="bg-white rounded-xl border border-pink-100 p-3 mb-3"
|
||
onClick={() => goDetail(row.id)}
|
||
>
|
||
<View className="flex items-center justify-between">
|
||
<Text className="text-sm font-semibold text-gray-900">{title}</Text>
|
||
<View className="flex items-center gap-2">
|
||
<View className={`px-2 py-1 rounded-full ${getStatusBadgeClass(statusTxt)}`}>
|
||
<Text className="text-xs text-white">{statusTxt}</Text>
|
||
</View>
|
||
<ArrowRight color="#cccccc" />
|
||
</View>
|
||
</View>
|
||
|
||
{!!desc && (
|
||
<View className="mt-2 text-xs text-gray-600">
|
||
<Text>{desc}</Text>
|
||
</View>
|
||
)}
|
||
|
||
<View className="mt-2 text-xs text-gray-500 flex items-center justify-between">
|
||
<Text>需求ID:{row.id ?? '-'}</Text>
|
||
<Text>{time || ''}</Text>
|
||
</View>
|
||
</View>
|
||
)
|
||
})
|
||
)}
|
||
|
||
{!!list.length && (
|
||
<View className="mt-2 flex justify-center">
|
||
<Button
|
||
fill="none"
|
||
size="small"
|
||
style={{ color: '#bdbdbd' }}
|
||
disabled={!hasMore || loadingMore}
|
||
onClick={loadMore}
|
||
>
|
||
{hasMore ? (loadingMore ? '加载中...' : '加载更多') : '没有更多了'}
|
||
</Button>
|
||
</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
</ConfigProvider>
|
||
</View>
|
||
)
|
||
}
|