Skip to Content

侧栏(Side Panel)

靠左的过滤区组件,作为父视图(ModelTableModelCard)的直接子节点放在内部。用户在侧栏中的选择会发布一条过滤条件,由父视图与主查询做 AND 合并。

三个组件共享同一套基础类型与协议:

组件UI 形态适用场景
<SideTree>层级树父子数据(部门树、模型树等)
<SideList>扁平行列表简单列表过滤,每行可带模板字段
<SideCard>富卡片 + 插槽每行需要头/体/脚 + 操作的列表过滤

适用父视图

父视图是否支持侧栏?
ModelTable
ModelCard
ModelForm / ModelSideFormSideCard / SideList——用作主从 UI 的「主」列表

每个父视图仅支持一个侧栏子元素。

快速开始 — <SideTree>

import { SideTree } from "@/components/views/shared/side-panel/SideTree"; <ModelTable modelName="SysField" orders={["modelName", "ASC"]}> <SideTree title="系统模型" modelName="SysModel" filterField="modelId" labelField="labelName" parentField="parentId" treeLimit={1000} selectionMode="single" defaultExpandedLevel={2} /> <Field fieldName="modelName" /> <Field fieldName="fieldName" /> <Field fieldName="labelName" /> <Field fieldName="fieldType" /> </ModelTable>

选中树节点后,表格按 modelId = <节点.id> 过滤。

快速开始 — <SideCard>

import { SideCard } from "@/components/views/shared/side-panel/SideCard"; import { Group } from "@/components/fields/composition"; import { Action } from "@/components/actions/Action"; <ModelTable modelName="DesignWorkItem"> <SideCard modelName="DesignApp" filterField="appId" searchable title="应用" > <SideCard.Header> <Field fieldName="appName" /> </SideCard.Header> <SideCard.Header align="right"> <Field fieldName="status" /> </SideCard.Header> <Group separator="-"> <Field fieldName="appCode" /> <Field fieldName="appType" /> </Group> <SideCard.Footer> <Field fieldName="updatedTime" /> </SideCard.Footer> <Action type="link" labelName="编辑" placement="header" href="/design/app/{id}" /> <Action type="custom" labelName="归档" placement="more" onClick={(ctx) => { /* ... */ }} /> </SideCard> <Field fieldName="name" /> <Field fieldName="status" /> </ModelTable>

快速开始 — <SideList>

import { SideList } from "@/components/views/shared/side-panel/SideList"; <ModelTable modelName="DesignField"> <SideList modelName="DesignModel" filterField="modelId" searchable > <Field fieldName="modelName" /> <Field fieldName="labelName" /> </SideList> <Field fieldName="fieldName" /> <Field fieldName="fieldType" /> </ModelTable>

通用协议

所有侧栏通过 SidePanelContainerContext(由父视图提供)发布选择。流程如下:

  1. 侧栏按自己的 modelName 查询记录(与父视图数据源独立)。
  2. 用户选择记录——扁平列表类用 useSideRecordList 内部状态,树用 TreePanel
  3. 侧栏调用 container.onFilterChange(filterField, selectedIds, selectedRecords, filterOperator?)
  4. 父视图将选择转为 FilterCondition,与工作区 / 搜索 / 列 / 工具栏等过滤 AND 合并进主查询。

由所选 id 生成的过滤形状:

  • 0 条选中 → 无过滤(清空)
  • 1 条选中 → [filterField, operator, value]
  • N 条选中 → [v0, OR, v1, OR, …, OR, vN]

operator 默认为 "=",可通过 filterOperator 覆盖(目前仅在 SideTree 上暴露)。

组件属性

公共基类 — SidePanelBaseProps

三者均继承:

属性类型必填默认值说明
modelNamestring继承父视图数据源。缺省为父视图的 modelName
filterFieldstring-父视图记录上用于过滤的字段。
filterValueFieldstring树为 idField,列表/卡片为 id侧栏记录上取过滤值的字段。
filterOperatorFilterOperator"="生成条件时使用的运算符。
selectionMode"single" | "multi""single"是否允许多选。
remoteSearchbooleanfalse为 true 时搜索走远端 API(["searchName", "CONTAINS", keyword]),而非客户端过滤。防抖 300ms。
titlestring-面板顶部标题。
classNamestring-根节点 className。

扁平列表基类 — SideFlatListPanelBaseProps

SideListSideCard 另增:

