Files
video-gen/video-gen-app/src/pages/CreditRecordsPage.tsx
T
2026-07-10 18:33:27 +08:00

177 lines
6.8 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { Table, Tag, Empty, Spin, Typography, Row, Col, Pagination } from 'antd';
import { WalletOutlined, PlusCircleOutlined, ThunderboltOutlined } from '@ant-design/icons';
import { getCredits } from '../api';
const CreditRecordsPage: React.FC = () => {
const [loading, setLoading] = useState(true);
const [records, setRecords] = useState<any[]>([]);
const [credits, setCredits] = useState(0);
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 getCredits(page, pageSize);
setRecords(data.records || []);
setCredits(data.credits || 0);
setTotal(data.total || 0);
} catch {
setRecords([]);
}
setLoading(false);
};
const handlePageChange = (newPage: number) => {
setPage(newPage);
};
const columns = [
{
title: '变动类型',
dataIndex: 'type',
key: 'type',
width: 120,
render: (text: string) => {
const typeConfig: Record<string, { color: string; label: string; bg: string }> = {
recharge: { color: '#10b981', label: '充值', bg: 'rgba(16,185,129,0.1)' },
consume: { color: '#ef4444', label: '消费', bg: 'rgba(239,68,68,0.1)' },
admin: { color: '#f59e0b', label: '管理员调整', bg: 'rgba(245,158,11,0.1)' },
refund: { color: '#8b5cf6', label: '退款', bg: 'rgba(139,92,246,0.1)' },
team_internal: { color: '#0958d9', label: '团队内部', bg: 'rgba(139,92,246,0.1)' },
};
const config = typeConfig[text] || { color: '#64748b', label: text, 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: '描述',
dataIndex: 'description',
key: 'description',
ellipsis: true,
},
{
title: '变动积分',
dataIndex: 'amount',
key: 'amount',
width: 120,
align: 'right' as const,
render: (amount: number) => (
<Typography.Text strong style={{ fontWeight: 700, color: amount > 0 ? '#10b981' : '#ef4444', fontSize: 15 }}>
{amount > 0 ? '+' : ''}{amount}
</Typography.Text>
),
},
{
title: '创建时间',
key: 'createdAt',
width: 180,
render: (_, record: any) => {
const createdAt = record.created_at || record.createdAt || record.create_time || record.createTime;
return createdAt ? new Date(createdAt).toLocaleString('zh-CN') : '-';
},
},
];
return (
<div>
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col xs={24} sm={8}>
<div style={{
borderRadius: 16, padding: 24,
background: 'linear-gradient(135deg, #f59e0b 0%, #ea580c 100%)',
position: 'relative', overflow: 'hidden',
}}>
<div style={{ position: 'absolute', right: -20, top: -20, width: 120, height: 120, borderRadius: '50%', background: 'rgba(255,255,255,0.1)' }} />
<div style={{ position: 'relative' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<WalletOutlined style={{ color: 'rgba(255,255,255,0.8)', fontSize: 16 }} />
<span style={{ color: 'rgba(255,255,255,0.8)', fontSize: 14 }}>可用积分</span>
</div>
<div style={{ color: '#fff', fontSize: 38, fontWeight: 800, lineHeight: 1 }}>
{credits.toLocaleString()}
</div>
</div>
</div>
</Col>
<Col xs={12} sm={8}>
<div style={{
borderRadius: 16, padding: 24, background: '#fff', border: '1px solid #f0f0f5',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<div style={{ width: 32, height: 32, borderRadius: 8, background: 'rgba(16,185,129,0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<PlusCircleOutlined style={{ color: '#10b981', fontSize: 14 }} />
</div>
<span style={{ color: '#94a3b8', fontSize: 14 }}>累计获得</span>
</div>
<div style={{ color: '#10b981', fontSize: 28, fontWeight: 800 }}>
{records.filter((r: any) => r.amount > 0).reduce((sum: number, r: any) => sum + r.amount, 0).toLocaleString()}
</div>
</div>
</Col>
<Col xs={12} sm={8}>
<div style={{
borderRadius: 16, padding: 24, background: '#fff', border: '1px solid #f0f0f5',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
<div style={{ width: 32, height: 32, borderRadius: 8, background: 'rgba(239,68,68,0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<ThunderboltOutlined style={{ color: '#ef4444', fontSize: 14 }} />
</div>
<span style={{ color: '#94a3b8', fontSize: 14 }}>累计消耗</span>
</div>
<div style={{ color: '#ef4444', fontSize: 28, fontWeight: 800 }}>
{records.filter((r: any) => r.amount < 0).reduce((sum: number, r: any) => sum + Math.abs(r.amount), 0).toLocaleString()}
</div>
</div>
</Col>
</Row>
<div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
<ThunderboltOutlined style={{ color: '#f59e0b', fontSize: 16 }} />
<Typography.Text strong style={{ fontSize: 16 }}>积分明细</Typography.Text>
</div>
<div style={{ borderRadius: 16, background: '#fff', border: '1px solid #f0f0f5', overflow: 'hidden' }}>
<Spin spinning={loading}>
{records.length === 0 ? (
<Empty
description={<span style={{ color: '#94a3b8' }}>暂无积分变动记录</span>}
/>
) : (
<>
<Table
dataSource={records}
columns={columns}
rowKey="id"
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 CreditRecordsPage;