fix: clarify client amounts and log date filters

This commit is contained in:
hectorzhao
2026-08-27 19:50:12 +08:00
parent ec721bf95a
commit 33fa3709d9
18 changed files with 136 additions and 82 deletions
+18 -25
View File
@@ -1,8 +1,8 @@
import { useEffect, useMemo, useState } from 'react';
import { CalendarDays, FileText, Search } from 'lucide-react';
import { Button, Input, Modal, Pagination, Select, SystemLogExport, Table, Tabs, Tag, type TableColumn } from '@/components/ui';
import { FileText, Search } from 'lucide-react';
import { Button, DateRangeInput, Input, Modal, Pagination, Select, SystemLogExport, Table, Tabs, Tag, type DateRangeValue, type TableColumn } from '@/components/ui';
import { adminApi, type OperationLogItem, type ProtocolInteractionLogItem } from '@/api/adminApi';
import { formatDateTime } from '@/utils/dateTime';
import { formatDateTime, recentBeijingDateRange } from '@/utils/dateTime';
type LogLevel = 'info' | 'success' | 'warning' | 'error';
@@ -25,8 +25,11 @@ export function AdminSystemLogsPage() {
const [keyword, setKeyword] = useState('');
const [level, setLevel] = useState('all');
const [module, setModule] = useState('all');
const [range, setRange] = useState('today');
const [filters, setFilters] = useState({ keyword: '', level: 'all', module: 'all', range: 'today' });
const [dateRange, setDateRange] = useState<DateRangeValue>(() => recentBeijingDateRange(7));
const [filters, setFilters] = useState<{ keyword: string; level: string; module: string; createdAtFrom?: string; createdAtTo?: string }>(() => {
const initialRange = recentBeijingDateRange(7);
return { keyword: '', level: 'all', module: 'all', createdAtFrom: initialRange.start, createdAtTo: initialRange.end };
});
const [page, setPage] = useState(1);
const pageSize = 5;
const [logs, setLogs] = useState<OperationLogItem[]>([]);
@@ -59,16 +62,17 @@ export function AdminSystemLogsPage() {
function query() {
setPage(1);
setFilters({ keyword: keyword.trim(), level, module, range });
setFilters({ keyword: keyword.trim(), level, module, createdAtFrom: dateRange.start, createdAtTo: dateRange.end });
}
function reset() {
setKeyword('');
setLevel('all');
setModule('all');
setRange('today');
const nextDateRange = recentBeijingDateRange(7);
setDateRange(nextDateRange);
setPage(1);
setFilters({ keyword: '', level: 'all', module: 'all', range: 'today' });
setFilters({ keyword: '', level: 'all', module: 'all', createdAtFrom: nextDateRange.start, createdAtTo: nextDateRange.end });
}
const columns = useMemo<Array<TableColumn<OperationLogItem>>>(() => [
@@ -118,14 +122,13 @@ export function AdminSystemLogsPage() {
value={level}
/>
<Select onChange={(event) => setModule(event.target.value)} options={moduleOptions} value={module} />
<DateRangeInput label="日志时间" onChange={setDateRange} placeholder="选择日志时间区间" value={dateRange} />
<div className="system-log-filters__actions">
<Button icon={<Search size={16} />} onClick={query}></Button>
<Button onClick={reset} variant="ghost"></Button>
</div>
</div>
<LogRange range={range} onChange={setRange} />
<div className="surface system-table-card">
<Table columns={columns} data={logs} emptyText={error || '暂无系统日志'} pagination={false} rowKey="id" />
<Pagination
@@ -222,7 +225,7 @@ function protocolStatusLabel(record: ProtocolInteractionLogItem) {
}
function ProtocolInteractionPanel({ active }: { active: boolean }) {
const [inputs, setInputs] = useState({ keyword: '', protocol: 'all', direction: 'all', eventType: 'all', status: 'all', range: 'today' });
const [inputs, setInputs] = useState(() => ({ keyword: '', protocol: 'all', direction: 'all', eventType: 'all', status: 'all', dateRange: recentBeijingDateRange(7) as DateRangeValue }));
const [filters, setFilters] = useState(inputs);
const [items, setItems] = useState<ProtocolInteractionLogItem[]>([]);
const [eventTypes, setEventTypes] = useState<string[]>([]);
@@ -235,7 +238,8 @@ function ProtocolInteractionPanel({ active }: { active: boolean }) {
useEffect(() => {
if (!active) return;
let cancelled = false;
adminApi.listProtocolInteractionLogs({ ...filters, page, pageSize })
const { dateRange, ...queryFilters } = filters;
adminApi.listProtocolInteractionLogs({ ...queryFilters, createdAtFrom: dateRange.start, createdAtTo: dateRange.end, page, pageSize })
.then((data) => {
if (cancelled) return;
setItems(data.items);
@@ -271,7 +275,7 @@ function ProtocolInteractionPanel({ active }: { active: boolean }) {
}
function reset() {
const next = { keyword: '', protocol: 'all', direction: 'all', eventType: 'all', status: 'all', range: 'today' };
const next = { keyword: '', protocol: 'all', direction: 'all', eventType: 'all', status: 'all', dateRange: recentBeijingDateRange(7) };
setInputs(next);
setFilters(next);
setPage(1);
@@ -286,9 +290,9 @@ function ProtocolInteractionPanel({ active }: { active: boolean }) {
<Select onChange={(event) => setInputs((value) => ({ ...value, direction: event.target.value }))} options={[{ label: '全部方向', value: 'all' }, ...Object.entries(directionLabels).map(([value, label]) => ({ value, label }))]} value={inputs.direction} />
<Select onChange={(event) => setInputs((value) => ({ ...value, eventType: event.target.value }))} options={[{ label: '全部事件', value: 'all' }, ...eventTypes.map((value) => ({ label: value, value }))]} value={inputs.eventType} />
<Select onChange={(event) => setInputs((value) => ({ ...value, status: event.target.value }))} options={[{ label: '全部结果', value: 'all' }, { label: '已接收', value: 'received' }, { label: '已受理', value: 'accepted' }, { label: '成功', value: 'success' }, { label: '重试中', value: 'retrying' }, { label: '失败', value: 'failed' }]} value={inputs.status} />
<DateRangeInput label="日志时间" onChange={(dateRange) => setInputs((value) => ({ ...value, dateRange }))} placeholder="选择日志时间区间" value={inputs.dateRange} />
<div className="system-log-filters__actions"><Button icon={<Search size={16} />} onClick={query}></Button><Button onClick={reset} variant="ghost"></Button></div>
</div>
<LogRange range={inputs.range} onChange={(range) => setInputs((value) => ({ ...value, range }))} />
<div className="surface system-table-card protocol-log-table">
<Table columns={columns} data={items} emptyText={error || '暂无通讯交互日志'} pagination={false} rowKey="id" />
<Pagination nextDisabled={page >= totalPages} onNext={() => setPage((value) => Math.min(totalPages, value + 1))} onPrevious={() => setPage((value) => Math.max(1, value - 1))} page={Math.min(page, totalPages)} totalPages={totalPages} onPageChange={setPage} previousDisabled={page <= 1} total={total} />
@@ -299,14 +303,3 @@ function ProtocolInteractionPanel({ active }: { active: boolean }) {
</div>
);
}
function LogRange({ range, onChange }: { range: string; onChange: (value: string) => void }) {
return (
<div className="system-log-range">
<span><CalendarDays size={18} /> </span>
{[{ label: '今天', value: 'today' }, { label: '近7天', value: '7d' }, { label: '近30天', value: '30d' }, { label: '全部', value: 'all' }].map((item) => (
<Button key={item.value} onClick={() => onChange(item.value)} size="sm" variant={range === item.value ? 'primary' : 'secondary'}>{item.label}</Button>
))}
</div>
);
}
+9 -26
View File
@@ -1,17 +1,18 @@
import { useEffect, useMemo, useState } from 'react';
import { CalendarDays, FileText, Search } from 'lucide-react';
import { FileText, Search } from 'lucide-react';
import {
Button,
DateRangeInput,
Input,
Pagination,
Select,
SystemLogExport,
Table,
Tag,
type DateRangeValue,
type TableColumn,
} from '@/components/ui';
import { clientApi, type OperationLogItem } from '@/api/adminApi';
import { formatDateTime } from '@/utils/dateTime';
import { formatDateTime, recentBeijingDateRange } from '@/utils/dateTime';
type LogLevel = 'info' | 'success' | 'warning' | 'error';
@@ -33,7 +34,7 @@ export function ClientSystemLogsPage() {
const [keyword, setKeyword] = useState('');
const [level, setLevel] = useState('all');
const [module, setModule] = useState('all');
const [range, setRange] = useState('today');
const [dateRange, setDateRange] = useState<DateRangeValue>(() => recentBeijingDateRange(7));
const [page, setPage] = useState(1);
const pageSize = 5;
const [logs, setLogs] = useState<OperationLogItem[]>([]);
@@ -42,7 +43,7 @@ export function ClientSystemLogsPage() {
const [error, setError] = useState('');
useEffect(() => {
clientApi.listSystemLogs({ keyword, level, module, range, page, pageSize })
clientApi.listSystemLogs({ keyword, level, module, createdAtFrom: dateRange.start, createdAtTo: dateRange.end, page, pageSize })
.then((data) => {
setLogs(data.items);
setModules(data.modules);
@@ -54,7 +55,7 @@ export function ClientSystemLogsPage() {
setTotal(0);
setError(err instanceof Error ? err.message : '系统日志加载失败');
});
}, [keyword, level, module, range, page]);
}, [keyword, level, module, dateRange.end, dateRange.start, page]);
const moduleOptions = useMemo(() => {
return [{ label: '全部模块', value: 'all' }, ...modules.map((item) => ({ label: item, value: item }))];
@@ -79,7 +80,7 @@ export function ClientSystemLogsPage() {
<span className="sms-send-title__icon"><FileText size={22} /></span>
<h1></h1>
</div>
<SystemLogExport exportLogs={clientApi.exportSystemLogs} filters={{ keyword, level, module, range }} portal="client" />
<SystemLogExport exportLogs={clientApi.exportSystemLogs} filters={{ keyword, level, module, createdAtFrom: dateRange.start, createdAtTo: dateRange.end }} portal="client" />
</div>
<div className="system-log-filters">
@@ -101,25 +102,7 @@ export function ClientSystemLogsPage() {
value={level}
/>
<Select onChange={(event) => { setModule(event.target.value); setPage(1); }} options={moduleOptions} value={module} />
</div>
<div className="system-log-range">
<span><CalendarDays size={18} /> </span>
{[
{ label: '今天', value: 'today' },
{ label: '近7天', value: '7d' },
{ label: '近30天', value: '30d' },
{ label: '全部', value: 'all' },
].map((item) => (
<Button
key={item.value}
onClick={() => setRange(item.value)}
size="sm"
variant={range === item.value ? 'primary' : 'secondary'}
>
{item.label}
</Button>
))}
<DateRangeInput label="日志时间" onChange={(value) => { setDateRange(value); setPage(1); }} placeholder="选择日志时间区间" value={dateRange} />
</div>
<div className="surface system-table-card">