Add LAN deploy scripts and improve admin billing/users UX.

Provide rsync deploy and restart tooling for the 100 server, document the workflow, and add pagination plus user filtering across billing and user management pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-06-16 20:46:59 +08:00
parent 8ad1a8a8da
commit 680e2c9427
11 changed files with 1079 additions and 275 deletions
+62
View File
@@ -0,0 +1,62 @@
type Props = {
page: number;
totalPages: number;
total: number;
pageSize: number;
onChange: (page: number) => void;
};
export function Pagination({ page, totalPages, total, pageSize, onChange }: Props) {
if (totalPages <= 1) return null;
const start = (page - 1) * pageSize + 1;
const end = Math.min(page * pageSize, total);
const pages: (number | '…')[] = [];
if (totalPages <= 7) {
for (let i = 1; i <= totalPages; i++) pages.push(i);
} else {
pages.push(1);
if (page > 3) pages.push('…');
for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) pages.push(i);
if (page < totalPages - 2) pages.push('…');
pages.push(totalPages);
}
return (
<div className="pagination">
<span className="pagination-info">
{start}{end} / {total.toLocaleString()}
</span>
<div className="pagination-controls">
<button
className="pagination-btn"
disabled={page <= 1}
onClick={() => onChange(page - 1)}
>
</button>
{pages.map((p, i) =>
p === '…' ? (
<span key={`ellipsis-${i}`} className="pagination-ellipsis"></span>
) : (
<button
key={p}
className={`pagination-btn${p === page ? ' active' : ''}`}
onClick={() => onChange(p)}
>
{p}
</button>
),
)}
<button
className="pagination-btn"
disabled={page >= totalPages}
onClick={() => onChange(page + 1)}
>
</button>
</div>
</div>
);
}