- 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.
7.8 KiB
租户访客楼层策略 — 代码重构实施指南
目标:在不破坏对外 HTTP / Feign 契约的前提下,实现规范中的 「组织
detail内以allow_zone_ids替代PersonResult.floorList」,使邀约页、UC-01 派梯与租户策略一致。
依据:访客邀约与派梯楼层一致性梳理、迁入组织规格(以下简称 《组织规格》)。
当前状态:电梯PersonRuleServiceImpl#addVisitor已不读策略表、不做 ∩。组织侧已落地TenantVisitorFloorPolicyService+ImgPersonServiceImpl#detail/page(isVisitor)的allow_zone_ids替代;部署组织库需执行docs/sql/organization_tenant_visitor_floor_policy.sql。电梯工程内已无TenantVisitorFloorPolicyDao(死代码已删)。
1. 重构原则(必须遵守)
| 原则 | 说明 |
|---|---|
| 策略语义 | 仅 「替代」:命中策略时 floorList = 配置中的 allow_zone_ids 解析结果;不要与 listByImageId 结果做 ∩ 作为规范主路径。 |
| 唯一对外楼层权威 | 消费「被访人可派梯/可邀约楼层」必须走 PersonService.detail → floorList(经 Intelligent → 组织)。 |
| 电梯侧 | 不新增「再算一遍策略」;不恢复 TenantVisitorFloorPolicyDao 参与 addVisitor 有效楼层计算。 |
| 接口兼容 | 《组织规格》约定:cwos-component-organization-interface 不为策略新增公开 DTO/方法时,策略仅作为服务层内部实现;对外仍只通过现有 detail 返回里的 floorList / floorNames 体现。 |
| UC-02 | 显式 floorIds 仍由调用方负责与业务单一致;若需 ⊆ 策略 的硬约束,在 BFF 实现,或单独立项改电梯且经评审。 |
2. 分阶段实施任务
阶段 A — 数据与组织工程骨架
-
策略表落库位置(二选一,推荐 组织库 为唯一主库)
- 推荐:在 组织服务使用的 MySQL 库 中创建与《组织规格》一致的表结构(字段含
business_id、policy_type、allow_zone_idsJSON、enabled、building_id可空等)。 - 迁移期:若生产数据仍在电梯库
tenant_visitor_floor_policy,做 一次性迁移脚本 + 运维切换窗口;迁移完成后电梯侧 Dao 仅删除调用,不必双写。
- 推荐:在 组织服务使用的 MySQL 库 中创建与《组织规格》一致的表结构(字段含
-
组织模块新增(均在
maven-ninca-common-component-organization)- Entity / Mapper / XML:
tenant_visitor_floor_policyCRUD 或至少 按business_id+ enabled 查询租户默认行(building_id IS NULL)。 TenantVisitorFloorPolicyService(命名可依项目惯例):boolean isPolicyActive(String businessId)或Optional<PolicyRow> findTenantDefault(String businessId)List<String> parseAllowZoneIds(String json)(健壮解析,非法 JSON → 视为未启用或记录告警)。
- 不做:在 interface 模块暴露新 REST(除非产品明确要求管理 API)。
- Entity / Mapper / XML:
阶段 B — 在 ImgPersonServiceImpl#detail 接入替代逻辑(核心)
文件:cwos-component-organization-service/.../ImgPersonServiceImpl.java,方法 detail。
插入点:在 elevatorFeignClient.listByImageId 成功、已根据 images 遍历得到 floorList / floorNames(原始) 之后;在 result.setFloorList / setFloorNames 之前增加分支:
伪代码:
原始列表 = 当前遍历 listByImageId 得到的 floorList, floorNames
若 TenantVisitorFloorPolicyService 对 businessId(及必要时 organizationIds)判定「启用且 allow 非空」:
floorList := allow_zone_ids 解析后的 zoneId 列表(顺序:与 JSON 数组顺序一致)
floorNames := 需与 floorList 对齐展示
选项 1:配置侧同时存 id→name 映射(扩展列或独立字典表)
选项 2:对 allow 中每个 zoneId 调现有 Zone Feign 批量查名称(注意批量与超时)
选项 3:若产品允许仅展示 zoneId,则 floorNames 可与 zoneId 同步占位(不推荐体验)
否则:
保持现有原始 listByImageId 语义
result.setFloorList(...)
result.setFloorNames(...)
注意:
defaultFloor/floorName(单人默认层展示) 与floorList(通行可达层) 语义不同,勿混写;参见 08 文档。- 启用判定键:与《组织规格》一致,以
business_id(Headerbusinessid/companyId)为主;若后续要 按机构细分,再扩展查询条件,不在本阶段默认实现。
阶段 C — 访客列表 page(isVisitor) 对齐(强烈建议)
文件:同一 ImgPersonServiceImpl,方法 page,分支 param.getIsVisitor() 非空。
- 现状:该分支内有 星河湾 40F/6F 等与
detail不一致的展示逻辑。 - 建议:在策略命中时 优先应用与
detail相同的替代结果(或抽 私有方法applyTenantVisitorFloorPolicy(resultRow, businessId, …)供detail与page共用),并 跳过与租户策略冲突的硬编码默认层块(参见《组织规格》§4.3)。 - 避免:邀约走
detail、列表走page时出现两套楼层。
阶段 D — 电梯侧清理(收尾)
- 确认
PersonRuleServiceImpl无TenantVisitorFloorPolicyDao注入与 ∩ 逻辑(当前梳理版本已符合则仅做静态检查)。 - 删除或标注废弃:
cw-elevator-application-data下TenantVisitorFloorPolicyDao/ Mapper / XML 若已不再被任何 Bean 引用 — 删除可减少歧义;若迁移脚本仍需参考表结构,可保留 DDL 文档到docs/sql,代码删除前 grep 全仓引用。 - 电梯库表:迁移完成后由 DBA 删表或归档(按运维规范)。
阶段 E — UC-02 与集成(可选增强)
- BFF:派梯前读取邀约单
floorIds,调用detail得到floorList(已含替代),校验floorIds ⊆ floorList(集合意义),失败则拒绝派梯并返回明确错误码。 - 幂等:邀约单号 + 派梯状态机由业务系统保证,电梯接口本身不变。
阶段 F — 测试与验收
| 场景 | 期望 |
|---|---|
| 未配置策略 | detail.floorList 与改造前 listByImageId 一致;UC-01 行为不变。 |
| 配置启用且 allow 非空 | detail.floorList 等于 allow 列表(替代);UC-01 开通层与邀约页一致。 |
| 关闭策略 / JSON 无效 | 回退原始语义;无启动报错。 |
page(isVisitor) |
与 detail 策略表现一致(验收抽样)。 |
3. 风险与缓解
| 风险 | 缓解 |
|---|---|
floorNames 与 id 不对齐 |
替代后必须统一用 Zone 服务补全名称或扩展配置。 |
| 性能:detail 每次多一次 DB + 可选批量 Zone | 策略行缓存(短 TTL)或本地缓存按 business_id。 |
| 跨楼栋首层(§4.8) | 产品确认单次 effective 是否允许多楼栋;否则约束邀约/UC-02 单层栋或拆分调用。 |
4. 推荐提交顺序(便于 Code Review)
- 组织库 DDL + Mapper + PolicyService(单测解析 JSON)。
detail接入替代 + 单元/集成测试(可 Mock Feign)。page分支对齐(若有)。- 电梯侧删除死代码 + 文档更新(本文 + 《一致性梳理》§6)。
- 迁移脚本在生产前演练。
文档版本:与仓库实施同步更新;重大契约变更需同步修改《组织规格》并评审。