feat: wire admin workflows to real APIs

This commit is contained in:
hectorzhao
2026-07-02 13:50:09 +08:00
parent f8c9b78c21
commit ab421cf8a7
42 changed files with 2596 additions and 250 deletions
+31 -11
View File
@@ -1,6 +1,6 @@
import { useMemo, useState } from 'react';
import { CalendarDays, Download, FileText, Search } from 'lucide-react';
import { Breadcrumb, Button, Input, Select, Table, Tag, type TableColumn } from '@/components/ui';
import { Button, Input, Pagination, Select, Table, Tag, type TableColumn } from '@/components/ui';
type LogLevel = 'info' | 'success' | 'warning' | 'error';
@@ -44,6 +44,8 @@ export function AdminSystemLogsPage() {
const [level, setLevel] = useState('all');
const [module, setModule] = useState('all');
const [range, setRange] = useState('today');
const [page, setPage] = useState(1);
const pageSize = 5;
const moduleOptions = useMemo(() => {
const modules = Array.from(new Set(logsSeed.map((item) => item.module)));
@@ -57,6 +59,9 @@ export function AdminSystemLogsPage() {
const matchesModule = module === 'all' || item.module === module;
return matchesKeyword && matchesLevel && matchesModule;
});
const totalPages = Math.max(1, Math.ceil(filteredLogs.length / pageSize));
const currentPage = Math.min(page, totalPages);
const pagedLogs = filteredLogs.slice((currentPage - 1) * pageSize, currentPage * pageSize);
const columns = useMemo<Array<TableColumn<AdminSystemLog>>>(() => [
{ key: 'time', title: '时间', width: '180px', render: (record) => <span className="muted">{record.time}</span> },
@@ -66,7 +71,18 @@ export function AdminSystemLogsPage() {
{ key: 'operator', title: '操作人', width: '120px', render: (record) => <strong>{record.operator}</strong> },
{ key: 'action', title: '动作', width: '140px', render: (record) => record.action },
{ key: 'resourceId', title: '资源ID', width: '150px', render: (record) => <span className="muted">{record.resourceId}</span> },
{ key: 'detail', title: '详情', render: (record) => <span className="system-log-detail">{record.detail}</span> },
{
key: 'detail',
title: '详情',
width: '320px',
render: (record) => (
<div className="system-log-detail-card">
<strong>{record.action}</strong>
<span>{record.detail}</span>
<small>{record.resourceId}</small>
</div>
),
},
{ key: 'ip', title: 'IP', width: '120px', render: (record) => <span className="muted">{record.ip}</span> },
], []);
@@ -75,23 +91,20 @@ export function AdminSystemLogsPage() {
<div className="system-page-toolbar">
<div className="sms-send-title">
<span className="sms-send-title__icon"><FileText size={22} /></span>
<div>
<Breadcrumb items={['系统管理', '系统日志']} />
<h1></h1>
</div>
<h1></h1>
</div>
<Button icon={<Download size={17} />} variant="secondary"></Button>
</div>
<div className="system-log-filters">
<Input
onChange={(event) => setKeyword(event.target.value)}
onChange={(event) => { setKeyword(event.target.value); setPage(1); }}
placeholder="搜索企业、操作人、动作、资源ID或详情"
prefix={<Search size={16} />}
value={keyword}
/>
<Select
onChange={(event) => setLevel(event.target.value)}
onChange={(event) => { setLevel(event.target.value); setPage(1); }}
options={[
{ label: '全部级别', value: 'all' },
{ label: '信息', value: 'info' },
@@ -101,7 +114,7 @@ export function AdminSystemLogsPage() {
]}
value={level}
/>
<Select onChange={(event) => setModule(event.target.value)} options={moduleOptions} value={module} />
<Select onChange={(event) => { setModule(event.target.value); setPage(1); }} options={moduleOptions} value={module} />
</div>
<div className="system-log-range">
@@ -124,9 +137,16 @@ export function AdminSystemLogsPage() {
</div>
<div className="surface system-table-card">
<Table columns={columns} data={filteredLogs} emptyText="暂无系统日志" rowKey="id" />
<Table columns={columns} data={pagedLogs} emptyText="暂无系统日志" rowKey="id" />
<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={filteredLogs.length}
/>
</div>
</section>
);
}