### 本次重点重构内容

1. 底层存储数据库切换为mysql
2. 对信息点编码进行调整，整体使用驼峰命名
3. 调整存储方式和分库分表方案，数据字典部分调整为平台字典单独一个库，集团数据和项目数据按集团进行分库，物理世界部分按集团进行分库，按项目进行分表
4. 枚举型信息点修改为引用数据标准化定义的数据
5. 提供可行的数据迁移方案

### 数据模型

------

1. 类型定义，用于描述现实世界的对象的分类，如空间、新风机等
2. 信息点定义，用于描述类型的属性
3. 对象数据，即类型定义的实例，表示现实世界中的一个具体的物体，比如一个具体的房间，一个具体的空调
4. 图类型，用于描述对象之间的关系的分类
5. 边类型，对图类型的补充说明
6. 关系数据，描述具体的关系，比如某个空调位于某个空间
7. 平台字典，系统内置的一组类型定义和信息点定义数据，与集团和项目无关
8. 集团变更，基于集团对平台字典的扩充和自定义，比如新增类型、新增信息点、修改信息点，集团变更需要审核，审核通过后才会生效，同时对其他集团不可见
9. 集团字典，是平台字典和通过审核的集团变更的数据的并集
10. 集团方案，根据业态不同，从集团字典中筛选（订阅）特定的类型和信息点形成方案，从而过滤掉实际业务中不关注的类型和信息点，集团方案是集团字典的子集，集团所拥有的项目必须应用一个且仅有一个集团方案
11. 项目变更，基于项目对平台字典的扩充和自定义，比如新增信息点、修改信息点，同样需要审核，审核通过后才会生效，同时对其他项目不可见
12. 项目字典，集团方案和项目变更的并集
13. 应用订阅，根据应用关注点不同，从项目字典中筛选（订阅）特定的类型和信息点，从而过滤掉应用不关注的类型和信息点，每个应用对每个项目都需要进行订阅配置

### 业务说明

------

1. 站在用户或数据字典使用方的角度来看数据字典有三层:平台级字典,集团级字典,项目级字典

2. 类型相同或信息点相同时（编码相同）项目级字典优先级最高,集团级次之,平台级字典最低,优先级高的会覆盖优先级低的

3. 使用数据字典时明确"使用的字典位于哪个层级"对需求的分析和理解会有很大帮助

4. 集团级数据、集团方案、项目级数据是数据字典内部逻辑概念，项目实际使用过程中应该不会用到这些概念

5. 应用和服务应该关注的是项目级字典和应用订阅内容

6. 对集团变更和项目变更的数据应该定时进行汇总分析，暂定线下人工处理

7. 默认每个类型都有id、name、localId、localName、objType、classCode、projectId，无需订阅，也不能取消订阅

8. 

   

### 字段约定

| 字段      | 说明                          | 备注 |
| --------- | ----------------------------- | ---- |
| class     | 类型                          |      |
| funcid    | 信息点                        |      |
| classCode | 类型定义的code: class.code    |      |
| className | 类型定义的name: class.name    |      |
| infoCode  | 信息点定义的code: funcid.code |      |
| infoName  | 信息点定义的name: funcid.name |      |
| groupCode | 集团编码                      |      |
| projectId | 项目ID                        |      |
| schemeId  | 集团方案ID                    |      |
|           |                               |      |
|           |                               |      |

### 数据结构

类型 class

| 字段       | 数据类型 | 说明                                                       |
| ---------- | -------- | ---------------------------------------------------------- |
| code       | String   | 全局唯一                                                   |
| name       | String   | 类型名称                                                   |
| aliasCode  | String   | 类型别名编码, 集团下唯一                                   |
| aliasName  | String   | 类型别名名称                                               |
| type       | String   | 类别:平台级common,集团级group,项目级project                |
| groupId    | String   | 集团id, type=group或type=project时该字段为集团id,否则为"0" |
| projectId  | String   | 集团id, type=project时该字段为项目id,否则为"0"             |
| majorCode  | String   | 专业编码, 上级类型是系统or设备时该字段有值                 |
| systemCode | String   | 系统编码,上级类型是设备时该字段有值,值为系统类型的code     |
| parentCode | String   | 上级类型code                                               |
|            |          |                                                            |

信息点 funcid

| 字段       | 数据类型          | 说明                                                         |
| ---------- | ----------------- | ------------------------------------------------------------ |
| code       | String            | 信息点编码,同类型下唯一                                      |
| name       | String            | 信息点名称                                                   |
| classCode  | String            | 类型编码                                                     |
| type       | String            | 字典级别:平台级common,集团级group,项目级project              |
| category   | String            | 信息点分类:静态,脉冲,阶段,时序                               |
| groupId    | String            | 集团id, type=group或type=project时该字段为集团id,否则为"0"   |
| projectId  | String            | 集团id, type=project时该字段为项目id,否则为"0"               |
| firstTag   | String            | 一级标签                                                     |
| secondTag  | String            | 二级标签                                                     |
| priority   | String            | 优先级                                                       |
| inputMode  | String            | 输入方式                                                     |
| unit       | String            | 单位                                                         |
| dataType   | String            | 数据类型                                                     |
| isMultiple | Boolean           | 是否复数                                                     |
| isRegion   | Boolean           | 是否区间                                                     |
| formater   | String            | 数据格式                                                     |
| dataSource | String / Object[] | 数据源取值范围/枚举值清单等,根据dataType有不同的内容         |
| note       | String            | 备注                                                         |
| subFlag    | String            | 子分类标记:是否可以按此信息点进行子分类替换,同一类型下目前只支持一个子分类信息点 |

