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
This commit is contained in:
反编译工作区
2026-04-24 10:35:31 +08:00
commit e2ac14719b
653 changed files with 50372 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
# 文档索引(反编译工作区)
本目录集中存放说明类文档与配套资源,按类别分子目录。
## 目录结构
| 目录 | 说明 |
|------|------|
| [business/](business/) | 业务走查、接口流、用例说明 |
| [build/](build/) | 构建环境、JDK 版本依据等 |
| [style/](style/) | 代码风格配置(P3C / Eclipse Formatter XML,供 Maven `formatter-maven-plugin` 引用) |
| [operations/](operations/) | 发布、私服上传等运维脚本 |
| [architecture/](architecture/) | 工程结构、Maven 聚合模块说明与模块间关系 |
反编译归档与解压树不在 `docs/` 内,而在仓库根目录 [**`artifacts/decompiled/`**](../artifacts/decompiled/)(与本文并列,见该目录 README)。
## 文档列表
### 工程说明(architecture
- [Maven 聚合工程说明](architecture/Maven聚合工程说明.md) — 五个 `maven-*` 聚合工程的定位、子模块、技术栈、工程间依赖与 `artifacts`/运行包分工。
### 业务(business
- [访客注册与派梯楼层业务流程走查](business/访客注册与派梯楼层业务流程走查.md) — 从第三方获取默认楼层到指定楼层、电梯 `add/visitor`、Feign 调用链与用例。
- [租户访客默认楼层技术产品方案](business/租户访客默认楼层技术产品方案.md) — 从第三方登记页初始化(数据项与接口溯源)到派梯开通的**闭环**、多租户默认楼层的实现路径评估与落地建议。
### 构建(build
- [ORIGINAL_BUILD_JDK.txt](build/ORIGINAL_BUILD_JDK.txt) — 原始运行包与构件体现的 **JDK 8** 依据;与各聚合父 POM 中 `maven-enforcer-plugin` 提示一致。
### 风格(style
- [alibaba-eclipse-codestyle.xml](style/alibaba-eclipse-codestyle.xml) — 阿里巴巴 P3C Eclipse 格式化配置;各 `maven-*/pom.xml``alibaba.eclipse.codestyle.path` 指向此处。
### 运维(operations
- [deploy_cw_elevator_v1_lib_to_nexus.py](operations/deploy_cw_elevator_v1_lib_to_nexus.py) — 将 V1 运行包 `lib` 下 JAR 批量 `deploy-file` 到 Nexus 的脚本。
## 反编译二进制与解压树(`artifacts/`
说明类文档在 **`docs/`**;从 JAR 反编译得到的 **`*.jar.src.zip` / `*.jar.src/`** 已归纳至仓库根目录 **`artifacts/decompiled/`**`archives``trees` 分类),详见 [artifacts/decompiled/README.md](../artifacts/decompiled/README.md)。
## 与 `dev-support` 的关系
`dev-support/` 下文档与配置已迁入 `docs/` 对应子目录。若本地仍有旧路径书签,请改为以 `docs/` 为准。
@@ -0,0 +1,197 @@
# Maven 聚合工程说明(反编译工作区)
> **适用范围**:本仓库根目录下五个以 `maven-` 为前缀的 **Maven Reactor(聚合父工程)**,由反编译产物整理而来,用于本地编译、走查与增量修改。
> **不适用范围**:各工程依赖的大量 **NINCA / 云从内部 JAR** 仍须通过 Nexus 等私服解析,本文仅描述**本仓库内可见的模块边界与协作关系**。
---
## 1. 文档目的
- 说明五个聚合工程各自的 **业务定位、子模块划分、技术栈选型原因**
- 说明工程之间的 **Maven 依赖与调用链上的协作**(与 `docs/business/` 中接口走查互补:本文偏「工程与构件」,走查文档偏「接口与数据流」)。
- 说明 **`maven-*`** 目录与 **`artifacts/decompiled/`**、**运行包目录** `cw-elevator-application-V1.0.0.20211103/` 的分工,避免混淆「可改源码树」与「仅对照归档」。
---
## 2. 五工程一览
| 仓库目录 | 聚合 artifactId(父 POM | `groupId` | 版本(父 POM | 子模块(`modules` |
|----------|---------------------------|-----------|----------------|----------------------|
| `maven-cloudwalk-cloud/` | `cloudwalk-cloud-decompiled-reactor` | `cn.cloudwalk.cloud` | `3.7.2-Brussels-SRX` | `cloudwalk-cloud-common``cloudwalk-common-event``cloudwalk-common-service` |
| `maven-cw-elevator-application/` | `cw-elevator-application-decompiled-reactor` | `cn.cloudwalk.elevator` | `1.0-SNAPSHOT` | `cw-elevator-application-common``data``service``web` |
| `maven-intelligent-cwoscomponent/` | `intelligent-cwoscomponent-decompiled-reactor` | `cn.cloudwalk.intelligent` | `2.9.2-xinghewan` | `intelligent-cwoscomponent-parent``interface``rest` |
| `maven-ninca-crk/` | `ninca-crk-decompiled-reactor` | `cn.cloudwalk.ninca` | `1.0.0` | `ninca-crk-gpu-std` |
| `maven-ninca-qk-alarm/` | `ninca-qk-alarm-decompiled-reactor` | `cn.cloudwalk.ninca` | `0.0.2-SNAPSHOT` | `ninca-qk-alarm-app-starter`(其下再含 web / interface 等子模块) |
---
## 3. 各工程详细说明
### 3.1 `maven-cloudwalk-cloud` — 云从公共云底座(事件与服务)
**定位**
聚合 **CloudWalk 内部通用能力**:消息与事件封装(`cloudwalk-common-event`)、通用服务侧抽象与实现(`cloudwalk-common-service`)。电梯应用、智能组件等上层工程普遍依赖这里的 **`CloudwalkResult`、Feign 封装、事件注解** 等构件。
**为何存在「`cloudwalk-cloud-common`」子模块**
反编译得到的子 JAR 原 `parent` 指向 **`cloudwalk-cloud-common`**,而原始父 POM 在工作区中缺失。本聚合工程增加 **`cloudwalk-cloud-common`** 模块,使子模块能 **先 `install` 到本地 `~/.m2`**,满足其它构件对「父 POM 坐标」的解析,同时由本 reactor **继承 Spring Boot**,统一 **Spring Cloud Greenwich** 与内部版本属性(如 `cwos-sdk-event` 与 V1 运行包 `lib` 对齐的说明见父 `pom.xml` 注释)。
**技术栈摘要**
- Spring Boot **2.1.x**(与父 POM 声明一致)
- Spring Cloud **Greenwich**`spring-cloud-dependencies` import
- Java **1.8**
**与其它工程关系**
**`maven-cw-elevator-application`**、**`maven-intelligent-cwoscomponent`**、**`maven-ninca-crk`** 等通过 `dependencyManagement` 或直连依赖引用 `cloudwalk-common-event` / `cloudwalk-common-service` 等坐标。
---
### 3.2 `maven-cw-elevator-application` — 电梯 / ACS 通行应用
**定位**
**电梯与门禁派梯相关业务应用**:人员通行规则(含访客 `add/visitor`)、设备、区域/空间 Feign、乘梯记录、MQTT 等。对应运行环境中常部署的 **`elevator-app`** 一类服务;业务走查见 `docs/business/访客注册与派梯楼层业务流程走查.md`
**子模块分层(推荐理解顺序)**
| 子模块 | 典型职责 |
|--------|----------|
| `cw-elevator-application-common` | 公共枚举、常量、工具、跨层 DTO/注解等 |
| `cw-elevator-application-data` | MyBatis 实体、Mapper、DAO 与数据源相关 |
| `cw-elevator-application-service` | 业务实现:`PersonRuleServiceImpl`、设备服务、记录服务等 |
| `cw-elevator-application-web` | Spring MVC 控制器,对外 HTTP API(如 `/elevator/person/add/visitor` |
**技术栈摘要**
- Spring Boot **2.1.x**、Java **1.8**
- MyBatis、分库分表(ShardingSphere 等版本在父 POM 属性中集中管理)
- 依赖 **`cloudwalk-common-*`**、**`intelligent-cwoscomponent-rest`** 等(与智能侧、组织侧集成)
**与运行包、反编译归档的关系**
- 父 POM 中属性 **`cw.elevator.v1.lib.dir`** 指向根目录 **`cw-elevator-application-V1.0.0.20211103/lib`**,用于与 **V1 运行包内 JAR 文件名** 对齐,便于 `install-file` 或私服核对。
- **`artifacts/decompiled/trees/cw-elevator-application-*-SNAPSHOT.jar.src`** 为历史解压对照;**日常改代码以 `maven-cw-elevator-application` 下各模块为准**。
---
### 3.3 `maven-intelligent-cwoscomponent` — 智能组件(接口 + REST)
**定位**
**智能操作系统组件(CWOS Component**:对上提供 **REST / Feign Client** 入口,对下通过 **Feign** 调用组织人员、电梯、图库、空间等微服务。在业务文档中常作为「第三方或网关」与 **`cw-elevator-application`** 之间的中转层(例如 `ElevatorPersonService.addVisitor` → Feign → `POST /elevator/person/add/visitor`)。
**子模块说明**
| 子模块 | 职责 |
|--------|------|
| `intelligent-cwoscomponent-parent` | 占位/对齐原多模块父工程坐标(若子模块引用需要) |
| `intelligent-cwoscomponent-interface` | API、参数、结果 DTO、对外 Service 接口定义 |
| `intelligent-cwoscomponent-rest` | 接口实现、Feign 客户端声明、与 Spring Cloud 集成 |
**技术栈摘要**
- Spring Boot **2.1.x**、Spring Cloud **Greenwich**
- 管理 **`cloudwalk-device-sdk-protocol-entity`** 等与设备协议相关的版本(父 POM 注释与 V1 `lib` 对齐)
**与其它工程关系**
- **`maven-cw-elevator-application`** 依赖 **`intelligent-cwoscomponent-rest`**(或同版本构件),形成「智能组件编排 ↔ 电梯落地」的链路。
- **`maven-ninca-crk`** 的 `ninca-crk-gpu-std`**`intelligent-cwoscomponent-rest`** 存在 **exclusion** 等精细依赖控制,说明 CRK 打包场景下需避免重复引入或版本冲突,以实际 **`ninca-crk-gpu-std/pom.xml`** 为准。
---
### 3.4 `maven-ninca-crk` — NINCA CRK 产品线(当前聚合 GPU 标准后端)
**定位**
**NINCA CRK**(门禁、考勤、访客、会议等组合能力)产品族中的 **标准 GPU 出入口后端** 工程 **`ninca-crk-gpu-std`**。子模块描述中体现为轻舟 1.4 体系下的 **标准 GPU 服务器-出入口版**;考勤、访客、门禁等大量 **web 模块以私服版本依赖** 引入,**不在本 reactor 的 `modules` 列表中展开**。
**为何使用 Boot 1.5 + Edgware**
父 POM 说明:为 **贴近原 `spring-boot-maven-plugin` 1.3.x 时代栈**,采用 Spring Boot **1.5.22** 与 Spring Cloud **Edgware**,减少与历史 fat jar 字节码、依赖树差异带来的构建问题。
**技术栈摘要**
- Spring Boot **1.5.x**、Cloud **Edgware**
- Java **1.8**
-**`intelligent-cwoscomponent-rest`**、**`cloudwalk-common-event`** 等版本在父 POM `dependencyManagement` 中锁定
**与其它工程关系**
依赖本仓库整理的 **`intelligent-cwoscomponent-rest`**、**`cloudwalk-common-event`** 等;更多 `ninca-crk-*` 构件从 Nexus 拉取。
---
### 3.5 `maven-ninca-qk-alarm` — 轻舟告警应用(Starter 聚合)
**定位**
**区域告警 / 轻舟告警(qk-alarm)** 可执行应用的 Maven 化聚合:原 **`ninca-qk-alarm-app`** 父 POM 缺失,由本 **`ninca-qk-alarm-decompiled-reactor`** 补齐 **`dependencyManagement`、插件版本、编码** 等,当前 reactor **直接列出的模块**为 **`ninca-qk-alarm-app-starter`**(可执行 JAR 形态业务的启动与组装入口)。
**子模块 `ninca-qk-alarm-app-starter` 说明**
- 依赖 **`ninca-qk-alarm-app-web`**、**`ninca-qk-alarm-app-interface`** 等同版本子构件,形成完整 Web + 接口层。
- 使用 **Curator + ZooKeeper**(版本在父 POM 统一管理),适用于注册发现或分布式协调类能力(以实际代码为准)。
**技术栈摘要**
- Spring Boot **2.1.x**、Java **1.8**
- MyBatis Spring Boot、Jacoco 等插件在父 POM `pluginManagement` 中声明
**与其它工程关系**
主要依赖 **`cloudwalk-common-web`** 等云从公共 Web 能力;与电梯、智能组件无强绑定,相对 **独立部署单元**
---
## 4. 工程间依赖与协作(简图)
下列关系表示 **Maven 依赖 / 常见运行时调用方向**,非严格部署拓扑。
```mermaid
flowchart LR
subgraph cloud [maven-cloudwalk-cloud]
CE[cloudwalk-common-event]
CS[cloudwalk-common-service]
end
subgraph intel [maven-intelligent-cwoscomponent]
IR[intelligent-cwoscomponent-rest]
end
subgraph elev [maven-cw-elevator-application]
EW[cw-elevator-application-web]
ES[cw-elevator-application-service]
end
subgraph crk [maven-ninca-crk]
GPU[ninca-crk-gpu-std]
end
subgraph alarm [maven-ninca-qk-alarm]
ST[ninca-qk-alarm-app-starter]
end
CE --> ES
CS --> ES
IR --> ES
ES --> EW
CE --> GPU
IR -.->|可能被 exclusion| GPU
CS --> ST
```
**文字归纳**
- **电梯应用** 依赖 **公共云模块** + **智能组件 REST**,对外暴露电梯 HTTP API;智能组件再通过 Feign 回调电梯、组织等。
- **CRK GPU 标准后端** 依赖公共事件、智能组件等,与考勤/访客等 **NINCA 模块** 打成一个可部署单元(具体以 `ninca-crk-gpu-std/pom.xml` 为准)。
- **告警应用** 相对独立,主要挂 **CloudWalk Web 公共栈**
---
## 5. 源码目录、`artifacts`、运行包三者的分工
| 位置 | 性质 | 建议使用方式 |
|------|------|----------------|
| **`maven-*/*/src/main/java`** | 已整理为 Maven 标准目录的 **主修改区** | 日常开发、编译、`mvn validate/package` |
| **`artifacts/decompiled/trees/*.jar.src`** | 反编译解压树 **归档对照** | 查历史包内资源、与 `META-INF/maven` 对照版本 |
| **`artifacts/decompiled/archives/*.jar.src.zip`** | 未解压的 **zip 备份** | 备份、交付留档 |
| **`cw-elevator-application-V1.0.0.20211103/`** | **V1 运行包展开**(含 `lib/` | 对齐线上依赖列表;`docs/operations/deploy_cw_elevator_v1_lib_to_nexus.py` 默认读取其 `lib` |
详见 [artifacts/decompiled/README.md](../../artifacts/decompiled/README.md)。
---
## 6. 构建与环境(延伸阅读)
- **JDK 版本依据**[ORIGINAL_BUILD_JDK.txt](../build/ORIGINAL_BUILD_JDK.txt)
- **各父 POM** 中 **`maven-enforcer-plugin`** 要求使用 JDK 8 范围,与上述依据一致。
- **代码风格**`docs/style/alibaba-eclipse-codestyle.xml`,各聚合工程通过属性 **`alibaba.eclipse.codestyle.path`** 引用。
- **私服与上传脚本**`docs/operations/deploy_cw_elevator_v1_lib_to_nexus.py`Nexus 地址见各父 POM 中 `nexus.baseUrl` 注释。
---
## 7. 文档维护
- 若新增第六个聚合工程,请在本表与各节补充 **目录、artifactId、modules、与其它工程的依赖边**
- 若 Spring Boot / Cloud 版本升级,请以各 **`maven-*/pom.xml`** 为准同步更新本文「技术栈摘要」小节。
+20
View File
@@ -0,0 +1,20 @@
原始运行包 / 官方构件体现的 Java 版本:Java 81.8
依据(摘录自本工作区内文件,便于审计):
1) cw-elevator-application-V1.0.0.20211103
- META-INF/MANIFEST.MFBuild-Jdk: 1.8.0_144
- META-INF/maven/.../cw-elevator-application-starter/pom.xml
maven.compiler.source=8maven.compiler.target=8
2) cw-elevator-application-V1.0.0.20211103/lib/cw-elevator-application-common-1.0-SNAPSHOT.jar
- META-INF/MANIFEST.MFBuild-Jdk: 1.8.0_144
3) cw-elevator-application-V1.0.0.20211103/lib/cloudwalk-common-event-3.7.2-Brussels-SRX.jar
- META-INF/MANIFEST.MFBuild-Jdk: 1.8.0_191
4) artifacts/decompiled/trees/ninca-crk-std-backend-V2.9.1_20210630.jar.src/META-INF/maven/.../pom.xml
- maven.compiler.source=1.8maven.compiler.target=1.8
结论:五个聚合 Maven 工程应与上述一致,使用 JDK 8 作为运行 Maven 的 JVMJAVA_HOME 指向 1.8.x),
字节码目标为 1.8。各聚合父 POM 已配置 maven-enforcer-plugin,要求 [1.8,1.9),避免误用 JDK 11+ 仅当“编译目标 8”导致注解处理器等问题。
@@ -0,0 +1,424 @@
# 租户访客默认楼层:技术产品方案
> **文档类型**:产品与工程技术方案(含**登记页数据项与接口溯源**、端到端闭环、数据模型与实施路线)。
> **前置阅读**:[访客注册与派梯楼层业务流程走查](访客注册与派梯楼层业务流程走查.md)(UC-01UC-06、对外 HTTP/Feign 与代码位置)。
> **关联工程**[Maven 聚合工程说明](../architecture/Maven聚合工程说明.md)`maven-cw-elevator-application`、`maven-intelligent-cwoscomponent` 等边界)。
---
## 1. 背景与问题陈述
### 1.1 业务背景
多租户部署下,不同机构对**访客可达楼层**的策略不一致:
- **默认诉求**:访客开通派梯时,若业务侧**不显式传楼层列表**(与 [UC-01](访客注册与派梯楼层业务流程走查.md) 一致),系统仍应开通派梯,但**不应简单等同于被访人组织侧 `floorList` 全集**。
- **典型例子(产品化名)**:**「广发基金」类租户**要求:访客**默认仅可派梯至 28 楼**(或某固定接待层),而被访人本人在组织中可能仍具备多层办公权限。
### 1.2 `floorIds` 是谁的字段、空与非空分别代表什么
#### 1.2.1 字段归属(哪个主体的属性)
`floorIds` **不是**组织人员主数据里「被访人」的持久化字段,也**不是**访客人员档案在组织库里的固定属性;在现有实现中,它是 **电梯应用对外接口** 的一次请求参数。
| 项目 | 说明 |
|------|------|
| **载体** | HTTP **`POST /elevator/person/add/visitor`** 的请求体(`AcsPersonAddVisitorForm` / 服务层 `AcsPersonAddVisitorParam`,见 `maven-cw-elevator-application`)。 |
| **语义** | **本次「给访客开通派梯」操作**中,调用方希望电梯在哪些 **空间分区(`zoneId`)** 上为 `visitorId` 写入默认通行规则并绑图库。 |
| **主体** | 归属主体是 **「派梯开通请求」**(一次 API 调用),由 **调用方**(第三方 BFF、访客业务后台、或 `intelligent-cwoscomponent-rest` 等)填入;电梯服务**读取**后执行落库与远程绑图库。 |
因此:在集成文档中应写清——**`floorIds` 列出的是「本次开通涉及的楼层 zoneId 列表」,由调用方在请求时提供;缺省(空)时电梯才按约定去组织侧拉被访人的 `floorList` 补全。**
#### 1.2.2 `floorIds` 非空时:业务含义与电梯行为
当调用方传入 **非空** `floorIds` 时(走查文档中的 **UC-02:访客派梯-第三方指定楼层**):
| 项目 | 说明 |
|------|------|
| **业务含义** | 调用方已明确「本次访客只(或优先)开通这些楼层」的意图;常见来源包括:登记/审批流程里已算好的**生效楼层**、访客在允许范围内**勾选的多层**、或业务规则直接指定的接待层列表。 |
| **电梯侧行为** | **不再**为补楼层去调 **`POST /component/person/detail`**;直接使用请求中的 `floorIds` 作为待写入规则的楼层列表,后续步骤(`zone/page` 取楼栋、`getDefaultByZoneId`、写 `image_rule_ref``batchBind` 等)与「列表来自组织补全」时相同,**仅楼层列表来源不同**。 |
| **责任边界** | **正确性、合法性、与租户策略及被访人授权的一致性**由调用方负责(或通过 BFF 统一校验);电梯按列表执行;若需「仍不得超过被访人 `floorList`」的硬约束,须在 **BFF、intelligent 或电梯增强**中择一层实现(见 §4、§5)。 |
#### 1.2.3 为什么调用方会选择「非空」(不依赖空列表)
| 动机 | 说明 |
|------|------|
| **与 UI/审批结果一致** | 登记页或审批单已确定可访楼层,开通时**显式写入**同一列表,避免电梯侧再解释「默认」。 |
| **多租户策略在域外已算完** | 推荐做法(§4):在第三方 BFF 做 `tenantAllow ∩ hostFloors`,把结果作为 `floorIds` 传入,电梯无需理解租户表。 |
| **避免 UC-01 与产品语义冲突** | 不传 `floorIds` 时电梯等价于「被访人 `floorList` 全集」;若产品要「小于全集」,**应传非空** `floorIds`,否则现网电梯逻辑无法满足。 |
| **集成契约清晰** | 显式列表便于审计、重放、幂等比对(可与登记快照 `effective_preview_json` 逐字一致)。 |
#### 1.2.4 `floorIds` 为空时:电梯侧补全(与上文对照)
当前电梯侧实现(`PersonRuleServiceImpl.addVisitor`)在 **`floorIds` 为空或缺省** 时:
1. 调用组织 **`/component/person/detail`**`personId` + `businessId`);
2. 将返回的 **`PersonResult.getFloorList()`** 赋给本次执行使用的楼层列表;
3. **不使用** `defaultFloor` 单字段作为补全依据。
因此:**仅在「调用方不传 `floorIds`」这一模式下**,现网电梯无法表达租户级收敛;多租户默认接待层需在 **调用方传非空 `floorIds`****电梯/ BFF 增强兜底** 中实现(见全文 §4、§6)。
### 1.3 文档目标
| 维度 | 目标 |
|------|------|
| **产品** | 定义租户策略、角色权限、配置流程、登记/邀约 **UX 与开通结果一致**、验收标准。 |
| **闭环** | 从**第三方系统在注册/邀约流程中初始化访客登记页**开始,明确**每个数据项从哪个系统、哪类接口获取**;经提交、审批(若有)到 **`add/visitor`** 生效,并给出**一致性校验**与回读建议。 |
| **技术** | 可选架构、推荐组合、数据模型与接口草案、改造边界、安全求交、**多租户默认访客楼层的实现路径综合评估**。 |
---
## 2. 端到端闭环:从第三方登记页初始化到派梯生效
本章回答:**登记页打开时要拉哪些数据、按什么顺序调接口、算出什么给 UI 存什么草稿、审批后如何与电梯开通对齐**,从而形成可审计、可测试的闭环。
### 2.1 闭环目标
| 目标 | 说明 |
|------|------|
| **同源计算** | 「页面上展示的预计可派梯楼层」与「最终调用 `add/visitor``floorIds`(或电梯兜底前的逻辑输入)」由**同一套规则函数**得出,避免两套逻辑漂移。 |
| **接口可追溯** | 每个 UI 字段可映射到**具体外部接口或本地配置**;本仓库已明确的接口见走查文档 §3~§4。 |
| **租户可配置** | `businessId`(机构 ID)贯穿上下文;租户策略变更后,**进行中的登记单**行为需在产品中定义(见 §2.7)。 |
### 2.2 阶段划分(第三方视角)
| 阶段 | 名称 | 参与系统 | 产出 |
|------|------|----------|------|
| **P0** | 登记页/邀约页 **初始化** | 第三方 + 组织 + 空间 +(可选)租户策略服务 | 表单默认值、`effectiveFloorsPreview`、可选楼层展示文案 |
| **P1** | 用户填写与 **校验** | 第三方前端 + 后端 | 通过校验的草稿 DTO |
| **P2** | **提交**登记/发起邀约 | 第三方 DB、工作流引擎 | 业务主键、状态机(待审批/已登记) |
| **P3** | **审批**(若存在) | 第三方审批流 | 通过/驳回;通过则触发 P4 |
| **P4** | **组织侧** 写入访客人员、拿到 `visitorId` | 组织/访客模块(**不在本反编译仓**,以实际 API 为准) | `visitorId` |
| **P5** | **派梯开通** | 第三方或 intelligent → **电梯** `POST /elevator/person/add/visitor` | 规则写入、图库绑定 |
| **P6** | **回读与告知** | 第三方查询电梯/通行结果或异步任务状态 | 与 P0 展示一致的「已开通楼层」说明 |
### 2.3 访客登记/邀约页:数据项定义与数据来源
下表面向**第三方业务系统**实现同学:列的是**逻辑字段**;物理表名由各自系统定义。接口路径以走查文档为准;**组织人员搜索**(选被访人)在走查中未展开,行内标注为**待对接清单**。
| 逻辑数据项 | 典型 UI 表现 | 数据来源 | 接口或服务(已知/占位) | 关键入参 / 出参 | 与租户楼层关系 |
|-------------|--------------|----------|---------------------------|-----------------|----------------|
| **租户/机构 ID** | 隐藏或顶部切换 | 登录态 / 网关注入 | 上下文 `businessId`,与 `CloudwalkCallContext.company` 一致 | `businessId` | 策略表主键维度 |
| **被访人 `personId`** | 选人组件 | **组织人员检索**(具体路径以 `ninca-common-component-organization` 或网关文档为准) | 占位:`POST .../person/page` 或等价检索 API | 选中行 → `personId` | 后续 `detail` 入参 |
| **被访人姓名/部门等展示** | 选人后回显 | 同上检索结果或二次 `detail` | 检索结果字段 **或** `POST /component/person/detail` | `PersonResult` 展示字段 | 非楼层核心 |
| **被访人授权楼层 ID 列表 `hostFloors`** | 一般不直接展示 ID | **组织**(与电梯 UC-01 同源) | **`POST /component/person/detail`** | 请求:`id`=被访人 `personId``businessId`;响应:`PersonResult.floorList` | 求交上界 |
| **`defaultFloor` / `floorInfoList` 等** | 若产品要展示「默认办公层」文案 | **组织** `detail` 同响应 | 同上 | `PersonResult.defaultFloor``floorInfoList` | **电梯补全不用 `defaultFloor`**;若 UI 用其展示,须与 `floorList` 语义对齐(走查 §8 风险 1) |
| **空间树/楼层名称** | 楼层中文名、楼栋 | **空间服务** `ninca-common` | **`POST /sysetting/zone/tree`**、**`POST /sysetting/zone/page`** | 用 `hostFloors``zoneId` **反查** `zoneName`、楼栋 | 仅展示增强 |
| **租户访客楼层策略** | 管理员配置页;登记页可不直接展示 | **租户策略存储**(自建表或配置中心) | 草案 §4.3 管理 API **或** 第三方本地表 + 管理端 | `policy_type``allow_zone_ids`、版本号 | **与 `hostFloors` 求交**得预览 |
| **`effectiveFloorsPreview`** | 「本次访问预计可开通派梯的楼层」 | **计算字段**(禁止手写死) | `computeEffective(policy, hostFloors, userOverride?)` | 输出 `List<zoneId>`,可附 `displayNames` | **必须与 P5 输入一致** |
| **访客可选楼层(若产品允许访客改)** | 多选框,默认选中 `effectiveFloorsPreview` | `effectiveFloorsPreview` 的子集 | 前端约束:用户勾选 ⊆ 预览集 | 提交 `userSelectedZoneIds` | 高敏租户可关闭多选 |
| **访客姓名、证件、事由、到访时间等** | 表单 | 用户输入 + 机构规则 | 第三方本地 | — | 与楼层正交 |
| **人脸/照片** | 采集/上传 | 用户 + 第三方存储 | 组织图库/人像接口以实际为准 | — | 走查未展开 |
| **策略版本号 `policyVersion`** | 可不展示 | 租户策略表 | 读取策略时返回 | 写入登记草稿 | 审计与回放 |
| **登记单草稿持久化** | — | 第三方 DB | 本地表建议字段:`draft_id, business_id, host_person_id, host_floors_snapshot_json, policy_snapshot_json, effective_preview_json, policy_version, status` | P5 时读出 `effective_preview` 或重算 | 支持审批前后回放 |
**不在本仓库的接口**(须在集成清单中单独列出):访客人员创建、`visitorId` 发放、审批流回调 URL、人像入库等——闭环在 P4 前依赖这些能力,本文仅要求:**P5 的 `floorIds` 与 P0 预览同源**。
### 2.4 接口编排顺序(推荐:登记页初始化一次请求链)
第三方**后端聚合接口**(推荐由自有 **BFF** 实现,避免前端直连多枚令牌)建议内部按序调用:
```
1) 校验 businessId、操作者权限
2) GET 租户访客楼层策略(若无则视为 HOST_FLOOR_LIST
3) POST /component/person/detailid=被访人 personId, businessId
→ 得 hostFloors = floorList(可能 null/空)
4) computeEffective(policy, hostFloors, requestedFromClient=null)
→ 若空:返回明确错误码,登记页展示「无法为该被访人开通访客派梯,请联系管理员」
5) 可选:POST /sysetting/zone/page 或 tree 子集调用,将 zoneId 映射为 zoneName / 楼栋
6) 返回给前端:{ hostPerson, effectiveFloorsPreview, displayNames, policyVersion, warnings }
```
前端**仅展示**第 6 步结果,**不在前端重复实现求交**(防篡改可签短期 token 或仅信服务端字段)。
### 2.5 可选:统一「预览」能力(降低集成方重复劳动)
可在 **第三方 BFF****intelligent** 增加只读接口(路径示例):
| 方法 | 路径(示例) | 入参 | 出参 |
|------|----------------|------|------|
| `POST` | `/api/visitor/register/preview-floors` | `businessId`, `hostPersonId`, 可选 `userSelectedZoneIds` | `hostFloors`, `tenantPolicy`, `effectiveZoneIds`, `displayFloors[]`, `policyVersion`, `canSubmit` |
**契约**`effectiveZoneIds` 的计算规则须与 P5 调用 `add/visitor` 时组装的 `floorIds` **完全一致**(同一服务端模块单元测试)。
### 2.6 P5 派梯开通:与登记页的衔接
| 路径 | 做法 |
|------|------|
| **推荐(方案 B** | 审批通过后,从登记单读出 **快照**或 **用相同函数重算**(若策略允许重算):组装 **`floorIds` = `effectiveZoneIds`**,调用 **`POST /elevator/person/add/visitor`**(或 `ElevatorPersonFeignClient.addVisitor`),走 **UC-02**。 |
| **兜底(方案 C/D** | 若历史集成方坚持不传 `floorIds`,则由电梯或 intelligent 在服务端求交(见 §4);登记页仍应按 §2.3 展示**与兜底后一致**的预览(通过同一预览 API 或文档约定算法)。 |
**时间参数**`begVisitorTime` / `endVisitorTime` 与走查一致,须与登记单有效期对齐。
### 2.7 闭环一致性:策略中途变更、重试与幂等
| 场景 | 产品建议 |
|------|----------|
| 管理员在**登记草稿未提交**时修改策略 | 下次打开登记页重新走 P0,**以新策略为准**。 |
| 草稿已提交、**待审批**期间策略变更 | 二选一并在需求中写死:**(a)** 审批节点展示「策略已变更请重审」并阻塞直到人工确认;**(b)** 以提交时刻 `policyVersion` **冻结**计算结果,审批通过仍按旧结果开通(需评估合规)。 |
| **审批通过瞬间**策略变更 | P5 使用**出队消息中的快照** `effective_preview_json`,避免 TOCTOU。 |
| 重复点击开通 | `visitorId` + 时间窗幂等;与电梯侧是否已存在规则引用需对齐(可查电梯侧人员规则再调,属增强项)。 |
### 2.8 端到端泳道图(闭环)
```mermaid
sequenceDiagram
participant U as 访客用户
participant FE as 第三方前端
participant BFF as 第三方BFF
participant Pol as 租户策略存储
participant Org as 组织 person/detail
participant Zone as 空间 zone/tree|page
participant Reg as 第三方登记库
participant Apv as 审批流
participant OrgW as 组织写访客
participant Elv as 电梯 add/visitor
U->>FE: 打开登记页
FE->>BFF: 初始化(被访人personId)
BFF->>Pol: 读策略(businessId)
BFF->>Org: detail(personId)
Org-->>BFF: floorList
BFF->>BFF: computeEffective
opt 展示楼层名
BFF->>Zone: page/tree(zoneIds)
Zone-->>BFF: names
end
BFF-->>FE: 预览+policyVersion
U->>FE: 填写并提交
FE->>BFF: 提交草稿
BFF->>Reg: 持久化快照
Reg-->>FE: draftId
opt 需审批
BFF->>Apv: 发起
Apv-->>BFF: 通过+token
end
BFF->>OrgW: 创建访客→visitorId
BFF->>Elv: add/visitor(visitorId,personId,floorIds=effective,...)
Elv-->>BFF: 成功/失败
BFF-->>FE: 结果与楼层说明
```
---
## 3. 产品方案
### 3.1 目标用户与角色
| 角色 | 职责 |
|------|------|
| **平台/租户管理员** | 在本机构内配置「访客默认楼层策略」、维护允许的 `zoneId` 列表或与楼栋的映射、查看审计日志。 |
| **被访人员工** | 日常办公权限仍在组织侧维护;不强制要求其理解访客策略。 |
| **访客** | 通过邀约/登记获得限时通行;仅应看到**实际可派梯楼层**(与开通结果一致)。 |
| **运维/实施** | 将「28 楼」等业务语言映射为空间服务中的 **`zoneId`**,并录入策略或导入模板。 |
### 3.2 用户故事(示例)
1. **作为租户管理员**,我希望为本机构配置「访客默认仅开放指定楼层集合」,以便满足物业/合规对访客活动范围的要求。
2. **作为租户管理员**,我希望可选策略为「与员工授权楼层求交」或「固定楼层但必须仍在员工授权内」,以便在**不放大访客权限**的前提下简化配置。
3. **作为访客业务系统**,在调用电梯开通接口时,我可以在不传 `floorIds` 的情况下仍得到符合租户策略的派梯结果(若采用电梯或 BFF 兜底策略)。
4. **作为访客**,我在登记完成前看到的「可访问楼层」说明,应与最终开通的楼层**一致**,避免纠纷。
### 3.3 策略类型(产品枚举建议)
| 策略代码(建议) | 产品名称 | 行为摘要 | 适用场景 |
|------------------|----------|----------|----------|
| `HOST_FLOOR_LIST` | 与现网 UC-01 一致 | 不传 `floorIds` 时,等价于被访人 **`floorList` 全集** | 默认租户、未配置策略时的回退 |
| `INTERSECT_ALLOWLIST` | 租户允许列表 ∩ 被访人楼层 | 最终楼层 = **`allowZoneIds``floorList`**(交集为空则失败并提示) | **广发基金类**:员工多层、访客只允许接待层等 |
| `FIXED_ZONES` | 固定楼层(仍 ∩ 被访人) | 最终楼层 = **`fixedZoneIds``floorList`** | 强固定少量楼层且必须与员工授权一致 |
| `EXPLICIT_ONLY` | 仅显式开通 | 业务侧**必须**传 `floorIds`(等价 UC-02);租户策略关闭「空列表自动补全」 | 金融高敏楼栋 |
**产品原则(建议写进需求)**:凡涉及「租户默认/固定楼层」的,**最终生效楼层必须 ⊆ 被访人 `floorList`**(安全底线,见第 5 章)。
### 3.4 管理端功能清单(MVP → 完整)
**MVP(最小可用)**
- 租户级开关:是否启用「访客楼层策略」。
- 策略类型选择 + **允许楼层多选**(选项数据来自空间树 `/sysetting/zone/tree` 或分页接口,与走查文档一致)。
- 保存后**审计**:操作人、时间、前后 JSON 快照。
**增强**
- 按**楼栋**分别配置(多栋园区)。
- 按**被访部门**或**职级**附加规则(优先级:部门规则 > 租户默认)。
- 导入/导出 CSV`businessId, zoneName, zoneId`)。
- 与「访客类型」联动(VIP 可走多层等,需单独权限模型)。
### 3.5 验收标准(补充闭环相关)
| 编号 | 场景 | 期望 |
|------|------|------|
| AC-1 | 租户配置「允许 {28F}」,被访人 `floorList` 含 28F 与其它层 | 不传 `floorIds` 时(若走兜底),访客**仅**开通 28F |
| AC-2 | 同上,被访人 `floorList` **不含** 28F | **开通失败**,返回明确错误(禁止静默落到其它层) |
| AC-3 | 租户未配置策略 | 行为与现网 **UC-01** 一致 |
| AC-4 | 业务显式传 `floorIds`UC-02 | **以传入为准**(或启用「显式也求交」须在集成合同写明) |
| AC-5 | 注册前 UI 展示楼层 | 与 `add/visitor` **最终生效楼层**一致(含策略与求交) |
| **AC-6** | 登记页初始化与 P5 开通相隔任意时间(策略不变) | **两次 `computeEffective` 结果一致**(或均使用快照) |
| **AC-7** | 仅改展示文案、不改服务端 | **禁止**;展示必须以服务端预览为准 |
---
## 4. 技术方案
### 4.1 方案族对比
| 方案 | 实现位置 | 优点 | 缺点 | 新租户扩展 |
|------|----------|------|------|------------|
| **A. 组织侧收窄 `floorList`** | `ninca-common-component-organization` | 不改电梯;与 UC-01 完全一致 | 员工本人权限与「访客可继承列表」易混 | 每租户数据治理 |
| **B. 业务/访客层显式传 `floorIds`** | 第三方 BFF:登记页与 P5 **同源计算** | 不改电梯;闭环最清晰(UC-02) | 多调用入口需统一 | 租户表在**业务库** |
| **C. 电梯侧策略引擎** | `PersonRuleServiceImpl.addVisitor` | 直连电梯的旧集成也能兜底 | 电梯存策略、发版耦合 | `businessId` 维表 |
| **D. intelligent BFF** | `intelligent-cwoscomponent-rest` | 不直接改电梯包 | 绕过 intelligent 的直连须约束 | 表可在 intelligent 库 |
| **E. 配置中心** | Nacos 等 | 变更快 | 审计弱 | 适合灰度,长期建议落库 |
**推荐组合(工程上较稳)**
1. **首选****方案 B** — 第三方 **BFF****P0 与 P5 共用** `computeEffective``add/visitor` **始终传 `floorIds`**
2. **可选兜底****方案 C 或 D** 仅在 `floorIds` 为空时求交;登记页预览仍应调用**同一预览逻辑**(可部署在 BFF 或 D),避免「兜底路径」与「预览路径」算法分叉。
### 4.2 核心算法(推荐伪代码)
设:
- `hostFloors` = 组织 `detail` 返回的 `floorList`(可能为空)。
- `tenantAllow` = 租户配置的允许访客楼层 `zoneId` 集合。
- `requested` = 调用方传入的 `floorIds`(可能为空)。
```
if requested 非空:
effective = requested // 默认信任;高敏合同可改为 requested ∩ tenantAllow ∩ hostFloors
else:
effective = tenantAllow ∩ hostFloors // 或 policy=HOST 时 tenantAllow 视为全集
if effective 为空:
返回业务错误(勿继续 zone page / insert
```
**电梯 `addVisitor` 当前风险点**:补全后未校验空列表即使用 `floorIds.get(0)`。无论采用何种产品方案,**建议在生效列表计算完成后统一做空集校验**,与 [UC-04](访客注册与派梯楼层业务流程走查.md) 治理合并。
### 4.3 数据模型草案(租户策略落库)
```sql
CREATE TABLE tenant_visitor_floor_policy (
id VARCHAR(32) PRIMARY KEY,
business_id VARCHAR(64) NOT NULL COMMENT '机构/租户 ID',
policy_type VARCHAR(32) NOT NULL,
allow_zone_ids TEXT COMMENT 'JSON 数组 zoneId',
building_id VARCHAR(64) COMMENT '可选',
enabled TINYINT(1) NOT NULL DEFAULT 1,
policy_version BIGINT NOT NULL DEFAULT 1 COMMENT '每次更新+1,供登记快照引用',
remark VARCHAR(256),
created_by VARCHAR(64),
created_at BIGINT,
updated_by VARCHAR(64),
updated_at BIGINT,
UNIQUE KEY uk_biz_building (business_id, building_id)
);
```
**缓存**:按 `businessId` 缓存;更新策略时递增 `policy_version` 并使缓存失效。
### 4.4 管理 API 草案(REST
| 方法 | 路径 | 说明 |
|------|------|------|
| `GET` | `/admin/tenant/{businessId}/visitor-floor-policy` | 查询当前策略 |
| `PUT` | `/admin/tenant/{businessId}/visitor-floor-policy` | 全量更新;**递增** `policy_version` |
| `POST` | `/admin/tenant/{businessId}/visitor-floor-policy/preview` | body`hostPersonId`;返回与登记页同源结构 |
### 4.5 电梯服务改造要点(若采用方案 C)
见前文;补充:**登记页预览若不走电梯**,则电梯内求交逻辑须与 BFF **算法对齐**(共享库或 OpenAPI 生成的客户端 stub 中携带版本号)。
### 4.6 「28 楼」与 zoneId 映射
- 空间:**`/sysetting/zone/tree`**、**`/sysetting/zone/page`**(走查 §3.2)。
- 台账:`businessId``buildingId``display_name``zoneId`、生效日期。
### 4.7 兼容性与集成契约
| 项目 | 建议 |
|------|------|
| **与 UC-02** | 集成合同写明:`floorIds` 非空是否二次求交。 |
| **幂等** | 审批消息带 `draft_id` + `effective_hash`P5 去重。 |
| **版本** | 请求带 `policyVersion`,与快照比对可告警。 |
---
## 5. 安全与合规
1. **权限上界**:访客生效楼层 ⊆ 被访人 **`floorList`**。
2. **禁止静默降级**:交集为空则失败并记录。
3. **审计**:策略变更、预览请求、开通请求(可采样)。
4. **数据隔离**:所有查询带 `businessId`
---
## 6. 多租户「默认访客楼层」实现路径综合评估
在已具备 **§2 闭环**(登记页初始化 → 快照 → 审批 → `add/visitor`)的前提下,对各实现路径按维度打分(**高 / 中 / 低** 为实施与维护成本或风险的主观分级,供选型会使用)。
### 6.1 评估维度说明
| 维度 | 含义 |
|------|------|
| **登记页契合** | 能否自然地在 **P0** 提供准确预览、少调接口。 |
| **闭环一致性** | 单源计算、快照、防 TOCTOU 是否易实现。 |
| **新租户成本** | 新开租户时配置、实施、回归工作量。 |
| **入侵性** | 对电梯/组织/第三方存量改动的范围。 |
| **绕过风险** | 存在不经过 BFF 直连电梯时是否仍安全。 |
### 6.2 综合对比表
| 路径 | 登记页契合 | 闭环一致性 | 新租户成本 | 入侵性 | 绕过风险 | 结论 |
|------|------------|------------|------------|--------|----------|------|
| **B:第三方 BFF + 显式 `floorIds`** | **高**BFF 聚合 detail+策略+zone | **高**(同函数+快照) | **低**(插策略行 + 空间台账) | **低**(电梯可不改) | **中**(依赖网关禁止直连) | **首推** |
| **Dintelligent 预览 + 转发** | **高** | **高**(预览与转发同模块) | **中**(需发布 intelligent | **中** | **中** | 适合已统一走 intelligent 的客户 |
| **C:仅电梯兜底** | **低**(预览仍需别处算,否则与 UI 不一致) | **中**(易双算法) | **低** | **高** | **低** | 作**兜底**,不宜单独承担预览 |
| **A:仅组织改 `floorList`** | **中** | **中**(与员工权限耦合) | **高**(组织数据治理难) | **高** | **低** | 仅当组织域已区分访客继承列时考虑 |
| **B + C** | **高** | **高** | **低** | **中** | **低** | **大型项目推荐**B 主路径 + C 防直连漏传 |
### 6.3 新租户接入检查清单(SOP)
1. 在空间服务确认 **`zoneId`** 与接待层名称。
2. 在租户策略表插入 **`business_id` + `INTERSECT_ALLOWLIST` + allow_zone_ids**(或走管理端保存)。
3. 第三方 BFF 配置 **Nexus/网关** 指向组织与空间。
4. 跑通 **P0 预览****P5 add/visitor** 自动化用例(覆盖 AC-1~AC-7)。
5. 培训租户管理员:**改策略会影响后续新单**;进行中单据策略见 §2.7。
---
## 7. 实施路线(建议阶段)
| 阶段 | 内容 | 产出 |
|------|------|------|
| **0** | 盘点所有 `add/visitor` 入口;登记页是否已有 `detail` 调用 | 调用方与数据项缺口表 |
| **1** | 定稿:§2.3 数据项表 + §2.7 策略变更策略 + AC-6/7 | PRD、接口契约 |
| **2** | 实现 BFF 聚合初始化 + 登记快照 + P5 显式 `floorIds` | 广发基金类租户上线 |
| **3** | 可选:电梯空列表校验 + C/D 兜底 + 监控 | 零 NPE、直连防护 |
---
## 8. 测试用例矩阵(摘录)
| ID | 阶段 | 条件 | 期望 |
|----|------|------|------|
| T0 | P0 | 被访人无 `floorList` | 预览失败,禁止提交 |
| T1 | P0→P5 | INTERSECT,有交集 | 预览与开通均为交集 |
| T6 | P0→P5 | 审批期间策略变更 + 冻结快照 | 开通结果与提交时预览一致 |
| T7 | P0 | 仅前端改楼层展示 | 服务端拒绝或覆盖(AC-7) |
(原 T1~T5 矩阵仍适用于纯开通层逻辑,可与上表合并维护。)
---
## 9. 文档版本与维护
| 项目 | 内容 |
|------|------|
| 输出路径 | `docs/business/租户访客默认楼层技术产品方案.md` |
| 依据代码 | `maven-cw-elevator-application``maven-intelligent-cwoscomponent`;闭环 P4 依赖组织访客 API(仓外) |
| 修订触发 | 登记页字段增减;`person/detail` 字段变更;`add/visitor` 契约变更 |
---
*本文档为方案级输出;组织人员检索、访客建档等接口以实际部署与网关路由为准。表结构与路径在实施前需经安全评审。*
@@ -0,0 +1,323 @@
# 访客注册与派梯楼层:完整业务流程走查
> **范围说明**:本文基于当前反编译工作区内的源码(`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.*` 为准。*
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
将 cw-elevator-application-V1.0.0.20211103/lib 下全部 JAR 作为初始构件上传到 Nexus。
脚本位置:docs/operations/deploy_cw_elevator_v1_lib_to_nexus.py(与文档同目录,便于运维查找)。
规则:
1. 若 JAR 内含 META-INF/maven/**/pom.properties,则使用其中的 groupId / artifactId / version。
2. 否则使用后备坐标:cn.cloudwalk.elevator.v1.bootlib:<文件名去 .jar>:V1.0.0.20211103
(保证与 Maven Central 坐标不冲突,且一文件一构件。)
version 含 SNAPSHOT 时上传到 maven-snapshots,否则 maven-releases。
需 ~/.m2/settings.xml 中配置 server idnexus-releases、nexus-snapshots(与 URL 对应)。
"""
from __future__ import annotations
import argparse
import os
import subprocess
import sys
import zipfile
from pathlib import Path
DEFAULT_LIB = Path(
"/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译"
"/cw-elevator-application-V1.0.0.20211103/lib"
)
RELEASES_URL = "http://192.168.3.12:8081/repository/maven-releases/"
SNAPSHOTS_URL = "http://192.168.3.12:8081/repository/maven-snapshots/"
RELEASES_ID = "nexus-releases"
SNAPSHOTS_ID = "nexus-snapshots"
FALLBACK_GROUP = "cn.cloudwalk.elevator.v1.bootlib"
FALLBACK_VERSION = "V1.0.0.20211103"
def read_maven_coords(jar: Path) -> tuple[str, str, str] | None:
try:
with zipfile.ZipFile(jar, "r") as zf:
for name in zf.namelist():
if name.endswith("pom.properties") and "META-INF/maven" in name.replace(
"\\", "/"
):
raw = zf.read(name).decode("utf-8", errors="replace")
props: dict[str, str] = {}
for line in raw.splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, _, v = line.partition("=")
props[k.strip()] = v.strip()
gid = props.get("groupId")
aid = props.get("artifactId")
ver = props.get("version")
if gid and aid and ver:
return gid, aid, ver
except (zipfile.BadZipFile, OSError):
return None
return None
def fallback_coords(jar: Path) -> tuple[str, str, str]:
stem = jar.name[:-4] if jar.name.lower().endswith(".jar") else jar.name
return FALLBACK_GROUP, stem, FALLBACK_VERSION
def is_snapshot_version(version: str) -> bool:
return "SNAPSHOT" in version.upper()
def deploy_one(
jar: Path,
group_id: str,
artifact_id: str,
version: str,
dry_run: bool,
) -> int:
url = SNAPSHOTS_URL if is_snapshot_version(version) else RELEASES_URL
rid = SNAPSHOTS_ID if is_snapshot_version(version) else RELEASES_ID
cmd = [
"mvn",
"-q",
"deploy:deploy-file",
f"-DrepositoryId={rid}",
f"-Durl={url}",
f"-Dfile={jar}",
f"-DgroupId={group_id}",
f"-DartifactId={artifact_id}",
f"-Dversion={version}",
"-Dpackaging=jar",
"-DgeneratePom=true",
]
if dry_run:
print("DRY-RUN:", " ".join(cmd))
return 0
r = subprocess.run(cmd, capture_output=True, text=True)
if r.returncode != 0:
combined = (r.stdout or "") + (r.stderr or "")
# Nexus maven-releases 对已存在 release 坐标禁止覆盖
if "cannot be updated" in combined:
print(f"SKIP (already in repo): {jar.name} -> {group_id}:{artifact_id}:{version}")
return 0
sys.stderr.write(f"FAIL {jar.name} -> {group_id}:{artifact_id}:{version}\n")
if r.stdout:
sys.stderr.write(r.stdout)
if r.stderr:
sys.stderr.write(r.stderr)
return r.returncode
def main() -> int:
p = argparse.ArgumentParser(description="Deploy all JARs from elevator V1 lib to Nexus.")
p.add_argument(
"--lib",
type=Path,
default=DEFAULT_LIB,
help="Directory containing .jar files",
)
p.add_argument("--dry-run", action="store_true", help="Print mvn commands only")
args = p.parse_args()
lib: Path = args.lib
if not lib.is_dir():
print("Not a directory:", lib, file=sys.stderr)
return 2
jars = sorted(lib.glob("*.jar"))
if not jars:
print("No JAR files in", lib, file=sys.stderr)
return 2
ok, fail = 0, 0
for i, jar in enumerate(jars, 1):
coords = read_maven_coords(jar)
if coords:
gid, aid, ver = coords
src = "embedded"
else:
gid, aid, ver = fallback_coords(jar)
src = "fallback"
print(f"[{i}/{len(jars)}] {jar.name} -> {gid}:{aid}:{ver} ({src})")
rc = deploy_one(jar, gid, aid, ver, args.dry_run)
if rc == 0:
ok += 1
else:
fail += 1
print(f"Done. ok={ok} fail={fail}")
return 0 if fail == 0 else 1
if __name__ == "__main__":
sys.exit(main())
+603
View File
@@ -0,0 +1,603 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="P3C-CodeStyle" version="13">
<!--可变参数的... Idea没有对应的配置项,强制insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<!--枚举值之间 Idea没有对应的配置项,强制insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=Java:SPACE_BEFORE_COMMA-->
<!--org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=Java:SPACE_BEFORE_COMMA
由于IDEA只有一个SPACE_BEFORE_COMMA选项,所以统一设置 insert_space_before_comma 为 do not insert
-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations"
value="do not insert"/>
<!--insert_space_before_comma end-->
<!--org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=Java:SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<!--IDEA只有一个配置项SPACE_AFTER_COMMAinsert_space_after_comma*统一设置成insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<!--insert_space_after_comma end-->
<!--org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=Java:SPACE_BEFORE_COLON-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=Java:SPACE_AFTER_COLON-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<!--IDEA不支持配置,默认do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<!--这个在Eclipse也没有找到配置的地方-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_semicolon=Java:SPACE_BEFORE_SEMICOLON
程序导入的时候强制将SPACE_BEFORE_SEMICOLON设置为false
-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<!--SPACE_AFTER_SEMICOLON=true-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<!--IDEA不支持配置,do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
value="do not insert"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
value="do not insert"/>
<!--IDEA不支持,使用默认-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<!--IDEA不支持配置,使用如下值,两者对应-->
<setting
id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
value="insert"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
value="do not insert"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
value="do not insert"/>
<!--Java:SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=Java:SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<!--IDEA使用了对应的配置:Java:SPACE_WITHIN_ARRAY_INITIALIZER_BRACES,但感觉不太好,IDEA默认不插入,Eclipse也使用不插入-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
value="do not insert"/>
<!--use default insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return"
value="insert"/>
<!--use default do not insert -->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<!--use default insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration"
value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw"
value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=Java:SPACE_BEFORE_SWITCH_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=Java:SPACE_BEFORE_CLASS_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration"
value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=Java:SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer"
value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=Java:SPACE_BEFORE_METHOD_LBRACE-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=Java:SPACE_AFTER_QUEST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=Java:SPACE_BEFORE_QUEST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=Java:SPACE_BEFORE_ANOTATION_PARAMETER_LIST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation"
value="do not insert"/>
<!--use default do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference"
value="do not insert"/>
<!--下面两个对应IDEA中的一个配置Java:SPACE_AROUND_ASSIGNMENT_OPERATORS,使用insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=Java:SPACE_BEFORE_CATCH_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=Java:SPACE_BEFORE_METHOD_CALL_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=Java:SPACE_BEFORE_TRY_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<!--下面两个对应IDEA中的一个配置Java:SPACE_AROUND_UNARY_OPERATOR,使用do not insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=Java:SPACE_BEFORE_IF_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=Java:SPACE_BEFORE_WHILE_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=Java:SPACE_AFTER_TYPE_CAST-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=Java:SPACE_BEFORE_METHOD_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=Java:SPACE_BEFORE_FOR_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=Java:SPACE_BEFORE_SYNCHRONIZED_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<!--org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=Java:SPACE_BEFORE_SWITCH_PARENTHESES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<!--下面两个对应IDEA中的一个配置Java:SPACE_AROUND_LAMBDA_ARROW,使用insert-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<!--SPACE_WITHIN_EMPTY_ARRAY_INITIALIZER_BRACES-->
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer"
value="do not insert"/>
<!--Idea -> Wrapping And Braces -> Simple classes in one line -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
<!--Idea -> Wrapping And Braces -> Simple method in one line -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
<!--因为Idea不支持配置,所以设置为 Idea默认值-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant"
value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="insert"/>
<!--Idea可以通过Wrap Always实现 TODO-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<!--Idea -> Wrapping And Braces -> Simple block in one line -> do not select -->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<!--Idea -> Wrapping And Braces -> try statement -> catch.... (Java:CATCH_ON_NEW_LINE)-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=Java:ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer"
value="do not insert"/>
<!--#org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=Java:ELSE_ON_NEW_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=Java:WHILE_ON_NEW_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement"
value="do not insert"/>
<!--org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=Java:FINALLY_ON_NEW_LINE-->
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement"
value="do not insert"/>
<!--comment start-->
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
<!--ENABLE_JAVADOC_FORMATTING-->
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<!--org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<!--IDEA无对应设置,所以关闭对block comment的格式化 -->
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<!--org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=Java:KEEP_FIRST_COLUMN_COMMENT-->
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<!--org.eclipse.jdt.core.formatter.use_on_off_tags=FORMATTER_TAGS_ENABLED-->
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<!--org.eclipse.jdt.core.formatter.disabling_tag=FORMATTER_OFF_TAG-->
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<!--org.eclipse.jdt.core.formatter.enabling_tag=FORMATTER_ON_TAG-->
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<!--下面的没有IDEA对应项,在代码里面对IDEA中使用默认值即可,LINE_COMMENT_AT_FIRST_COLUMN BLOCK_COMMENT_AT_FIRST_COLUMN设置为false-->
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments"
value="false"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<!--和IDEA保持一致,注释换行-->
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<!--comment end-->
<!--org.eclipse.jdt.core.formatter.blank_lines_after_imports=Java:BLANK_LINES_AFTER_IMPORTS-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_imports=Java:BLANK_LINES_BEFORE_IMPORTS-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_after_package=Java:BLANK_LINES_AFTER_PACKAGE-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=Java:BLANK_LINES_AROUND_CLASS-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<!--org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=Java:BLANK_LINES_BEFORE_METHOD_BODY-->
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_field=Java:BLANK_LINES_AROUND_FIELD-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_method=Java:BLANK_LINES_AROUND_METHOD-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<!--org.eclipse.jdt.core.formatter.blank_lines_before_package=Java:BLANK_LINES_BEFORE_PACKAGE-->
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<!--下面IDEA没有对应设置,使用对应值即可-->
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<!--org.eclipse.jdt.core.formatter.indentation.size=Java:IndentOptions:INDENT_SIZE-->
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<!--org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/>
<!--org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<!--org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=Java:IndentOptions:SMART_TABS-->
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<!--org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=Java:INDENT_CASE_FROM_SWITCH-->
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<!--KEEP_INDENTS_ON_EMPTY_LINES-->
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<!--org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<!--Java:IndentOptions:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<!--下面IDEA没有对应设置,使用对应值即可-->
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header"
value="true"/>
<!--Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<!--下面没有对应的IDEA设置,Eclipse先使用对应值-->
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression"
value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="16"/>
<!--IDEA默认配置在同一行,Eclipse使用对应值即可-->
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration"
value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<!--Java:BINARY_OPERATION_SIGN_ON_NEXT_LINE-->
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<!--ASSIGNMENT_WRAP 需要设置为 WRAP_AS_NEEDED WRAP_AS_NEEDED . Add in jdt.core-3.12it's not work in previous version -->
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<!--IDEA无配置项,Eclipse使用对应值即可-->
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<!--org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=Java:KEEP_CONTROL_STATEMENT_IN_ONE_LINE-->
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<!--org.eclipse.jdt.core.formatter.compact_else_if=Java:SPECIAL_ELSE_IF_TREATMENT-->
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<!--Java:ALIGN_GROUP_FIELD_DECLARATIONS-->
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<!--Java:<Programmatic>-->
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<!--统一为end_of_lintIDEA默认一致-->
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration"
value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<!-- <setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
-->
<!--Java:KEEP_SIMPLE_BLOCKS_IN_ONE_LINE-->
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<!--Java:CLASS_BRACE_STYLE,统一使用end_of_line TODO-->
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<!--org.eclipse.jdt.core.formatter.lineSplit=RIGHT_MARGIN-->
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
</profile>
</profiles>