Initial CMPP frontend prototype
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { ChevronLeft, ChevronRight, Search } from 'lucide-react';
|
||||
import { Button, DateRangeInput, Input, Select, type DateRangeValue } from '@/components/ui';
|
||||
|
||||
type RechargeRecord = {
|
||||
id: string;
|
||||
enterprise: string;
|
||||
rechargedAt: string;
|
||||
amount?: number;
|
||||
balance?: number;
|
||||
operator?: string;
|
||||
};
|
||||
|
||||
const rechargeRecords: RechargeRecord[] = [
|
||||
{ id: 'RCG202601120001', enterprise: 'XXXX科技有限公司', rechargedAt: '2026-01-12 19:27:19', amount: 1000, balance: 1000, operator: '李XXX' },
|
||||
{ id: 'RCG202601120002', enterprise: 'XXX公司名字', rechargedAt: '2026-01-12 19:27:19', amount: 500, balance: 5896.25, operator: '张三' },
|
||||
{ id: 'RCG202601120003', enterprise: 'XXX公司名字XXX公司名字', rechargedAt: '2026-01-12 19:27:19', amount: 192.29, balance: 0, operator: '张三' },
|
||||
{ id: 'RCG202601120004', enterprise: '', rechargedAt: '2026-01-12 19:27:19', amount: 2617.09, balance: 0, operator: '李四' },
|
||||
{ id: 'RCG202601120005', enterprise: '', rechargedAt: '2026-01-12 19:27:19', amount: 122, balance: 0, operator: '' },
|
||||
{ id: 'RCG202601120006', enterprise: '', rechargedAt: '2026-01-12 19:27:19' },
|
||||
{ id: 'RCG202601120007', enterprise: '', rechargedAt: '2026-01-12 19:27:19' },
|
||||
{ id: 'RCG202601120008', enterprise: '', rechargedAt: '2026-01-12 19:27:19' },
|
||||
];
|
||||
|
||||
function getDate(value: string) {
|
||||
return value.slice(0, 10);
|
||||
}
|
||||
|
||||
function formatAmount(value?: number) {
|
||||
if (value === undefined) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return value.toLocaleString('zh-CN', {
|
||||
maximumFractionDigits: 2,
|
||||
minimumFractionDigits: Number.isInteger(value) ? 0 : 2,
|
||||
});
|
||||
}
|
||||
|
||||
export function AdminRechargeRecordsPage() {
|
||||
const [enterpriseKeyword, setEnterpriseKeyword] = useState('');
|
||||
const [dateRange, setDateRange] = useState<DateRangeValue>({});
|
||||
|
||||
const filteredRows = useMemo(
|
||||
() => rechargeRecords.filter((item) => {
|
||||
const rechargeDate = getDate(item.rechargedAt);
|
||||
const matchesEnterprise = !enterpriseKeyword || item.enterprise.includes(enterpriseKeyword);
|
||||
const matchesStartDate = !dateRange.start || rechargeDate >= dateRange.start;
|
||||
const matchesEndDate = !dateRange.end || rechargeDate <= dateRange.end;
|
||||
return matchesEnterprise && matchesStartDate && matchesEndDate;
|
||||
}),
|
||||
[dateRange.end, dateRange.start, enterpriseKeyword],
|
||||
);
|
||||
|
||||
function resetFilters() {
|
||||
setEnterpriseKeyword('');
|
||||
setDateRange({});
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="page-stack admin-recharge-page">
|
||||
<div className="page-heading">
|
||||
<div>
|
||||
<div className="breadcrumb-line">数据详单 / <strong>充值记录</strong></div>
|
||||
<h1>充值记录</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="surface admin-recharge-filter">
|
||||
<Input label="企业名称" onChange={(event) => setEnterpriseKeyword(event.target.value)} value={enterpriseKeyword} />
|
||||
<DateRangeInput label="充值日期" onChange={setDateRange} value={dateRange} />
|
||||
<div className="admin-recharge-filter__actions">
|
||||
<Button icon={<Search size={16} />}>查询</Button>
|
||||
<Button onClick={resetFilters} variant="ghost">重置</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="surface admin-recharge-table-card">
|
||||
<div className="ui-table-wrap">
|
||||
<table className="ui-table admin-recharge-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>企业名称</th>
|
||||
<th>充值时间</th>
|
||||
<th>充值金额</th>
|
||||
<th>充值后余额</th>
|
||||
<th>操作人</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredRows.map((record) => (
|
||||
<tr key={record.id}>
|
||||
<td><strong>{record.enterprise}</strong></td>
|
||||
<td>{record.rechargedAt}</td>
|
||||
<td>{formatAmount(record.amount)}</td>
|
||||
<td>{formatAmount(record.balance)}</td>
|
||||
<td>{record.operator}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="admin-recharge-pagination">
|
||||
<Select options={[{ label: '10条/页', value: '10' }, { label: '20条/页', value: '20' }]} value="10" />
|
||||
<div>
|
||||
<Button icon={<ChevronLeft size={16} />} iconOnly variant="ghost">上一页</Button>
|
||||
<Button size="sm" variant="ghost">24</Button>
|
||||
<Button size="sm">25</Button>
|
||||
<Button size="sm" variant="ghost">26</Button>
|
||||
<span>...</span>
|
||||
<Button size="sm" variant="ghost">63</Button>
|
||||
<Button icon={<ChevronRight size={16} />} iconOnly variant="ghost">下一页</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user