演示

如何做移动端适配

用 useMediaQuery(SCREENS.md) 检测移动端,保持同一数据源,将桌面 DataTable + PageTitle 切换为移动卡片 + FAB——不要在小屏上隐藏功能。

目标

交付在桌面密集高效、在移动端易读易点的列表/详情页——小屏不砍能力。

  • 同一查询 / 数据源;仅分支展示
  • 桌面 — 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 不一致