对象 object

| 字段           | 数据类型       | 说明               |
| -------------- | -------------- | ------------------ |
| id             | String         | id，全局唯一       |
| projectId      | String         | 项目id，不可为空   |
| classCode      | String         | 类型code，不可为空 |
| 其他信息点编码 | 根据信息点定义 |                    |
|                |                |                    |

关系 relation

| 字段    | 数据类型 | 说明         |
| ------- | -------- | ------------ |
| graphId | String   | 图实例id     |
| rel     | String   | 边类型       |
| from    | String   | 对象id       |
| to      | String   | 对象id       |
| infos   | Object   | 关系附加信息 |



### 信息点数据类型

| 数据类型   | 类型名称 | 信息点分类          | 是否复数   | 是否区间   | 数据源                           | 格式   |
| ---------- | -------- | ------------------- | ---------- | ---------- | -------------------------------- | ------ |
| INTEGER    | 整数     | 静态/脉冲/时序/阶段 | true/false | true/false | {$gt:10, $lt:50}                 | 无     |
| DOUBLE     | 浮点型   | 静态/脉冲/时序/阶段 | true/false | true/false | {$gte:10.1, $lt:50.9}            | 无     |
| BOOLEAN    | 布尔值   | 静态/脉冲/时序/阶段 | true/false | false      |                                  | 无     |
| STRING     | 字符串   | 静态/脉冲/时序/阶段 | true/false | false      | (字符串长度区间){$gt:10, $lt:50} | 无     |
| DATETIME   | 日期时间 | 静态/脉冲/时序/阶段 | true/false | true/false | {'$gt':'0915', '$lt':'1031'}     | 'MMdd' |
| ENUM       | 单选枚举 | 静态/脉冲/时序/阶段 | true/false | false      | 应用数据标准化中定义的数据类型   | 无     |
| MENUM      | 多选枚举 | 静态/脉冲/时序/阶段 | true/false | false      | 应用数据标准化中定义的数据类型   | 无     |
| ATTACHMENT | 附件     | 静态                | true/false | false      |                                  | pdf    |
| OBJECT     | 对象     | 静态                | true/false | false      |                                  | 对象id |

说明

```
把原来的data_type拆解成多个属性,减少了data_type种类数量
使用新的数据类型时,使用新的数据类型时,创建或编辑信息点需要明确指出数据类型、动静分类、是否复数、是否区间、长度（可选）、取值区间（可选）、格式（可选）
Tree、Topology、Route、Function四种类型不再支持(有需求再加回来)

动静分类（静态 STATIC、脉冲 PULSE、时序 SEQUENTIAL、阶段 GRADATION）应该是信息点的一个分类，不是数据类型的属性，放在这里是为了更直观更容易理解
根据动静分类区分动态量或静态量,静态量的值存储的是具体的数据,动态量的值存储的是表号-功能号,动态量包括脉冲量、时序量和阶段量
根据是否区间来判断存储的值是具体值还是区间, 比如INTEGER非区间的值12, 区间值[8, 15],为了区分开闭区间,这里实际存储为{$gt: 12, $lte: 15}, 其中$gt大于,$lt小于,$gte大于等于,$lte小于等于
根据是否复数区分存储的值是单个值还是多个值,单个值存储形式为xxx,多个值存储形式为[xxx, yyy],如果同时是复数和区间,存储的是多个区间
取值区间可以约束值的取值范围,可以通过取值区间做一次校验,如果是区间值,区间也应该是在取值区间的内部
统一用DATETIME表示日期和时间,通过格式设定具体存储的内容,格式由数据字典进行维护,物理世界存储的数据严格符合格式
格式是数据存储的数据格式或文件格式,对于日期时间附件对象等可进行校验
单选枚举Enum单数存储为GC, 复数存储为[GC, JK]
多选枚举MEnum单数存储为[GC, JK], 复数存储为[[GC], [GC,JK]], 多选枚举单数和单选枚举复数的存储形式一样应该不会出现问题,因为实际使用时是和类型(Enum,Menum)一起使用,

```

### 接口清单

1. 查询类型定义
2. 查询信息点定义
3. 创建变更（集团变更、项目变更）
4. 查询变更
5. 修改变更
6. 提交变更（发起审核）
7. 创建集团方案
8. 集团方案订阅、取消订阅类型与信息点（批量）
9. 应用订阅、取消订阅类型与信息点（批量）
10. 保存对象（批量，创建、修改）
11. 删除对象（批量）
12. 创建关系（批量）
13. 删除关系（批量）
14. 根据关系查询对象
15. 根据对象和信息点查询实时数据（批量）
16. 根据对象、信息点、开始结束时间查询分精度数据（批量）
17. 发送控制指令（批量，异步，返回指令查询码）
18. 根据指令查询码查询执行结果（批量）

