# 访客注册与派梯:被访人、访客与楼层 — 源码级业务流程 > 本文与 `**cw-elevator-application-service/docs/08-visitor-registration-and-elevator-auth.md**` 互补:08 偏「接口步骤清单」,本文强调 **被访人 / 访客 / 楼层** 三者关系与 **类方法落点**。电梯应用不负责完整「访客档案登记 UI」,但 `**add/visitor` 显式依赖两条人员主键**。 --- ## 1. 术语(避免混用) | 称呼 | HTTP / 参数字段 | 含义 | 数据哪里来 | | ----------- | ----------------------------- | ----------------------------------------------------- | -------------------------------------------- | | **访客** | `visitorId` | 已在**平台人员体系**存在的档案 ID(登记/同步发生在访客业务或 CWOS 组件侧) | 组织库 `cw_is_person` 等;常打 **「访客」标签** | | **被访人(员工)** | `personId` | **接待访客的员工**,用于在 **未传 `floorIds`** 时拉取其可派梯楼层 | 同库在职人员,与 `cw_is_person_organization_ref` 挂组织 | | **生效楼层** | 内部 `param.floorIds`(可能由服务端改写) | 最终写入 `**image_rule_ref`**、绑定图库的 **楼层 zoneId 列表**(雪花串) | 见 §3 | **易错点**:`personId` **不是**访客 ID,而是**被访员工** ID。 --- ## 2. 端到端角色关系(产品语义) ```mermaid flowchart LR subgraph 登记域["登记域(多在外部/组件)"] V["访客档案 visitorId"] H["员工档案 personId\n被访人"] end subgraph 电梯域["电梯应用"] A["POST /elevator/person/add/visitor"] R["image_rule_ref\npersonId=visitorId"] end H -->|Feign detail 取 floorList| A V --> A A --> R ``` - **访客要访问的是员工(被访人)** → API 上体现为:用 `**personId`** 定位被访人,用 `**visitorId**` 定位访客档案。 - **电梯侧写规则**:按 `**visitorId`** 在各区写入规则引用(`ImageRuleRefAddDto.personId = visitorId`),**不是**写在被访人名下。 --- ## 3. 楼层从哪里来(核心业务逻辑) 实现类:`**PersonRuleServiceImpl#addVisitor`**(`person/impl/PersonRuleServiceImpl.java`)。 ### 3.1 调用方 **传入非空 `floorIds`** - **跳过**被访人详情与租户策略整段。 - **直接使用**调用方给出的楼层列表作为 `**effectiveFloors`**(需非空,否则 `76260531`)。 - **责任**:楼层合法性、是否仍应受租户策略约束,由调用方或上游 BFF 保证(产品文档另有说明)。 ### 3.2 调用方 **未传 / 空 `floorIds`(常见访客路径)** 1. `**PersonService#detail`**(Feign,组件 `**/component/person/detail**`) - 入参:`PersonDetailParam.id = param.getPersonId()`(**被访人**)、`businessId = context.getCompany().getCompanyId()`。 - 出参:`**PersonResult.getFloorList()`** → 记为 `**hostFloors**`(字符串列表,元素为电梯域认可的 **zoneId**,雪花形态,与 `**image_rule_ref.zone_id`** 一致)。 2. **失败分支** - detail 失败 / 无数据 / `**hostFloors` 为空** → `**76260531`**(无可用楼层依据)。 3. **租户默认策略(可选收窄)** - `**TenantVisitorFloorPolicyDao#selectEnabledTenantDefault(companyId)`** → 表 `**tenant_visitor_floor_policy**`。 - 条件:`enabled=1`、`policy_type=INTERSECT_ALLOWLIST`、租户级默认(`building_id` 空)。 - `**allow_zone_ids**`:JSON 字符串数组,解析为 `**allowSet**`。 - **生效楼层**:`**effectiveFloors = hostFloors 按原顺序过滤,仅保留 ∈ allowSet`**(`intersectPreserveHostOrder`)。 - 若交集 **为空** → `**76260532`**(与租户允许楼层无交集)。 4. **首层 → 楼栋 → 图库** - 取 `**effectiveFloors.get(0)`**,`**ZoneService#page**` 得 `**ZoneResult**`,再 `**deviceImageStoreDao.getByBuildingId(首层 parentId)**` → `**imageStoreId**`。 5. **逐层写规则 + 绑访客图库** - 对每个 floorId:`**imageRuleRefDao.getDefaultByZoneId`** → 组装 `**ImageRuleRefAddDto**`,`**personId = param.getVisitorId()**`(访客)。 - `**imageStorePersonService.batchBind**`:把 **访客** 绑到该楼栋图库,访期 `**begVisitorTime` / `endVisitorTime`**。 - `**updateGroupPersonRef**`:同步组人员引用。 ### 3.3 小结公式 - **无显式 floorIds 时**: \text{effectiveFloors} = \begin{cases} \text{hostFloors} & \text{无启用策略或 allow 为空} \text{hostFloors} \cap \text{allowzoneids} & \text{策略启用且 allow 非空} \end{cases} - **交集为空** → `**76260532`**;**hostFloors 为空** → `**76260531`**。 --- ## 4. 与「访客注册」一词的边界 | 步骤 | 是否在电梯仓实现 | | ------------------------------------ | ------------------ | | 访客姓名/证件/人脸建档、预约单 | **否**(外部系统 / 组件) | | 拿到 `**visitorId` + 被访员工 `personId`** | 前置条件 | | **派梯授权**(写规则 + 绑图库) | **是**,`addVisitor` | 因此:**完整「访客注册」业务** = 外部登记 + **本接口授权**;本文楼层逻辑仅覆盖授权链。 --- ## 5. 关键源码索引 | 步骤 | 类 / 方法 | | ------- | ---------------------------------------------------------- | | HTTP 入口 | `AcsPersonController` → `/elevator/person/add/visitor` | | 聚合逻辑 | `PersonRuleServiceImpl#addVisitor` | | 被访人楼层 | `PersonService#detail` → `PersonResult#getFloorList` | | 租户策略 | `TenantVisitorFloorPolicyDao#selectEnabledTenantDefault` | | 策略表 | `tenant_visitor_floor_policy` | | 规则落库 | `ImageRuleRefDao#getDefaultByZoneId` / `insertList` | | 图库 | `ImageStorePersonService#batchBind`、`updateGroupPersonRef` | --- ## 6. 测试数据在建模上的要求 - **每条用例**应能指向:**组织 / 部门**、**一名被访员工(host)**、**一名访客(visitor)**。 - 导出脚本从 DB 解析:**员工** = 部门下在职人员;**访客** = 带「访客」标签的人员池,按套件 `**business_id`** 过滤,与用例 **轮询配对**(避免同源语义缺失)。 - 详见 `**tools/visitor_floor_verification/config/test_matrix.json`** 与导出快照 `**host_employee` / `visitor_for_api**` 字段。