标准页型
标准页型是"外壳 + 页面零件"的组装示例,业务系统复制其中一个页面改数据即可。 所有页面都在 src/pages/ 下,路由注册在 src/App.tsx。
页面清单
| 页面 | 路由 | 文件 | 说明 |
|---|---|---|---|
| 工作台 | / | dashboard-page.tsx | 指标卡 + 图表 + 待办列表 |
| 客户管理 | /customers | customers-page.tsx | 筛选 + 表格 + 批量操作 + 分页 |
| 客户详情 | /customers/:customerId | customer-detail-page.tsx | 描述列表 + 时间线 + 侧栏容器 |
| 设置 | /settings | settings-page.tsx | 外观 / 配色 / 无障碍 / 通知 / 快捷键 |
| 通知中心 | /notifications | notifications-page.tsx | 筛选 + 搜索区 + 已读同步 |
| 登录 | /login | login-page.tsx | 独立外壳(不带控制台) |
| 注册 | /register | register-page.tsx | 手机或邮箱验证 + 密码强度 |
| 找回密码 | /forgot-password | forgot-password-page.tsx | 提交后进入"已发送"状态 |
页面骨架
tsx
export function CustomersPage() {
return (
<>
<PageHeader
eyebrow="Customer"
title={t('sample.customersTitle')}
description="筛选、导出与批量操作都在同一层工具栏。"
actions={<Button>新建客户</Button>}
/>
<ListModule search={<SearchFilters onSubmit={applyFilters}>…</SearchFilters>}>
<TableToolbar>…</TableToolbar>
<DataTable … />
<PagePager page={page} pageCount={pageCount} onPageChange={setPage} />
</ListModule>
</>
);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
页面零件
| 组件 | 位置 | 用途 |
|---|---|---|
PageHeader | components/page.tsx | 页头:eyebrow(必填)+ title + description + actions |
ListModule | components/list-module.tsx | "筛选区 + 内容区"的列表外壳,筛选区去掉外边框、改用虚线分隔 |
SearchFilters / SearchField / SearchActions | components/search-filters.tsx | 筛选区与字段、操作区 |
TableToolbar / BulkActions / RowActions | components/table-* | 表格工具条与行操作 |
FixedBar | components/fixed-bar.tsx | 长表单粘底操作条 |
PagePager / CursorPagination | components/page-pager.tsx | 两种分页(见数据展示) |
PageButton | components/page-button.tsx | 上一步 / 下一步按钮,自带箭头图标 |
PageTabs | components/page-tabs.tsx | 页面级页签栏 |
PageReloadButton | components/page-reload-button.tsx | 顶栏刷新:"重建当前页",不播进入动画 |
EmptyState / ErrorState / LoadingState | components/page.tsx | 三态占位 |
RouteError / NotFoundPage | components/route-error.tsx | 路由错误边界与 404 |
登录 / 注册 / 找回密码
三个页面共用一个外壳 AuthLayout:左侧品牌与卖点、右侧表单区、底部版权, 它们不在控制台外壳内(src/App.tsx 里是同级路由),所以没有侧栏与顶栏。
tsx
export function LoginPage() {
return (
<AuthLayout>
<AuthHeading title={t('login.title')} description={t('login.description')} />
<form>…</form>
</AuthLayout>
)
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
注册的验证方式(手机 / 邮箱)用 InputOTP + 分段切换,未验证不允许提交; 密码强度用 PasswordStrength 实时反馈。这些页面只演示表单与校验,不接身份服务。
退出登录
两处入口,都是同一个回调:
| 位置 | 组件 |
|---|---|
| 侧栏底部用户菜单 | UserMenu → onSignOut |
| 个人中心弹窗 | UserProfile → onSignOut |
tsx
async function signOut() {
await auth.logout() // 业务实现
void navigate('/login')
}1
2
3
4
2
3
4
模板里的实现只做跳转(src/app/app-layout.tsx)。