目标
交付在桌面密集高效、在移动端易读易点的列表/详情页——小屏不砍能力。
- 同一查询 / 数据源;仅分支展示
- 桌面 — DataTable + PageTitle 操作
- 移动 — 卡片列表 + FAB 主操作
- 转换 UI;不要用空占位隐藏功能
1. 前置条件
需要已有可加载数据的插件页面,并使用 shared UI 组件。
- 可用 @quan-erp/shared-ui(useMediaQuery、SCREENS、DataTable、PageTitle、PageContent)
- 已有桌面端 columns / rows 的列表页
- 若页面在移动底栏出现,可选已配置 bottom nav
2. 检测移动端
使用共享断点助手。SCREENS.md 是 Quark ERP 插件页的标准移动/桌面分界。
- 低于 md 断点时 isMobile === true
- 不要用临时的 window.innerWidth 判断
TSXisMobile
import { useMediaQuery, SCREENS } from "@quan-erp/shared-ui";
const isMobile = useMediaQuery(SCREENS.md);3. 切换布局(同一数据)
只请求一次。把同一 data / isLoading 传给两个分支。移动端简化或省略密集 PageTitle 操作行,主操作放到 FAB。
- 桌面 — 保留 DataTable 密度与 PageTitle 工具栏
- 移动 — 卡片列表;创建/编辑用 FAB
- 不要仅为移动端再跑一次查询
JSONtitle + content
1{isMobile ? (
2 <div />
3) : (
4 <PageTitle>
5 <div className="flex items-center justify-between w-full">
6 <span>{translation.get("feature", "Feature")}</span>
7 <Button onClick={() => setCreateOpen(true)}>Add</Button>
8 </div>
9 </PageTitle>
10)}
11
12<PageContent>
13 {isMobile ? (
14 <MobileListView data={data} isLoading={isLoading} />
15 ) : (
16 <DataTable columns={columns} data={data} />
17 )}
18</PageContent>4. 移动端卡片模式
优先 cupertino 风格卡片,便于点击与阅读。行操作用 ghost 图标按钮,而非密集表格操作列。
- 卡片外壳 — bg-card、p-4、rounded-3xl、cupertino-corner、border、shadow-sm、flex flex-col gap-3
- 展示决策所需字段;其余放 sheet/dialog
- 编辑 / 删除 / 状态仍可触达——移入卡片或详情,不要删掉
5. 下拉刷新与底栏
移动列表应用下拉刷新重新请求。若页面在底栏中,上移 FAB 以免被挡住。
- 用户期望下拉刷新的列表配合 Pull to refresh
- FAB 位置 — 底栏可见用 bottom-25;隐藏用 bottom-5(见 FAB how-to)
- useIsContainInBottomNavBar(`/${metadata.name}/…`)(@quan-erp/base-frontend)
6. 验证
缩放浏览器或使用设备模式,确认两种展示共享同一批记录与操作。
- 宽视口 — DataTable + PageTitle 操作可见
- 窄视口 — 卡片列表 + FAB;核心功能无“移动端不可用”空壳
- 创建 / 编辑 / 删除在移动端仍可到达
- 下拉刷新更新同一列表数据
- 底栏可见时 FAB 避开底栏(bottom-25)
常见错误
- 在移动端隐藏列或整块功能,而不是转换 UI
- 单独的移动端 API,与桌面数据漂移
- 桌面显示 FAB(或移动端只有表格操作却无 FAB)
- 忽略底栏重叠 — FAB 被挡住
- 自定义断点与插件内 SCREENS.md 不一致