chore: 工作区反编译与 Maven/文档/脚本同步到发布分支

- artifacts/decompiled 树与相关源码变更
- maven-cw-elevator-application 业务 docs 与 package-info
- scripts 下 formatter 校验与辅助脚本
- 其他子工程/接口与发布线一并纳入版本控制

Made-with: Cursor

Former-commit-id: e102e8cab64e575bcd23c9a66a598aa1892bb492
This commit is contained in:
反编译工作区
2026-04-25 09:35:35 +08:00
parent 1c28fcedfc
commit dee355b4a7
2000 changed files with 133077 additions and 169300 deletions
@@ -0,0 +1,108 @@
# 00 总览:模块定位与领域结构
## 1. 模块在系统中的位置
`cw-elevator-application-service` 是电梯应用的 **业务编排与领域服务实现** 层:
- **向上** 被 `cw-elevator-application-web`HTTP 入口)等调用。
- **向下** 依赖 `cw-elevator-application-data`DAO/MyBatis)与多类 **OpenFeign 客户端**(CWOS 设备/人员/图库/系统设置、访客标准服务、第三方 MQTT 等)。
- **横切** 使用 Spring 事件(`CloudwalkEventManager`)、缓存(`@Cacheable`)、异步(`@Async`)等。
```mermaid
flowchart LR
subgraph Web["cw-elevator-application-web"]
C[Controllers]
end
subgraph Svc["cw-elevator-application-service 本文档范围"]
D[device]
P[passrule / person]
R[record]
Z[zone / code]
M[mqtt / export / ...]
end
subgraph Data["cw-elevator-application-data"]
DAO[DAO / Mapper]
end
subgraph Ext["外部服务 Feign / HTTP"]
W[CWOS intelligent-*]
V[访客 ninca-crk-std]
Q[MQTT 第三方]
end
C --> Svc
Svc --> DAO
Svc --> W
Svc --> V
Svc --> Q
```
## 2. 领域全景(思维导图)
```mermaid
mindmap
root((elevator service))
设备 device
本应用电梯设备 CRUD
与平台设备联动分页
重组绑定 楼层/人员/条件
异步任务 进度
通行与人员
规则 passrule
图库规则 image 规则
人员 acs 与 规则 person
记录 record
通行记录
识别记录
分析统计
区域与编码
区域树 zone
电梯码 codeElevatorArea
集成
mqtt 推送
导出 export
下载 downloadcenter
文件 storage
```
## 3. 核心服务接口与包对应关系
```mermaid
classDiagram
class AcsElevatorDeviceService
class AcsDeviceTaskService
class AcsPassRuleService
class ImageRuleRefService
class AcsPersonService
class PersonRuleService
class AcsElevatorRecordService
class AcsRecogRecordService
class ZoneService
class AcsElevatorCodeService
class MqttService
AcsElevatorDeviceService : +设备与绑定编排
AcsDeviceTaskService : +updateFloors 任务推进
AcsPassRuleService : +规则 CRUD 与图库 list
ImageRuleRefService : +图库视角规则
AcsPersonService : +人员 page 等
PersonRuleService : +规则内人员/访客
AcsElevatorRecordService : +通行记录
AcsRecogRecordService : +识别记录 add
ZoneService : +区域树
AcsElevatorCodeService : +电梯码
MqttService : +sendInfoToOne
```
## 4. 与外部系统协作(逻辑视图)
| 外部能力 | 典型用途 |
|----------|----------|
| `intelligent` 设备/人员/图库/系统设置 | 设备主数据、人员同步、图库、区域树 |
| `ninca-crk-std`IP 配置 + RestTemplate 或 Feign | 访客 **three 线****Feign `VisitorFeignClient`** 不同路径 |
| `cloudwalk-device-thirdparty` / MQTT | 发布主题推送识别摘要 |
| DaVinci 文件分片 | `AcsFileStorageService` 大文件 |
| 下载中心 | 异步任务结果取回 |
## 5. 读文档建议
1. 先读 [01-device-and-task.md](01-device-and-task.md) 理解「设备—楼层—任务」主路径。
2. 再读 [02-passrule-and-person.md](02-passrule-and-person.md) 理解规则与人员两条下发线。
3. 记录、MQTT 与事件见 [03-record-recognition.md](03-record-recognition.md) 与 [04-mqtt-visitor-event.md](04-mqtt-visitor-event.md)。
@@ -0,0 +1,75 @@
# 01 设备与设备任务(`device`
## 1.1 业务目标
- 维护 **本应用视角** 的电梯设备与平台设备(`DeviceService`)的关联数据。
- 支持 **重组/绑定**:按区域、标签、组织等条件选择楼层,将 **人员****规则** 批量下发到设备侧(经远程服务)。
- 通过 **设备任务**`AcsDeviceTaskService` / `AcsDeviceTaskServiceImpl`)在楼层维度 **有界并行** 执行远程步骤,并 **按完成顺序** 推进任务上的 `bindDevices` 等进度(与走查约定 §9 一致)。
## 1.2 主接口 `AcsElevatorDeviceService`
| 方法 | 行为概要 |
|------|----------|
| `add` / `edit` / `delete` | 电梯设备增删改,写本库并协调平台设备信息 |
| `get` / `getById` / `getFo` | 分页列表、单条、表单选项数据 |
| `getBuildingId` / `getBusinessId` | 从查询条件解析楼宇或租户 |
| `devicePage` | 走 **平台** 设备分页,与 `Acs` 表关联展示 |
| `listUnbindFloors` / `listFloors` / `listCondition` / `listConditionByLabelIds` | 绑定时待选楼层、已绑楼层、条件筛选(标签等) |
| `bindingFloors` / `bindingPerson` | 启动绑定:创建/更新设备任务,异步 `updateFloors` |
| `getTask` / `setTaskStop` | 查询任务进度、停止任务 |
**实现类**`device/impl/AcsElevatorDeviceServiceImpl.java`
## 1.3 设备任务 `AcsDeviceTaskService`
| 方法 | 行为概要 |
|------|----------|
| `updateFloors` | 在 **增加楼层 / 删除楼层** 两路上,将远程调用按 **每批 `UPDATE_FLOORS_FLOOR_PARALLEL` 个楼层** 提交到 `elevatorRemoteBoundedExecutor``FeignThreadLocalUtil` 在子任务中恢复租户上下文;每步成功再 `advanceBindProgressOne` 更新 `bindDevices`。 |
**实现类**`device/impl/AcsDeviceTaskServiceImpl.java`
## 1.4 用例级视图(操作者:管理员 / 系统)
```mermaid
flowchart TB
subgraph 电梯设备管理
A[增删改电梯设备]
B[分页查询/详情]
end
subgraph 重组绑定
C[选楼层/人员或规则]
D[启动 bindingFloors/bindingPerson]
E[异步 updateFloors]
end
A --> B
C --> D --> E
```
## 1.5 时序:启动楼层绑定后异步推进(概念)
```mermaid
sequenceDiagram
participant Web as Web/Controller
participant Dev as AcsElevatorDeviceServiceImpl
participant Task as AcsDeviceTaskService
participant Pool as 有界线程池
participant Remote as 人员/规则 Feign
Web->>Dev: bindingFloors(参数)
Dev->>Task: 异步 updateFloors(...)
loop 每批楼层
Task->>Pool: invokeAll(子任务)
Pool->>Remote: add/delete 单楼层步骤
Remote-->>Task: 成功
Task->>Task: advanceBindProgressOne(taskId)
end
```
## 1.6 设备设置子域 `device/setting`
- **`AcsDeviceSettingService`**:如体温相关设置查询(`getTemperatureSetting`)。
- **`AcsDeviceImageStoreAppBindService`**:设备与图库应用绑定/解绑等(实现见 `setting/impl`)。
## 1.7 与邻域关系
- **规则/人员**`updateFloors` 内调 `PersonRuleService``ImageRuleRefService` 等,取决于绑定参数是 `personId` 还是标签/组织。
- **data 层**`AcsDeviceTaskDao`、设备相关 DAO 在 **data 模块**
@@ -0,0 +1,68 @@
# 02 通行规则与人员(`passrule` / `person`
## 2.1 业务目标
- **通行规则**:按 **区域/楼层/图库/标签/组织** 等维护通行策略,与平台图库、设备绑定任务配合。
- **图库规则引用**`ImageRuleRefService`):从 **图库/图片 ID** 视角查规则列表、只增规则、人员列表、分页等,与 `AcsPassRuleService` 的「规则主 CRUD」互补。
- **人员**`AcsPersonService` 面向业务侧人员维护;`PersonRuleService`**规则上下文** 下做人员/访客的增删改查及 **与图库人员** 的关联(如 `personDetail`)。
## 2.2 `AcsPassRuleService` 方法表
| 方法 | 概要 |
|------|------|
| `listFloor` | 规则关联楼层列表 |
| `getIsDefaultByZoneId` | 区域下是否默认规则等标识 |
| `add` / `update` / `delete` / `detail` / `page` / `list` | 标准 CRUD 与详情分页 |
| `listByImageId` | 按图库/图片查规则 DTO 列表,供设备或绑定流使用 |
## 2.3 `ImageRuleRefService` 方法表
| 方法 | 概要 |
|------|------|
| `page` | 图库规则分页(与规则查询参数共用部分字段) |
| `listFloor` | 图库侧楼层规则列表 |
| `listByPersonInfo` | 按人维度列规则/楼层 |
| `listByPersonList` | 批量人列表与规则关系 |
| `detail` | 单条图库规则详情 |
| `addOnlyRule` | **仅** 建规则(设备任务中「非人员」线可能走此路) |
| `update` / `delete` | 更新/删除,与 `AcsPassRuleService` 分工依实现类而定 |
**实现基类提示**`passrule/impl/AbstractAcsPassService.java` 可抽取与远程/DAO 的共性。
## 2.4 `AcsPersonService` 与 `PersonRuleService`
| 接口 | 特点 |
|------|------|
| `AcsPersonService` | `add` / `edit` / `delete` / `page` / `timeDetail` / `pageByApp` |
| `PersonRuleService` | 在规则域增加 `addVisitor``personDetail(图库人员)` 等 |
## 2.5 用例图(简)
```mermaid
flowchart LR
Admin((管理员))
Admin --> P1[维护通行规则]
Admin --> P2[按图查规则/楼层]
Admin --> P3[维护人员/访客]
P1 --> S1[AcsPassRuleService]
P2 --> S2[ImageRuleRefService]
P3 --> S3[PersonRuleService / AcsPersonService]
```
## 2.6 时序:仅创建规则(与设备任务线关联)
```mermaid
sequenceDiagram
participant Task as AcsDeviceTaskServiceImpl
participant IMG as ImageRuleRefService
Task->>IMG: addOnlyRule(区域/标签/组织)
IMG-->>Task: CloudwalkResult
Note over Task: 成功后再推进 bind 进度
```
## 2.7 与设备任务关系(概念)
- **人员绑定**`updateFloors` 中若带 `personId`,走 `PersonRuleService.add/delete`**楼层/区域** 维度。
- **非人员**(标签/组织):建/删 **规则名**`ImageRuleRef` DAO,并调 `imageRuleRefService` 的删除或 `addOnlyRule`
更多细节以 `AcsPassRuleServiceImpl.java``AcsDeviceTaskServiceImpl.java` 源码为准。
@@ -0,0 +1,63 @@
# 03 通行记录与识别记录(`record`)
## 3.1 业务目标
- **电梯通行/开门记录**`AcsElevatorRecordService`):分页查询、**新增**(落库、访客判断、发域事件)、修改状态、统计、Redis 缓存键等。
- **人员识别记录**`AcsRecogRecordService`):单接口 `add`,与图库/识别流对接。
- **图库文件**`PersonFileService`):`upload` 小图片字节上传,给记录新增时 **Base64 解码后** 调图库。
- **`SendRecordTimeService`**:接口体为空,**无方法**,可视为占位或历史契约保留。
## 3.2 `AcsElevatorRecordService` 方法表
| 方法 | 概要 |
|------|------|
| `openRecord` | 分页查开门记录明细,**一年** 窗口校验;组装区域/片区/人员展示字段 |
| `add` | 见 [04-mqtt-visitor-event.md](04-mqtt-visitor-event.md) 的访客与事件说明 |
| `modify` | 按条件改开门记录 **状态**(如从 INIT 更新) |
| `createCache` | 分布式任务锁下 **Redis 缓存** 初始化 |
| `pageInfo` | 分页查询请求维表信息类结果 |
| `analyseCycle` / `analyseCount` | 按周期/条件的开门统计、排行等 |
**实现类**`record/impl/AcsElevatorRecordServiceImpl.java`
## 3.3 识别子域
- **`AcsRecogRecordService#add`**`AcsRecogRecordServiceImpl` 中增加识别记录(实现细节见同文件)。
## 3.4 流程图:`openRecord` 主路径
```mermaid
flowchart TD
A[入参+分页] --> B{时间跨度>1年?}
B -- 是 --> X[失败返回]
B -- 否 --> C[DAO 分页]
C --> D[去重取片区/区域id]
D --> E[批量查设备片区名]
E --> F[取区域树缓存/区域父名]
F --> G[批量查人员底库照]
G --> H[组装 AcsElevatorRecordResult 分页返回]
```
## 3.5 时序:`add` 落库前访客与人员(节选)
```mermaid
sequenceDiagram
participant S as AcsElevatorRecordServiceImpl
participant HTTP as ninca-crk-std HTTP
participant P as PersonService
participant DAO as AcsElevatorRecordDao
participant EVT as CloudwalkEventManager
S->>HTTP: POST three/visitor/record/query
HTTP-->>S: 是否访客+被访人
S->>P: detail(识别脸 id)
P-->>S: 工号/组织
S->>DAO: add(DTO)
S->>EVT: publish(VisitorRecordPushEvent)
```
## 3.6 领域事件
- 类型:`record/result/VisitorRecordPushEvent.java`
- 主题 `getTopic()` 固定为 `VISITOR_RECORD_TOPIC`(供订阅方区分)。
与 MQTT 的关系见 [04-mqtt-visitor-event.md](04-mqtt-visitor-event.md)。
@@ -0,0 +1,51 @@
# 04 MQTT、访客与域事件
## 4.1 双通道:访客查询
| 方式 | 路径/Bean | 使用场景(本模块) |
|------|-----------|---------------------|
| **HTTP + RestTemplate** | `combineAuthClientURI("intelligent/three/visitor/record/query")` | `AcsElevatorRecordServiceImpl#add` 反查是否访客 |
| **Feign** | `VisitorFeignClient``/intelligent/visitor/record/query` | 定义在 `visitor/client`**本模块内无直接注入调用** |
两者 **不是** 同一路径;业务上均面向标准访客中心,但 **「three」** 与 **「intelligent」** 为产品/版本差异,部署时需与 `ninca-crk-std` 实际路由一致。
## 4.2 `MqttService` 与 `MqttServiceImpl`
| 项 | 说明 |
|----|------|
| `sendInfoToOne` | `@Async`:先 **睡眠约 10s** 等待识别记录落库,再查识别流水,拼 `AcsElevatorRecordMqttParam`,向 topic `{businessId}+_elevator_record` 发 JSON |
| 远程 | `MqttFeignClient#publish` → 设备第三方 MQTT 服务 |
**调用关系**:本模块中 **`AcsElevatorRecordServiceImpl` 注入了 `MqttService` 但当前未调用**;若产品要求「保存记录后推送大屏」,可在 **监听 `VisitorRecordPushEvent` 的处理器****在 `add` 成功后** 显式调用 `sendInfoToOne`(需评估与异步睡眠设计是否一致)。
## 4.3 时序:MQTT 推送(当显式调用 `sendInfoToOne` 时)
```mermaid
sequenceDiagram
participant Caller as 业务/监听器
participant M as MqttServiceImpl
participant DAO as AcsRecogRecordDao
participant F as MqttFeignClient
Caller->>M: sendInfoToOne(DTO)
Note over M: sleep 10s
M->>DAO: page(识别流水)
DAO-->>M: 人名/标签
M->>F: publish(topic, JSON)
F-->>M: CloudwalkResult
```
## 4.4 状态机:从「仅事件」到「+ MQTT」(部署选项)
```mermaid
stateDiagram-v2
[*] --> RecordSaved: add DAO 成功
RecordSaved --> EventPublished: VisitorRecordPushEvent
EventPublished --> MqttOptional: 可选
MqttOptional --> MqttPush: 若接线 sendInfoToOne
MqttOptional --> NoMqtt: 当前默认
```
## 4.5 域事件与 MQTT 解耦说明
- `VisitorRecordPushEvent``CloudwalkEventManager` 发布,**不保证** 与 MQTT 同一步骤执行。
- 下游可独立订阅 **事件****MQTT topic**,避免强耦合。
@@ -0,0 +1,45 @@
# 05 区域与电梯区域编码(`zone` / `codeElevatorArea`
## 5.1 `ZoneService`
| 方法 | 概要 |
|------|------|
| `tree` | 入参 `ZoneNextTreeParam`,调 **平台区域/系统设置** 能力,组装 **下一级树** 等,返回 `List<ZoneTreeResult>`(实现中常经 Feign + 工具类 `ZoneTreeCollectors` |
| `page` | 区域维度的分页列表 `ZoneResult` |
**实现类**`zone/impl/ZoneServiceImpl.java`
## 5.2 `AcsElevatorCodeService``codeElevatorArea`
| 方法 | 概要 |
|------|------|
| `insertNew` / `updateOld` | 电梯与区域绑定的 **编码** 数据维护 |
| `get` / `getFirstByParentId` | 单条/按父级取首条 |
| `mapByZoneIds` | **批量** 按区域 id 查电梯编码,供树形接口 **一次** 拉取,避免 N+1(见接口内 Javadoc |
## 5.3 时序:区域树 + 树上网格批量取码(概念)
```mermaid
sequenceDiagram
participant Web as 上层
participant Z as ZoneService
participant Sy as 平台区域服务
participant C as AcsElevatorCodeService
Web->>Z: tree(参数)
Z->>Sy: Feign 取区域
Sy-->>Z: AreaTree
Z-->>Web: ZoneTreeResult
Web->>C: mapByZoneIds(多 zoneId)
C-->>Web: Map 区域id→编码
```
## 5.4 用例简图
```mermaid
flowchart TB
U[运营/系统]
U --> T[浏览区域树选楼层]
U --> M[维护电梯-区域码]
T --> ZoneService
M --> AcsElevatorCodeService
```
@@ -0,0 +1,51 @@
# 06 导出、下载与存储(`export` / `downloadcenter` / `storage`
## 6.1 异步导出 `export`
- 抽象基类:`AcsAbstractExportAsyncService` —— 泛型封装 **分页拉取** → 转 Excel 行 DTO → 与下载中心协作。
- **实现示例**`ElevatorDeviceExportService`
- 注入 `AcsElevatorDeviceService#get` 取设备分页。
-`queryPage` 中将 DTO 转为 `ElevatorDeviceRecordExcelResult`,并翻译 **在线/禁用** 等展示中文。
**典型时序**(概念):
```mermaid
sequenceDiagram
participant User as 用户/任务
participant E as ElevatorDeviceExportService
participant D as AcsElevatorDeviceService
participant DC as 下载中心
User->>E: 触发导出任务
loop 分页
E->>D: get(查询+分页)
D-->>E: 行数据
end
E->>DC: 完成文件/回写状态
```
## 6.2 下载中心 `AcsDownloadCenterService`
| 方法 | 概要 |
|------|------|
| `createDownload` | 创建下载任务/令牌 |
| `finishDownload` | 任务完成回执 |
| `queryDownloadStatus` | 轮询或查询状态 |
**实现类**`downloadcenter/impl/AcsDownloadCenterServiceImpl.java`(以源码为准)。
## 6.3 分片文件 `AcsFileStorageService``storage`
| 方法 | 概要 |
|------|------|
| `filePartInit` / `filePartAppend` / `filePartFinish` | DaVinci/门户 **分片上传** 生命周期 |
| `getFileBase64` | 按 id 回读为 Base64 |
## 6.4 ER/依赖(导出子域)
```mermaid
flowchart LR
Export[导出任务] --> Abs[AcsAbstractExportAsyncService]
Abs --> Svc[具体领域 Service 如 设备]
Abs --> Download[AcsDownloadCenterService]
Storage[AcsFileStorageService] -.大文件.-> 门户
```
@@ -0,0 +1,42 @@
# 07 横切与公共(`common` / `cacheable` / 基类)
## 7.1 `AcsApplicationService`
- 方法 `getApplicationId`:按业务/租户等解析 **应用 ID**`AcsApplicationServiceImpl` 实现,细节见类)。
## 7.2 `AcsAreaTreeCacheableService`
- 包装 `SysettingAreaService#tree`
- `@Cacheable``ACS_AreaTreeCache`key 与 `CacheOverrideConfig`**租户前缀** 拼出,减少区域树 **重复远程调用**
## 7.3 基类
| 类 | 作用 |
|----|------|
| `AbstractCloudwalkService` | 与 Cloudwalk 框架通用基能力(见父类/模块) |
| `AbstractAcsDeviceService` | 设备域公用:区域树展平、构造带 `FeignThreadLocalUtil``CloudwalkCallContext` 等(见 `common/AbstractAcsDeviceService` |
| `AbstractAcsPassService` | 通行/规则子域抽取(见 `passrule/impl` |
## 7.4 空接口
- `SendRecordTimeService`:无方法;若需扩展 **发送记录时间** 类能力,可在此增方法并由实现类承载。
## 7.5 包级 `package-info`
各子包在源码中已逐步补充 `package-info.java``device`/`record`/`mqtt`/`visitor` 等),可与本 `docs` 互参。
## 7.6 多维度总览表(维度矩阵)
| 维度 | 读者关注点 | 建议文档 |
|------|------------|----------|
| 业务价值 | 电梯设备、规则、人员、记录 | 01–03 |
| 集成 | 访客、MQTT、Feign | 04, 00 |
| 可运维 | 缓存、异步、任务进度 | 01, 07, 04 |
| 可观测 | 事件、topic、锁 | 03, 04, 03-锁 |
**读文档优先级(示意,非绝对)**
| | 远程依赖多 | 本地/缓存多 |
|--|------------|-------------|
| **写路径多** | 设备任务、规则+人员 | (较少) |
| **读路径多** | 记录 openRecord | 区域树缓存、电梯码 map |
@@ -0,0 +1,207 @@
# 访客与电梯业务:注册/登记与派梯授权完整说明
> 本文档针对 **本仓库 `cw-elevator-application`(以 service 层为逻辑落点)** 中与「访客」相关的 **完整可追踪路径** 做说明,并区分行业语义下常被混用的 **「访客登记/注册」** 与 **「在电梯域为访客授派梯权」**。
## 1. 概念与边界
| 概念 | 通常含义 | 在本项目中的落点 |
|------|----------|------------------|
| **访客主数据登记/注册** | 在**标准访客/一卡通**中录入:姓名、证号、访期、人脸、被访人、访客单等 | **不在**电梯应用内实现完整登记 UI;主数据以 **人员 ID`personId`****标准访客服务** 的档案形式存在。电梯服务通过 `PersonService`、图库、`ninca-crk-std` 的 HTTP/ Feign 与**既有档案**对接。 |
| **电梯侧「访客派梯授权」** | 在已存在**访客人员 ID** 的前提下,为指定**楼层**写入通行规则、绑定图库、设访期,使闸机/电梯能识别其通行 | **本应用显式能力**`PersonRuleService#addVisitor` → HTTP `POST /elevator/person/add/visitor`(见下文)。 |
| **通行中「是否访客」打标** | 识别到人脸后,写通行记录时判断是否访客、回填被访人 | `AcsElevatorRecordServiceImpl#add` 中调 **`intelligent/three/visitor/record/query`**,不创建新访客档案。 |
**结论**:若将「访客注册」理解为**在平台完整新建访客档案**,其主流程在 **外部标准服务**;本仓文档的「电梯侧部分」是 **(1) 授权** 与 **(2) 业务记录打标** 的完整、可追溯描述。
---
## 2. 总览图:访客相关双主线
```mermaid
flowchart TB
subgraph 标准域["标准访客/人员/图库(多在外部或 CWOS 组件)"]
VReg[访客档案登记/维护]
P[平台人员 personId]
G[图库 imageStoreId]
end
subgraph 电梯应用
A["POST /elevator/person/add/visitor\naddVisitor 派梯授权"]
B["AcsElevatorRecordService#add\nthree 线反查访客+被访人"]
end
VReg -.->|产生 visitor 对应人员ID| P
P --> A
A --> G
B -->|只读反查| VReg
```
---
## 3. 主线 A:访客派梯授权(核心业务逻辑)
### 3.1 对外入口
| 项 | 值 |
|----|-----|
| HTTP 方法/路径 | `POST` **`/elevator/person/add/visitor`** |
| Web | `AcsPersonController#addVisitor``person/controller/AcsPersonController.java` |
| 入参体 | `AcsPersonAddVisitorForm` → 复制为 `AcsPersonAddVisitorParam` |
| 服务 | `PersonRuleService#addVisitor` |
| 实现 | `PersonRuleServiceImpl#addVisitor``person/impl/PersonRuleServiceImpl.java` |
**入参字段(`AcsPersonAddVisitorParam`**
| 字段 | 含义 |
|------|------|
| `visitorId` | 访客在**平台人员体系**中的人员主键(非电梯单独造号) |
| `personId` | **被访人**人员主键,用于在**未传 floorIds 时**拉取被访人可通行楼层 |
| `begVisitorTime` / `endVisitorTime` | 图库绑定**有效期**(见 `ImageStorePersonBindParam` |
| `floorIds` | 可选。若**非空**,则跳过被访人楼层与租户策略的自动推算,**直接使用**该列表作为要授权的楼层 id 集合 |
### 3.2 处理步骤(与源码顺序一致)
1. **若调用方未传 `floorIds`**
-`PersonService#detail`**被访人** `PersonResult`
- 失败或无人 → 返回 `CloudwalkResult.fail``76260531` 等,以返回码为准)。
- 取被访人 **`floorList`** 作为候选楼层;**为空** → 失败 `76260531`
2. **租户访客楼层策略(可选收窄)**
-`TenantVisitorFloorPolicyDao#selectEnabledTenantDefault(businessId)` 读**启用**的默认策略行(`TenantVisitorFloorPolicyDto`)。
-`enabled==1``allowZoneIds`(JSON 字符串数组)解析出非空列表:
**被访人 `floorList`****策略允许 zone id 集合** 做**有序交集**`intersectPreserveHostOrder`:保留被访人原顺序、只留落在 allow 中的楼层)。
- 交完若**为空** → 失败 **`76260532`**(可配置文案,表示与租户策略无交集)。
3. **若调用方已传 `floorIds`**
- 以上「被访人楼层 + 策略求交」**整段不执行**;**直接使用**传入的 `floorIds` 作为 `effectiveFloors` 后续逻辑已合并进 `param.setFloorIds` 分支,最终以 `param.getFloorIds()` 非空为继续条件;若仍为空则 `76260531`
4. **解析首楼层所属楼栋 → 取图库 ID**
-`zoneService.page`**第一个 `floorId`**`ZoneResult`,再 `deviceImageStoreDao.getByBuildingId(首楼层 parentId)`**`imageStoreId`**(与楼栋绑定的图库)。
5. **每层写入「人员挂默认规则」的规则引用行**
- 对每个 `floorId`:查 `imageRuleRefDao.getDefaultByZoneId(floorId)`**该楼层默认规则**
-`ImageRuleRefAddDto` 列表:新建 UUID、`businessId``personId=visitorId`、挂 `parentRule``name`/`zoneId`/`zoneName` 自默认规则、`personDelete=0` 等。
- `imageRuleRefDao.insertList(insertList)` 批量落库(电梯侧**规则与人员**关系,供通行策略使用)。
6. **图库人员绑定与分组同步**
- `ImageStorePersonBindParam``imageStoreId``personIds=[visitorId]`、长期 null 作长期、起止时间用 `begVisitorTime`/`endVisitorTime`
- `imageStorePersonService.batchBind` —— 将访客**绑定**到本楼栋图库并带有效期。
-`updateGroupPersonRef`:对同一 `visitorId` + `imageStoreId` 做**组人员引用**更新(与通行业务的图库组一致)。
7. 任一步远程失败:返回 Feign/平台返回的 code/message 或 `76260530` 等包装异常(见 `catch`)。
### 3.3 活动图(无 floorIds,有租户策略时)
```mermaid
flowchart TD
Start([收到 add/visitor]) --> F{floorIds 已传?}
F -- 是 --> G[直接使用 floorIds]
F -- 否 --> D[被访人 detail]
D --> H{有 floorList?}
H -- 否 --> E1[失败 76260531]
H -- 是 --> T{租户策略 enabled=1 且 allow 非空?}
T -- 否 --> G
T -- 是 --> I[与 allowZoneIds 求交]
I --> J{交后非空?}
J -- 否 --> E2[失败 76260532]
J -- 是 --> G
G --> K[首 floor → 楼栋 → imageStoreId]
K --> L[每楼层: 写 ImageRuleRef + 默认父规则]
L --> M[图库 batchBind 访客+访期]
M --> N[updateGroupPersonRef]
N --> Ok([成功])
```
### 3.4 时序图
```mermaid
sequenceDiagram
autonumber
participant C as 前端/调用方
participant API as AcsPersonController
participant PR as PersonRuleServiceImpl
participant PS as PersonService(CWOS)
participant DB as ImageRuleRefDao/租户策略表
participant Z as ZoneService
participant D as DeviceImageStoreDao
participant IS as ImageStorePersonService
C->>API: POST /elevator/person/add/visitor
API->>PR: addVisitor(param, context)
opt 未带 floorIds
PR->>PS: detail(被访人)
PS-->>PR: floorList
PR->>DB: 读租户策略 + 求交
end
PR->>Z: page(查首层 zone)
Z-->>PR: 楼栋信息
PR->>D: getByBuildingId(楼栋)
D-->>PR: imageStoreId
loop 每层
PR->>DB: getDefaultByZoneId 规则
PR->>DB: insertList 人员规则引用
end
PR->>IS: batchBind(访期+访客+图库)
IS-->>PR: 成功
PR->>IS: updateGroupPersonRef
PR-->>API: CloudwalkResult
API-->>C: Boolean
```
### 3.5 策略与数据表(只读理解)
- **`tenant_visitor_floor_policy`**:租户级默认策略;`allow_zone_ids`**JSON 数组字符串**,表示允许作为访客派梯的 **区域/楼层 id**`enabled=1` 时参与**交集收紧**(见 DTO 注释与 DAO)。
---
## 4. 主线 B:通行记录落库时「访客身份」的认定(非注册)
**场景**:设备侧上报识别结果 **`add` 一条电梯通行/开门记录**。
**实现**`AcsElevatorRecordServiceImpl#add` 中,在**写本库**之前:
1. 组装 `VisitorRecordQueryParam``visitorId = addDTO.getRecognitionFaceId()`(**识别脸/访客侧 id**,与产品约定有关)、`businessId` 为租户;请求头 `businessId` 同。
2. `RestTemplateUtil.post`**`http://{ninca-crk-std}/intelligent/three/visitor/record/query`**
3. 若返回列表**非空**`isVisitor=1`,并从首条 `VisitorResult``personId` 写入 **被访人** `interviewee`
4. 此接口**不**在电梯服务内**新建**访客主档,仅**查询**与打标;与 `VisitorFeignClient`` /intelligent/visitor/record/query` **路径不同**(见 [04-mqtt-visitor-event.md](04-mqtt-visitor-event.md))。
```mermaid
sequenceDiagram
participant R as AcsElevatorRecordServiceImpl
participant HTTP as ninca-crk-std three/query
participant DAO as 电梯记录 DAO
R->>HTTP: visitorId+tenant
HTTP-->>R: List 访客档案或空
R->>DAO: add(含 isVisitor, interviewee)
```
---
## 5. 与图库/通行「访客标签」的其它关系
- **MQTT 侧**`MqttServiceImpl` 在识别流水中若 `personLabelIds` **含 `"1"`**,在 MQTT JSON 中置 `isVisitor=true`(**标签**语义,与上一节**档案访客**是不同判断维度)。见 `MqttServiceImpl``VISITOR_LABEL_CODE`
- **域事件**`VisitorRecordPushEvent` 在记录 `add` 成功后发布,**主题**为 `VISITOR_RECORD_TOPIC`;不替代访客主数据登记。
---
## 6. 错误与日志索引(addVisitor 相关,便于排障)
| 场景 | 码/信息方向 |
|------|-------------|
| 被访人查不到/无 floorList/最终 floor 为空 | `76260531`(及 message 中 `getMessage` 文案) |
| 与租户 `allowZoneIds` 交后无楼层 | `76260532` |
| 其它未预期异常 | `76260530` 包装为 `ServiceException` |
| 图库 `batchBind` 失败 | 透传 `bindResult` 的 code/message |
**日志关键词**`根据被访人添加访客派梯权限``租户访客楼层策略求交``访客添加派梯权限``远程调用绑定人员图库`
---
## 7. 本文档在仓库中的位置
- 与 [INDEX.md](INDEX.md) 其它分册互补:本文件专门 **深挖访客在电梯服务中的业务闭环**;部署与接口清单仍以运行环境及标准访客系统文档为准。
---
## 8. 关键源码索引
| 说明 | 路径(相对于 `maven-cw-elevator-application/…` 下模块) |
|------|--------------------------------------------------------|
| 入口 Controller | `cw-elevator-application-web/.../person/controller/AcsPersonController.java` |
| 派梯实现 | `cw-elevator-application-service/.../person/impl/PersonRuleServiceImpl.java` `addVisitor` |
| 入参 | `.../person/param/AcsPersonAddVisitorParam.java` |
| 策略 DTO/DAO | `cw-elevator-application-data/.../person/dto/TenantVisitorFloorPolicyDto.java``TenantVisitorFloorPolicyDao` |
| 记录打标 | `.../record/impl/AcsElevatorRecordServiceImpl.java` `add` |
最后更新以当前工作区代码为准;若你方将「访客注册」**唯一定义**为 **HTTP `/elevator/person/add/visitor`** 这一条,可忽略第 4 节,仅将第 3 节作为上线评审主材料。
@@ -0,0 +1,55 @@
# `cw-elevator-application-service` 业务逻辑文档总索引
本目录以 **本 Maven 模块源码根**`src/main/java/cn/cloudwalk/elevator`)为范围,对电梯应用 **业务编排层** 作多维度说明:分域业务、接口级能力、用例/时序/流程等图(Mermaid)及与外部系统的协作关系。
| 元数据 | 说明 |
|--------|------|
| 模块路径 | `maven-cw-elevator-application/cw-elevator-application-service` |
| 文档根 | 本目录 `.../cw-elevator-application-service/docs/` |
| 源码包根 | `cn.cloudwalk.elevator` |
| 产出形态 | Markdown + Mermaid(可用支持 Mermaid 的 IDE、Git 站点或 [mermaid.live](https://mermaid.live) 渲染) |
## 与仓库级文档的关系
- 全仓约定、走查、接口不变等说明见仓库根下 **`../../../docs/`**(相对本文件)。
- 本目录专注 **本 service 模块内** 类职责与业务流程梳理,不替代对外 API 合同文档。
## 分册导航
| 文档 | 内容摘要 |
|------|----------|
| [00-overview.md](00-overview.md) | 模块定位、包结构、领域全景、组件依赖图 |
| [01-device-and-task.md](01-device-and-task.md) | 设备 CRUD、绑定楼层/人员、设备任务与并行推进 |
| [02-passrule-and-person.md](02-passrule-and-person.md) | 通行规则、图库规则引用、人员规则、人员管理 |
| [03-record-recognition.md](03-record-recognition.md) | 电梯通行记录、识别记录、图库文件、分析统计 |
| [04-mqtt-visitor-event.md](04-mqtt-visitor-event.md) | MQTT 推送、访客查询差异、域事件 `VisitorRecordPushEvent` |
| [05-zone-code.md](05-zone-code.md) | 区域树/分页、电梯区域编码 |
| [06-export-download-storage.md](06-export-download-storage.md) | 异步导出、下载中心、分片存储 |
| [07-cross-cutting.md](07-cross-cutting.md) | 缓存、公共应用 ID、基类、空接口等横切项 |
| [08-visitor-registration-and-elevator-auth.md](08-visitor-registration-and-elevator-auth.md) | **访客:登记/授权边界、派梯 `add/visitor` 全链路、记录打标、时序/活动图** |
## 包 → 主入口(速查)
| 包路径 | 主要 `*Service` 接口 / 类 |
|--------|---------------------------|
| `device` | `AcsElevatorDeviceService``AcsDeviceTaskService` |
| `device/setting` | `AcsDeviceSettingService``AcsDeviceImageStoreAppBindService` |
| `passrule` | `AcsPassRuleService``ImageRuleRefService` |
| `person` | `AcsPersonService``PersonRuleService` |
| `record` | `AcsElevatorRecordService``AcsRecogRecordService``PersonFileService``SendRecordTimeService`(空) |
| `zone` | `ZoneService` |
| `codeElevatorArea` | `AcsElevatorCodeService` |
| `mqtt` | `MqttService` |
| `export` | `AcsAbstractExportAsyncService` 子类如 `ElevatorDeviceExportService` |
| `downloadcenter` | `AcsDownloadCenterService` |
| `storage` | `AcsFileStorageService` |
| `common` | `AcsApplicationService` |
| `cacheable` | `AcsAreaTreeCacheableService`(非 interface,为 `@Service` 包装) |
## 图例说明
- **用例图**:采用 Mermaid `flowchart` / `C4` 简图表达参与者与用例分箱;需要标准 UML 用例图时可自工具导出。
- **时序图**`sequenceDiagram` 表示一次调用链。
- **活动/状态**`flowchart TB``stateDiagram-v2` 表示分支与状态。
最后更新与源码版本以当前工作区 `cw-elevator-application-service` 反编译/还原代码为准;若与线上运行版本不一致,以发布制品为准。