属性类型必填默认值说明
filtersFilterCondition-查询源记录时的基础过滤。与工作区过滤 AND 合并。
ordersOrderCondition-源记录排序。
limitnumber200最大加载条数。
searchablebooleanfalse是否显示搜索框。
formViewComponentType<SideFormCreateDialogProps>-ModelSideForm.enableCreate 开启时,+ 按钮打开此对话框组件。

SideTree 专有属性

属性类型必填默认值说明
labelFieldstring-树节点标签字段。
parentFieldstring-父 id 字段(扁平树可传 "")。
idFieldstring"id"节点 id 字段。
disabledFieldstring-为真时令节点不可用。
treeFieldsstring[]-额外拉取的字段。
treeFiltersFilterCondition-树数据源的额外过滤。
treeLimitnumber-查询条数上限。
ordersOrderCondition-第一个排序字段用作树排序键。
defaultExpandedLevelnumber-初始展开深度。
heightnumber560树视口高度。

SideCard 插槽

SideCard 支持组合式子节点:

插槽渲染位置说明
<SideCard.Header>卡片标题行可多个;align="right" 靠右
<SideCard.Header align="right">标题行右侧... 菜单之前
顶层 <Field /> 等任意节点卡片正文处于 RecordContext 内——Field 为展示模式
<SideCard.Footer>卡片底部
<Action />每张卡片的操作;由 placement 决定位置见下文 SideCard 操作 placement

SideCard 操作 placement {#sidecard-action-placement}

placement位置可见性
header标题行内,紧靠标题区字段始终可见
inline正文下方始终可见
more右上角 ... 下拉悬停 / 展开时
  • 省略时默认 inline
  • 操作接收带 idrow(记录数据)、modelNameActionExecutionContext
  • 点击操作不会触发卡片选中。
  • hidden / disabled 按每张卡片单独计算。

通用行为

  • 面板宽度固定 280px;无公开宽度 API。
  • 多选时,生成过滤会把多个选中值用 OR 合并。
  • searchable=true 显示搜索框;默认客户端(跨字段值过滤),或 remoteSearch=true 走服务端(防抖 300ms,调用 ["searchName","CONTAINS",keyword])。
  • SideCard / SideListRecordContext 提供每行数据——Field 子节点自动展示模式(无需再配 FieldPropsContext)。
  • SideTree 封装现有 TreePanelsearchMode 默认为 "local"remoteSearch=true 时为 "server"
  • SideCardSideList 可放在 ModelSideForm 中作为主从的「主」列表(见 ModelSideForm)。

自定义侧栏

目录内提供三类共用设施:

useSideRecordList 钩子

用于展示扁平记录列表(形态类似 SideList/SideCard)。负责:

  • 读取容器上下文 + modelName 回退
  • 元数据 + 工作区过滤
  • 搜索状态 + 防抖 + 查询参数
  • useSearchListQuery 拉数
  • remoteSearch=false 时的客户端搜索过滤
  • 选择状态(内部 vs ModelSideForm 托管)
  • 通过 onFilterChange 向容器发布选择
  • 托管模式下自动选中第一条
import { useSideRecordList } from "@/components/views/shared/side-panel/use-side-record-list"; const { container, effectiveModelName, metaModel, searchTerm, setSearchTerm, filteredRecords, isLoading, selectedId, handleSelect, } = useSideRecordList({ modelName, filterField, filters, orders, limit, remoteSearch, });

自由渲染 JSX——状态机由钩子维护。

buildSidePanelFilterCondition

父视图(ModelTable / ModelCard)用来把面板选中 id 转为过滤条件。多数场景无需直接使用;父视图已接好。若扩展新的父视图类型可再导出调用:

import { buildSidePanelFilterCondition } from "@/components/views/shared/side-panel/build-filter"; const filter = buildSidePanelFilterCondition(filterField, selectedIds, { filterOperator: "=", });

SidePanelBaseProps / SideFlatListPanelBaseProps

自定义面板类型时从这里扩展,以保持同一契约:

import type { SideFlatListPanelBaseProps } from "@/components/views/shared/side-panel/types"; interface MyPanelProps extends SideFlatListPanelBaseProps { // 面板专有 props }

目录内文件

文件用途
SideTree.tsx树形侧栏组件
SideList.tsx扁平列表侧栏组件
SideCard.tsx富卡片侧栏 + SidePanelContainerProvider / useOptionalSidePanelContainer
SidePanelSearch.tsxSideList / SideCard 内部搜索输入
use-side-record-list.ts扁平列表侧栏共用状态钩子
build-filter.ts选中 id → FilterCondition
types.ts共用类型层级
index.ts桶导出
最后更新于