fix: polish channel groups and add production deployment
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { ChevronLeft, ChevronRight, Plus, Search } from 'lucide-react';
|
||||
import { Breadcrumb, Button, DateRangeInput, Input, Modal, Select, Textarea, Tag, type DateRangeValue } from '@/components/ui';
|
||||
import { adminApi, type AccountTransaction, type RechargeOrder, type TenantAccount, type TenantOption } from '@/api/adminApi';
|
||||
import { Plus, Search } from 'lucide-react';
|
||||
import { Breadcrumb, Button, DateRangeInput, Input, Modal, Pagination, Select, Textarea, Tag, type DateRangeValue } from '@/components/ui';
|
||||
import { adminApi, type RechargeOrder, type TenantAccount, type TenantOption } from '@/api/adminApi';
|
||||
|
||||
type ManualRechargeForm = {
|
||||
tenantId: string;
|
||||
@@ -37,12 +37,12 @@ function RemarkCell({ value }: { value?: string }) {
|
||||
export function AdminRechargeRecordsPage() {
|
||||
const [records, setRecords] = useState<RechargeOrder[]>([]);
|
||||
const [accounts, setAccounts] = useState<TenantAccount[]>([]);
|
||||
const [transactions, setTransactions] = useState<AccountTransaction[]>([]);
|
||||
const [tenants, setTenants] = useState<TenantOption[]>([]);
|
||||
const [enterpriseKeyword, setEnterpriseKeyword] = useState('');
|
||||
const [dateRange, setDateRange] = useState<DateRangeValue>({});
|
||||
const [manualOpen, setManualOpen] = useState(false);
|
||||
const [form, setForm] = useState<ManualRechargeForm>({ tenantId: '', amount: '', smsUnits: '0', operator: '运营', remark: '' });
|
||||
const [page, setPage] = useState(1);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
@@ -50,16 +50,14 @@ export function AdminRechargeRecordsPage() {
|
||||
setLoading(true);
|
||||
setError('');
|
||||
try {
|
||||
const [nextTenants, nextRecords, nextAccounts, nextTransactions] = await Promise.all([
|
||||
const [nextTenants, nextRecords, nextAccounts] = await Promise.all([
|
||||
adminApi.listTenants(),
|
||||
adminApi.listManualRecharges(),
|
||||
adminApi.listAccounts(),
|
||||
adminApi.listTransactions(),
|
||||
]);
|
||||
setTenants(nextTenants);
|
||||
setRecords(nextRecords);
|
||||
setAccounts(nextAccounts);
|
||||
setTransactions(nextTransactions);
|
||||
setForm((current) => ({ ...current, tenantId: current.tenantId || nextTenants[0]?.id || '' }));
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : '充值记录加载失败');
|
||||
@@ -84,6 +82,14 @@ export function AdminRechargeRecordsPage() {
|
||||
}),
|
||||
[dateRange.end, dateRange.start, enterpriseKeyword, records, tenants],
|
||||
);
|
||||
const pageSize = 10;
|
||||
const totalPages = Math.max(1, Math.ceil(filteredRows.length / pageSize));
|
||||
const currentPage = Math.min(page, totalPages);
|
||||
const visibleRows = filteredRows.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
||||
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
}, [dateRange.end, dateRange.start, enterpriseKeyword, records.length]);
|
||||
|
||||
function resetFilters() {
|
||||
setEnterpriseKeyword('');
|
||||
@@ -151,16 +157,15 @@ export function AdminRechargeRecordsPage() {
|
||||
<tr><td className="ui-table__empty" colSpan={7}>正在加载真实充值记录...</td></tr>
|
||||
) : filteredRows.length === 0 ? (
|
||||
<tr><td className="ui-table__empty" colSpan={7}>暂无真实充值记录</td></tr>
|
||||
) : filteredRows.map((record) => {
|
||||
) : visibleRows.map((record) => {
|
||||
const account = accounts.find((item) => item.tenantId === record.tenantId);
|
||||
const transaction = transactions.find((item) => item.relatedId === record.id);
|
||||
const tenantName = record.tenant?.name ?? tenants.find((tenant) => tenant.id === record.tenantId)?.name ?? record.tenantId;
|
||||
return (
|
||||
<tr key={record.id}>
|
||||
<td><strong>{tenantName}</strong></td>
|
||||
<td>{new Date(record.paidAt ?? record.createdAt).toLocaleString('zh-CN')}</td>
|
||||
<td>{formatAmount(record.amountCents / 100)}</td>
|
||||
<td>{formatAmount((transaction?.balanceAfter ?? account?.balanceCents ?? 0) / 100)}</td>
|
||||
<td>{formatAmount((account?.balanceCents ?? 0) / 100)}</td>
|
||||
<td><Tag tone="warning">人工充值</Tag></td>
|
||||
<td>{record.operatorId || '运营'}</td>
|
||||
<td><RemarkCell value={record.remark ?? undefined} /></td>
|
||||
@@ -171,18 +176,14 @@ export function AdminRechargeRecordsPage() {
|
||||
</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>
|
||||
<Pagination
|
||||
nextDisabled={currentPage >= totalPages}
|
||||
onNext={() => setPage((value) => Math.min(totalPages, value + 1))}
|
||||
onPrevious={() => setPage((value) => Math.max(1, value - 1))}
|
||||
page={currentPage}
|
||||
previousDisabled={currentPage <= 1}
|
||||
total={filteredRows.length}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{manualOpen ? (
|
||||
|
||||
Reference in New Issue
Block a user