Files
lislgosms/src/apps/client/ClientBillingPage.tsx
T

69 lines
3.4 KiB
TypeScript

import { useEffect, useState } from 'react';
import { WalletCards } from 'lucide-react';
import { Pagination, Tag } from '@/components/ui';
import { clientApi, type RechargeOrder } from '@/api/adminApi';
import { formatCents } from '@/utils/currency';
import { formatDateTime } from '@/utils/dateTime';
export function ClientBillingPage() {
const [balanceCents, setBalanceCents] = useState(0);
const [orders, setOrders] = useState<RechargeOrder[]>([]);
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const pageSize = 10;
const totalPages = Math.max(1, Math.ceil(orders.length / pageSize));
const currentPage = Math.min(page, totalPages);
const visibleOrders = orders.slice((currentPage - 1) * pageSize, currentPage * pageSize);
useEffect(() => {
setLoading(true);
Promise.all([clientApi.getDashboard(), clientApi.listOrders()])
.then(([dashboard, nextOrders]) => {
setBalanceCents(dashboard.accounts[0]?.balanceCents ?? 0);
setOrders(nextOrders);
setError('');
})
.catch((reason: Error) => setError(reason.message || '账户信息加载失败'))
.finally(() => setLoading(false));
}, []);
return (
<section className="page-stack">
<div className="page-heading">
<div><p className="eyebrow">账户</p><h1>账户余额</h1></div>
</div>
<div className="dashboard-grid enterprise-summary-grid">
<div className="surface mini-status-card">
<WalletCards size={22} />
<div><span>当前可用余额</span><strong>¥{formatCents(balanceCents)}</strong><small>短信发送仅按现金余额校验。</small></div>
</div>
</div>
<div className="surface section-stack">
<div className="section-heading"><div><h2>充值记录</h2><p className="muted">如需充值,请联系平台运营人员。</p></div><Tag tone="info">{orders.length} </Tag></div>
{loading ? <p className="muted">正在加载账户信息...</p> : null}
{error ? <p className="form-error">{error}</p> : null}
{!loading && !error ? (
<div className="ui-table-wrap">
<table className="ui-table">
<thead><tr><th>订单号</th><th>充值时间</th><th>充值金额</th><th>状态</th><th>备注</th></tr></thead>
<tbody>
{visibleOrders.length === 0 ? <tr><td className="ui-table__empty" colSpan={5}>暂无充值记录</td></tr> : visibleOrders.map((order) => (
<tr key={order.id}>
<td><span className="table-mono-id">{order.orderNo}</span></td>
<td>{formatDateTime(order.paidAt ?? order.createdAt)}</td>
<td>¥{formatCents(order.amountCents)}</td>
<td><Tag tone={order.status === 'paid' ? 'success' : 'warning'}>{order.status === 'paid' ? '已入账' : order.status}</Tag></td>
<td>{order.remark || '-'}</td>
</tr>
))}
</tbody>
</table>
</div>
) : null}
<Pagination nextDisabled={currentPage >= totalPages} onNext={() => setPage((value) => Math.min(totalPages, value + 1))} onPrevious={() => setPage((value) => Math.max(1, value - 1))} page={currentPage} totalPages={totalPages} onPageChange={setPage} previousDisabled={currentPage <= 1} total={orders.length} />
</div>
</section>
);
}