初始化
parent
bea35b4088
commit
0d2516111b
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="测试环境" uuid="1a997504-607b-4542-9f26-c2818d8dd0a5">
|
||||
<driver-ref>mysql.8</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:mysql://nlb-kd2xz70qhllfet2koj.cn-beijing.nlb.aliyuncsslb.com:33068</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||
</jdbc-additional-properties>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
# ZCloud Java 项目公共开发规范与模板
|
||||
|
||||
> 本文件可复制到新项目直接使用。服务名、包名、网关前缀、领域边界和业务规则应写在项目自己的文档中,不要写入本公共模板。
|
||||
|
||||
## 1. DDD 分层
|
||||
|
||||
新项目统一采用 DDD 多模块结构,实际包名前缀、服务名和网关前缀由项目自行定义。
|
||||
|
||||
| 模块 | 职责 | 禁止事项 |
|
||||
| --- | --- | --- |
|
||||
| `web-client` | API、Cmd、Qry、Co | 依赖 App、Domain、Infrastructure |
|
||||
| `web-adapter` | Web/App/Socket Controller、Dubbo Facade 等入站适配 | 直接访问 Mapper、编写业务规则 |
|
||||
| `web-app` | Client 接口实现、执行器、用例编排、事务 | 堆积可复用领域规则、长事务调用远程服务 |
|
||||
| `web-domain` | 领域实体、值对象、领域服务、Gateway 接口 | 依赖 MyBatis、Dubbo、HTTP、外部 DTO |
|
||||
| `web-infrastructure` | Gateway 实现、Dubbo/HTTP 调用、DO、Mapper、Repository | 向 Domain 泄漏 DO 或外部 DTO |
|
||||
| `start` | 启动、配置、XXL-JOB 装配 | 编写业务逻辑 |
|
||||
|
||||
标准调用链:
|
||||
|
||||
```text
|
||||
Adapter -> Client接口(App实现) -> Executor -> Domain/Gateway -> Infrastructure
|
||||
```
|
||||
|
||||
公司文档允许执行器或 Adapter 直接调用基础设施能力;采用 DDD 分层的项目优先通过 Domain Gateway。纯协议转换且不进入领域用例的场景,Adapter 才可直接引用外部 Facade。
|
||||
|
||||
## 2. 命名与对象基类
|
||||
|
||||
| 类型 | 命名/基类 | 放置位置 |
|
||||
| --- | --- | --- |
|
||||
| 领域实体 | `XxxE` | `web-domain/model` |
|
||||
| 领域网关 | `XxxGateway` | `web-domain/gateway` |
|
||||
| 网关实现 | `XxxGatewayImpl` | `web-infrastructure/gatewayimpl` |
|
||||
| 持久化对象 | `XxxDO extends BaseDO` | `persistence/dataobject` |
|
||||
| Mapper | `XxxMapper` | `persistence/mapper` |
|
||||
| 新增/修改命令 | `XxxAddCmd`、`XxxUpdateCmd extends Command` | `web-client` |
|
||||
| 分页查询 | `XxxPageQry extends BasePageQuery` | `web-client` |
|
||||
| 返回对象 | `XxxCo extends ClientObject` | `web-client` |
|
||||
| 执行器 | `XxxAddExe`、`XxxUpdateExe`、`XxxRemoveExe`、`XxxQueryExe` | `web-app` |
|
||||
|
||||
- Cmd、Qry、Co 和 Adapter 使用的服务接口统一定义在 `web-client`。
|
||||
- 不得直接返回 DO、领域实体或第三方 DTO。
|
||||
- 不得在 `persistence.dataobject` 和 `persistence.domainobject` 创建同名 DO;新增 DO 统一放 `dataobject`。
|
||||
|
||||
## 3. HTTP 接口模板
|
||||
|
||||
- 路径使用 `/{gateway-prefix}/{resource}`,其中网关前缀由具体项目确定。
|
||||
- GET、POST、PUT、DELETE 按资源语义使用。
|
||||
- Controller 只做参数接收、校验、权限控制和应用服务调用。
|
||||
- 新增、修改分别使用 AddCmd、UpdateCmd,配合 `@Validated` 和 Bean Validation。
|
||||
- Swagger 使用 `@Api`、`@ApiOperation`、`@ApiModelProperty`;Swagger 的 `required` 不能代替参数校验注解。
|
||||
- 当前用户通过 `AuthContext.getCurrentUser()` 获取,不信任前端传入的租户、单位、创建人等身份字段。
|
||||
|
||||
```java
|
||||
@ApiOperation("新增")
|
||||
@PostMapping("/save")
|
||||
@PreAuthorize("@pms.hasPermission('实际菜单或按钮权限编码')")
|
||||
public SingleResponse<XxxCo> add(@Validated @RequestBody XxxAddCmd cmd) {
|
||||
return xxxService.add(cmd);
|
||||
}
|
||||
```
|
||||
|
||||
接口权限编码必须取自实际菜单/按钮配置,禁止复制示例编码。
|
||||
|
||||
### 标准返回类
|
||||
|
||||
| 类型 | 场景 |
|
||||
| --- | --- |
|
||||
| `SingleResponse<T>` | 单条数据 |
|
||||
| `PageResponse<T>` | 分页数据 |
|
||||
| `MultiResponse<T>` | 集合数据 |
|
||||
| `Response` | 无返回数据 |
|
||||
|
||||
禁止新增另一套通用响应外壳。批量操作存在部分成功时,在标准响应承载的 Co 中返回逐条结果。
|
||||
|
||||
## 4. 数据权限模板
|
||||
|
||||
接口权限控制“能否调用”,数据权限控制“能看到哪些数据”,两者不能互相替代。
|
||||
|
||||
```java
|
||||
@Mapper
|
||||
@DataScopes({
|
||||
@DataScope(
|
||||
method = "selectOne",
|
||||
menuPerms = "实际菜单权限编码",
|
||||
tenantAlias = "tenant_id"
|
||||
)
|
||||
})
|
||||
public interface XxxMapper extends BaseMapper<XxxDO> {
|
||||
}
|
||||
```
|
||||
|
||||
- `method` 与实际 Mapper 方法名一致。
|
||||
- `menuPerms` 使用实际权限编码。
|
||||
- `tenantAlias` 与 SQL 中租户列或表别名一致;多表查询必须写明确表别名。
|
||||
- 定时任务和 Dubbo 等非登录态入口必须明确租户、单位、环境范围,禁止默认跨租户扫描。
|
||||
|
||||
## 5. App、Domain 与异常模板
|
||||
|
||||
- App 服务实现负责把 Client 请求分派到执行器。
|
||||
- 执行器负责参数转换、用例编排、事务和 Gateway 调用。
|
||||
- 可复用业务规则放入领域实体或领域服务。
|
||||
- 写操作使用 `@Transactional(rollbackFor = Exception.class)`。
|
||||
- 领域模型不得调用基础设施层、Mapper、Repository 实现或 Dubbo Facade。
|
||||
- 保存失败、业务校验失败及远程调用失败统一转换为项目 `BizException`。
|
||||
- 转换异常时保留原异常日志/异常链;错误信息不能泄露密钥、人脸、证件或完整敏感报文。
|
||||
|
||||
## 6. Dubbo 服务模板
|
||||
|
||||
Dubbo 公共契约统一维护在组织公共接口项目 `zcloud_gbs_common`。新项目使用公共仓库的实际发布版本,不在规范中固定开发机绝对路径。
|
||||
|
||||
Maven 坐标:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.zcloud.gbscommon</groupId>
|
||||
<artifactId>zcloud_gbscommon</artifactId>
|
||||
<version>${zcloud.gbscommon.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
使用已有 Dubbo 能力时,先在 Common 项目中查找对应 Facade、Request、Response,禁止在业务项目内重复定义同名公共契约。
|
||||
|
||||
### 发布服务
|
||||
|
||||
1. 在 Common 项目的 `src/main/java/com/zcloud/gbscommon/{业务域}` 定义公共契约:
|
||||
- `facade/XxxFacade`
|
||||
- `request/XxxQry`、`XxxCmd`
|
||||
- `response/XxxCo`
|
||||
2. 服务项目在 Adapter 实现 Facade,使用 `@DubboService` 发布。
|
||||
3. Facade 只做校验、协议转换和应用服务调用。
|
||||
4. 修改 Common 契约属于跨项目变更:字段和方法确认后再修改、发布约定版本,并在消费项目验证依赖更新;未经明确需求不得直接修改 Common 项目。
|
||||
|
||||
```java
|
||||
@DubboService
|
||||
public class XxxFacadeImpl implements XxxFacade {
|
||||
// 调用应用服务
|
||||
}
|
||||
```
|
||||
|
||||
### 调用服务
|
||||
|
||||
- 启动类增加 `@EnableFacadeRpcClient`。
|
||||
- 消费方使用公共契约,并通过 `@DubboReference(check = false)` 注入。
|
||||
- DDD 项目优先在 Infrastructure GatewayImpl 中调用 Facade 并转换外部 DTO。
|
||||
- `check = false` 只是不在启动时检查提供方,不代表可以忽略运行期失败。
|
||||
- 写接口自动重试可能造成重复业务,必须结合幂等性设置超时和重试策略。
|
||||
|
||||
```java
|
||||
@DubboReference(check = false)
|
||||
private XxxFacade xxxFacade;
|
||||
```
|
||||
|
||||
## 7. 用户、岗位、部门、企业翻译模板
|
||||
|
||||
按 ID 补充系统内公共信息时使用 `TranslateField`:
|
||||
|
||||
- 用户:`getZcloudUserInfoById(s)`
|
||||
- 岗位:`getZcloudPostInfoById(s)`
|
||||
- 部门:`getZcloudDpetInfoById(s)`
|
||||
- 企业:`getZcloudCorpInfoById(s)`
|
||||
- 对象/集合:`translateZcloudCommonInformation(data, XxxCo.class)`
|
||||
|
||||
列表必须使用 `ByIds` 或集合翻译,禁止循环逐条兑换造成 N+1 远程调用。
|
||||
|
||||
```java
|
||||
@ZCloudTranslates({
|
||||
@ZCloudTranslate(
|
||||
primaryKeyType = TranslateEunm.USER,
|
||||
primaryKey = "userId",
|
||||
mappedFields = {"userName:username"}
|
||||
),
|
||||
@ZCloudTranslate(
|
||||
primaryKeyType = TranslateEunm.POST,
|
||||
primaryKey = "postId",
|
||||
mappedFields = {"postName:name"}
|
||||
),
|
||||
@ZCloudTranslate(
|
||||
primaryKeyType = TranslateEunm.DEPT,
|
||||
primaryKey = "deptId",
|
||||
mappedFields = {"deptName:name"}
|
||||
),
|
||||
@ZCloudTranslate(
|
||||
primaryKeyType = TranslateEunm.CORP,
|
||||
primaryKey = "corpId",
|
||||
mappedFields = {"corpName:name"}
|
||||
)
|
||||
})
|
||||
public class XxxCo extends ClientObject {
|
||||
}
|
||||
```
|
||||
|
||||
- `primaryKeyType`:翻译类型。
|
||||
- `primaryKey`:当前类中的 ID 属性。
|
||||
- `mappedFields`:`当前类目标属性:common Co来源属性`。
|
||||
- 翻译结果用于展示补充;核心业务判断应显式查询并校验。
|
||||
|
||||
## 8. 分页和动态查询模板
|
||||
|
||||
- 分页 Qry 继承 `BasePageQuery`,返回 `PageResponse<T>`。
|
||||
- `toHashMap` 查询键使用“操作符前缀 + 驼峰字段”,基础设施层转换为下划线列名。
|
||||
|
||||
| 前缀 | SQL 条件 | 示例 |
|
||||
| --- | --- | --- |
|
||||
| `Like` | `LIKE` | `LikePersonName` |
|
||||
| `eq` | `=` | `eqTaskStatus` |
|
||||
| `gt` | `>` | `gtCreateTime` |
|
||||
| `lt` | `<` | `ltCreateTime` |
|
||||
| `le` | `<=` | `leCreateTime` |
|
||||
| `ge` | `>=` | `geCreateTime` |
|
||||
| `ne` | `<>` | `neTaskStatus` |
|
||||
|
||||
前缀大小写必须与公共 `toHashMap` 解析规则一致;新增条件前先核对公共组件,禁止自行拼接 SQL 运算符。
|
||||
|
||||
## 9. 数据库模板
|
||||
|
||||
所有新建业务表必须包含以下公共字段:
|
||||
|
||||
```sql
|
||||
`delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '删除标识true false',
|
||||
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
|
||||
`create_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人姓名',
|
||||
`update_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人姓名',
|
||||
`tenant_id` bigint DEFAULT NULL COMMENT '租户id',
|
||||
`org_id` bigint DEFAULT NULL COMMENT '单位id',
|
||||
`version` int DEFAULT NULL COMMENT '版本',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`create_id` bigint DEFAULT NULL COMMENT '创建人id',
|
||||
`update_id` bigint DEFAULT NULL COMMENT '修改人id',
|
||||
`env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识'
|
||||
```
|
||||
|
||||
- 表使用 InnoDB、`utf8mb4`、`utf8mb4_0900_ai_ci`。
|
||||
- `version` 是本地乐观锁版本,业务版本另设 `data_version`。
|
||||
- `delete_enum` 是本地逻辑删除,不等于业务 `DELETE/DISABLE/REVOKE/EXPIRE`。
|
||||
- 多租户业务索引考虑 `tenant_id`,共享环境同时考虑 `env`。
|
||||
- 任务号、幂等键、外部回执号等必须有唯一约束。
|
||||
- 状态扫描组合索引应覆盖状态、下次执行时间、优先级等实际条件。
|
||||
- 不配置跨服务语义的数据库物理外键。
|
||||
- DDL、DO、Mapper、XML 保持一致;变更表结构同步维护 DDL 和正式迁移脚本。
|
||||
- 大报文和敏感信息应加密或仅存脱敏快照,禁止写普通日志。
|
||||
|
||||
## 10. XXL-JOB 模板
|
||||
|
||||
- 生产定时任务统一使用 XXL-JOB,不新增仅依赖本地 `@Scheduled` 的任务。
|
||||
- Handler 使用唯一且稳定的 `@XxlJob` 名称。
|
||||
- Job 只读取调度参数、触发应用用例、返回结果;业务逻辑放在 App/Domain。
|
||||
- 通过任务号、唯一键或锁保证业务幂等。
|
||||
- 失败必须抛出或返回失败,让调度中心感知;禁止吞异常后返回成功。
|
||||
|
||||
```java
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class XxxJob {
|
||||
private final XxxApplicationService xxxApplicationService;
|
||||
|
||||
@XxlJob("projectXxxJob")
|
||||
public ReturnT<String> execute(String param) {
|
||||
xxxApplicationService.execute(param);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 11. 开发完成检查表
|
||||
|
||||
- [ ] Client、Adapter、App、Domain、Infrastructure 职责和依赖方向正确。
|
||||
- [ ] Cmd/Co/PageQry 分别继承 `Command`、`ClientObject`、`BasePageQuery`。
|
||||
- [ ] Controller 无 Mapper 调用和业务规则,返回标准 Response 类型。
|
||||
- [ ] 接口配置真实 `@PreAuthorize` 权限编码,查询配置正确 `@DataScopes`。
|
||||
- [ ] Dubbo 契约来自 `zcloud_gbs_common`,提供方使用 `@DubboService`,消费方启用 RPC Client。
|
||||
- [ ] 外部调用完成 DTO 防腐转换、超时、异常和幂等处理。
|
||||
- [ ] 公共信息使用批量翻译,`mappedFields` 方向正确。
|
||||
- [ ] 写操作事务和 `BizException` 处理正确,不存在远程长事务。
|
||||
- [ ] DDL、DO、Mapper、XML、公共字段和索引一致。
|
||||
- [ ] XXL-JOB 名称唯一,任务幂等,失败可被调度中心感知。
|
||||
- [ ] 日志和响应未泄露人脸、证件、文件、密钥或完整敏感报文。
|
||||
- [ ] 完成与改动风险匹配的 Maven 编译、测试和 `git diff` 检查。
|
||||
|
|
@ -2,7 +2,7 @@ nacos:
|
|||
url: prod-nacos:8848
|
||||
namespace: jjb-dragon
|
||||
application:
|
||||
name: jjb-saas-zcloud-edgeguard
|
||||
name: zcloud_gbs_edgeguard
|
||||
version:
|
||||
gateway: edgeguard
|
||||
cn-name: 边缘人脸区域安全
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ nacos:
|
|||
url: 192.168.20.100:30290
|
||||
namespace: jjb-dragon
|
||||
application:
|
||||
name: jjb-saas-zcloud-edgeguard
|
||||
name: zcloud_gbs_edgeguard
|
||||
version:
|
||||
gateway: edgeguard
|
||||
cn-name: 边缘人脸区域安全
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
sdk:
|
||||
server:
|
||||
app-key: 722091ff53dd4abba078c2a00efd4a42
|
||||
app-key: 99626aa02f274e43be0f8acbe6f625f8
|
||||
client:
|
||||
gateway:
|
||||
url: ${common.gateway.network.http.external}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
sdk:
|
||||
server:
|
||||
app-key: 722091ff53dd4abba078c2a00efd4a42
|
||||
app-key: 99626aa02f274e43be0f8acbe6f625f8
|
||||
client:
|
||||
gateway:
|
||||
url: ${common.gateway.network.http.external}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.gateway;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.model.AlarmDisposalE;
|
||||
|
||||
public interface AlarmDisposalGateway {
|
||||
Boolean add(AlarmDisposalE disposal);
|
||||
Boolean update(AlarmDisposalE disposal);
|
||||
AlarmDisposalE getById(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.gateway;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.model.AlarmE;
|
||||
|
||||
public interface AlarmGateway {
|
||||
Boolean add(AlarmE alarm);
|
||||
Boolean update(AlarmE alarm);
|
||||
AlarmE getById(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.gateway;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
|
||||
|
||||
public interface RegionCameraGateway {
|
||||
Boolean add(RegionCameraE regionCamera);
|
||||
Boolean update(RegionCameraE regionCamera);
|
||||
Boolean deleteById(Long id);
|
||||
RegionCameraE getById(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.gateway;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
|
||||
|
||||
public interface RegionGateway {
|
||||
Boolean add(RegionE region);
|
||||
Boolean update(RegionE region);
|
||||
Boolean deleteById(Long id);
|
||||
RegionE getById(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.model;
|
||||
|
||||
import com.alibaba.cola.domain.Entity;
|
||||
import com.jjb.saas.framework.domain.model.BaseE;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/** 报警处置结论领域模型。 */
|
||||
@Data
|
||||
@Entity
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class AlarmDisposalE extends BaseE {
|
||||
private Long id;
|
||||
private Long alarmId;
|
||||
private Integer isFalseAlarm;
|
||||
private Integer isHiddenHazard;
|
||||
private String disposalResultCode;
|
||||
private String disposalResultName;
|
||||
private String disposalDescription;
|
||||
private String hiddenId;
|
||||
private String hiddenCreateStatus;
|
||||
private String hiddenCreateError;
|
||||
private Long handlerUserId;
|
||||
private String handlerUserName;
|
||||
private Long handlerDeptId;
|
||||
private String handlerDeptName;
|
||||
private Date disposedTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.model;
|
||||
|
||||
import com.alibaba.cola.domain.Entity;
|
||||
import com.jjb.saas.framework.domain.model.BaseE;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/** 第三方报警领域模型。 */
|
||||
@Data
|
||||
@Entity
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class AlarmE extends BaseE {
|
||||
private Long id;
|
||||
private String alarmNo;
|
||||
private String sourceSystem;
|
||||
private Date alarmTime;
|
||||
private Date receivedTime;
|
||||
private String alarmAddress;
|
||||
private Long corpId;
|
||||
private String corpNameSnapshot;
|
||||
private Long regionId;
|
||||
private String regionCode;
|
||||
private String regionNameSnapshot;
|
||||
private String regionPathSnapshot;
|
||||
private String cameraSource;
|
||||
private String cameraId;
|
||||
private String cameraNameSnapshot;
|
||||
private String alarmImageUrl;
|
||||
private String disposalStatus;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.model;
|
||||
|
||||
import com.alibaba.cola.domain.Entity;
|
||||
import com.jjb.saas.framework.domain.model.BaseE;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/** 区域与第三方摄像头绑定领域模型。 */
|
||||
@Data
|
||||
@Entity
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RegionCameraE extends BaseE {
|
||||
private Long id;
|
||||
private Long regionId;
|
||||
private Long corpId;
|
||||
private String cameraSource;
|
||||
private String cameraId;
|
||||
private String cameraName;
|
||||
private String cameraUnitId;
|
||||
private String cameraUnitName;
|
||||
private String cameraTypeCode;
|
||||
private String cameraTypeName;
|
||||
private String cameraLevelCode;
|
||||
private String cameraLevelName;
|
||||
private String cameraDeptId;
|
||||
private String cameraDeptName;
|
||||
private String onlineStatus;
|
||||
private String cameraSnapshot;
|
||||
private Date cameraSyncedAt;
|
||||
private Long leaderUserId;
|
||||
private String bindStatus;
|
||||
private Date boundTime;
|
||||
private Date unboundTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.zcloud.gbs.edgeguard.domain.model;
|
||||
|
||||
import com.alibaba.cola.domain.Entity;
|
||||
import com.jjb.saas.framework.domain.model.BaseE;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/** 区域领域模型。 */
|
||||
@Data
|
||||
@Entity
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RegionE extends BaseE {
|
||||
private Long id;
|
||||
private String regionCode;
|
||||
private String regionName;
|
||||
private Long corpId;
|
||||
private Long parentId;
|
||||
private String treePath;
|
||||
private Integer treeLevel;
|
||||
private Integer sortNo;
|
||||
private Long leaderUserId;
|
||||
private String coordinateSystem;
|
||||
/** 四个有序坐标点的 JSON 数组。 */
|
||||
private String fencePoints;
|
||||
private String regionStatus;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.zcloud.gbs.edgeguard.gatewayimpl;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.gateway.AlarmDisposalGateway;
|
||||
import com.zcloud.gbs.edgeguard.domain.model.AlarmDisposalE;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDisposalDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.AlarmDisposalRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlarmDisposalGatewayImpl implements AlarmDisposalGateway {
|
||||
private final AlarmDisposalRepository repository;
|
||||
|
||||
@Override
|
||||
public Boolean add(AlarmDisposalE disposal) {
|
||||
return repository.save(toDO(disposal));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(AlarmDisposalE disposal) {
|
||||
return repository.updateById(toDO(disposal));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlarmDisposalE getById(Long id) {
|
||||
return toEntity(repository.getById(id));
|
||||
}
|
||||
|
||||
private AlarmDisposalDO toDO(AlarmDisposalE source) {
|
||||
AlarmDisposalDO target = new AlarmDisposalDO();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
private AlarmDisposalE toEntity(AlarmDisposalDO source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
AlarmDisposalE target = new AlarmDisposalE();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.zcloud.gbs.edgeguard.gatewayimpl;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.gateway.AlarmGateway;
|
||||
import com.zcloud.gbs.edgeguard.domain.model.AlarmE;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.AlarmRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlarmGatewayImpl implements AlarmGateway {
|
||||
private final AlarmRepository repository;
|
||||
|
||||
@Override
|
||||
public Boolean add(AlarmE alarm) {
|
||||
return repository.save(toDO(alarm));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(AlarmE alarm) {
|
||||
return repository.updateById(toDO(alarm));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlarmE getById(Long id) {
|
||||
return toEntity(repository.getById(id));
|
||||
}
|
||||
|
||||
private AlarmDO toDO(AlarmE source) {
|
||||
AlarmDO target = new AlarmDO();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
private AlarmE toEntity(AlarmDO source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
AlarmE target = new AlarmE();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.zcloud.gbs.edgeguard.gatewayimpl;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
|
||||
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionCameraDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.RegionCameraRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RegionCameraGatewayImpl implements RegionCameraGateway {
|
||||
private final RegionCameraRepository repository;
|
||||
|
||||
@Override
|
||||
public Boolean add(RegionCameraE regionCamera) {
|
||||
return repository.save(toDO(regionCamera));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(RegionCameraE regionCamera) {
|
||||
return repository.updateById(toDO(regionCamera));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteById(Long id) {
|
||||
return repository.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionCameraE getById(Long id) {
|
||||
return toEntity(repository.getById(id));
|
||||
}
|
||||
|
||||
private RegionCameraDO toDO(RegionCameraE source) {
|
||||
RegionCameraDO target = new RegionCameraDO();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
private RegionCameraE toEntity(RegionCameraDO source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
RegionCameraE target = new RegionCameraE();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.zcloud.gbs.edgeguard.gatewayimpl;
|
||||
|
||||
import com.zcloud.gbs.edgeguard.domain.gateway.RegionGateway;
|
||||
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.RegionRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RegionGatewayImpl implements RegionGateway {
|
||||
private final RegionRepository repository;
|
||||
|
||||
@Override
|
||||
public Boolean add(RegionE region) {
|
||||
return repository.save(toDO(region));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(RegionE region) {
|
||||
return repository.updateById(toDO(region));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteById(Long id) {
|
||||
return repository.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionE getById(Long id) {
|
||||
return toEntity(repository.getById(id));
|
||||
}
|
||||
|
||||
private RegionDO toDO(RegionE source) {
|
||||
RegionDO target = new RegionDO();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
|
||||
private RegionE toEntity(RegionDO source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
RegionE target = new RegionE();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.jjb.saas.framework.repository.basedo.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("edgeguard_alarm")
|
||||
public class AlarmDO extends BaseDO {
|
||||
private String alarmNo;
|
||||
private String sourceSystem;
|
||||
private Date alarmTime;
|
||||
private Date receivedTime;
|
||||
private String alarmAddress;
|
||||
private Long corpId;
|
||||
private String corpNameSnapshot;
|
||||
private Long regionId;
|
||||
private String regionCode;
|
||||
private String regionNameSnapshot;
|
||||
private String regionPathSnapshot;
|
||||
private String cameraSource;
|
||||
private String cameraId;
|
||||
private String cameraNameSnapshot;
|
||||
private String alarmImageUrl;
|
||||
private String disposalStatus;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.jjb.saas.framework.repository.basedo.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("edgeguard_alarm_disposal")
|
||||
public class AlarmDisposalDO extends BaseDO {
|
||||
private Long alarmId;
|
||||
private Integer isFalseAlarm;
|
||||
private Integer isHiddenHazard;
|
||||
private String disposalResultCode;
|
||||
private String disposalResultName;
|
||||
private String disposalDescription;
|
||||
private String hiddenId;
|
||||
private String hiddenCreateStatus;
|
||||
private String hiddenCreateError;
|
||||
private Long handlerUserId;
|
||||
private String handlerUserName;
|
||||
private Long handlerDeptId;
|
||||
private String handlerDeptName;
|
||||
private Date disposedTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.jjb.saas.framework.repository.basedo.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("edgeguard_region_camera")
|
||||
public class RegionCameraDO extends BaseDO {
|
||||
private Long regionId;
|
||||
private Long corpId;
|
||||
private String cameraSource;
|
||||
private String cameraId;
|
||||
private String cameraName;
|
||||
private String cameraUnitId;
|
||||
private String cameraUnitName;
|
||||
private String cameraTypeCode;
|
||||
private String cameraTypeName;
|
||||
private String cameraLevelCode;
|
||||
private String cameraLevelName;
|
||||
private String cameraDeptId;
|
||||
private String cameraDeptName;
|
||||
private String onlineStatus;
|
||||
private String cameraSnapshot;
|
||||
private Date cameraSyncedAt;
|
||||
private Long leaderUserId;
|
||||
private String bindStatus;
|
||||
private Date boundTime;
|
||||
private Date unboundTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.jjb.saas.framework.repository.basedo.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("edgeguard_region")
|
||||
public class RegionDO extends BaseDO {
|
||||
private String regionCode;
|
||||
private String regionName;
|
||||
private Long corpId;
|
||||
private Long parentId;
|
||||
private String treePath;
|
||||
private Integer treeLevel;
|
||||
private Integer sortNo;
|
||||
private Long leaderUserId;
|
||||
private String coordinateSystem;
|
||||
private String fencePoints;
|
||||
private String regionStatus;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDisposalDO;
|
||||
|
||||
public interface AlarmDisposalMapper extends BaseMapper<AlarmDisposalDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDO;
|
||||
|
||||
public interface AlarmMapper extends BaseMapper<AlarmDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionCameraDO;
|
||||
|
||||
public interface RegionCameraMapper extends BaseMapper<RegionCameraDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionDO;
|
||||
|
||||
public interface RegionMapper extends BaseMapper<RegionDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.BaseRepository;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDisposalDO;
|
||||
|
||||
public interface AlarmDisposalRepository extends BaseRepository<AlarmDisposalDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.BaseRepository;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDO;
|
||||
|
||||
public interface AlarmRepository extends BaseRepository<AlarmDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.BaseRepository;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionCameraDO;
|
||||
|
||||
public interface RegionCameraRepository extends BaseRepository<RegionCameraDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.BaseRepository;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionDO;
|
||||
|
||||
public interface RegionRepository extends BaseRepository<RegionDO> {
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository.impl;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDisposalDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.mapper.AlarmDisposalMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.AlarmDisposalRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AlarmDisposalRepositoryImpl extends BaseRepositoryImpl<AlarmDisposalMapper, AlarmDisposalDO>
|
||||
implements AlarmDisposalRepository {
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository.impl;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.AlarmDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.mapper.AlarmMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.AlarmRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AlarmRepositoryImpl extends BaseRepositoryImpl<AlarmMapper, AlarmDO>
|
||||
implements AlarmRepository {
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository.impl;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionCameraDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.mapper.RegionCameraMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.RegionCameraRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class RegionCameraRepositoryImpl extends BaseRepositoryImpl<RegionCameraMapper, RegionCameraDO>
|
||||
implements RegionCameraRepository {
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.zcloud.gbs.edgeguard.persistence.repository.impl;
|
||||
|
||||
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
|
||||
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionDO;
|
||||
import com.zcloud.gbs.edgeguard.persistence.mapper.RegionMapper;
|
||||
import com.zcloud.gbs.edgeguard.persistence.repository.RegionRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class RegionRepositoryImpl extends BaseRepositoryImpl<RegionMapper, RegionDO>
|
||||
implements RegionRepository {
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
-- 综合平台区域与摄像头绑定表结构(MySQL 8.0)
|
||||
-- 摄像头主数据来自第三方,本系统只保存区域、摄像头绑定和负责人。
|
||||
|
||||
CREATE TABLE `edgeguard_region` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '区域主键id',
|
||||
`region_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '区域编码,对外稳定唯一标识',
|
||||
`region_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '区域名称',
|
||||
`corp_id` bigint NOT NULL COMMENT '所属企业id,企业主数据来自公共服务',
|
||||
`parent_id` bigint NOT NULL DEFAULT 0 COMMENT '父区域id,0表示企业下的顶级区域',
|
||||
`tree_path` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '/' COMMENT '祖先路径,例如/1/10/',
|
||||
`tree_level` int NOT NULL DEFAULT 1 COMMENT '区域层级,企业下顶级区域为1',
|
||||
`sort_no` int NOT NULL DEFAULT 0 COMMENT '同级排序号',
|
||||
`leader_user_id` bigint NOT NULL COMMENT '区域负责人用户id',
|
||||
`coordinate_system` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '坐标系WGS84/GCJ02/BD09',
|
||||
`fence_points` json NOT NULL COMMENT '有序电子围栏坐标点,一期必须为4个点',
|
||||
`region_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'ENABLED' COMMENT '区域状态ENABLED/DISABLED',
|
||||
`delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '删除标识true false',
|
||||
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
|
||||
`create_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人姓名',
|
||||
`update_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人姓名',
|
||||
`tenant_id` bigint DEFAULT NULL COMMENT '租户id',
|
||||
`org_id` bigint DEFAULT NULL COMMENT '单位id',
|
||||
`version` int DEFAULT NULL COMMENT '版本',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`create_id` bigint DEFAULT NULL COMMENT '创建人id',
|
||||
`update_id` bigint DEFAULT NULL COMMENT '修改人id',
|
||||
`env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_region_code` (`region_code`),
|
||||
KEY `idx_region_tree` (`tenant_id`, `corp_id`, `parent_id`, `delete_enum`, `sort_no`),
|
||||
KEY `idx_region_path` (`tenant_id`, `corp_id`, `tree_path`(191)),
|
||||
KEY `idx_region_status` (`tenant_id`, `corp_id`, `region_status`, `delete_enum`),
|
||||
KEY `idx_region_leader` (`leader_user_id`),
|
||||
CONSTRAINT `chk_region_fence_four_points` CHECK ((JSON_TYPE(`fence_points`) = 'ARRAY') AND (JSON_LENGTH(`fence_points`) = 4))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='企业区域树表';
|
||||
|
||||
CREATE TABLE `edgeguard_region_camera` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '区域摄像头绑定主键id',
|
||||
`region_id` bigint NOT NULL COMMENT '本地区域id',
|
||||
`corp_id` bigint NOT NULL COMMENT '所属企业id,冗余用于权限和查询校验',
|
||||
`camera_source` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头来源系统编码',
|
||||
`camera_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '第三方摄像头唯一标识',
|
||||
`camera_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头名称缓存,第三方为权威数据源',
|
||||
`camera_unit_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头所属单位第三方标识缓存',
|
||||
`camera_unit_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头所属单位名称缓存',
|
||||
`camera_type_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头类型编码缓存',
|
||||
`camera_type_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头类型名称缓存',
|
||||
`camera_level_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头等级编码缓存',
|
||||
`camera_level_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头等级名称缓存',
|
||||
`camera_dept_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头主管部门第三方标识缓存',
|
||||
`camera_dept_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头主管部门名称缓存',
|
||||
`online_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '在线状态缓存ONLINE/OFFLINE/UNKNOWN',
|
||||
`camera_snapshot` json DEFAULT NULL COMMENT '第三方摄像头扩展字段快照',
|
||||
`camera_synced_at` datetime DEFAULT NULL COMMENT '摄像头缓存最近同步时间',
|
||||
`leader_user_id` bigint DEFAULT NULL COMMENT '摄像头负责人用户id',
|
||||
`bind_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'BOUND' COMMENT '绑定状态BOUND/UNBOUND',
|
||||
`bound_time` datetime NOT NULL COMMENT '最近绑定时间',
|
||||
`unbound_time` datetime DEFAULT NULL COMMENT '最近解绑时间',
|
||||
`delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '删除标识true false',
|
||||
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
|
||||
`create_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人姓名',
|
||||
`update_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人姓名',
|
||||
`tenant_id` bigint DEFAULT NULL COMMENT '租户id',
|
||||
`org_id` bigint DEFAULT NULL COMMENT '单位id',
|
||||
`version` int DEFAULT NULL COMMENT '版本',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`create_id` bigint DEFAULT NULL COMMENT '创建人id',
|
||||
`update_id` bigint DEFAULT NULL COMMENT '修改人id',
|
||||
`env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_camera_source_id` (`camera_source`, `camera_id`),
|
||||
KEY `idx_region_camera` (`tenant_id`, `region_id`, `bind_status`, `delete_enum`),
|
||||
KEY `idx_camera_corp` (`tenant_id`, `corp_id`, `delete_enum`),
|
||||
KEY `idx_camera_filter` (`tenant_id`, `region_id`, `camera_level_code`, `online_status`, `delete_enum`),
|
||||
KEY `idx_camera_name` (`camera_name`),
|
||||
KEY `idx_camera_leader` (`leader_user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='区域与第三方摄像头绑定表';
|
||||
|
||||
-- 第三方报警主数据。隐患主流程复用 ZcloudHiddenFacade,本系统只保存隐患id。
|
||||
CREATE TABLE `edgeguard_alarm` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '报警主键id',
|
||||
`alarm_no` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '第三方报警编号',
|
||||
`source_system` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '报警来源系统编码',
|
||||
`alarm_time` datetime NOT NULL COMMENT '第三方报警发生时间',
|
||||
`received_time` datetime NOT NULL COMMENT '综合平台接收时间',
|
||||
`alarm_address` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '报警地址',
|
||||
`corp_id` bigint DEFAULT NULL COMMENT '报警所属企业id',
|
||||
`corp_name_snapshot` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '报警时企业名称快照',
|
||||
`region_id` bigint DEFAULT NULL COMMENT '报警所属区域id',
|
||||
`region_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '报警时区域编码快照',
|
||||
`region_name_snapshot` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '报警时区域名称快照',
|
||||
`region_path_snapshot` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '报警时区域完整路径快照',
|
||||
`camera_source` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头来源系统编码',
|
||||
`camera_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '第三方摄像头唯一标识',
|
||||
`camera_name_snapshot` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '报警时摄像头名称快照',
|
||||
`alarm_image_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '第三方报警截图地址',
|
||||
`disposal_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'PENDING' COMMENT '处置状态PENDING/DISPOSED',
|
||||
`delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '删除标识true false',
|
||||
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
|
||||
`create_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人姓名',
|
||||
`update_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人姓名',
|
||||
`tenant_id` bigint DEFAULT NULL COMMENT '租户id',
|
||||
`org_id` bigint DEFAULT NULL COMMENT '单位id',
|
||||
`version` int DEFAULT NULL COMMENT '版本',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`create_id` bigint DEFAULT NULL COMMENT '创建人id',
|
||||
`update_id` bigint DEFAULT NULL COMMENT '修改人id',
|
||||
`env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_source_alarm_no` (`source_system`, `alarm_no`),
|
||||
KEY `idx_alarm_disposal` (`tenant_id`, `corp_id`, `disposal_status`, `alarm_time`),
|
||||
KEY `idx_alarm_region` (`tenant_id`, `corp_id`, `region_id`, `disposal_status`, `alarm_time`),
|
||||
KEY `idx_alarm_pending_timeout` (`tenant_id`, `disposal_status`, `received_time`, `region_id`),
|
||||
KEY `idx_alarm_camera` (`camera_source`, `camera_id`, `alarm_time`),
|
||||
KEY `idx_alarm_statistics` (`tenant_id`, `corp_id`, `disposal_status`, `alarm_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='第三方报警主表';
|
||||
|
||||
CREATE TABLE `edgeguard_alarm_disposal` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '报警处置主键id',
|
||||
`alarm_id` bigint NOT NULL COMMENT '报警主键id',
|
||||
`is_false_alarm` tinyint(1) NOT NULL COMMENT '是否误报0否1是',
|
||||
`is_hidden_hazard` tinyint(1) DEFAULT NULL COMMENT '是否隐患0否1是,非误报时必填',
|
||||
`disposal_result_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '处置结果字典编码',
|
||||
`disposal_result_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '处置结果名称快照',
|
||||
`disposal_description` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '处置说明',
|
||||
`hidden_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '关联隐患id,仅判定为隐患时有值',
|
||||
`hidden_create_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '隐患创建状态PENDING/SUCCESS/FAILED',
|
||||
`hidden_create_error` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '最近隐患创建失败信息',
|
||||
`handler_user_id` bigint NOT NULL COMMENT '处置人用户id',
|
||||
`handler_user_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '处置人姓名快照',
|
||||
`handler_dept_id` bigint DEFAULT NULL COMMENT '处置部门id',
|
||||
`handler_dept_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '处置部门名称快照',
|
||||
`disposed_time` datetime NOT NULL COMMENT '提交处置时间',
|
||||
`delete_enum` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '删除标识true false',
|
||||
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
|
||||
`create_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人姓名',
|
||||
`update_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人姓名',
|
||||
`tenant_id` bigint DEFAULT NULL COMMENT '租户id',
|
||||
`org_id` bigint DEFAULT NULL COMMENT '单位id',
|
||||
`version` int DEFAULT NULL COMMENT '版本',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`create_id` bigint DEFAULT NULL COMMENT '创建人id',
|
||||
`update_id` bigint DEFAULT NULL COMMENT '修改人id',
|
||||
`env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_disposal_alarm` (`alarm_id`),
|
||||
KEY `idx_disposal_hidden` (`hidden_id`),
|
||||
KEY `idx_hidden_create_retry` (`hidden_create_status`, `update_time`),
|
||||
KEY `idx_disposal_handler` (`tenant_id`, `handler_user_id`, `disposed_time`),
|
||||
KEY `idx_disposal_result` (`tenant_id`, `is_false_alarm`, `is_hidden_hazard`, `disposed_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='报警处置结论表';
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.zcloud.gbs.edgeguard.persistence.mapper.AlarmDisposalMapper">
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.zcloud.gbs.edgeguard.persistence.mapper.AlarmMapper">
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.zcloud.gbs.edgeguard.persistence.mapper.RegionCameraMapper">
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.zcloud.gbs.edgeguard.persistence.mapper.RegionMapper">
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,398 @@
|
|||
# 边缘人脸识别区域安全设计方案
|
||||
|
||||
## 1. 当前需求结论
|
||||
|
||||
综合平台维护企业下面的区域树,并向第三方提供区域查询接口。
|
||||
|
||||
当前功能范围:
|
||||
|
||||
- 一个企业可以维护多棵或多层区域树。
|
||||
- 区域支持新增同级区域、新增下级区域、修改和删除。
|
||||
- 区域包含区域名称、负责人和电子围栏坐标。
|
||||
- 当前原型要求电子围栏由 4 个有顺序的坐标点组成。
|
||||
- 摄像头主数据来自第三方接口,综合平台不维护摄像头主档。
|
||||
- 综合平台保存区域与摄像头的绑定关系。
|
||||
- 每个已绑定摄像头可以设置负责人。
|
||||
- 选择区域后,右侧列表展示该区域直接绑定的摄像头。
|
||||
- 人员、公司、部门、人脸和人员区域准入关系不属于本功能维护范围。
|
||||
- 综合平台不主动推送,由第三方主动调用区域开放接口。
|
||||
|
||||
## 2. 领域边界
|
||||
|
||||
```text
|
||||
企业(外部公共数据)
|
||||
└── 区域(综合平台维护,树结构)
|
||||
├── 下级区域
|
||||
└── 摄像头绑定(摄像头主数据来自第三方)
|
||||
└── 摄像头负责人
|
||||
```
|
||||
|
||||
### 2.1 企业
|
||||
|
||||
- 企业作为区域树的根节点和数据隔离维度。
|
||||
- 企业主数据不在区域表中重复维护,只保存 `corp_id`。
|
||||
- 页面树由“企业虚拟根节点 + 本地区域节点”组合生成。
|
||||
- 企业名称通过公共信息翻译或企业公共接口获取,不作为区域的权威数据保存。
|
||||
|
||||
### 2.2 区域
|
||||
|
||||
区域是本功能的聚合根,负责:
|
||||
|
||||
- 企业归属。
|
||||
- 父子层级。
|
||||
- 区域名称。
|
||||
- 区域负责人。
|
||||
- 电子围栏坐标。
|
||||
- 区域状态和逻辑删除。
|
||||
|
||||
### 2.3 摄像头
|
||||
|
||||
- 摄像头名称、所属单位、类型、等级、主管部门、在线状态等来自第三方接口。
|
||||
- 本系统不成为摄像头主数据的权威维护方,但会冗余列表展示和查询所需的摄像头缓存字段。
|
||||
- 本系统保存第三方摄像头唯一标识、来源系统、区域绑定、摄像头负责人,以及名称、所属单位、类型、等级、主管部门、在线状态等快照。
|
||||
- 绑定摄像头时写入快照;后续可按查询或定时策略刷新,第三方数据始终是权威来源。
|
||||
- 第三方临时不可用时可以展示本地最近快照,并显示最近同步时间;不得把缓存快照作为修改第三方摄像头的依据。
|
||||
|
||||
## 3. 关键设计决策
|
||||
|
||||
### 3.1 公司节点不进入区域表
|
||||
|
||||
区域表只存真实区域。顶级区域的 `parent_id` 为空或为 `0`,通过 `corp_id` 归属企业。这样不会把外部企业主数据和本地区域数据混为一种实体。
|
||||
|
||||
页面树建议返回统一节点结构:
|
||||
|
||||
```text
|
||||
nodeType = CORP 企业虚拟节点
|
||||
nodeType = REGION 本地区域节点
|
||||
```
|
||||
|
||||
### 3.2 区域树规则
|
||||
|
||||
- 同一企业下,同一父节点中的区域名称建议唯一。
|
||||
- 子区域必须与父区域属于同一企业、租户和单位。
|
||||
- 禁止把节点移动到自身或自己的子孙节点下面。
|
||||
- 删除包含子区域的节点时,默认禁止删除,先迁移或删除子节点。
|
||||
- 删除仍绑定摄像头的区域时,默认禁止删除,先解除或迁移绑定。
|
||||
- 查询区域树时使用批量查询后在内存组树,禁止递归逐节点查询数据库。
|
||||
|
||||
是否允许跨层级移动区域、区域最大层级和区域排序规则仍需产品确认。
|
||||
|
||||
### 3.3 四点电子围栏
|
||||
|
||||
建议数据库保存一个有顺序的坐标数组,而不是设计 `point1_x` 到 `point4_y` 八个固定字段:
|
||||
|
||||
```json
|
||||
[
|
||||
{"seq": 1, "longitude": 113.123456, "latitude": 23.123456},
|
||||
{"seq": 2, "longitude": 113.223456, "latitude": 23.123456},
|
||||
{"seq": 3, "longitude": 113.223456, "latitude": 23.223456},
|
||||
{"seq": 4, "longitude": 113.123456, "latitude": 23.223456}
|
||||
]
|
||||
```
|
||||
|
||||
一期保存时强制校验:
|
||||
|
||||
- 必须恰好 4 个点。
|
||||
- 点序号不可重复,按顺时针或逆时针排序。
|
||||
- 经度范围 `[-180, 180]`,纬度范围 `[-90, 90]`。
|
||||
- 相邻点和首尾点不能重复。
|
||||
- 四条边不能自相交。
|
||||
- 围栏面积不能为 0。
|
||||
- 必须明确坐标系,例如 WGS84、GCJ-02 或 BD-09;坐标系作为字段保存,禁止默认猜测。
|
||||
|
||||
使用 JSON 可以满足当前 4 点要求,同时允许未来扩展为多边形。如果后续需要“判断坐标是否在区域内”等空间检索,再增加 MySQL `POLYGON` 空间字段和空间索引。
|
||||
|
||||
### 3.4 负责人
|
||||
|
||||
- 区域负责人保存用户 ID,不重复保存用户主档。
|
||||
- 摄像头负责人保存在区域摄像头绑定记录中。
|
||||
- 页面通过 `TranslateField` 批量翻译负责人姓名,禁止循环逐人查询。
|
||||
- 原型中负责人是必填单选;是否允许多个负责人,需要产品确认。
|
||||
- 人员被停用或删除后,负责人绑定如何处理,需要明确校验或提示规则。
|
||||
|
||||
### 3.5 摄像头绑定
|
||||
|
||||
- 选择摄像头时调用第三方接口获取可选摄像头列表。
|
||||
- 保存时只提交选中的第三方摄像头 ID,本系统必须再次校验摄像头存在性和调用方数据范围。
|
||||
- 建议一期约束“一个来源系统中的一个摄像头只能绑定一个区域”。如果业务允许一个摄像头属于多个区域,再取消唯一约束。
|
||||
- 重复选择已经绑定到当前区域的摄像头应幂等成功。
|
||||
- 已绑定其他区域时,应返回明确提示,不静默迁移。
|
||||
- 解绑只删除本地关系,不调用第三方删除摄像头。
|
||||
- 在线状态等动态字段不写入本地绑定表,以第三方实时结果为准。
|
||||
|
||||
## 4. 表结构草案
|
||||
|
||||
原型可以确定两张核心业务表。所有表都包含根目录 `AGENTS.md` 规定的公共字段。可执行评审的 MySQL 8.0 DDL 草案见 `web-infrastructure/src/main/resources/RegionManagementDDL.sql`。
|
||||
|
||||
### 4.1 区域表 `security_region`
|
||||
|
||||
| 字段 | 类型建议 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `bigint` | 区域主键 |
|
||||
| `region_code` | `varchar(64)` | 区域编码,建议提供稳定的对外标识 |
|
||||
| `region_name` | `varchar(100)` | 区域名称 |
|
||||
| `corp_id` | `bigint` | 所属企业 ID |
|
||||
| `parent_id` | `bigint` | 父区域 ID,顶级区域为空或 0 |
|
||||
| `tree_path` | `varchar(1000)` | 祖先路径,用于子树查询和防循环 |
|
||||
| `tree_level` | `int` | 区域层级,企业下顶级区域从 1 开始 |
|
||||
| `sort_no` | `int` | 同级排序 |
|
||||
| `leader_user_id` | `bigint` | 区域负责人用户 ID |
|
||||
| `coordinate_system` | `varchar(32)` | 坐标系,例如 GCJ02 |
|
||||
| `fence_points` | `json` | 有序电子围栏坐标点,一期固定 4 点 |
|
||||
| `region_status` | `varchar(32)` | `ENABLED/DISABLED` |
|
||||
|
||||
建议索引:
|
||||
|
||||
- 唯一索引:`region_code`,是否叠加租户维度按编码生成规则确定。
|
||||
- 同级名称唯一:`tenant_id + corp_id + parent_id + region_name + delete_enum`。由于可空字段会影响 MySQL 唯一约束,正式 DDL 需采用非空默认值或规范化唯一键。
|
||||
- 树查询索引:`tenant_id + corp_id + parent_id + delete_enum + sort_no`。
|
||||
- 负责人查询索引:`leader_user_id`,仅在存在反向查询需求时增加。
|
||||
|
||||
### 4.2 区域摄像头绑定表 `security_region_camera`
|
||||
|
||||
| 字段 | 类型建议 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `bigint` | 主键 |
|
||||
| `region_id` | `bigint` | 本地区域 ID |
|
||||
| `camera_source` | `varchar(64)` | 摄像头来源系统编码 |
|
||||
| `camera_id` | `varchar(128)` | 第三方摄像头唯一标识 |
|
||||
| `camera_name` | `varchar(255)` | 摄像头名称缓存 |
|
||||
| `camera_unit_id/name` | `varchar` | 所属单位标识及名称缓存 |
|
||||
| `camera_type_code/name` | `varchar` | 类型编码及名称缓存 |
|
||||
| `camera_level_code/name` | `varchar` | 等级编码及名称缓存 |
|
||||
| `camera_dept_id/name` | `varchar` | 主管部门标识及名称缓存 |
|
||||
| `online_status` | `varchar(32)` | 在线状态缓存 |
|
||||
| `camera_snapshot` | `json` | 第三方其他扩展字段快照 |
|
||||
| `camera_synced_at` | `datetime` | 缓存最近同步时间 |
|
||||
| `leader_user_id` | `bigint` | 摄像头负责人用户 ID |
|
||||
| `bind_status` | `varchar(32)` | `BOUND/UNBOUND`,若逻辑删除足够可不单设 |
|
||||
| `bound_time` | `datetime` | 绑定时间 |
|
||||
|
||||
建议索引:
|
||||
|
||||
- 唯一索引:`tenant_id + camera_source + camera_id`,落实一个摄像头只绑定一个区域。
|
||||
- 区域列表索引:`tenant_id + region_id + delete_enum`。
|
||||
- 摄像头负责人索引:`leader_user_id`,仅在需要按负责人查询时增加。
|
||||
|
||||
当前只缓存已经绑定的摄像头,因此展示字段直接放在绑定表中即可。如果后续要求缓存全部第三方摄像头、未绑定摄像头也要离线搜索,或一个摄像头允许绑定多个区域,则应拆分为“摄像头缓存表 + 区域摄像头关系表”。
|
||||
|
||||
## 5. 页面功能拆解
|
||||
|
||||
### 5.1 区域树
|
||||
|
||||
- 按当前用户数据权限加载企业。
|
||||
- 批量查询企业下全部区域并组装树。
|
||||
- 支持新增顶级区域、同级区域和下级区域。
|
||||
- 支持修改和删除区域。
|
||||
- 选中区域后显示企业/区域面包屑。
|
||||
|
||||
### 5.2 新增或修改区域
|
||||
|
||||
入参建议:
|
||||
|
||||
- `parentId`:新增顶级区域时为空。
|
||||
- `corpId`:必填。
|
||||
- `regionName`:必填。
|
||||
- `leaderUserId`:按当前原型必填。
|
||||
- `coordinateSystem`:必填。
|
||||
- `fencePoints`:必填且恰好 4 点。
|
||||
- `sortNo`:可选。
|
||||
|
||||
### 5.3 选择摄像头
|
||||
|
||||
- 显示当前区域路径。
|
||||
- 调用第三方接口分页查询摄像头。
|
||||
- 支持视频名称、等级、在线状态等第三方支持的条件。
|
||||
- 已绑定当前区域的摄像头默认勾选。
|
||||
- 已绑定其他区域的摄像头应禁选或明确标识。
|
||||
- 确认后计算新增绑定和解除绑定差异,在一个本地事务中保存。
|
||||
|
||||
### 5.4 区域摄像头列表
|
||||
|
||||
列表字段来自两部分:
|
||||
|
||||
| 字段 | 来源 |
|
||||
| --- | --- |
|
||||
| 视频名称、所属单位、类型、等级、主管部门、在线状态 | 本地缓存字段展示,第三方接口负责刷新 |
|
||||
| 所属区域、摄像头负责人、绑定时间 | 本地绑定字段 |
|
||||
|
||||
列表操作:设置摄像头负责人、查看第三方摄像头详情、解除绑定。原型中的“删除”建议在业务文案中改为“解绑”,避免误解为删除第三方摄像头。
|
||||
|
||||
## 6. 接口建议
|
||||
|
||||
### 6.1 内部区域管理接口
|
||||
|
||||
| 能力 | 建议接口语义 |
|
||||
| --- | --- |
|
||||
| 区域树 | 按数据权限返回企业虚拟根和区域树 |
|
||||
| 新增区域 | 新增顶级或下级区域 |
|
||||
| 修改区域 | 修改名称、负责人、围栏和排序 |
|
||||
| 删除区域 | 校验子区域和摄像头绑定后逻辑删除 |
|
||||
| 区域摄像头分页 | 查询选中区域直接绑定的摄像头 |
|
||||
| 可选摄像头分页 | 代理/调用第三方摄像头查询能力 |
|
||||
| 保存摄像头绑定 | 批量计算并保存绑定差异 |
|
||||
| 设置摄像头负责人 | 更新绑定记录负责人 |
|
||||
| 解除摄像头绑定 | 逻辑删除本地绑定关系 |
|
||||
|
||||
### 6.2 第三方区域开放接口
|
||||
|
||||
综合平台作为区域数据提供方,建议至少提供:
|
||||
|
||||
- 区域分页查询。
|
||||
- 区域详情查询。
|
||||
- 区域树查询。
|
||||
|
||||
开放接口是否返回区域绑定摄像头需要第三方确认。建议区域和摄像头绑定分别返回,避免区域树报文过大:
|
||||
|
||||
- `RegionCo`:区域自身信息、层级、负责人、围栏。
|
||||
- `RegionCameraCo`:区域 ID、第三方摄像头 ID、摄像头负责人。
|
||||
|
||||
第三方开放接口使用独立鉴权和数据范围,不直接复用页面登录权限。
|
||||
|
||||
## 7. DDD 落位
|
||||
|
||||
| 模块 | 内容 |
|
||||
| --- | --- |
|
||||
| `web-client` | Region、RegionCamera 的 Cmd、Qry、Co 和服务接口 |
|
||||
| `web-adapter` | 区域管理 Controller、第三方区域开放接口 |
|
||||
| `web-app` | 区域增删改查、组树、摄像头绑定和负责人设置执行器 |
|
||||
| `web-domain` | `RegionE`、`RegionCameraBindingE`、树及围栏规则、Gateway |
|
||||
| `web-infrastructure` | DO、Mapper、Repository、GatewayImpl、第三方摄像头 Facade 适配 |
|
||||
| `start` | RPC Client 和配置装配;当前不需要推送定时任务 |
|
||||
|
||||
第三方摄像头访问能力在 Domain 定义 Gateway,在 Infrastructure 通过 Dubbo 或 HTTP 实现。外部摄像头 DTO 不进入 Domain 和 Client。
|
||||
|
||||
## 8. 待确认问题
|
||||
|
||||
### 区域
|
||||
|
||||
- 是否需要区域编码,对外唯一标识采用 ID 还是编码?
|
||||
- 顶级区域 `parent_id` 使用 `NULL` 还是 `0`?
|
||||
- 区域最大层级是多少,是否允许移动节点?
|
||||
- 区域负责人是否只能有一个?
|
||||
- 坐标使用哪种坐标系?四点是否永远固定,还是后续允许任意多边形?
|
||||
- 是否要求判断摄像头坐标或告警坐标是否处于区域内?
|
||||
- 区域是否需要启用/停用状态?
|
||||
|
||||
### 摄像头
|
||||
|
||||
- 摄像头第三方接口的系统、协议和 Common Facade 是什么?
|
||||
- 摄像头唯一主键是什么,是否跨企业唯一?
|
||||
- 是否支持分页及原型中的名称、等级、在线状态筛选?
|
||||
- 一个摄像头是否只能绑定一个区域?
|
||||
- 查询某区域时只展示直接绑定摄像头,还是包含所有子区域摄像头?
|
||||
- 解绑后负责人是否随绑定记录一起失效?
|
||||
- 第三方不可用时页面是报错,还是允许展示本地快照?
|
||||
|
||||
### 开放接口
|
||||
|
||||
- 第三方只查询区域,还是同时查询区域摄像头绑定?
|
||||
- 需要全量分页、区域树还是更新时间增量查询?
|
||||
- 是否需要返回逻辑删除区域和已解除绑定关系?
|
||||
- 鉴权、签名、IP 白名单及租户范围如何确定?
|
||||
|
||||
## 9. 当前不开发内容
|
||||
|
||||
- 人员、企业、部门、岗位和人脸主数据维护。
|
||||
- 人员与区域准入关系。
|
||||
- 摄像头主数据维护和删除。
|
||||
- 主动推送、推送任务、回执和失败重试。
|
||||
|
||||
上一版人员推送 DDL 已删除。当前 `RegionManagementDDL.sql` 是根据原型形成的区域表草案;坐标系、摄像头唯一性和区域删除规则确认后,再作为正式迁移脚本执行。
|
||||
|
||||
## 10. 第三方报警接收与处置
|
||||
|
||||
### 10.1 接入方式
|
||||
|
||||
报警由第三方产生,建议综合平台提供报警接收回调接口,由第三方主动调用:
|
||||
|
||||
```text
|
||||
第三方 -> 鉴权/验签 -> 幂等校验 -> 报警落库 -> 返回受理成功
|
||||
└-> 用户后续处置
|
||||
```
|
||||
|
||||
以 `sourceSystem + alarmNo` 作为幂等键。第三方重复推送同一报警编号时返回已受理,不重复新增。接收接口只负责报警可靠落库,不同步执行隐患长流程。
|
||||
|
||||
第三方至少传摄像头和区域信息,本系统校验并固化企业、区域及摄像头历史快照。区域或摄像头无法识别时是否拒绝接收,待双方接口协议确定。
|
||||
|
||||
报警业务报文只要求当前确认字段:报警编号、报警时间、报警地址、区域、摄像头和一张报警截图。来源系统、接收时间及处置状态属于综合平台接入和管理字段,不要求第三方提供。
|
||||
|
||||
### 10.2 图片传输
|
||||
|
||||
当前暂定第三方在 JSON 报警报文中直接传单张截图 URL,综合平台在 `alarm_image_url` 中保存并用于详情展示,不接收文件流,也不保存 BLOB 或 Base64。
|
||||
|
||||
正式联调前需要确认 URL 是否长期有效、是否需要鉴权、是否允许综合平台服务端访问。如果 URL 是短期签名地址,应改为稳定文件 ID,或由综合平台接收后转存统一文件服务。
|
||||
|
||||
### 10.3 处置状态机
|
||||
|
||||
```text
|
||||
PENDING(未处置)
|
||||
├─ 误报=是 -> DISPOSED
|
||||
└─ 误报=否
|
||||
├─ 隐患=否 -> 填写结果 -> DISPOSED
|
||||
└─ 隐患=是 -> 创建隐患 -> DISPOSED
|
||||
```
|
||||
|
||||
- 误报直接闭环,不进入隐患流程。
|
||||
- 非误报必须选择是否隐患。
|
||||
- 非隐患必须填写处置结果,提交后闭环。
|
||||
- 隐患调用 `ZcloudHiddenFacade.aiHiddenAndSave(HiddenAddCmd)`,以报警编号作为 `foreignKey`。
|
||||
- 隐患流程和进度以隐患服务为准,本地不再维护报警闭环状态。
|
||||
- 当前报警不经过派单、转办或审批,每条报警只提交一次处置结论;处置人、处置时间及公共更新审计字段用于留痕。
|
||||
|
||||
### 10.4 数据表
|
||||
|
||||
区域、摄像头绑定、报警和处置统一维护在 `web-infrastructure/src/main/resources/RegionManagementDDL.sql`,报警部分包含:
|
||||
|
||||
| 表 | 用途 |
|
||||
| --- | --- |
|
||||
| `edgeguard_alarm` | 报警事实、区域/摄像头快照、当前状态、统计维度 |
|
||||
| `edgeguard_alarm_disposal` | 是否误报、是否隐患、直接处置结果及关联隐患 ID |
|
||||
|
||||
Common 已有 `ZcloudHiddenFacade` 的 `aiHiddenAndSave`、`listByForeignKey` 和 `queryHiddenCheckStatus` 等能力。本系统不复制隐患主表,也不缓存隐患状态、级别和进度。创建成功后只在报警处置表保存 `hidden_id`;详情页根据该 ID 调用隐患服务查询实时详情。
|
||||
|
||||
为处理隐患接口临时失败,处置表仅额外保存 `hidden_create_status` 和 `hidden_create_error`。它们属于调用可靠性字段,不是隐患业务数据。以报警编号作为 `foreignKey` 保证隐患创建幂等。
|
||||
|
||||
### 10.5 统计
|
||||
|
||||
一期直接聚合报警主表,不建统计结果表:
|
||||
|
||||
- 股份端按 `corp_id` 统计各分公司报警总数、未处置和已处置。
|
||||
- 分公司端按 `region_id` 统计各区域报警总数、未处置和已处置。
|
||||
- 可统计误报数、隐患数和非隐患处置数。
|
||||
|
||||
报警保存发生时的企业、区域和摄像头快照,后续改名或移动不影响历史台账。数据量较大后再增加按日汇总表。
|
||||
|
||||
### 10.6 待确认
|
||||
|
||||
- 第三方报警接口的 JSON 报文、鉴权、签名及重试规则。
|
||||
- 第三方报警 ID 是否在来源系统内永久唯一。
|
||||
- 报警截图 URL 的有效期、访问鉴权和网络可达性。
|
||||
- 处置结果字典。
|
||||
- 误报是否仍需填写处置原因。
|
||||
- 隐患级别、确认人、整改人和期限由谁填写。
|
||||
- 是否允许修改处置结论、重新打开报警及是否需要审批。
|
||||
|
||||
### 10.7 报警查看权限升级
|
||||
|
||||
当前需求只控制报警列表的可见范围,不需要增加业务表:
|
||||
|
||||
- 摄像头负责人从报警入库开始即可查看该摄像头产生的报警。
|
||||
- 报警保持 `PENDING` 且超过配置的升级时长后,所属区域负责人也可以查看。
|
||||
- 当前升级时长为 10 分钟,必须配置化,禁止硬编码在查询 SQL 中。
|
||||
- 超时基准使用综合平台 `received_time`,不使用第三方 `alarm_time`,避免延迟推送导致报警刚入库就被升级。
|
||||
- 报警处置后进入台账的查看范围按页面数据权限确定,不再依赖 10 分钟规则。
|
||||
|
||||
查询逻辑:
|
||||
|
||||
```text
|
||||
当前用户是摄像头负责人
|
||||
OR
|
||||
当前用户是区域负责人
|
||||
AND disposal_status = PENDING
|
||||
AND received_time <= 当前时间 - 配置分钟数
|
||||
```
|
||||
|
||||
摄像头负责人从 `edgeguard_region_camera.leader_user_id` 获取,区域负责人从 `edgeguard_region.leader_user_id` 获取。负责人发生变更后按当前负责人权限查询;如果未来要求报警产生时锁定负责人,再在报警表增加负责人快照字段。
|
||||
|
||||
本规则只表示“能够在列表看到”,不表示系统主动通知。若后续要求短信、消息中心或待办提醒,并需要记录发送结果和防止重复通知,再设计通知记录或升级标记。
|
||||
Loading…
Reference in New Issue