Files
starRiverProperty/docs/business/访客注册与派梯楼层业务流程走查.md
T
反编译工作区 e2ac14719b Initial commit: five Maven reactors and docs only
Track maven-cloudwalk-cloud, maven-cw-elevator-application,
maven-intelligent-cwoscomponent, maven-ninca-crk, maven-ninca-qk-alarm,
and docs/. Other workspace paths ignored via .gitignore.

Made-with: Cursor
2026-04-24 10:35:31 +08:00

18 KiB
Raw Blame History

访客注册与派梯楼层:完整业务流程走查

范围说明:本文基于当前反编译工作区内的源码(maven-cw-elevator-applicationmaven-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,组织侧访客人员主键
楼层 分区/空间 IDzoneId / floorId)表示,与 PersonResult.floorList 元素一致

2. 业务总览(从「默认楼层」到「指定楼层」)

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.detailFeign → POST /component/person/detail),取 PersonResult.getFloorList()不是 PersonResult.defaultFloor 单字段。
  • 第三方设定具体楼层」:在请求体中携带非空的 floorIds 调用 POST /elevator/person/add/visitor(或经 ElevatorPersonService 转发),电梯侧不再调人员详情补楼层。

3. 流程 A:第三方如何获知「默认」楼层(可走的接口)

第三方若自行在注册前展示「被访人默认可达楼层」,应在组织侧完成数据拉取;本仓库可见的权威数据源为人员详情返回的 floorList(及可能同时返回的 defaultFloorfloorInfoList 等,但电梯访客派梯仅用 floorList 补全逻辑)。

3.1 推荐:人员详情(与电梯补全逻辑一致)

项目 内容
调用方 任意有权限的服务;intelligent 中为 RestPersonServiceImplPersonFeignClient
服务名配置 ${feign.component-organization.name:ninca-common-component-organization}
HTTP POST /component/person/detail
请求体 PersonDetailParamid = 被访人 personIdbusinessId = 机构
响应 CloudwalkResult<PersonResult>,关注 floorListList<String> 楼层/分区 ID

代码位置(Feign 声明):

@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):

    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/treePOST /sysetting/zone/page
用途 按楼栋展示树、按条件查分区;不替代人员已授权楼层列表
@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」不同维度
    @RequestMapping({"/floor"})
    public CloudwalkResult<CloudwalkPageAble<AcsPassRuleFloorResult>>
        listFloor(@RequestBody AcsPassRuleFloorForm form) {
        ...
            return this.imageRuleRefService.listFloor(param, getCloudwalkContext());

3.4 访客记录查询(识别访客身份,非楼层来源)

电梯乘梯记录中通过 RestTemplateintelligent/three/visitor/record/query,用于判断是否访客及被访人,不参与 addVisitor 楼层列表计算:

            URI uri =
                combineAuthClientURI("intelligent/three/visitor/record/query", (MultiValueMap<String, String>)null);
            VisitorRecordQueryParam form = new VisitorRecordQueryParam();
            form.setVisitorId(addDTO.getRecognitionFaceId());
            ...

另有 Feign VisitorFeignClientninca-crk-std/intelligent/visitor/record/query,与上为不同网关路径,同属访客记录查询能力。


4. 流程 B:第三方设定「具体楼层」并开通访客派梯

4.1 对外 HTTP(电梯应用)

项目 内容
Method / Path POST /elevator/person/add/visitor
Controller AcsPersonController#addVisitor
Body AcsPersonAddVisitorFormAcsPersonAddVisitorParam
    @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
@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

实现类:PersonRuleServiceImplmaven-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) 构造 ZoneQueryParamzoneService.page 查分区页,取首条 ZoneResultparentId(楼栋) Feign → POST /sysetting/zone/page
3 deviceImageStoreDao.getByBuildingId(parentId) 得图库 imageStoreId 本地 DAO
4 每个 floorIdimageRuleRefDao.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

关键代码(补全楼层 + 循环写规则 + 绑图库):

            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(与上表一致):

@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/addPersonRuleServiceImpl.add:按单个 zoneId(楼层)与 parentId(楼栋)给多名 personIds 写规则并绑图库;调人员 detailfloorList。用于从已有人员批量加通行权限的另一条业务线。

    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 的端到端闭环,见 租户访客默认楼层技术产品方案(文中 §2)。


8. 风险与待确认项(走查结论)

  1. PersonResult.defaultFloorfloorList:电梯 addVisitor 仅使用 floorList。若产品「默认访问楼层」对应 defaultFloor 标量,需核对组织服务是否在 detail 中把二者对齐,否则存在语义偏差
  2. floorIds.get(0):补全后若列表为空,会在取首元素时失败;第三方或组织数据需保证一致性。
  3. cwos-sdk-event与本文无关的依赖问题不影响本业务链结论。
  4. 访客注册主流程(表单、审批、写组织人员表)若在三方工程,需在对应仓库继续搜 ElevatorPersonServiceaddVisitor/elevator/person/add/visitor 的引用以闭合「从注册到派梯」的端到端文档。

9. 文档版本信息

项目 内容
输出路径 docs/business/访客注册与派梯楼层业务流程走查.md
依据代码根目录 maven-cw-elevator-applicationmaven-intelligent-cwoscomponent
说明 外部服务行为以接口契约为准,组织服务内部如何组装 floorList 需在 ninca-common-component-organization 源码中二次走查

本文档由代码走查自动生成梳理,若接口路径随部署配置变化,请以运行环境 application*.ymlfeign.* 为准。