Files
goalfylearning-admin-web/src/pages/FinanceTransactionLogs.tsx
2025-12-04 20:54:44 +08:00

129 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useMemo, useState } from 'react';
import { Card, Table, Typography, Form, Input, DatePicker, Button, Space, Select } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { FinanceApiService } from '../services/api';
const FinanceTransactionLogs: React.FC = () => {
const [data, setData] = useState<any[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [size, setSize] = useState(20);
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const buildParams = (p = page, s = size) => {
const vals = form.getFieldsValue();
const range = vals.range as any[] | undefined;
const start = range?.[0]?.format?.('YYYY-MM-DD') || undefined;
const end = range?.[1]?.format?.('YYYY-MM-DD') || undefined;
return {
page: p,
size: s,
user_id: vals.user_id,
order_id: vals.order_id,
type: vals.type,
status: vals.status,
start,
end,
} as any;
};
const fetchList = async (p = page, s = size) => {
setLoading(true);
try {
const res = await FinanceApiService.listTransactionLogs(buildParams(p, s));
setData(res?.data || res?.list || []);
setTotal(res?.total || 0);
} finally {
setLoading(false);
}
};
useEffect(() => { fetchList(); }, []);
const columns: ColumnsType<any> = useMemo(() => ([
{ title: '流水ID', dataIndex: 'transaction_id', key: 'transaction_id' },
{ title: '用户id', dataIndex: 'user_id', key: 'user_id' },
{ title: '订单id', dataIndex: 'order_id', key: 'order_id' },
{ title: '流水类型', dataIndex: 'type', key: 'type' },
{ title: '金额(最小单位)', dataIndex: 'amount', key: 'amount' },
{ title: '货币', dataIndex: 'currency', key: 'currency' },
{ title: '操作前余额', dataIndex: 'balance_before', key: 'balance_before' },
{ title: '操作后余额', dataIndex: 'balance_after', key: 'balance_after' },
{ title: '状态', dataIndex: 'status', key: 'status' },
{ title: '描述', dataIndex: 'description', key: 'description' },
{ title: 'PayPal交易ID', dataIndex: 'paypal_transaction_id', key: 'paypal_transaction_id' },
{ title: '创建时间', dataIndex: 'created_at', key: 'created_at' },
]), []);
return (
<Card bordered={false} title={<Typography.Title level={4} style={{ margin: 0 }}></Typography.Title>}>
<Form
form={form}
onFinish={() => fetchList(1, size)}
style={{ marginBottom: 20 }}
>
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
{/* 第一行用户ID、订单编号、流水类型、状态、时间范围 */}
<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap', alignItems: 'center' }}>
<Form.Item name="user_id" label="用户PID:" style={{ margin: 0, flex: '0 0 auto' }}>
<Input allowClear placeholder="用户ID" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="order_id" label="订单编号:" style={{ margin: 0, flex: '0 0 auto' }}>
<Input allowClear placeholder="订单编号" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="type" label="流水类型:" style={{ margin: 0, flex: '0 0 auto' }}>
<Select allowClear placeholder="充值/退款/消费" style={{ width: 220 }}
options={[
{ label: 'recharge', value: 'recharge' },
{ label: 'refund', value: 'refund' },
{ label: 'consume', value: 'consume' },
]}
/>
</Form.Item>
<Form.Item name="status" label="状态:" style={{ margin: 0, flex: '0 0 auto' }}>
<Select allowClear placeholder="成功/失败/待定" style={{ width: 220 }}
options={[
{ label: 'success', value: 'success' },
{ label: 'failed', value: 'failed' },
{ label: 'pending', value: 'pending' },
]}
/>
</Form.Item>
</div>
{/* 第二行:时间范围和按钮 */}
<div style={{ display: 'flex', gap: '16px', alignItems: 'center', flexWrap: 'wrap' }}>
<Form.Item name="range" label="时间范围:" style={{ margin: 0, flex: '0 0 auto' }}>
<DatePicker.RangePicker style={{ width: 300 }} />
</Form.Item>
<Form.Item style={{ margin: 0, flex: '0 0 auto' }}>
<Space size="middle">
<Button type="primary" htmlType="submit" onClick={() => { setPage(1); }} size="middle">
</Button>
<Button onClick={() => { form.resetFields(); fetchList(1, size); setPage(1); }} size="middle">
</Button>
</Space>
</Form.Item>
</div>
</div>
</Form>
<Table
rowKey={(r) => r.id || r.transaction_id}
columns={columns}
dataSource={data}
loading={loading}
pagination={{ current: page, pageSize: size, total, onChange: (p, s) => { setPage(p); setSize(s); fetchList(p, s); } }}
scroll={{ x: 1200 }}
/>
</Card>
);
};
export default FinanceTransactionLogs;