Skip to Content

ModelCard

可组合的卡片网格视图,具备:

  • 通过 RecordContext 元数据驱动卡片渲染
  • 服务端分页查询
  • 工具栏搜索 / 过滤 / 排序控制
  • 可选侧栏过滤(SideTree、SideCard、SideList)
  • 每张卡片删除操作
  • 点击导航至记录详情(通过 linkTo 限定在当前路由子树)

相关文档

  • ModelTable — 表格网格视图(共用工具栏对话框、侧栏与数据钩子)
  • ModelForm — 卡片点击打开的详情表单
  • Action — 操作系统(用于侧栏)
  • Field — 通过 RecordContext 在卡片内渲染的字段组件

快速开始

import { Field } from "@/components/fields"; import { ModelCard } from "@/components/views/card"; export default function DesignAppPage() { return ( <ModelCard modelName="DesignApp" enableDelete> <ModelCard.Header> <Field fieldName="appName" /> </ModelCard.Header> <Field fieldName="appCode" /> <Field fieldName="appType" /> <Field fieldName="status" /> <ModelCard.Footer> <Field fieldName="updatedTime" /> </ModelCard.Footer> </ModelCard> ); }

卡片插槽声明

ModelCard 采用复合组件模式提取插槽。直接子节点分类如下:

插槽组件渲染位置
HeaderModelCard.Header卡片头部区域
Body(默认)Field / 任意子节点卡片内容区域
FooterModelCard.Footer卡片底部区域
ActionsAction由位置推断(见下)
Side PanelSideTree / SideCard / SideList左侧侧栏——见 侧栏

未包在 ModelCard.Header 或 ModelCard.Footer 中的子节点作为主体内容渲染。任意插槽内的 Field 通过 RecordContext 以展示模式渲染——与 SideCard 相同机制。

含全部插槽的示例:

<ModelCard modelName="DesignApp"> <ModelCard.Header> <Field fieldName="appName" /> </ModelCard.Header> <Field fieldName="appCode" /> <Field fieldName="appType" /> <ModelCard.Footer> <Field fieldName="updatedTime" /> </ModelCard.Footer> </ModelCard>

级联字段

插槽接受点号记法 <Field> 声明,读取关联记录上的字段:

<ModelCard modelName="AppEnv"> <Field fieldName="name" /> <Field fieldName="lastActivityId.status" widgetType="StatusIcon" /> <Field fieldName="ownerId.email" /> </ModelCard>

卡片遍历器遍历三个插槽(header / body / footer),将自动收集的 SubQuery 折叠进列表查询,并通过 POST /metadata/resolveCascadedPaths 解析叶子 metaField。嵌套在自定义函数组件(而非直接插槽子节点)中的级联路径对遍历器不可见——请内联声明。完整参考:级联字段路径。

Actions

ModelCard 支持 Action 组件做每张卡片操作。placement 由 Action 在 JSX 树中的定义位置推断——而非 placement 属性。

定义位置渲染位置有效 placement
ModelCard.Header 内CardHeader 右侧,始终可见"header"
顶层主体子节点CardContent 右侧"inline"
任一处,且 placement="more"... 下拉(与删除合并)"more"

显式 placement 属性仅用于识别 "more"。"header" 与 "inline" 以树中位置为准。

头部 Actions

<ModelCard modelName="DesignApp"> <ModelCard.Header> <Field fieldName="appName" /> <Action type="link" label="Edit" href="/studio/app/{id}/design-model" /> </ModelCard.Header> </ModelCard>

ModelCard.Header 内的 Action 在卡片头部右侧、插槽内容旁渲染为 outline 按钮。

内联(主体)Actions

<ModelCard modelName="DesignApp"> <ModelCard.Header> <Field fieldName="appName" /> </ModelCard.Header> <Field fieldName="status" /> <Action label="Publish" operation="publish" confirmMessage="Publish this app?" /> </ModelCard>

顶层 Action 子节点(不在插槽包装内)渲染在主体内容区域右侧。

下拉(more)Actions

<ModelCard modelName="DesignApp" enableDelete> <ModelCard.Header> <Field fieldName="appName" /> <Action label="Archive" operation="archive" placement="more" /> </ModelCard.Header> </ModelCard>

placement="more" 将操作放入 ... 悬停下拉。同时设置 enableDelete 时,删除选项追加在同一下拉底部(带分隔线)。

带字符串模板插值的链接 Action

字符串 href 支持 {placeholder} 模板变量。支持的占位符:

占位符解析为
{id}当前记录 ID
{modelName}卡片模型名
{anyFieldName}记录中该字段的值
// Record ID <Action type="link" label="Edit" href="/studio/app/{id}/design-model" /> // Any record field <Action type="link" label="Open" href="/studio/app/{appCode}/design-model" /> // Multiple placeholders <Action type="link" label="Open" href="/studio/app/{id}/version/{currentVersion}" />

需要条件逻辑时使用函数形式:

<Action type="link" label="Open" href={({ id }) => `/studio/app/${id}/design-model`} />

组合示例

