Files
starRiverProperty/docs/business/访客注册与派梯楼层业务流程走查.md
T
hpd840321 7b2bd307f1 Initial commit: reorganized source tree
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
2026-05-09 09:56:45 +08:00

324 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 访客注册与派梯楼层:完整业务流程走查
> **范围说明**:本文基于本仓库内 Maven 工程源码(`maven-cw-elevator-application`、`maven-intelligent-cwoscomponent` 等)梳理**接口调用链、业务逻辑与用例**。
> **访客业务后台**(如「轻舟 / intelligent/three」访客注册、审批流)若不在本仓库,文中以「第三方业务系统」统称,并标明本仓库可见的**被调接口**与**出站 Feign/HTTP**。
---
## 1. 术语与角色
| 术语 | 含义 |
|------|------|
| 第三方业务系统 | 访客注册、邀约、审批等上层应用;可经 intelligent 组件或直接调电梯服务 |
| 组织人员服务 | `ninca-common-component-organization`(可配置),提供人员详情、图库人员绑定等 |
| 空间/区域服务 | `ninca-common``/sysetting/zone`,提供楼栋-楼层树、分区 page |
| 电梯应用 | `cw-elevator-application`,维护派梯规则 `image_rule_ref`、设备图库绑定等 |
| 被访人 | `personId`,组织侧人员主键 |
| 访客 | `visitorId`,组织侧访客人员主键 |
| 楼层 | 以 **分区/空间 ID**`zoneId` / `floorId`)表示,与 `PersonResult.floorList` 元素一致 |
---
## 2. 业务总览(从「默认楼层」到「指定楼层」)
```mermaid
flowchart TB
subgraph third [第三方业务系统]
A[访客注册/邀约完成]
B{是否已知具体楼层 zoneId 列表?}
C[调组织服务拉人员详情]
D[组装 floorIds 显式列表]
end
subgraph org [组织人员服务 ninca-common-component-organization]
P["POST /component/person/detail"]
I["POST /component/imagestore/person/batchBind 等"]
end
subgraph intel [intelligent-cwoscomponent-rest 可选]
E["ElevatorPersonService.addVisitor → Feign"]
end
subgraph elev [电梯 cw-elevator-application]
F["POST /elevator/person/add/visitor"]
G["PersonRuleServiceImpl.addVisitor"]
end
A --> B
B -->|否 需默认| C
C --> P
P -->|PersonResult.floorList| third
B -->|是 或 已补全| D
D --> E
C --> E
E --> F
F --> G
G -->|缺 floorIds 时内部再调 P 取 floorList| P
G --> I
```
**要点**
- 「**默认有哪些楼层**」在本仓库电梯侧的实现是:**未传 `floorIds` 时**,调用 **`PersonService.detail`**Feign → **`POST /component/person/detail`**),取 **`PersonResult.getFloorList()`****不是** `PersonResult.defaultFloor` 单字段。
- 「**第三方设定具体楼层**」:**在请求体中携带非空的 `floorIds`** 调用 **`POST /elevator/person/add/visitor`**(或经 `ElevatorPersonService` 转发),电梯侧**不再**调人员详情补楼层。
---
## 3. 流程 A:第三方如何获知「默认」楼层(可走的接口)
第三方若**自行**在注册前展示「被访人默认可达楼层」,应在**组织侧**完成数据拉取;本仓库可见的**权威数据源**为人员详情返回的 **`floorList`**(及可能同时返回的 `defaultFloor``floorInfoList` 等,但电梯访客派梯**仅用** `floorList` 补全逻辑)。
### 3.1 推荐:人员详情(与电梯补全逻辑一致)
| 项目 | 内容 |
|------|------|
| 调用方 | 任意有权限的服务;intelligent 中为 `RestPersonServiceImpl``PersonFeignClient` |
| 服务名配置 | `${feign.component-organization.name:ninca-common-component-organization}` |
| HTTP | **`POST /component/person/detail`** |
| 请求体 | `PersonDetailParam``id` = 被访人 `personId``businessId` = 机构 |
| 响应 | `CloudwalkResult<PersonResult>`,关注 **`floorList`**`List<String>` 楼层/分区 ID |
代码位置(Feign 声明):
```19:32:maven-intelligent-cwoscomponent/intelligent-cwoscomponent-rest/src/main/java/cn/cloudwalk/rest/cwoscomponent/intelligent/person/feign/PersonFeignClient.java
@FeignClient(name = "${feign.component-organization.name:ninca-common-component-organization}",
path = "/component/person", fallback = PersonFeignClientFallback.class)
public interface PersonFeignClient {
...
@RequestMapping(value = {"/detail"}, method = {RequestMethod.POST})
CloudwalkResult<PersonResult> detail(@RequestBody PersonDetailParam paramPersonDetailParam);
```
`PersonResult` 中与楼层相关的字段(电梯 `addVisitor` **补全时只用 `floorList`**):
```27:34:maven-intelligent-cwoscomponent/intelligent-cwoscomponent-interface/src/main/java/cn/cloudwalk/client/cwoscomponent/intelligent/person/result/PersonResult.java
private String defaultFloor;
private String chooseFloor;
private List<String> floorList;
private List<AcsPassRuleImageResultDto> floorInfoList;
...
private String defaultChooseFloor;
```
### 3.2 辅助:空间树 / 楼层分页(电梯网关或管理端常用)
| 项目 | 内容 |
|------|------|
| Feign | `ZoneFeignClient` → `${feign.ninca-common.name:ninca-common}` |
| HTTP | **`POST /sysetting/zone/tree`**、**`POST /sysetting/zone/page`** |
| 用途 | 按楼栋展示树、按条件查分区;**不替代**人员已授权楼层列表 |
```16:23:maven-cw-elevator-application/cw-elevator-application-service/src/main/java/cn/cloudwalk/elevator/zone/client/ZoneFeignClient.java
@FeignClient(name = "${feign.ninca-common.name:ninca-common}", path = "/sysetting/zone",
fallback = ZoneFeignClientFallback.class)
public interface ZoneFeignClient {
@RequestMapping(value = {"/tree"}, method = {RequestMethod.POST})
...
@RequestMapping(value = {"/page"}, method = {RequestMethod.POST})
CloudwalkResult<CloudwalkPageAble<ZoneResult>> page(ZoneQueryParam paramZoneQueryParam) throws ServiceException;
}
```
### 3.3 辅助:通行规则-楼层列表(管理派梯规则维度)
| 项目 | 内容 |
|------|------|
| Controller | `AcsPassRuleController` |
| HTTP | **`POST /elevator/passRule/floor`** 等 |
| 用途 | 规则/图库与楼层关系维护与查询;与「人员 floorList」不同维度 |
```45:55:maven-cw-elevator-application/cw-elevator-application-web/src/main/java/cn/cloudwalk/elevator/passrule/controller/AcsPassRuleController.java
@RequestMapping({"/floor"})
public CloudwalkResult<CloudwalkPageAble<AcsPassRuleFloorResult>>
listFloor(@RequestBody AcsPassRuleFloorForm form) {
...
return this.imageRuleRefService.listFloor(param, getCloudwalkContext());
```
### 3.4 访客记录查询(识别访客身份,非楼层来源)
电梯乘梯记录中通过 **RestTemplate** 调 **`intelligent/three/visitor/record/query`**,用于判断是否访客及被访人,**不参与** `addVisitor` 楼层列表计算:
```262:274:maven-cw-elevator-application/cw-elevator-application-service/src/main/java/cn/cloudwalk/elevator/record/impl/AcsElevatorRecordServiceImpl.java
URI uri =
combineAuthClientURI("intelligent/three/visitor/record/query", (MultiValueMap<String, String>)null);
VisitorRecordQueryParam form = new VisitorRecordQueryParam();
form.setVisitorId(addDTO.getRecognitionFaceId());
...
```
另有 Feign **`VisitorFeignClient`**`ninca-crk-std` 的 **`/intelligent/visitor/record/query`**,与上为不同网关路径,同属访客记录查询能力。
---
## 4. 流程 B:第三方设定「具体楼层」并开通访客派梯
### 4.1 对外 HTTP(电梯应用)
| 项目 | 内容 |
|------|------|
| Method / Path | **`POST /elevator/person/add/visitor`** |
| Controller | `AcsPersonController#addVisitor` |
| Body | `AcsPersonAddVisitorForm` → `AcsPersonAddVisitorParam` |
```53:62:maven-cw-elevator-application/cw-elevator-application-web/src/main/java/cn/cloudwalk/elevator/person/controller/AcsPersonController.java
@RequestMapping({"/add/visitor"})
public CloudwalkResult<Boolean> addVisitor(@RequestBody AcsPersonAddVisitorForm form) {
AcsPersonAddVisitorParam param =
(AcsPersonAddVisitorParam)BeanCopyUtils.copyProperties(form, AcsPersonAddVisitorParam.class);
try {
return this.personRuleService.addVisitor(param, getCloudwalkContext());
```
### 4.2 经 intelligent 的 Feign(业务方 SDK 式调用)
| 项目 | 内容 |
|------|------|
| 接口 | `ElevatorPersonService.addVisitor` |
| 实现 | `RestElevatorPersonServiceImpl` |
| Feign | `ElevatorPersonFeignClient` |
| 目标 | `${feign.elevator.name:elevator-app}` **`POST /elevator/person/add/visitor`** |
```11:15:maven-intelligent-cwoscomponent/intelligent-cwoscomponent-rest/src/main/java/cn/cloudwalk/rest/cwoscomponent/intelligent/elevator/feign/ElevatorPersonFeignClient.java
@FeignClient(name = "${feign.elevator.name:elevator-app}", path = "/elevator/person",
fallback = ElevatorPersonFeignClientFallback.class)
public interface ElevatorPersonFeignClient {
@RequestMapping(value = {"/add/visitor"}, method = {RequestMethod.POST})
CloudwalkResult<Boolean> addVisitor(@RequestBody AcsPersonAddVisitorParam paramAcsPersonAddVisitorParam);
```
### 4.3 请求字段语义(用例输入)
| 字段 | 必填性 | 说明 |
|------|--------|------|
| `visitorId` | 是 | 访客在组织侧人员 ID |
| `personId` | 是 | 被访人 ID;**补全楼层时**用于 `detail` |
| `begVisitorTime` / `endVisitorTime` | 视图库接口 | 传入图库绑定有效期 |
| `floorIds` | 否 | **非空**:第三方显式指定可派梯楼层;**空/缺省**:由电梯侧按被访人 **`floorList`** 补全 |
---
## 5. 电梯侧核心业务逻辑:`PersonRuleServiceImpl.addVisitor`
实现类:`PersonRuleServiceImpl``maven-cw-elevator-application/.../PersonRuleServiceImpl.java`)。
### 5.1 步骤分解
| 步骤 | 逻辑 | 外部依赖 |
|------|------|----------|
| 1 | 若 `floorIds` 为空 → `PersonDetailParam(personId, businessId)` → **`personService.detail`** | Feign → **`POST /component/person/detail`**,取 **`getFloorList()`** 赋给 `floorIds` |
| 2 | 用 **`floorIds.get(0)`** 构造 `ZoneQueryParam`**`zoneService.page`** 查分区页,取首条 `ZoneResult` 得 **`parentId`(楼栋)** | Feign → **`POST /sysetting/zone/page`** |
| 3 | **`deviceImageStoreDao.getByBuildingId(parentId)`** 得图库 `imageStoreId` | 本地 DAO |
| 4 | 对 **每个 `floorId`**`imageRuleRefDao.getDefaultByZoneId(floorId)` 取默认通行规则,组装 **`ImageRuleRefAddDto`**(访客 `visitorId` 挂父规则) | 本地 DAO |
| 5 | **`imageRuleRefDao.insertList`** 批量写入派梯规则引用 | 本地 DAO |
| 6 | 组装 **`ImageStorePersonBindParam`**(图库、访客 ID、有效期),**`imageStorePersonService.batchBind`** | Feign → **`POST /component/imagestore/person/batchBind`** |
| 7 | **`imageStorePersonService.updateGroupPersonRef`** 更新组与人员引用 | Feign → **`POST /component/imagestore/person/updateGroupPersonRef`** |
关键代码(补全楼层 + 循环写规则 + 绑图库):
```170:223:maven-cw-elevator-application/cw-elevator-application-service/src/main/java/cn/cloudwalk/elevator/person/impl/PersonRuleServiceImpl.java
if (CollectionUtils.isEmpty(param.getFloorIds())) {
PersonDetailParam detailParam = new PersonDetailParam();
detailParam.setId(param.getPersonId());
detailParam.setBusinessId(context.getCompany().getCompanyId());
CloudwalkResult<PersonResult> detail = this.personService.detail(detailParam, context);
param.setFloorIds(((PersonResult)detail.getData()).getFloorList());
}
ZoneQueryParam zoneQueryParam = new ZoneQueryParam();
zoneQueryParam.setId(param.getFloorIds().get(0));
...
for (String floorId : param.getFloorIds()) {
ImageRuleRefResultDto defaultRule = this.imageRuleRefDao.getDefaultByZoneId(floorId);
...
addDto.setPersonId(param.getVisitorId());
...
}
...
CloudwalkResult<ImgStoreBatchBindPersonResult> bindResult =
this.imageStorePersonService.batchBind(imageStorePersonBindParam, context);
...
this.imageStorePersonService.updateGroupPersonRef(refParam, context);
```
图库 Feign(与上表一致):
```19:41:maven-intelligent-cwoscomponent/intelligent-cwoscomponent-rest/src/main/java/cn/cloudwalk/rest/cwoscomponent/intelligent/imagestore/feign/ImageStorePersonFeignClient.java
@FeignClient(name = "${feign.component-organization.name:ninca-common-component-organization}",
path = "/component/imagestore/person", fallback = ImageStorePersonFeignClientFallback.class)
public interface ImageStorePersonFeignClient {
...
@RequestMapping(value = {"/batchBind"}, method = {RequestMethod.POST})
CloudwalkResult<ImgStoreBatchBindPersonResult>
batchBind(@RequestBody ImageStorePersonBindParam paramImageStorePersonBindParam);
@RequestMapping(value = {"/updateGroupPersonRef"}, method = {RequestMethod.POST})
CloudwalkResult<Boolean>
updateGroupPersonRef(@RequestBody UpdateGroupPersonRefParam paramUpdateGroupPersonRefParam);
```
### 5.2 与「内部员工」派梯开通的对比(非访客)
**`POST /elevator/person/add`** → `PersonRuleServiceImpl.add`:按**单个** `zoneId`(楼层)与 `parentId`(楼栋)给多名 **`personIds`** 写规则并绑图库;**不**调人员 `detail` 取 `floorList`。用于从已有人员批量加通行权限的另一条业务线。
```79:136:maven-cw-elevator-application/cw-elevator-application-service/src/main/java/cn/cloudwalk/elevator/person/impl/PersonRuleServiceImpl.java
public CloudwalkResult<Boolean> add(AcsPersonAddParam param, CloudwalkCallContext context) throws ServiceException {
...
ImageRuleRefResultDto defaultRule = this.imageRuleRefDao.getDefaultByZoneId(param.getZoneId());
...
for (String personId : param.getPersonIds()) {
...
addDto.setZoneId(param.getZoneId());
```
---
## 6. 接口调用流转汇总表
| 序号 | 调用方向 | 协议与路径 | 典型触发 |
|------|----------|------------|----------|
| 1 | 第三方 / intelligent → 电梯 | `POST /elevator/person/add/visitor` | 访客开通派梯 |
| 2 | 电梯 → 组织 | `POST /component/person/detail` | `floorIds` 为空时补全 |
| 3 | 电梯 → 空间 | `POST /sysetting/zone/page` | 取楼层所属楼栋 |
| 4 | 电梯 → 组织 | `POST /component/imagestore/person/batchBind` | 访客绑图库 |
| 5 | 电梯 → 组织 | `POST /component/imagestore/person/updateGroupPersonRef` | 更新组人关系 |
| 6 | 第三方自行(可选) | `POST /component/person/detail` | 注册前展示默认可达楼层 |
| 7 | 管理端(可选) | `POST /elevator/passRule/floor` 等 | 规则/楼层维护 |
| 8 | 电梯 → 网关 HTTP | `POST intelligent/three/visitor/record/query` | 乘梯记录识别访客 |
---
## 7. 用例(UC)说明
| 用例 ID | 名称 | 前置条件 | 主流程 | 期望结果 |
|---------|------|----------|--------|----------|
| UC-01 | 访客派梯-使用被访人默认楼层列表 | 被访人 `personId` 在组织侧 `detail` 返回**非空** `floorList`;访客已注册 | 调 `add/visitor` 且 **不传 `floorIds`** | 电梯取 `floorList` 为访客写入各层默认规则并绑图库 |
| UC-02 | 访客派梯-第三方指定楼层 | `floorIds` 为合法 zoneId 列表 | 调 `add/visitor` 且 **传入 `floorIds`** | **不再**调 `person/detail` 补楼层;按列表写规则 |
| UC-03 | 注册前展示「可访楼层」 | 需与被访人授权一致 | 第三方先调 **`/component/person/detail`**,展示 `floorList`(或产品定义的 `defaultFloor` 映射) | UI 与电梯补全逻辑对齐(若仅用 `defaultFloor` 需与产品确认是否与 `floorList` 一致) |
| UC-04 | `floorList` 为空 | 被访人无派梯楼层 | `add/visitor` 不传 `floorIds` | `floorIds` 仍为空 → 后续 `get(0)` 等**可能异常**;第三方应校验或传显式楼层 |
| UC-05 | 内部人员加单层派梯 | 已知 `zoneId`、楼栋 `parentId` | `POST /elevator/person/add` | 单层规则 + 图库绑定 |
| UC-06 | 乘梯记录标记访客 | 识别到人脸 | 记录服务调 **`visitor/record/query`** | 回填 `isVisitor`、被访人 |
**扩展(租户访客默认楼层)**:若需「在 UC-01 不传 `floorIds` 的前提下,按租户策略收敛访客楼层(如默认仅开放某接待层)」的产品与技术设计,以及**从第三方登记页初始化数据项、接口编排到 `add/visitor` 的端到端闭环**,见 [租户访客默认楼层技术产品方案](租户访客默认楼层技术产品方案.md)(文中 **§2**)。
---
## 8. 风险与待确认项(走查结论)
1. **`PersonResult.defaultFloor` 与 `floorList`**:电梯 `addVisitor` **仅使用 `floorList`**。若产品「默认访问楼层」对应 `defaultFloor` 标量,需核对组织服务是否在 `detail` 中把二者对齐,否则存在**语义偏差**。
2. **`floorIds.get(0)`**:补全后若列表为空,会在取首元素时失败;第三方或组织数据需保证一致性。
3. **`cwos-sdk-event` 等**与本文无关的依赖问题不影响本业务链结论。
4. **访客注册主流程**(表单、审批、写组织人员表)若在三方工程,需在对应仓库继续搜 **`ElevatorPersonService`**、**`addVisitor`**、**`/elevator/person/add/visitor`** 的引用以闭合「从注册到派梯」的端到端文档。
---
## 9. 文档版本信息
| 项目 | 内容 |
|------|------|
| 输出路径 | `docs/business/访客注册与派梯楼层业务流程走查.md` |
| 依据代码根目录 | `maven-cw-elevator-application`、`maven-intelligent-cwoscomponent` |
| 说明 | 外部服务行为以接口契约为准,组织服务内部如何组装 `floorList` 需在 **ninca-common-component-organization** 源码中二次走查 |
---
*本文档由代码走查自动生成梳理,若接口路径随部署配置变化,请以运行环境 `application*.yml` 中 `feign.*` 为准。*