polish(admin): 抽出后台控件包并统一各页布局与交互

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 19:03:21 +08:00
parent cfc6c1403b
commit f73d2a89e8
23 changed files with 1720 additions and 1412 deletions

View File

@@ -0,0 +1,46 @@
import type { ReactNode } from "react";
/** 控制台模块:标题 / 说明 / 右上 extra;列表页一张表一块 */
export default function AdminSection({
title,
description,
extra,
children,
className = "",
bodyClassName = "",
flush = false,
}: {
title?: ReactNode;
description?: ReactNode;
extra?: ReactNode;
children: ReactNode;
className?: string;
bodyClassName?: string;
/** 无内边距,适合表格/列表铺满 */
flush?: boolean;
}) {
const hasHead = title != null || description != null || extra != null;
return (
<section className={`panel overflow-hidden ${className}`.trim()}>
{hasHead && (
<div
className="px-4 sm:px-5 py-3.5 flex items-start justify-between gap-3 flex-wrap"
style={{ borderBottom: "1px solid var(--line)" }}
>
<div className="min-w-0">
{title != null && (
<h2 className="font-medium text-[15px]" style={{ color: "var(--ink)" }}>
{title}
</h2>
)}
{description != null && description !== "" && (
<p className="meta text-[12.5px] mt-0.5 leading-relaxed">{description}</p>
)}
</div>
{extra != null && <div className="shrink-0">{extra}</div>}
</div>
)}
<div className={`${flush ? "" : "p-4 sm:p-5"} ${bodyClassName}`.trim()}>{children}</div>
</section>
);
}