<ModelCard modelName="DesignApp" enableDelete> <ModelCard.Header> <Field fieldName="appName" /> {/* → outline button in CardHeader */} <Action type="link" label="Edit" href="/studio/app/{id}/design-model" /> {/* → ... dropdown */} <Action type="default" label="Archive" operation="archive" placement="more" /> </ModelCard.Header> <Field fieldName="status" /> {/* → inline button in CardContent */} <Action type="default" label="Publish" operation="publish" /> <ModelCard.Footer> <Field fieldName="updatedTime" /> </ModelCard.Footer> </ModelCard>

点击导航

卡片点击行为限定在当前路由子树:

  1. linkTo="x"(或从 <MultiView.Tab> 继承)→ ${pathname}/x/{id}?mode=read
  2. 默认 — ${pathname}/{id}?mode=read(当前目录的 [id]/page.tsx)

linkTo 必须是匹配 /^[a-zA-Z0-9_-]+$/ 的单一子目录名。 ModelCard 有意不支持自由点击处理器与跨路由 URL——将点击目标保持在当前路由子树内,与权限边界一致。

默认

// Clicking card with id "abc" navigates to ${pathname}/abc?mode=read <ModelCard modelName="DesignApp"> <ModelCard.Header> <Field fieldName="appName" /> </ModelCard.Header> <Field fieldName="appCode" /> </ModelCard>

使用 linkTo(子目录)

详情页再深一层时(常见于 MultiView 内):

// Clicking card with id "abc" navigates to ${pathname}/edit/abc?mode=read <ModelCard modelName="DesignApp" linkTo="edit"> <ModelCard.Header> <Field fieldName="appName" /> </ModelCard.Header> <Field fieldName="appCode" /> </ModelCard>

删除操作

enableDelete={true} 时,每张卡片悬停显示带「Delete」选项的 ... 菜单。点击后确认对话框,再调用删除 API 并刷新卡片网格。

<ModelCard modelName="DesignApp" enableDelete> <ModelCard.Header> <Field fieldName="appName" /> </ModelCard.Header> <Field fieldName="appCode" /> </ModelCard>

侧栏

ModelCard 支持与 ModelTable 相同的侧栏组件。声明一个侧栏作为直接子节点:

import { SideTree } from "@/components/views/shared/side-panel/SideTree"; <ModelCard modelName="Product" enableDelete> <SideTree title="Category" modelName="Category" filterField="categoryId" labelField="name" parentField="parentId" selectionMode="single" /> <ModelCard.Header> <Field fieldName="name" /> </ModelCard.Header> <Field fieldName="sku" /> <Field fieldName="status" /> </ModelCard>

侧栏行为与 ModelTable 相同:

  • 选择构建过滤条件,与 AND 合并
  • 固定宽度 280px
  • 支持 SideTree、SideCard、SideList
  • 活动树过滤在工具栏活动状态栏显示为徽章
  • 所有侧栏组件支持 remoteSearch 在客户端过滤与服务端搜索间切换

完整侧栏属性参考见 ModelTable 侧栏。

标签页过滤

ModelCard 本身无 tabs 属性。基于标签的过滤切换(或混合视图类型)请用 <MultiView> 包裹卡片网格——见 MultiView。

网格布局

卡片在响应式 CSS Grid 中渲染:

屏幕默认列数
< sm1
sm – lg2
lg – xl3
>= xl4

用 columns 属性覆盖:

<ModelCard modelName="DesignApp" columns={3}> ... </ModelCard>

工具栏

卡片工具栏是 ModelTable 工具栏的简化子集:

功能ModelCardModelTable
搜索是是
过滤对话框是是
排序对话框是是
创建按钮是是
列-是
分组-是
批量编辑-是
导入/导出-是
行选择-是

活动过滤/排序状态在工具栏下方以可清除徽章显示。

核心属性

属性类型必填默认值说明
modelNamestring是-元数据与数据 API 的模型名。
labelstring否-覆盖头部页面标题。默认为 metaModel.label。
descriptionstring否-覆盖头部副标题。默认为 metaModel.description。
ordersOrderCondition否-推荐默认排序。优先于 initialParams.orders 与 MultiView.Tab.orders(上下文)。
filtersFilterCondition否-推荐基础过滤。优先于 initialParams.filters 与 MultiView.Tab.filters(上下文)。与工作区/运行时过滤 AND 合并。见 precedence。
initialParamsQueryParamsWithoutFields否-高级初始查询设置(pageSize 等)。filters / orders 优先用顶层属性。
childrenReactNode否-ModelCard.Header、Field、ModelCard.Footer,以及一个可选侧栏。
enableCreateboolean否true工具栏显示创建按钮。投影模型(MetaModel.projection === true——只读模型,映射到另一模型所有的表)强制关闭。
enableDeleteboolean否false每张卡片显示 ... 删除操作。投影模型同 enableCreate 强制关闭。
pageSizenumber否20服务端页大小。
columnsnumber否-固定网格列数(1–6)。默认响应式。
linkTostring否-点击导航的子目录名(单段)。前往 ${pathname}/${linkTo}/${id}?mode=read。省略则默认 ${pathname}/${id}?mode=read。

过滤合并行为

与 ModelTable 相同。运行时过滤以 AND 合并:

  • 基础过滤(initialParams.filters)
  • 活动标签过滤
  • 侧栏过滤
  • 搜索过滤(["searchName", "CONTAINS", keyword])
  • 工具栏条件过滤
最后更新于