Files
pay-bridge/frontend/src/pages/trade/index.tsx
2026-03-13 15:51:59 +08:00

98 lines
2.7 KiB
TypeScript

import { useState } from 'react'
import { Table, Tag, Input, Select, Space, Card } from 'antd'
import { useQuery } from '@tanstack/react-query'
import type { ColumnsType } from 'antd/es/table'
import dayjs from 'dayjs'
import { tradeApi } from '../../api/trade'
import { formatAmount, tradeStatusMap, payMethodMap } from '../../utils/format'
import type { TradeOrder, TradeStatus } from '../../types'
const { Search } = Input
const statusOptions = [
{ label: '全部', value: '' },
{ label: '待支付', value: 'PAYING' },
{ label: '已支付', value: 'PAID' },
{ label: '已关闭', value: 'CLOSED' },
{ label: '已退款', value: 'REFUNDED' },
]
export default function TradePage() {
const [status, setStatus] = useState('')
const [offset, setOffset] = useState(0)
const limit = 20
const { data, isLoading } = useQuery({
queryKey: ['trades', status, offset],
queryFn: () => tradeApi.list({ status, limit, offset }),
})
const columns: ColumnsType<TradeOrder> = [
{ title: '交易号', dataIndex: 'trade_no', width: 180 },
{ title: '商户订单号', dataIndex: 'merchant_order_no', width: 160 },
{ title: '应用', dataIndex: 'app_id', width: 120 },
{
title: '金额',
dataIndex: 'amount',
width: 100,
render: (v) => formatAmount(v),
},
{
title: '支付方式',
dataIndex: 'pay_method',
width: 120,
render: (v) => payMethodMap[v] ?? v,
},
{
title: '状态',
dataIndex: 'status',
width: 90,
render: (v: TradeStatus) => {
const s = tradeStatusMap[v]
return s ? <Tag color={s.color}>{s.label}</Tag> : v
},
},
{
title: '支付时间',
dataIndex: 'pay_time',
width: 160,
render: (v) => v ? dayjs(v).format('YYYY-MM-DD HH:mm:ss') : '-',
},
{
title: '创建时间',
dataIndex: 'created_at',
width: 160,
render: (v) => dayjs(v).format('YYYY-MM-DD HH:mm:ss'),
},
]
const list: TradeOrder[] = data?.data?.data?.list ?? []
return (
<Card>
<Space style={{ marginBottom: 16 }}>
<Select
options={statusOptions}
value={status}
onChange={(v) => { setStatus(v); setOffset(0) }}
style={{ width: 120 }}
placeholder="状态筛选"
/>
<Search placeholder="搜索交易号/商户订单号" style={{ width: 260 }} allowClear />
</Space>
<Table
rowKey="trade_no"
columns={columns}
dataSource={list}
loading={isLoading}
scroll={{ x: 1100 }}
pagination={{
pageSize: limit,
current: Math.floor(offset / limit) + 1,
onChange: (page) => setOffset((page - 1) * limit),
}}
/>
</Card>
)
}