Repository navigation
选人组件升级:能力探测的分层 PeoplePicker(搜索优先默认 + 组织树/人群渐进增强) #2112
Copy link
Copy link
Closed
Description
背景 / 问题
当前的「选人」能力是把通用 LookupField 套在 sys_user 上实现的(UserField 只是把 reference 锁死为 sys_user、display_field 设为 name 的薄包装,见 packages/fields/src/widgets/UserField.tsx)。也就是说——选的时候和普通 lookup 没区别(同一个搜索弹窗 + RecordPickerDialog),只有表格只读单元格用 UserCellRenderer 渲染成头像。
这套在小团队够用,但面向真实组织(几百~上千人)时体验明显不足:
- 只有"搜索 + 平铺列表",没有组织维度——用户记不全名字就抓瞎,缺部门/团队这个导航入口。
- 多选体验弱——逐个勾选,没有"已选区"实时回显、不能整组选、勾错要回列表里找。
- 消歧信息不足——同名的人在列表里只有名字,缺部门/邮箱等二级标识。
- 头像依赖
$expand——拿不到展开对象时UserCellRenderer退化成纯 ID 文本(见packages/fields/src/index.tsx的UserCellRenderer)。 - 无人事语义——离职/停用过滤、"最近联系人""我的下属"等都没有。
模式调研结论
- 左组织树 + 右成员 + 穿梭框 是钉钉/企业微信/飞书等「组织通讯录」产品的中国特色形态。
- 西方企业软件(Salesforce / Workday / ServiceNow)几乎不用树浏览,而是
搜索优先 + 声明式候选过滤(Lookup Filter) + 命名人群(Public Group / Queue / Team)——用抽象让你"几乎不需要从几千人里手挑个人"。 - 关键约束:ObjectUI 是通用开发工具,不是每个客户都启用组织结构,因此选人器不能硬依赖
sys_business_unit被启用/填充。
方案:能力探测的分层选人器(PeoplePicker)
把"搜索优先"作为默认主形态,组织树和选人群作为 capability-detected 的渐进增强,运行时探测对象是否启用,没启用就根本不渲染对应 UI——对未开组织功能的客户零负担。
| 档位 | 触发条件 | 形态 | 对标 |
|---|---|---|---|
| Tier 0 搜索版(默认) | 永远可用,零配置 | type-ahead + 最近联系人 + 富信息行(头像/部门/邮箱)+ 已选区 chips | Salesforce lookup |
| Tier 1 + 组织树 | 探测到 sys_business_unit 存在且有数据 |
左树点亮(SplitPaneGrid + ObjectTree),点节点过滤右列表 |
钉钉/飞书 |
| Tier 2 + 选人群 | 探测到 sys_team 启用 |
可直接选 Team/Group,不展开成员 | SF Public Group/Queue |
复用现有积木(不重造轮子)
- 分栏 + 拖拽:
packages/plugin-gridSplitPaneGrid - 左树:
packages/plugin-treeObjectTree(sys_business_unit已自带org_chart的type:'tree'视图,parentField: 'parent_business_unit_id',可直接复用) - 右列表查询/分页/多选内核:从
packages/fields/src/widgets/RecordPickerDialog.tsx抽出复用 - 最近联系人:已有的
recentLookups
数据模型(已确认,平台对象)
源自 framework-stagefield-typed/packages/platform-objects/src/identity/:
sys_business_unit— 部门/组织树,父字段parent_business_unit_id,带kind/active/manager_user_id。sys_business_unit_member— 用户↔部门多对多 junction(is_primary、role_in_business_unit、effective-dated,支持矩阵组织)。sys_user.primary_business_unit_id— 平台已为本场景冗余的字段,注释原文:"Lets a user-lookup filter candidates by business unit without traversing the membership junction"。→ 右列表按部门筛人走它即可,无需碰 junction。sys_team/sys_team_member— 扁平协作分组(= SF Public Group),Tier 2 的人群来源。sys_user可用展示字段:name(searchable)、email(searchable)、image(头像)、manager_id;无 job_title → 富信息行副标题用email + 部门名;离职过滤用banned。
作者侧 opt-in(草案)
Field.user({
multiple: true,
picker: 'org-tree', // 缺省 'search' = 现状;探测不到组织对象时自动降级回搜索
org: { object: 'sys_business_unit', userOrgField: 'primary_business_unit_id', cascade: false },
display: { subtitle: ['primary_business_unit_id.name', 'email'], avatarField: 'image' },
filters: { banned: { $ne: true } },
})待定决策
- 右列表显示"主属成员"还是"全部成员(含矩阵)"? 建议默认主属(走
primary_business_unit_id,简单快),cascade(选父含子)+ 矩阵全成员(走 junction)作为 P2 开关。
落地顺序
- Step 1 从
RecordPickerDialog抽出useRecordQuery(查询/分页/多选状态),现有 dialog 切过去验证不回归。 - Step 2
SelectionTray+ 富信息行 → 单栏多选选人器(= Tier 0,零依赖、可独立上线)。 - Step 3 加能力探测 + 左树(
ObjectTree+SplitPaneGrid)→ Tier 1,仅对启用组织的客户点亮。 - Step 4 字段接线:
picker元数据 → widget registry,user/owner按配置切换。 - Step 5(可选) 选 Team/Group → Tier 2。
建议先交付 Step 1–2(Tier 0):老外也认、对所有客户都有价值、不依赖组织功能;组织树纯加分。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
os-zhuang commentedon Jun 30, 2026
落地顺序收敛建议:第一版只做 Tier 0(搜索优先),把"搜索做强到能替代组织树"作为重点
核对了 framework 的数据模型、并调研了中外主流选人器之后,建议把 v1 收敛为纯搜索版,组织树/公司多组织维度全部留到 v2 按需再上。理由:中国之所以离不开组织树,根因是"重名 + 搜索弱";只要把搜索做强(拼音 + 富信息行消歧),就直接顶替了组织树"导航 + 消歧"的核心价值,对中西客户都受用,且不依赖任何尚未拍板的多组织模型。
v1 范围(Tier 0,可独立上线)
RecordPickerDialog抽出useRecordQuery(查询/分页/多选状态),现有 dialog 切过去验证不回归(纯重构)。SelectionTray+ 富信息行。v1 搜索增强要点(这些才让搜索足以替代树)
sys_user.primary_business_unit_id展示字段,无需公司维度recentLookups已有,大多数选人是重复选那几个SelectionTray)banned等)v1 明确推迟(全部属于"树那一档",不阻塞 v1)
SplitPaneGrid+ObjectTree)、能力探测 / 树开关保留的架构钩子(避免 v2 返工)
useRecordQuery与SelectionTray做成可复用内核,v2 的树档右列表 + 已选区直接复用——树是"接线",不是"重做"。v2+ 组织树档的设计结论(先记录,供将来)
sys_business_unit中parent_business_unit_id IS NULL AND active(可能多根 → 虚拟超级根);primary_business_unit_id往上爬父链)。sys_company的虚拟节点(framework#2483);公司本身有股权/并表层级(parent_company_id),与 BU 组织树正交。关联
sys_company维度(v1 不依赖,v2 树档的公司层来源)Generated by Claude Code
os-zhuang commentedon Jun 30, 2026
v1 进一步简化:采用"租户-per-子公司",公司/组织树跨公司档暂缓
架构决定:每个公司 = 一个租户(隔离靠现有多租户 RLS),集团级查看走超管。对选人器的影响:
useRecordQuery抽取 + 富信息行(头像/部门/邮箱)+SelectionTray穿梭框 + recents + 过滤;即:v1 = 租户内、搜索优先的人员选择器;组织树(若做)退化为"本子公司 BU 树",无任何跨公司复杂度。
Generated by Claude Code
feat(fields): PeoplePicker interaction polish — keyboard, highlight, …
feat(fields): search-first PeoplePicker for user fields (#2112) (#2144)
fix(plugin-grid): bulk-action params render the shared form field wid…