optimize ui loading and dashboard performance

This commit is contained in:
hectorzhao
2026-08-27 15:17:47 +08:00
parent 7ff019e829
commit ecb567c0da
28 changed files with 1307 additions and 132 deletions
+36 -5
View File
@@ -1,3 +1,4 @@
import { useEffect, useState } from 'react';
import { Alert, Badge, Button } from './ui.jsx';
const selectedBlue = '#2563EB';
@@ -55,7 +56,7 @@ export function Panel({ title, aside, children, className = '' }) {
export function ApiNotice({ loading, error, onRetry }) {
if (loading) {
return <Alert title="正在读取真实 API">正在从 LisgloSIPS API 拉取页面数据</Alert>;
return null;
}
if (error) {
return (
@@ -68,6 +69,32 @@ export function ApiNotice({ loading, error, onRetry }) {
return null;
}
export function PageLoadingDialog({ loading, message = '页面加载中,请稍候…', delay = 2000 }) {
const [visible, setVisible] = useState(false);
useEffect(() => {
if (!loading) {
setVisible(false);
return undefined;
}
const timer = window.setTimeout(() => setVisible(true), delay);
return () => window.clearTimeout(timer);
}, [delay, loading]);
if (!visible) return null;
return (
<div className="page-loading-backdrop" role="status" aria-live="polite" aria-label={message}>
<div className="page-loading-dialog">
<span className="page-loading-spinner" aria-hidden="true" />
<div>
<strong>{message}</strong>
<span>正在读取真实业务数据请不要重复刷新</span>
</div>
</div>
</div>
);
}
export function EmptyState({ title = '暂无数据', children = '当前筛选条件下没有可展示的数据。' }) {
return (
<div className="empty-state">
@@ -139,10 +166,10 @@ export function StatusBadge({ children }) {
return <Badge tone={toneForStatus(children)}>{children}</Badge>;
}
export function SimpleTable({ columns, rows, onRowClick, selectedKey }) {
export function SimpleTable({ columns, rows, onRowClick, selectedKey, loading = false, emptyTitle = '暂无数据', emptyDescription }) {
return (
<div className="table-shell">
<table className="proto-table">
<table className="proto-table" aria-busy={loading}>
{columns.some((column) => column.width) ? (
<colgroup>
{columns.map((column) => <col key={column.key} style={column.width ? { width: column.width } : undefined} />)}
@@ -154,10 +181,14 @@ export function SimpleTable({ columns, rows, onRowClick, selectedKey }) {
</tr>
</thead>
<tbody>
{rows.length === 0 ? (
{loading && rows.length === 0 ? Array.from({ length: 4 }, (_, rowIndex) => (
<tr className="table-skeleton-row" key={`skeleton-${rowIndex}`} aria-hidden="true">
{columns.map((column) => <td key={column.key}><span className="table-skeleton-cell" /></td>)}
</tr>
)) : rows.length === 0 ? (
<tr>
<td colSpan={columns.length}>
<EmptyState />
<EmptyState title={emptyTitle}>{emptyDescription}</EmptyState>
</td>
</tr>
) : rows.map((row, index) => (