Files
video-gen/video-gen-app/src/pages/OrderRecordsPage.tsx
T
2026-06-15 17:50:47 +08:00

177 lines
5.9 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { Table, Tag, Empty, Spin, Typography, Pagination } from 'antd';
import { FileTextOutlined, AlipayCircleOutlined, WechatOutlined } from '@ant-design/icons';
import { getPaymentOrders } from '../api';
const OrderRecordsPage: React.FC = () => {
const [loading, setLoading] = useState(true);
const [orders, setOrders] = useState<any[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [pageSize] = useState(10);
useEffect(() => {
loadData();
}, [page]);
const loadData = async () => {
setLoading(true);
try {
const data = await getPaymentOrders(page, pageSize);
setOrders(data.items || []);
setTotal(data.total || 0);
} catch {
setOrders([]);
}
setLoading(false);
};
const handlePageChange = (newPage: number) => {
setPage(newPage);
};
const columns = [
{
title: '订单号',
key: 'orderNo',
width: 200,
render: (_, record: any) => {
const orderNo = record.order_no || record.orderNo || record.id;
return (
<span style={{ fontFamily: 'monospace', fontSize: 13, color: '#64748b' }}>
{orderNo}
</span>
);
},
},
{
title: '支付方式',
key: 'paymentMethod',
width: 100,
render: (_, record: any) => {
const method = record.payment_method || record.paymentMethod || 'wechat';
const methodConfig: Record<string, { icon: React.ReactNode; label: string; color: string }> = {
alipay: { icon: <AlipayCircleOutlined style={{ fontSize: 16 }} />, label: '支付宝', color: '#1677ff' },
wechat: { icon: <WechatOutlined style={{ fontSize: 16 }} />, label: '微信支付', color: '#07c160' },
};
const config = methodConfig[method] || methodConfig.wechat;
return (
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<span style={{ color: config.color }}>{config.icon}</span>
<span style={{ fontSize: 13, color: '#374151' }}>{config.label}</span>
</div>
);
},
},
{
title: '金额',
key: 'amount',
width: 100,
align: 'right' as const,
render: (_, record: any) => {
const amount = record.amount || record.total_amount || 0;
return (
<Typography.Text strong style={{ fontWeight: 700, fontSize: 14, color: '#1e293b' }}>
¥{amount}
</Typography.Text>
);
},
},
{
title: '获得积分',
key: 'credits',
width: 100,
align: 'center' as const,
render: (_, record: any) => {
const credits = record.credits || record.credit_amount || 0;
return (
<Typography.Text strong style={{ fontWeight: 600, fontSize: 14, color: '#f59e0b' }}>
{credits}
</Typography.Text>
);
},
},
{
title: '状态',
key: 'status',
width: 100,
render: (_, record: any) => {
const status = record.status || 'pending';
const statusConfig: Record<string, { color: string; label: string; bg: string }> = {
pending: { color: '#f59e0b', label: '待支付', bg: 'rgba(245,158,11,0.1)' },
paid: { color: '#10b981', label: '已支付', bg: 'rgba(16,185,129,0.1)' },
refunded: { color: '#94a3b8', label: '已退款', bg: 'rgba(148,163,184,0.1)' },
failed: { color: '#ef4444', label: '支付失败', bg: 'rgba(239,68,68,0.1)' },
cancelled: { color: '#64748b', label: '已取消', bg: 'rgba(100,116,139,0.1)' },
processing: { color: '#0ea5e9', label: '处理中', bg: 'rgba(14,165,233,0.1)' },
};
const config = statusConfig[status] || { color: '#64748b', label: status, bg: 'rgba(100,116,139,0.1)' };
return (
<Tag color={config.color} style={{ background: config.bg, fontWeight: 500, padding: '4px 12px' }}>
{config.label}
</Tag>
);
},
},
{
title: '创建时间',
key: 'createdAt',
width: 180,
render: (_, record: any) => {
const createdAt = record.created_at || record.createdAt;
return createdAt ? new Date(createdAt).toLocaleString('zh-CN') : '-';
},
},
{
title: '支付时间',
key: 'paidAt',
width: 180,
render: (_, record: any) => {
const paidAt = record.paid_at || record.paidAt;
return paidAt ? new Date(paidAt).toLocaleString('zh-CN') : '-';
},
},
];
return (
<div>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
<FileTextOutlined style={{ color: '#0ea5e9', fontSize: 16 }} />
<Typography.Text strong style={{ fontSize: 16 }}>订单记录</Typography.Text>
<span style={{ color: '#94a3b8', fontSize: 13 }}> {orders.length} 条记录</span>
</div>
<div style={{ borderRadius: 16, background: '#fff', border: '1px solid #f0f0f5', overflow: 'hidden' }}>
<Spin spinning={loading}>
{orders.length === 0 ? (
<Empty
description={<span style={{ color: '#94a3b8' }}>暂无订单记录</span>}
/>
) : (
<>
<Table
dataSource={orders}
columns={columns}
rowKey="order_no"
pagination={false}
bordered={false}
/>
<div style={{ padding: '16px', textAlign: 'right' }}>
<Pagination
current={page}
pageSize={pageSize}
total={total}
onChange={handlePageChange}
size="small"
/>
</div>
</>
)}
</Spin>
</div>
</div>
</div>
);
};
export default OrderRecordsPage;