dev #7

Merged
yuanqiang merged 67 commits from dev into test 2 weeks ago
  1. 20
      dk-api/api-business/src/main/java/org/dromara/business/api/domain/RemoteBusinessAlertRequest.java
  2. 2
      dk-api/api-system/src/main/java/org/dromara/system/api/RemoteConfigService.java
  3. 4
      dk-api/api-system/src/main/java/org/dromara/system/api/RemoteDeptService.java
  4. 11
      dk-api/api-system/src/main/java/org/dromara/system/api/RemoteSubmailConfigService.java
  5. 615
      dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/debug/ErrorCodeEnum.java
  6. 29
      dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/map/api/AbstractOfflineMapService.java
  7. 6
      dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/psdk/PsdkWidgetValue.java
  8. 2
      dk-common/common-mybatis/src/main/resources/common-mybatis.yml
  9. 6
      dk-common/common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java
  10. 28
      dk-modules/business/pom.xml
  11. 160
      dk-modules/business/src/main/java/org/dromara/business/controller/BusinessAlertConstructInfoOssController.java
  12. 127
      dk-modules/business/src/main/java/org/dromara/business/controller/BusinessAlertController.java
  13. 89
      dk-modules/business/src/main/java/org/dromara/business/controller/BusinessLayerController.java
  14. 32
      dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlert.java
  15. 6
      dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlertConstructInfo.java
  16. 74
      dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlertConstructInfoOss.java
  17. 70
      dk-modules/business/src/main/java/org/dromara/business/domain/BusinessLayer.java
  18. 27
      dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java
  19. 73
      dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertConstructInfoOssBo.java
  20. 68
      dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessLayerBo.java
  21. 23
      dk-modules/business/src/main/java/org/dromara/business/domain/model/enums/LayerTypeEnum.java
  22. 88
      dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessAlertConstructInfoOssVo.java
  23. 5
      dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessAlertConstructInfoVo.java
  24. 33
      dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessAlertVo.java
  25. 76
      dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessLayerVo.java
  26. 8
      dk-modules/business/src/main/java/org/dromara/business/dubbo/RemoteBusinessAlertServiceImpl.java
  27. 4
      dk-modules/business/src/main/java/org/dromara/business/feign/FeignDeviceGroup.java
  28. 20
      dk-modules/business/src/main/java/org/dromara/business/mapper/BusinessAlertConstructInfoOssMapper.java
  29. 5
      dk-modules/business/src/main/java/org/dromara/business/mapper/BusinessAlertMapper.java
  30. 20
      dk-modules/business/src/main/java/org/dromara/business/mapper/BusinessLayerMapper.java
  31. 69
      dk-modules/business/src/main/java/org/dromara/business/service/IBusinessAlertConstructInfoOssService.java
  32. 7
      dk-modules/business/src/main/java/org/dromara/business/service/IBusinessAlertService.java
  33. 27
      dk-modules/business/src/main/java/org/dromara/business/service/IBusinessLayerService.java
  34. 193
      dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertConstructInfoOssServiceImpl.java
  35. 412
      dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java
  36. 16
      dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertStatisticsServiceImpl.java
  37. 143
      dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessLayerServiceImpl.java
  38. 264
      dk-modules/business/src/main/java/org/dromara/business/utils/FreemarkerUtil.java
  39. 101
      dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java
  40. 127
      dk-modules/business/src/main/java/org/dromara/business/utils/ImageRotator.java
  41. 283
      dk-modules/business/src/main/java/org/dromara/business/utils/ZipStreamUtil.java
  42. 3
      dk-modules/business/src/main/java/org/dromara/business/utils/constants/MinIOConstants.java
  43. 12
      dk-modules/business/src/main/resources/mapper/business/BusinessAlertConstructInfoOssMapper.xml
  44. 7
      dk-modules/business/src/main/resources/mapper/business/BusinessAlertMapper.xml
  45. 76
      dk-modules/business/src/main/resources/mapper/business/BusinessLayerMapper.xml
  46. BIN
      dk-modules/business/src/main/resources/templates/1.png
  47. BIN
      dk-modules/business/src/main/resources/templates/2.png
  48. 1943
      dk-modules/business/src/main/resources/templates/alert.ftl
  49. 125
      dk-modules/business/src/main/resources/templates/pdfAlert.ftl
  50. 16
      dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteBusinessAlertFeign.java
  51. 18
      dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteConfigFeign.java
  52. 4
      dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteSystemFeign.java
  53. 32
      dk-modules/sample/src/main/java/org/dromara/sample/manage/config/XingluoApiConfig.java
  54. 82
      dk-modules/sample/src/main/java/org/dromara/sample/manage/config/XingluoApiEnum.java
  55. 110
      dk-modules/sample/src/main/java/org/dromara/sample/manage/config/xingluoApiType.json
  56. 2
      dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceQrtzController.java
  57. 80
      dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/SampleEngineRecordController.java
  58. 17
      dk-modules/sample/src/main/java/org/dromara/sample/manage/model/entity/EngineRecordEntity.java
  59. 5
      dk-modules/sample/src/main/java/org/dromara/sample/manage/model/entity/TaskJobEntity.java
  60. 17
      dk-modules/sample/src/main/java/org/dromara/sample/manage/model/entity/WarningRecordEntity.java
  61. 2
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceService.java
  62. 6
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/ISampleEngineRecordService.java
  63. 46
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceFlightRecordsServiceImpl.java
  64. 13
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceServiceImpl.java
  65. 12
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/EngineRecordServiceImpl.java
  66. 36
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/LiveStreamServiceImpl.java
  67. 483
      dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/SampleEngineRecordServiceImpl.java
  68. 11
      dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java
  69. 3
      dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java
  70. 48
      dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java
  71. 7
      dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java
  72. 2
      dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/dto/WaylineJobDTO.java
  73. 2
      dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java
  74. 15
      dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/AiCompareServiceImpl.java
  75. 24
      dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java
  76. 1
      dk-modules/system/pom.xml
  77. 2
      dk-modules/system/src/main/java/org/dromara/system/DKSystemApplication.java
  78. 6
      dk-modules/system/src/main/java/org/dromara/system/config/ProjectTablePrefixConfig.java
  79. 5
      dk-modules/system/src/main/java/org/dromara/system/controller/system/SysConfigController.java
  80. 37
      dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java
  81. 12
      dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDictDataController.java
  82. 12
      dk-modules/system/src/main/java/org/dromara/system/controller/system/SysRoleController.java
  83. 10
      dk-modules/system/src/main/java/org/dromara/system/controller/system/SysUserController.java
  84. 44
      dk-modules/system/src/main/java/org/dromara/system/domain/SysDepartBoundary.java
  85. 1
      dk-modules/system/src/main/java/org/dromara/system/domain/SysUser.java
  86. 1
      dk-modules/system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java
  87. 25
      dk-modules/system/src/main/java/org/dromara/system/domain/kmz/KmzResult.java
  88. 15
      dk-modules/system/src/main/java/org/dromara/system/domain/kmz/Placemark.java
  89. 1
      dk-modules/system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java
  90. 5
      dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteConfigServiceImpl.java
  91. 11
      dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteDeptServiceImpl.java
  92. 1
      dk-modules/system/src/main/java/org/dromara/system/dubbo/RemotePostServiceImpl.java
  93. 41
      dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteSubmailConfigServiceImpl.java
  94. 1
      dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java
  95. 4
      dk-modules/system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java
  96. 2
      dk-modules/system/src/main/java/org/dromara/system/service/ISysConfigService.java
  97. 6
      dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java
  98. 7
      dk-modules/system/src/main/java/org/dromara/system/service/ISysDeptService.java
  99. 4
      dk-modules/system/src/main/java/org/dromara/system/service/ISysSubmailConfigService.java
  100. 1
      dk-modules/system/src/main/java/org/dromara/system/service/ISysUserService.java

20
dk-api/api-business/src/main/java/org/dromara/business/api/domain/RemoteBusinessAlertRequest.java

@ -0,0 +1,20 @@
package org.dromara.business.api.domain;
import lombok.Data;
import org.dromara.business.api.domain.vo.RemoteBusinessAlertVo;
import java.util.List;
/**
* 预警任务对象 business_alert
*
* @author LionLi
* @date 2025-02-27
*/
@Data
public class RemoteBusinessAlertRequest {
private List<RemoteBusinessAlertVo> alertVoList;
private String activeProfile;
}

2
dk-api/api-system/src/main/java/org/dromara/system/api/RemoteConfigService.java

@ -23,6 +23,8 @@ public interface RemoteConfigService {
*/
String selectStreamIp();
boolean selectXingluoAutoSubmit();
// List<String> selectStreamType(String deviceSn);
}

4
dk-api/api-system/src/main/java/org/dromara/system/api/RemoteDeptService.java

@ -24,9 +24,11 @@ public interface RemoteDeptService {
RemoteDeptVo selectDeptById(Long deptId);
List<Map<String,Object>> getNamePathList();
List<Map<String,Object>> getNamePathList(Long deptId);
List<RemoteDeptVo> selectListByParentId(String deptId);
RemoteDeptVo getByParentId(String deptId);
List<RemoteDeptVo> listTreeDeptByChild(Long deptId);
}

11
dk-api/api-system/src/main/java/org/dromara/system/api/RemoteSubmailConfigService.java

@ -3,6 +3,10 @@ package org.dromara.system.api;
import org.dromara.common.core.domain.R;
import org.dromara.system.api.domain.vo.RemoteClientVo;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 客户端服务
*
@ -17,4 +21,11 @@ public interface RemoteSubmailConfigService {
*/
R<String> remoteCmdSend(String code, String multiParam );
/**
* @param code 编码
* @param alertList 预警信息
* @return 客户端对象
*/
void remoteSend(String code,List<Map<String, Object>> alertList);
}

615
dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/debug/ErrorCodeEnum.java

@ -0,0 +1,615 @@
package org.dromara.common.sdk.cloudapi.debug;
import org.dromara.common.sdk.common.IErrorInfo;
import org.dromara.common.sdk.mqtt.events.IEventsErrorCode;
import org.dromara.common.sdk.mqtt.services.IServicesErrorCode;
import java.util.Arrays;
/**
* @author sean.zhou
* @version 0.1
* @date 2021/11/25
*/
public enum ErrorCodeEnum implements IServicesErrorCode, IEventsErrorCode, IErrorInfo {
E219004(219004, "飞行任务已过期,无法执行(上云重新选择任务执行时间:任务过期) 机场日志"),
E219014(219014, "机场不属于该项目,无法执行当前操作或执行飞行任务,请将机场迁回该项目或到机场所在项目重试(机场不属于该项目,权限隔离:检查机场工作项目是否匹配) 机场日志"),
E219016(219016, "飞行任务已被挂起,无法执行(任务挂起:检查任务是否挂起) 机场日志"),
E219018(219018, "机场执行飞行任务过程中超时未响应,1小时未上报任何状态(设备离线或设备mqtt连接中断,无法上报信息:1.检查机场是否开机 2.检查机场网络是否正常 3.如仍未解决拉取机场日志反馈售后分析。) 机场日志"),
E219101(219101, "服务器异常,请稍后重试(dtcp服务异常:拉取机场日志联系售后分析。) 机场日志"),
E219102(219102, "机场已离线,无法执行飞行任务,请检查机场是否已断电,机场网络连接是否正常(设备离线或设备mqtt连接中断,无法上报信息:1.检查机场是否开机 2.检查机场网络是否正常 3.如仍未解决问题拉取机场日志联系售后分析) 机场日志"),
E219103(219103, "项目中不存在此机场,无法执行飞行任务(机场不属于该项目,权限隔离:1.检查机场工作项目是否匹配) 机场日志"),
E219104(219104, "服务器内部错误,无法执行飞行任务(服务配置错误,无法识别该命令:拉取机场日志反馈售后分析) 机场日志"),
E219105(219105, "云端与机场通信异常,无法执行飞行任务(机场没有在10s内回复任务命令reply:拉取机场日志反馈售后分析) 机场日志"),
E219304(219304, "机场数据雨量过大(天气阻飞:检查是否开启项目在线天气阻飞,如没有则为气象站阻飞) 机场日志"),
E219305(219305, "机场数据风速过大(天气阻飞:检查是否开启项目在线天气阻飞,如没有则为气象站阻飞) 机场日志"),
E312001(312001, "一致性升级失败(触发一致性升级,但设备没有请求一致性升级,会返回该错误码:尝试在固件升级时开启无人机,并关闭无人机的4G增强)"),
E312003(312003, "固件升级失败(校验文件MD5失败:检查下发文件的MD5)"),
E312010(312010, "固件升级错误(下发的升级请求命令与协议不符合:1、检查下发mqtt命令格式是否有误。注意文件大小是整数类型,不是字符串 2、回复ota_progress方法可以停止错误推送)"),
E312013(312013, "固件升级失败(需要关闭4G,并在无人机开机状态下更新固件:请检查固件升级包是否匹配对应机型)"),
E312014(312014, "设备升级中,请勿重复操作"),
E312015(312015, "机场:{dock_org_name} 业务繁忙无法进行设备升级,请等待机场处于空闲中后再试"),
E312016(312016, "升级失败,机场和飞行器图传链路异常,请重启机场和飞行器后重试"),
E312022(312022, "飞行器开机失败或未连接,请检查飞行器是否在舱内,是否安装电池,机场和飞行器是否已对频"),
E312023(312023, "推杆闭合失败无法升级飞行器,请检查急停按钮是否被按下,推杆是否有异物卡住"),
E312026(312026, "离线升级包解压失败 检查一下下载的离线固件包是否损坏,或者重新下发一下"),
E312027(312027, "升级失败,机场未检测到飞行器"),
E312028(312028, "升级失败,设备升级过程中设备被重启"),
E312029(312029, "设备重启中无法进行设备升级,请等待设备重启完成后重试"),
E312030(312030, "升级失败,飞行器增强图传开启后无法升级,请关闭飞行器增强图传后重试"),
E312031(312031, "重试升级出错 可能是传输断开 重启飞机和飞行器后重试,确保机场网络可以访问到指令的文件下载地址"),
E312306(312306, "升级失败,固件文件包下载失败,网络异常,请检查网络状态 网络环境导致固件下载失败"),
E312307(312307, "升级失败,固件文件包下载失败,网络异常,请检查网络状态 网络异常、网络差、有防火墙等"),
E312502(312502, "升级失败 无"),
E312527(312527, "文件错误或者被删除 检查传入的file地址是否能访问到,并且点击连接可以下载文件。"),
E312534(312534, "飞机升级失败,飞机在机场重启失败。 1、检查无人机开机。 2、关闭无人机和机场的4G增强,拔掉4G模块。 3、固件有防回滚,不可降级"),
E312704(312704, "飞行器电量过低,请充电至20%以上后重试"),
E314000(314000, "设备当前无法支持该操作,建议检查设备当前工作状态"),
E314001(314001, "飞行任务下发失败,请稍后重试 机场日志 司空2服务异常 拉取机场日志反馈售后分析。"),
E314002(314002, "飞行任务下发失败,请稍后重试 任务没下发fingerprint"),
E314003(314003, "航线文件格式不兼容,请检查航线文件是否正确"),
E314004(314004, "飞行任务下发失败,请稍后重试或重启机场后重试(文件地址获取不到) 机场日志 1. 机场网络不稳定存在数据波动 2. 网络DNS服务器解析失败 1、检查机场和飞机的固件版本是否配套,具体配套版本可以查看机场的发布记录或者上云API 版本的发布记录。 2、检查下发任务中的URL是否正确,在浏览器中输入该URL,需要能够自动触发下载。 3、检查机场网络是否能够访问该下发任务中的URL。 4、检查云端服务是否正常回复了机场请求的任务资源获取接口。(云端一定要回复该接口,机场才能正常获取航线文件) 5、如果同一个航线文件有时可以正常执行,有时却报错,需要排查机场的网络带宽是否稳定。"),
E314005(314005, "飞行任务下发失败,请稍后重试或重启机场后重试"),
E314006(314006, "飞行器初始化失败,请重启机场后重试"),
E314007(314007, "机场传输航线至飞行器失败,请重启机场后重试 机场日志、飞机日志 1、图传信号质量不佳 2、设备存在异常 1、重启机场和飞行器重试 2、交叉验证飞行器或机场的图传功能是否正常 3、拉取机场和飞行器日志提单给售后分析 4、检查机场拖链处馈线是否发生断裂,主控模块处SMA接口是否拧紧 5、飞机与机场的图传信息指令不佳导致,检查图传信号 6、检查航线文件是否有问题。可以用Pilot上传航线文件到飞机,看看能不能识别。 7、第一个航点不能设置isRisky为true"),
E314008(314008, "飞行器起飞前准备超时,请重启机场后重试"),
E314009(314009, "飞行器初始化失败,请重启机场后重试"),
E314010(314010, "航线执行失败,请重启机场后重试 机场日志、飞机日志 1、航线距离机场过远 2、航线未知原因退出 1、重新下发任务 2、重启机场再次尝试 3、多次尝试仍未解决拉取机场和飞机日志联系售后分析"),
E314011(314011, "机场系统异常,无法获取飞行任务执行结果 重启机场再次尝试"),
E314012(314012, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试 机场日志、飞机日志 1、固件版本过低 2、设备逻辑异常 1、请升级最新固件 2、如果升级后还有问题,请检查是否有阻飞的HMS上报,按对应提示排查解决 3、如果仍无法解决请拉取机场和飞行器日志联系售后分析 4、检查飞机固件与机场固件是否匹配"),
E314013(314013, "飞行任务下发失败,机场无法获取到本次飞行任务的航线,无法执行飞行任务,请稍后重试 机场日志、飞机日志 机场异常重启(上一次任务未执行完成,本地缓存了该任务执行信息,下次启动会将上次任务结果上报) 1、重新下发任务 2、多次尝试仍未解决拉取机场和飞机日志联系售后分析 https://sdk-forum.dji.net/hc/zh-cn/articles/16745838728985"),
E314014(314014, "机场系统异常,飞行任务执行失败,请稍后重试 机场日志 机场异常重启(上一次任务未执行完成,本地缓存了该任务执行信息,下次启动会将上次任务结果上报) 1、重新下发任务 2、如果重新下发任务无法恢复,需要关掉“设备运维界面”里面的“用户改善计划”"),
E314015(314015, "机场传输精准复拍航线至飞行器失败,无法执行飞行任务,请稍后重试或重启机场后重试"),
E314016(314016, "航线文件解析失败,无法执行飞行任务,请检查航线文件 机场不支持执行除了精准复拍外的其他航线类型,KMZ超过1MB 删除KMZ中的res目录(地形信息)"),
E314017(314017, "机场系统异常,飞行任务执行失败,请稍后重试 精准复拍类型KMZ文件错误"),
E314018(314018, "飞行器RTK定位异常,无法执行飞行任务,请稍后重试或重启机场后重试"),
E314019(314019, "飞行器RTK收敛失败,无法执行飞行任务,请稍后重试或重启机场后重试"),
E314020(314020, "飞行器不在停机坪正中间或飞行器朝向不正确,无法执行飞行任务,请检查飞行器位置和朝向 机场日志、飞机日志 1、飞行器不在机场停机坪正中间或飞行器摆放方向不正确 2、电离层闪烁 3、飞行器内部定位异常 1、确认飞机在机场上的摆放位置和方向是否正确 2、确认没有电离层闪烁现象 3、查看HMS报错信息,根据提示进行排查 4、重启飞行器,多次重启后仍存在问题请拉取机场和飞行器日志联系售后分析"),
E314021(314021, "飞行器RTK定位异常,无法执行飞行任务,请稍后重试或重启机场后重试 机场日志、飞机日志 1、电离层闪烁 2、飞行器内部定位异常 1、确认没有电离层闪烁现象 2、查看HMS报错信息 3、重启飞行器,多次重启后仍存在问题请拉取机场和飞行器日志联系售后分析"),
E314024(314024, "进离场航线下发失败,请稍后重试或重启机场后重试"),
E314025(314025, "RTK收敛超时,用户手动取消任务"),
E314200(314200, "任务失败,由于机场网络断开,飞行器已自动返航,请确保机场已连接网络后再试 检查机场网络情况,然后重试 机场与MQTT之间的连接断开。检查网络情况"),
E315000(315000, "机场通信异常,请重启机场后重试"),
E315001(315001, "A起B降-起飞机场设置SDR拓扑信息失败 1、机场通信异常,请远程开启飞机并等待1分钟后,再次下发任务重试 2、sdr_id信息有误"),
E315002(315002, "A起B降-降落机场设置编号失败 云端回复机场时不要超过30秒,不要过慢,信息保证准确。失败就需要从头重试"),
E315003(315003, "机场通信异常,请重启机场后重试"),
E315004(315004, "任务失败,请等待两个机场都空闲后,再次下发任务重试"),
E315005(315005, "机场通信异常,请重启机场后重试"),
E315006(315006, "机场通信异常,请重启机场后重试"),
E315007(315007, "机场通信异常,请将机场升级到最新版本或重启机场后重试 RTK异常,RTK配置信息失败 1、确保起飞时RTK收敛 2、二代机库即使是模拟飞行也要保证RTK收敛才可以模拟"),
E315008(315008, "降落机场和起飞机场标定信息不一致,请确认两个机场均链路通畅且使用了相同的网络信息标定"),
E315009(315009, "机场通信异常,请重启机场后重试 固件潜在问题,等待固件更新"),
E315010(315010, "无法停止飞行任务,请稍后重试,如果仍报错请联系大疆售后"),
E315011(315011, "无法停止飞行任务,请稍后重试,如果仍报错请联系大疆售后"),
E315012(315012, "无法停止飞行任务,请稍后重试,如果仍报错请联系大疆售后"),
E315013(315013, "飞行任务下发失败,请稍后重试,如果仍报错请联系大疆售后"),
E315014(315014, "当前任务类型不支持设置返航点"),
E315015(315015, "返航点设置失败,请稍后重试,如果仍报错请联系大疆售后"),
E315016(315016, "飞行任务下发失败,请稍后重试,如果仍报错请联系大疆售后 蛙跳任务中回复的机场current_step有误,与机场的实际状态不匹配"),
E315017(315017, "飞行任务下发失败,请稍后重试,如果仍报错请联系大疆售后"),
E315018(315018, "任务失败,请等待两个机场都空闲后,再次下发任务重试"),
E315019(315019, "设备部署位置不佳,无法执行蛙跳任务,请选择其他机场再试"),
E315050(315050, "机场系统异常,请重启机场后重试"),
E315051(315051, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315052(315052, "机场位置未收敛,请等待一段时间后重试"),
E315053(315053, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315054(315054, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315055(315055, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315056(315056, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315057(315057, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315058(315058, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315059(315059, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315060(315060, "A起B降-SDR信息中,A控数量分配过多 蛙跳任务飞机的控制源设置错误,可能两个机场的control_source_index都是1"),
E315061(315061, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315062(315062, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后 检查蛙跳任务是否缺少参数"),
E315063(315063, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315064(315064, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E315065(315065, "任务失败,请重启机场并再次下发任务后重试,如果仍报错请联系大疆售后"),
E316001(316001, "备降点设置失败"),
E316002(316002, "备降安全转移高度设置失败"),
E316003(316003, "飞行器参数配置失败,请重启机场后重试 机场日志、飞机日志 设置起飞高度失败(图传链路不稳导致) 1、重新下发任务 2、重试多次后依然存在请拉取机场和飞行器日志"),
E316004(316004, "失控行为设置失败"),
E316005(316005, "飞行器RTK收敛失败,无法执行飞行任务,请稍后重试或重启机场后重试 机场日志、飞机日志 1、安装环境存在遮挡 2、电离层闪烁 3、机场RTK未标定 4、图传断链 5、设备工作异常 1、确认APP踏勘选址结果是否大于80分 2、确认没有电离层闪烁现象 3、确认机场RTK完成标定 4、重新下发任务 5、重试多次依然失败后拉取机场和飞机的日志"),
E316006(316006, "任务超时,飞行器已丢失或降落时机场未开启舱盖或展开推杆,飞行器无法降落回机场,请尽快至机场部署现场检查飞行器状况"),
E316007(316007, "飞行器初始化失败,请重启机场后重试"),
E316008(316008, "机场获取飞行器控制权失败,无法执行飞行任务,请确认遥控器未锁定控制权 机场日志、飞机日志 1、飞行控制权获取失败 2、遥控器B控接管后锁定控制权 3、机场与飞行器图传链路逻辑错误 1、确认飞机和机场已经对频 2、如有B控连接,请关闭遥控器后重试 3、重启机场和飞行器重试"),
E316009(316009, "飞行器电量低,无法执行飞行任务,请充电后(建议≥50%)重试 机场日志、飞机日志 飞行器电量不足 等待充电至30%以上"),
E316010(316010, "机场未检测到飞行器,无法执行飞行任务,请检查舱内是否有飞行器,机场与飞行器是否已对频,或重启机场后重试 机场日志、飞机日志 1、图传未推送飞控OSD 2、飞行器与机场图传链路不稳定 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析"),
E316011(316011, "飞行器降落位置偏移过大,请检查飞行器是否需要现场摆正"),
E316012(316012, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试 1、图传质量差导致 2、检查flight id是否有下划线或其它特殊字符"),
E316013(316013, "电池电量查询失败"),
E316014(316014, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试"),
E316015(316015, "飞行器RTK收敛位置距离机场过远,无法执行飞行任务,请重启机场后重试 机场日志、飞机日志 1、安装环境存在遮挡 2、电离层闪烁 3、设备工作异常 1、确认APP踏勘选址结果是否大于80分 2、确认没有电离层闪烁现象 3、确认机场RTK完成标定 4、重新下发任务 5、重试多次依然失败后拉取机场和飞机的日志"),
E316016(316016, "飞行器降落至机场超时,可能是机场与飞行器断连导致,请通过直播查看飞行器是否降落至舱内"),
E316017(316017, "获取飞行器媒体数量超时,可能是机场与飞行器断连导致,请通过直播查看飞行器是否降落至舱内"),
E316018(316018, "飞行任务执行超时,可能是机场与飞行器断连导致,请通过直播查看飞行器是否降落至舱内"),
E316019(316019, "机场系统错误,无法执行飞行任务,请稍后重试"),
E316020(316020, "飞行器使用的RTK信号源错误,请稍后重试 机场日志、飞机日志 1、飞行器RTK源使用错误 2、飞行器在与机场对频使用前连接过D-RTK2基站/网络RTK/自定义网络RTK等 1、重新下发任务 2、多次下发依然异常,请拉取机场和飞机日志联系售后分析"),
E316021(316021, "飞行器RTK信号源检查超时,请稍后重试 机场日志、飞机日志 图传断链不稳定 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析"),
E316022(316022, "飞行器无法执行返航指令,请检查飞行器是否已开机,机场与飞行器是否已断连,请确认无以上问题后重试"),
E316023(316023, "飞行器无法执行返航指令,飞行器已被B控接管,请在B控操控飞行器,或关闭B控后重试"),
E316024(316024, "飞行器执行返航指令失败,请检查飞行器是否已起飞,确认飞行器已起飞后请重试"),
E316025(316025, "飞行器参数配置失败,请稍后重试或重启机场后重试 设置返航高度失败 返航高度的格式不是整数类型"),
E316026(316026, "机场急停按钮被按下,无法执行飞行任务,请释放急停按钮后重试 机场日志、飞机日志 急停按钮被按下 向外拔出急停按钮"),
E316027(316027, "飞行器参数配置超时,请稍后重试或重启机场后重试"),
E316029(316029, "机场急停按钮被按下,飞行器将飞往备降点降落,请立即检查飞行器是否已安全降落并将飞行器放回至机场"),
E316030(316030, "返航点刷新失败,请稍后重试 机场日志、飞机日志 链路不稳定 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析"),
E316031(316031, "机场系统运行异常,请重新下发任务 机场日志、飞机日志 设置返航模式失败;二代机库下发任务需指定返航模式"),
E316032(316032, "获取电池数据超时,请稍后重试或重启飞行器后重试 机场日志、飞机日志 图传丢包 1、重新下发任务 2、多次下发依然异常,请拉取机场和飞机日志联系售后分析"),
E316033(316033, "飞行器电池循环次数过高,为保证飞行安全,已自动终止任务,建议更换该电池 机场日志、飞机日志 电池循环次数超过500次 1、检查电池循环次数是否过高 2、确认没有超过500次需要拉取机场和飞机日志联系售后分析"),
E316034(316034, "无法起飞,飞行器固件版本与机场固件版本不匹配,为保证飞行安全请升级固件后再试 升级机场和飞机固件到最新版本"),
E316035(316035, "进离场航线下发失败,请确保设备固件为最新版本后重新下发任务,如果持续报错,请联系大疆售后。"),
E316050(316050, "飞行器因电量过低在舱外降落,请立即检查飞行器是否已安全降落并将飞行器放回至机场"),
E316051(316051, "飞行任务异常,飞行器在舱外降落,请立即检查飞行器是否已安全降落并将飞行器放回至机场"),
E316052(316052, "飞行任务异常,飞行器将飞往备降点降落,请立即检查飞行器是否已安全降落并将飞行器放回至机场"),
E316053(316053, "用户已操控飞行器降落,请立即检查飞行器是否已安全降落并将飞行器放回至机场"),
E316054(316054, "无法启动模拟器,启动模拟器需要RTK收敛"),
E316100(316100, "获取相机概要信息失败,请重试"),
E316101(316101, "设置相机为单拍模式失败,请重试"),
E316102(316102, "关闭相机水印失败,请重试"),
E316103(316103, "设置测光模式为平均测光失败,请重试"),
E316104(316104, "切换镜头到广角镜头失败,请重试"),
E316105(316105, "设置相机存储照片失败,请重试"),
E316106(316106, "红外变焦倍数设置失败,请重试"),
E316107(316107, "照片尺寸设置为4K失败,请重试"),
E316108(316108, "设置照片存储格式为JPEG失败,请重试"),
E316109(316109, "关闭相机畸变矫正失败,请重试"),
E316110(316110, "打开相机机械快门失败,请重试"),
E316111(316111, "设置对焦模式失败,请重试"),
E317001(317001, "获取飞行器媒体文件数量失败,请重启机场后重试"),
E317002(317002, "飞行器存储格式化失败,飞行器未开机、未连接或未检测到相机,请确认无以上问题后重试,或重启飞行器后重试"),
E317003(317003, "飞行器存储格式化失败,请重启飞行器后重试"),
E317004(317004, "机场媒体文件格式化失败,请稍后重试或重启机场后重试"),
E317005(317005, "飞行器结束录像失败,本次飞行任务的媒体文件可能无法上传 调用结束录像的方法时飞行器已经退出指令飞行模式,需在指令飞行模式下结束录像。"),
E317006(317006, "无法格式化,请等待当前飞行器媒体文件下载完成后再试"),
E317007(317007, "获取媒体文件数量失败,请稍后重试,如本架次任务有媒体文件且持续报错可联系大疆售后"),
E318101(318101, "飞行因HMS告警,无法执行飞行任务 检查HMS相关告警"),
E319001(319001, "机场作业中或设备异常反馈上传日志中,无法执行飞行任务,请等待当前飞行任务或操作执行完成后重试"),
E319002(319002, "机场系统运行异常,请重启机场后重试 机场日志、飞机日志 机场内部通讯异常 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析"),
E319003(319003, "机场系统运行异常,请重新下发任务 机场日志、飞机日志 1、云端下发了不存在的flight_id任务 2、机场内部缓存任务异常 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析 3、是否任务下发过于频繁 4、任务执行时间是否超出execute_time前后30秒。"),
E319004(319004, "飞行任务执行超时,已自动终止本次飞行任务 机场日志、飞机日志 机场与云端时间不同步 1、检查机场与云端时间是否一致 2、任务下发与执行指令间隔不得超过30秒 3、断点续飞时mission_id需与之前的航线mission_id不同"),
E319005(319005, "云端与机场通信异常,无法执行飞行任务 机场日志、飞机日志 机场与云端时间不同步 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析"),
E319006(319006, "取消飞行任务失败,飞行任务已经在执行中"),
E319007(319007, "修改飞行任务失败,飞行任务已经在执行中"),
E319008(319008, "机场时间与云端时间不同步,机场无法执行飞行任务 机场日志 机场与云端时间不同步 1、重启飞行器和机场,重新下发任务 2、多次下发依然不行,请拉取机场和飞机日志进一步分析 3、若内网服务器与设备时间存在误差,需要在服务器上搭建NTP服务器,通过配置接口同步设备时间。"),
E319009(319009, "飞行任务下发失败,请稍后重试或重启机场后重试"),
E319010(319010, "机场固件版本过低,无法执行飞行任务,请升级机场固件为最新版本后重试"),
E319015(319015, "机场正在初始化中,无法执行飞行任务,请等待机场初始化完成后重试"),
E319016(319016, "机场正在执行其他飞行任务,无法执行本次飞行任务 机场日志、飞机日志 机场正在执行上一个任务 等待上个任务执行完成,再下发任务"),
E319017(319017, "机场正在处理上次飞行任务媒体文件,无法执行本次飞行任务,请稍后重试 机场日志、飞机日志 1、机场正在获取飞行器媒体列表 2、上个任务未收到云端ACK消息 等待列表获取完成"),
E319018(319018, "机场正在自动导出日志(设备异常反馈),无法执行飞行任务,请稍后重试"),
E319019(319019, "机场正在拉取日志(设备异常反馈),无法执行飞行任务,请稍后重试 检查是否调用了拉取日志功能"),
E319020(319020, "航线中断失败,请稍后重试"),
E319021(319021, "退出远程控制失败,请稍后重试"),
E319022(319022, "指点飞行失败,请稍后重试"),
E319023(319023, "指点飞行停止失败,请稍后重试"),
E319024(319024, "一键起飞失败,请稍后重试"),
E319025(319025, "机场未准备完成,无法执行云端下发的飞行任务,请稍后重试"),
E319026(319026, "飞行器电池电量低于用户设置的任务开始执行电量,请等待充电完成后再执行飞行任务"),
E319027(319027, "机场或飞行器剩余存储容量过低,无法执行飞行任务,请等待媒体文件上传释放存储后再执行飞行任务"),
E319028(319028, "正在更新自定义飞行区"),
E319029(319029, "正在更新离线地图"),
E319030(319030, "操作失败,无飞行器控制权 DRC控制需要在1分钟内至少下发一次心跳。"),
E319031(319031, "控制权异常,请刷新重试 使用Method: drone_control进行飞行控制时,需要保证seq从0开始连续递增,不论是单次发送还是连续发送。"),
E319032(319032, "指点飞行失败,请稍后重试"),
E319033(319033, "虚拟摇杆操作失败,请稍后重试 检查发送的指令seq是否递增。"),
E319034(319034, "虚拟摇杆操作失败,请稍后重试"),
E319035(319035, "急停失败,请稍后重试"),
E319036(319036, "设备远程调试中,请稍后重试"),
E319037(319037, "设备远程调试中,请稍后重试 设备本地调试中,请稍后重试 机场连接了USB进行调试,请断开USB连接。"),
E319038(319038, "设备正在升级,请稍后重试"),
E319042(319042, "航线恢复失败,请稍后重试"),
E319043(319043, "取消返航失败,请稍后重试"),
E319044(319044, "航线任务已结束,无法恢复"),
E319045(319045, "急停成功,请重新按键操作;WASD失败 1、检查DRC命令的seq是否从0开始递增 2、检查是否暂停了航线再执行DRC控制 飞行器报错319045后,下一个飞行控制指令需要seq从0开始递增。注意:飞行控制drone_control与DRC心跳heart_beat的seq是独立的。"),
E319046(319046, "无法暂停航线,飞行器尚未进入航线或已退出航线 不处于航线任务中。调用流程问题,比如在指令飞行过程中暂停航线。"),
E319999(319999, "机场系统运行异常,请重启机场后重试 未知错误,需要根据下发的指令来判断哪个业务导致问题 1、切镜头不能切换到normal镜头 2、检查参数是否有误 3、红外相关参数设置,需要将直播画面切换到直播镜头"),
E321000(321000, "航线执行异常,请稍后重试或重启机场后重试 机场日志、飞机日志 航线未知原因退出 拉取机场和飞机日志联系售后分析"),
E321001(321001, "mission id不存在"),
E321002(321002, "wayline info错误"),
E321003(321003, "要执行的航线文件版本不匹配"),
E321004(321004, "航线文件解析失败,无法执行飞行任务,请检查航线文件"),
E321005(321005, "航线缺少断点信息,机场无法执行飞行任务"),
E321006(321006, "无效的命令"),
E321016(321016, "模拟器打开失败"),
E321257(321257, "飞行任务已在执行中,请勿重复执行"),
E321258(321258, "飞行任务无法终止,请检查飞行器状态"),
E321259(321259, "飞行任务未开始执行,无法终止飞行任务"),
E321260(321260, "飞行任务未开始执行,无法中断飞行任务"),
E321261(321261, "飞行任务冲突,无法获取飞机控制权"),
E321262(321262, "该状态下无法恢复航线"),
E321513(321513, "航线规划高度已超过飞行器限高,机场无法执行飞行任务 机场日志、飞机日志 1、存在限飞区 2、用户设置了限高 1、检查是否存在限飞区 2、检查用户设置的限高 3、检查航线文件 4、检查飞机位置"),
E321514(321514, "任务失败,起点或终点位于限远区域的缓冲区内或超过限远距离,机场无法执行飞行任务 机场日志、飞机日志 1、存在限飞区 2、用户设置了限远 1、检查是否存在限飞区 2、检查用户设置的限远 3、检查航线文件 4、检查飞机位置"),
E321515(321515, "航线穿过限飞区,机场无法执行飞行任务"),
E321516(321516, "飞行器飞行高度过低,飞行任务执行被终止"),
E321517(321517, "飞行器触发避障,飞行任务执行被终止。为保证飞行安全,请勿用当前航线执行断点续飞任务 飞机日志 1、存在障碍物 2、存在降雨或有雾天气 3、概率偶现误检测 1、检查航线与障碍物距离是否小于5米 2、检查是否存在降雨或有雾天气 3、手动触发返航并对飞行器视觉进行标定 4、多次重试标定依然存在问题,请拉取飞机日志反馈售后分析。"),
E321518(321518, "RTK信号弱,为保证飞行安全,已自动终止本次飞行任务"),
E321519(321519, "飞行器接近限飞区或限远距离自动返航,无法完成航线飞行 飞机日志 存在限飞区 检查是否存在限飞区与飞机位置高度"),
E321520(321520, "打pitch/roll杆中断航线(农机航线专用)"),
E321521(321521, "超过机场限飞区限高"),
E321522(321522, "请求自动起飞失败"),
E321523(321523, "飞行器起桨失败,请稍后重试,如果仍报错请联系大疆售后 机场日志、飞机日志 1、桨叶存在破损 2、桨叶垫片过紧 3、飞机摆放位置变化导致误检测 1、检查桨叶状态 2、检查桨叶垫片是否过紧 3、将飞行器在停机坪上摆放正确"),
E321524(321524, "飞行器起飞前准备失败,可能是飞行器无GPS或档位错误导致,请检查飞行器状态 飞机日志 1、有可能是因为没有GPS或档位不对等原因导致,具体原因需分析日志 2、拉取飞行器日志联系售后分析"),
E321525(321525, "农机航线:仿地绕行失败,暂停航线"),
E321527(321527, "飞行器RTK收敛失败,无法执行飞行任务,请稍后重试或重启机场后重试 请检查飞行器RTK是否收敛成功"),
E321528(321528, "触碰自定义飞行区边界,航线任务已暂停 机场日志、飞机日志 规划的航线任务与规划的自定义飞行区有冲突 重新规划并下发航线任务或重新规划并上传自定义飞行区"),
E321530(321530, "飞行航线过程中轨迹规划失败,航线任务已暂停"),
E321531(321531, "进离场航线执行失败,请联系大疆售后。"),
E321532(321532, "进离场航线执行失败,请联系大疆售后。"),
E321533(321533, "进离场航线执行失败,请联系大疆售后。"),
E321769(321769, "飞行器卫星定位信号差,无法执行飞行任务,请重启机场后重试 机场日志、飞机日志 飞行器GPS信号弱 1、检查飞行器是否飞过信号差区域 2、检查飞行器是否受到HMS干扰 3、多次出现请拉取飞行器日志联系售后分析"),
E321770(321770, "飞行器档位错误,无法执行飞行任务,请重启机场后重试 机场日志、飞机日志 B控接管,且B控不是N档或接管后未切换档位 检查B控状态"),
E321771(321771, "飞行器返航点未设置,无法执行飞行任务,请重启机场后重试"),
E321772(321772, "飞行器电量低于30%,无法执行飞行任务,请充电后重试(建议电量≥50%)"),
E321773(321773, "低电量返航 机场日志、飞机日志 飞机电量过低 1、确认航线是否过长 2、确认飞行时电量是否充足 3、确认是否存在大风HMS告警 4、确认是否有电池相关错误码 5、确认电池健康状态 6、多次出现请拉取飞机日志"),
E321774(321774, "ADSB(触发ADS-B主动避让功能才会有)"),
E321775(321775, "飞行器航线飞行过程中失联,无法完成航线飞行 机场日志、飞机日志 飞行器与机场图传断连 1、确认失去RC信号时飞行器位置是否过远 2、确认失去RC信号时飞行器与机场是否存在遮挡 3、多次出现请拉取机场和飞行器日志联系售后分析"),
E321776(321776, "飞行器RTK收敛失败,无法执行飞行任务,请重启机场后重试"),
E321777(321777, "飞行器未悬停,无法开始执行飞行任务"),
E321778(321778, "用户使用B控操控飞行器起桨,机场无法执行飞行任务"),
E321779(321779, "实时仿地过程中,相机状态有问题(过亮、过暗、两侧亮度不一致)"),
E321780(321780, "实时仿地用户设置的仿地高度不合法(大于200m或小于30m)"),
E321781(321781, "实时仿地过程中全局地图计算出错"),
E321782(321782, "home点未匹配RTK开关状态"),
E321784(321784, "任务过程中遇到大风紧急返航"),
E322023(322023, "飞机严重故障,无法执行(hms level为3的故障)"),
E322025(322025, "找不到对应的负载(多负载情况下才有用)"),
E322026(322026, "航点动作执行失败"),
E322027(322027, "农机大田果树航线:喷洒药箱无药、播撒料箱无料"),
E322028(322028, "农机航线:避障开启,但雷达断链"),
E322281(322281, "用户退出航线,任务失败,机场执行飞行任务过程被手动打断或异常终止(例如按停止航线按钮)"),
E322282(322282, "机场执行飞行任务过程中被中断,飞行器被云端设备或B控接管 机场日志、飞机日志 B控接管后按暂停键中断航线 确认用户是否有操作"),
E322283(322283, "机场执行飞行任务过程中被用户触发返航,无法完成航线飞行 机场日志、飞机日志 用户通过司空2或遥控器主动触发返航 确认用户是否有操作"),
E322284(322284, "农机航线:用户在航线飞行过程中,主动打开/关闭仿地绕行开关"),
E322285(322285, "用户切换RC-Mode档位"),
E322332(322332, "航点坐标超出了合理范围 1、检查航线是否过远 2、检查航线是否过高或过低"),
E322536(322536, "航线任务WP平台初始化失败"),
E322537(322537, "Job退出但Mission异常运行"),
E322538(322538, "飞机已经起桨,不允许直接起飞,需要停桨才能开始航线"),
E322539(322539, "航线的断点信息错误,机场无法执行飞行任务"),
E322540(322540, "使用不支持的坐标系"),
E322541(322541, "使用不支持的高度模式"),
E322542(322542, "使用不支持的过渡航线模式"),
E322543(322543, "使用不支持的yaw模式"),
E322544(322544, "使用不支持的转yaw方向模式"),
E322545(322545, "使用不支持的航点类型"),
E322546(322546, "航线文件格式错误,首尾航点不能使用协调转弯类型"),
E322547(322547, "航线文件格式错误,航线全局速度超过合理范围"),
E322548(322548, "航线文件格式错误,航点数量异常"),
E322549(322549, "航线文件格式错误,经纬度数据异常"),
E322550(322550, "航线文件格式错误,转弯截距异常"),
E322551(322551, "航段最大速度超过合理范围"),
E322552(322552, "航段目标速度超过合理范围"),
E322553(322553, "航点yaw角度超过合理范围"),
E322554(322554, "垂直航段yaw模式异常"),
E322555(322555, "断点续飞的mission_id输入错误"),
E322556(322556, "断点续飞的progress信息输入错误"),
E322557(322557, "断点续飞的任务状态异常"),
E322558(322558, "断点续飞的航点index信息输入错误"),
E322559(322559, "断点续飞的经纬度信息输入错误"),
E322560(322560, "断点续飞的航点yaw输入错误"),
E322561(322561, "断点续飞的标志位设置错误"),
E322562(322562, "读取轨迹信息失败"),
E322563(322563, "航线轨迹生成失败,请检查飞机视觉镜头是否存在脏污或重启飞机后再试,如果仍报错请联系大疆售后。"),
E322564(322564, "轨迹库运行失败"),
E322565(322565, "航线避障紧急刹车"),
E322588(322588, "找不到对应动作"),
E322591(322591, "动作INDEX不能重复"),
E322592(322592, "动作数量异常(过多或过少)"),
E322593(322593, "动作树不能为空"),
E322594(322594, "航线文件格式错误,航点动作有误 动作树层级不能为空"),
E322595(322595, "航线文件格式错误,动作ID不能重复 动作ID不能重复;航线文件中的wpml:actionId不得重复"),
E322596(322596, "动作节点子节点数量不能小于2"),
E322597(322597, "动作INDEX超过合理范围"),
E322598(322598, "动作ID值不能为65535"),
E322599(322599, "动作树生成错误(子节点数量不等于下层节点数量)"),
E322600(322600, "动作树层级过多"),
E322601(322601, "动作树层级过少"),
E322602(322602, "动作组数量超过合理范围"),
E322603(322603, "航线文件格式错误,动作树生效范围错误"),
E322604(322604, "动作树根节点状态错误"),
E322605(322605, "动作树普通节点状态错误"),
E322606(322606, "断点续飞中动作index超过合理范围"),
E322607(322607, "动作树数量错误"),
E322608(322608, "断点信息中触发器运行结果异常"),
E322609(322609, "断点续飞中动作组ID信息不能重复"),
E322610(322610, "断点续飞中动作组位置不能重复"),
E322611(322611, "断点续飞中动作组位置超过合理范围"),
E322612(322612, "续飞中动作id不在断点信息中"),
E322613(322613, "续飞中不能修改动作状态为中断"),
E322614(322614, "断点信息错误导致续飞失败"),
E322634(322634, "未找到对应的动作执行器"),
E322649(322649, "未找到触发器"),
E322650(322650, "到点触发参数设置错误"),
E324012(324012, "日志压缩过程超时,所选日志过多,请减少选择的日志后重试"),
E324013(324013, "设备日志列表获取失败,请稍后重试"),
E324014(324014, "设备日志列表为空,请刷新页面或重启机场后重试"),
E324015(324015, "飞行器已关机或未连接,无法获取日志列表,请确认飞行器在舱内,通过远程调试将飞行器开机后重试"),
E324016(324016, "机场存储空间不足,日志压缩失败,请清理机场存储空间或稍后重试"),
E324017(324017, "日志压缩失败,无法获取所选飞行器日志,请刷新页面或重启机场后重试"),
E324018(324018, "日志文件拉取失败,导致本次设备异常反馈上传失败,请稍后重试或重启机场后重试"),
E324019(324019, "因机场网络异常,日志上传失败,请稍后重试。如果连续多次出现该问题,请联系代理商或大疆售后进行网络排障"),
E324021(324021, "因机场断电或重启导致日志导出中断,日志导出失败,请稍后重试"),
E324030(324030, "因机场网络异常、飞行器图传链路异常等原因,媒体文件暂时无法上传或文件已上传但云端读取失败 1、该任务已经不存在于上传队列中 检查是否存在网络波动"),
E324042(324042, "飞机未连接,无法查询/更新/开关证书 需要飞机开机后再操作解禁证书。"),
E325000(325000, "机场没有收到4G发送的dongle信息 1、在打开4G或者关闭4G时会报这个错 2、命令超时 与SDR和LTE链路切换有关,dongle或链路信息获取超时。请检查飞机是否开机,4G dongle是否正常工作。"),
E325001(325001, "云端下发给机场的命令不符合格式要求,机场无法执行 JSON解析错误 1、数据格式与文档不匹配 2、数据超出了允许范围"),
E325003(325003, "设备端命令响应错误,请重试 命令未知错误 1、检查下发指令参数是否与文档一致 2、需起飞后才可使用DRC命令控云台 3、相机模式错误,如录像模式下拍照 4、非直播红外镜头情况下设置红外参数 5、双光相机设置保存的照片类型。"),
E325004(325004, "设备端命令请求已超时,请重试 请求超时。需确认调用方法及流程正确。"),
E325005(325005, "当前机场无法响应任务,请稍后重试"),
E325006(325006, "当前机场启动检查中,请稍后重试"),
E325007(325007, "当前机场执行作业任务中,请稍后重试"),
E325008(325008, "当前机场处理作业任务结果中,请稍后重试"),
E325009(325009, "当前机场执行远程日志导出中,请稍后重试"),
E325010(325010, "当前机场更新自定义飞行区中,请稍后重试"),
E325011(325011, "当前机场更新离线地图中,请稍后重试"),
E325012(325012, "当前飞机未连接,请稍后重试"),
E325013(325013, "设备正忙,请稍后重试"),
E325014(325014, "未知错误 检查切换镜头指令的video_type大小写是否有误"),
E326002(326002, "飞行器未安装DJI Cellular模块"),
E326003(326003, "飞行器DJI Cellular模块中未安装SIM卡"),
E326004(326004, "飞行器DJI Cellular模块需要强制升级,否则无法使用"),
E326005(326005, "操作失败,增强图传无法建立连接,请检查4G信号强度,或咨询运营商查询套餐流量和APN设置 检查4G模块是否亮绿灯"),
E326006(326006, "增强图传开关切换失败,请稍后重试"),
E326007(326007, "切换链路的JSON请求无效 JSON数据异常 发送的MQTT命令格式有误,需要注意link_workmode参数为整数类型。"),
E326008(326008, "机场未安装DJI Cellular模块"),
E326009(326009, "机场DJI Cellular模块中未安装SIM卡"),
E326010(326010, "机场DJI Cellular模块需要强制升级,否则无法使用"),
E326011(326011, "检查飞机是否开机,需要飞机开机进行设置。"),
E326015(326015, "设备繁忙,稍后重试"),
E326103(326103, "当前eSIM正在激活中,请稍后再试"),
E326104(326104, "当前eSIM正在切换运营商中,请稍后再试"),
E326105(326105, "DJI增强图传模块正在切换模式中,请稍后再试"),
E326106(326106, "DJI增强图传模块异常,请重启设备后再试,如果仍报错请联系大疆售后"),
E326107(326107, "请在设备管理 > 机场 > 设备运维中激活DJI增强图传模块的eSIM或插入SIM卡后再试"),
E327000(327000, "参数设置失败,请稍后重试"),
E327001(327001, "参数设置失败,请稍后重试 需检查DRC连接状态是否为已连接 1、可通过监控Topic:thing/product/{gateway_sn}/events,method为drc_status_notify上报的状态是否为2(已连接) 2、若未上报可监控机场OSD状态上报的drc_state:2(已连接)"),
E327002(327002, "获取控制权失败,请稍后重试"),
E327003(327003, "获取控制权失败,请稍后重试 被抢夺设备不在线 需根据飞机上报的OSD payload_index传入正确payload_index"),
E327004(327004, "画面拖动失败,请重试"),
E327005(327005, "双击画面归中失败 https://sdk-forum.dji.net/hc/zh-cn/articles/20319918034073"),
E327006(327006, "拍照失败 1、开启录像需将相机切换到录像模式 2、开启录像前需获取负载控制权"),
E327007(327007, "开始录像失败 检查相机模式和负载控制权"),
E327008(327008, "停止录像失败"),
E327009(327009, "切换相机模式失败 可能原因: 1、未插SD卡 2、SD卡有问题,不兼容 3、升级到最新固件重试 4、未抢夺负载控制权 5、下发指令频率过高,相机回调状态未响应"),
E327010(327010, "ZOOM相机变焦失败 1、在机场上报的OSD中查看zoom_factor是否变化 2、使用遥控器连接飞机,查看变焦倍数是否变化 3、设置变焦倍数为其它值,查看云端是否能获知 4、命令超时未收到回包 5、相机模块内部错误(当前状态不支持)"),
E327011(327011, "IR相机变焦失败"),
E327012(327012, "获取控制权失败,请稍后重试"),
E327013(327013, "参数设置失败,请稍后重试"),
E327014(327014, "云台已达限位"),
E327015(327015, "直播启动失败,建议刷新直播或重新打开设备小窗 无效的相机镜头类型"),
E327016(327016, "失联动作设置失败,请重试"),
E327017(327017, "指点飞行高度设置失败,请重试"),
E327018(327018, "指点飞行模式切换失败,请重试"),
E327019(327019, "当前状态无法看向标注点 当前状态不支持“look at”"),
E327020(327020, "全景拍照停止命令超时"),
E327050(327050, "当前设备状态不支持播放音频"),
E327051(327051, "下载音频文件失败"),
E327052(327052, "喊话器处理模式切换失败"),
E327053(327053, "上传音频文件失败 1、检查storage_config_get请求与回复是否正常 2、确认OSS配置正确 3、确认喊话器支持PSDK3.6及以上版本 4、无人机和机场固件升级至最新 5、检查文件MD5是否正确"),
E327054(327054, "播放音频失败 音频可通过命令检查:ffplay -nodisp -autoexit -ar 16000 -ac 1 -f s16le -i xxx.pcm"),
E327055(327055, "设置工作模式失败"),
E327056(327056, "上传文本失败"),
E327057(327057, "停止播放失败"),
E327058(327058, "设置播放模式失败"),
E327059(327059, "设置音量失败 基于司空2交叉验证喊话器功能是否正常"),
E327060(327060, "设置控件值失败"),
E327061(327061, "发送文本值失败"),
E327062(327062, "切换系统语言失败"),
E327063(327063, "获取设备功能列表失败 检查自定义飞行区参数是否缺失"),
E327064(327064, "获取设备配置文件失败"),
E327065(327065, "获取设备图片文件失败"),
E327066(327066, "设备文件压缩失败"),
E327067(327067, "设备文件上传失败"),
E327068(327068, "上传音频文件失败,MD5校验失败"),
E327069(327069, "上传音频文件失败"),
E327070(327070, "上传音频文件失败,异常终止"),
E327071(327071, "上传TTS文本失败,MD5校验失败"),
E327072(327072, "上传TTS文本失败"),
E327073(327073, "上传TTS文本失败,异常终止"),
E327074(327074, "喊话器重播失败"),
E327075(327075, "喊话器编码失败"),
E327201(327201, "全景拍照失败"),
E327202(327202, "全景拍摄终止"),
E327203(327203, "当前设备不支持全景拍照"),
E327204(327204, "系统繁忙,无法全景拍照"),
E327205(327205, "请求失败,无法全景拍照"),
E327206(327206, "飞机未起飞,无法开始全景拍摄"),
E327207(327207, "控制权获取失败,全景拍摄终止"),
E327208(327208, "未知相机错误,无法开始全景拍摄"),
E327209(327209, "相机超时,全景拍摄终止"),
E327210(327210, "无法全景拍照"),
E327211(327211, "存储空间不足,全景拍摄终止"),
E327212(327212, "飞机运动中,无法开始全景拍摄"),
E327213(327213, "云台运动中,无法开始全景拍摄"),
E327214(327214, "用户操作摇杆,全景拍摄终止"),
E327215(327215, "碰到限飞区,全景拍摄终止"),
E327216(327216, "触发距离限制,全景拍摄终止"),
E327217(327217, "云台受阻,全景拍摄终止"),
E327218(327218, "拍照失败,全景拍摄终止"),
E327219(327219, "全景图片拼接失败"),
E327220(327220, "加载标定参数失败,全景拍摄终止"),
E327221(327221, "调整相机参数失败,全景拍摄终止"),
E327500(327500, "飞行器镜头除雾失败,请稍后重试"),
E327504(327504, "播放音频失败 1、检查音频文件格式"),
E328023(328023, "因飞机告警导致无法起飞"),
E328051(328051, "飞机未完成实名登记,请连接遥控器,按照指引完成实名登记后飞行"),
E328052(328052, "飞机实名登记状态已注销,请连接遥控器,按照指引完成实名登记后飞行"),
E328079(328079, "电池认证失败,请更换DJI官方电池(0x1610004F) 1、请检查使用的电池是否为DJI官方电池,设备固件是否最新(如不是最新请升级至最新且匹配版本),非官方电池将阻飞; 2、请更换电池排查;如果更换多个电池故障依旧,建议使用75%浓度以上的酒精擦拭电池或者机身上的金属触点;"),
E332514(332514, "HMS告警导致的无法起飞"),
E336000(336000, "指点飞行命令发送失败,请重试"),
E336001(336001, "飞行器数据异常,无法响应指令"),
E336002(336002, "飞行器GPS信号差"),
E336003(336003, "飞行器定位失效,无法响应指令"),
E336004(336004, "指点飞行自主规划失败"),
E336005(336005, "飞行器返航点未更新"),
E336006(336006, "飞行器已失联,已退出指点飞行"),
E336017(336017, "飞行器电量不足以完成当前任务"),
E336018(336018, "已切换飞行器规划模式"),
E336019(336019, "指点飞行因限高自动调整飞行高度"),
E336513(336513, "目标点在禁飞区内"),
E336514(336514, "目标点超出飞行器限远"),
E336515(336515, "目标点在禁飞区内"),
E336516(336516, "目标点超出飞行器限高"),
E336517(336517, "目标点超出飞行器限低"),
E337025(337025, "飞行器无法起飞"),
E337026(337026, "目标点异常,请重试 设置的目标点经纬度超出了有效范围"),
E337027(337027, "飞行器速度设置异常,请重试"),
E337028(337028, "飞行器版本异常,请检查飞行器版本"),
E337029(337029, "飞行器无法响应当前任务,请稍后重试"),
E337030(337030, "指令飞行安全离场高过低 起飞高度输入过低"),
E337537(337537, "已触碰禁飞区"),
E337538(337538, "已触碰飞行器限远"),
E337539(337539, "已触碰禁飞区"),
E337540(337540, "已触碰飞行器限高或限高区"),
E337541(337541, "已触碰飞行器限低"),
E337542(337542, "飞行器起飞失败,请重试"),
E337543(337543, "目标点可能在障碍物内,请检查周边环境"),
E337544(337544, "检测到障碍物,请检查周边环境"),
E337545(337545, "飞行器规划异常,请重试 规划因为某种原因删除了路径 10.1.8版本会修复。起飞时RTK不收敛会导致该报错。"),
E337546(337546, "已触碰自定义飞行区边界"),
E338001(338001, "飞行器通信异常,无法执行飞行任务,请重启飞行器与机场后重试"),
E338002(338002, "飞行器通信异常,无法执行飞行任务,请重启飞行器与机场后重试"),
E338003(338003, "飞行器通信异常,无法执行飞行任务,请重启飞行器与机场后重试"),
E338004(338004, "飞行器通信异常,无法执行飞行任务,请重启飞行器与机场后重试"),
E338005(338005, "起飞机场与降落机场部署距离超出限制,无法执行飞行任务,请选择两个部署距离不超过15km的机场执行任务"),
E338006(338006, "无法执行飞行任务,请检查降落机场是否已申请解禁证书、是否位于自定义禁飞区或是否位于自定义飞行区外"),
E338007(338007, "目标降落机场部署突破限高区限高,无法执行任务,请申请解禁证书后再试"),
E338008(338008, "目标降落机场部署突破飞行器设置的限高,无法执行任务,请调整限高后重试"),
E338009(338009, "飞行器GPS定位信号差,无法执行任务,请重启飞行器后重试"),
E338010(338010, "飞行器定位失效,无法执行任务,请重启飞行器后重试"),
E338011(338011, "任务失败,目标机场处于地理鸟笼作业区域外,请重新规划任务后再试"),
E338017(338017, "飞行器数据更新失败,无法执行任务,请重启飞行器后重试"),
E338018(338018, "飞行器数据更新失败,无法执行任务,请重启飞行器后重试"),
E338019(338019, "飞行器到目标机场的返航路线正在规划中,无法执行任务,请重启飞行器后重试"),
E338020(338020, "飞行器无法根据规划的路径到达目标降落机场,无法执行任务,请重新选择降落机场后再试"),
E338021(338021, "飞行器当前电量不足以到达目标降落机场,无法执行任务,请给飞行器充电后重试"),
E338049(338049, "响应遥控器杆量,已退出指点飞行"),
E338050(338050, "响应终止指令,已退出指点飞行"),
E338051(338051, "飞行器低电量返航,已退出指点飞行"),
E338052(338052, "飞行器低电量降落,已退出指点飞行"),
E338053(338053, "附近有载人机,已退出指点飞行"),
E338054(338054, "响应其他高优先级任务,已退出指点飞行"),
E338255(338255, "飞行器通信异常,无法执行飞行任务,请重启飞行器与机场后重试"),
E386534(386534, "航线错误。上云API不支持通过KML设置模板航线。必须基于WPML来生成航线"),
E386535(386535, "航线执行异常,请稍后重试或重启机场后重试"),
E513001(513001, "直播失败,飞行器不存在或飞行器类型错误 机场日志、飞机日志 云端直播命令内容有误,例如本地机场或飞机的SN是4SEDL13001002C,但实际收到的云端命令中SN与本地SN不匹配。需要查看云端日志定位。 请检查云端发送到机场的命令格式是否正确(机场上报的直播能力中携带了机场及飞机设备的SN号,需要检查云端下发的直播命令中的SN号是否与其匹配)"),
E513002(513002, "直播失败,相机不存在或相机类型错误 机场日志、飞机日志 直播错误,相机不存在,飞机没有挂Z30,却要求Z30的图传,就需要报此错误 请检查云端发送到机场的命令格式是否正确(机场上报的直播能力中携带了相机的video_id,需要检查云端下发的直播命令中的video_id是否与其匹配)"),
E513003(513003, "相机已经在直播中,请勿重复开启直播 机场日志、飞机日志 重复点播,相机已经在直播中(云端已特殊处理) 通过state查看直播状态,确定是否有镜头正在直播"),
E513005(513005, "直播失败,直播参数(清晰度)设置错误 机场日志、飞机日志 直播错误,策略不支持,比如APP只支持标清、高清、超清、自适应四种直播策略,不支持其他类型的策略 请检查云端发送到机场的直播命令格式是否正确(直播命令中携带的清晰度枚举值是否在合理范围内)"),
E513006(513006, "操作失败,相机未开启直播,无法响应直播设置 机场日志、飞机日志 \"直播视频没有图传订阅(liveview订阅中没有该码流) 直播错误,当前APP不在liveview界面,无法响应某些直播设置\" 非正常流程,请上传机场及飞机日志反馈售后进行故障分析"),
E513008(513008, "操作失败,相机未开启直播,无法响应直播设置 机场日志、飞机日志 liveview订阅的图传通道数据异常(图传码流为0) \"1、检查飞机与机场之间的图传质量(由于图传受干扰,导致机场接收到的飞机图传码流异常;如果确认图传质量良好但仍出现513008错误码,请上传机场及飞机日志用于定位) 2、飞机不能直播也有可能是机场的固件问题,要把机场固件升级到最新。\""),
E513009(513009, "无"),
E513010(513010, "直播失败,设备无法联网 机场日志、飞机日志 无法连接流媒体服务 \"直播声网连接失败 设备无法连接到直播服务器,可能原因有。 1、网络不佳,未能连接上流媒体服务器 2、流媒体服务器配置有误 3、流媒体服务器不支持的推流格式,例如:非WHIP信令的WebRTC服务。 4、如果使用WebRTC协议,请注意:机场2 WebRTC直播在国内仅支持HTTP,在海外支持HTTPS的Dolby服务器。这种情况下,可以用HTTP做个反向代理。\""),
E513011(513011, "操作失败,设备未开启直播 机场日志、飞机日志 停止或设置清晰度请求失败,因为没有正在直播 机场向直播服务器发起Register注册时超时。可能是服务器没有收到这条注册消息或者服务器流程异常。"),
E513012(513012, "操作失败,设备已在直播中,不支持切换镜头"),
E513013(513013, "直播失败,直播使用的视频传输协议不支持"),
E513014(513014, "直播失败,直播参数错误或者不完整 机场日志、飞机日志 URL参数错误 请检查云端发送到机场的直播命令格式是否正确"),
E513015(513015, "直播异常,网络卡顿 机场日志、飞机日志 网络拥塞 请检查机场网络状态(机场上行带宽至少10Mbps)"),
E513016(513016, "直播异常,视频解码失败 机场日志、飞机日志 视频关键帧错误(长时间收不到关键帧) \"1、非正常流程,请上传机场及飞机日志用于定位编码问题 2、检查是否网络原因导致关键帧丢失\""),
E513017(513017, "直播已暂停,请等待当前飞行器媒体文件下载完成后再试 机场日志、飞机日志 由于相机进入回放导致无法直播 检查飞机是否处于执行完毕航线任务后上传媒体过程中,此时无法开启飞机直播。其他情况如出现513017请上传机场及飞行器日志反馈售后分析"),
E513099(513099, "直播失败,请稍后重试 内部错误 \"1、重启机场和飞行器后重试 2、检查直播参数特别是参数的数据类型是否有误。\""),
E514100(514100, "机场运行异常,请重启机场后重试"),
E514101(514101, "推杆闭合失败,请检查停机坪上是否存在异物,飞行器方向是否放反,或重启机场后重试 机场日志、飞机日志 1、停机坪电源线断裂 2、推杆舵机损坏 3、推杆被异物卡住 1、根据HMS报错信息进行故障排查 2、重启机场后进行重试 3、检查推杆状态 4、可能存在硬件损坏:停机坪电源线断裂/推杆舵机损坏/推杆被异物卡住"),
E514102(514102, "推杆展开失败,请检查停机坪上是否存在异物,或重启机场后重试"),
E514103(514103, "飞行器电量低,无法执行飞行任务,请充电后(建议≥50%)重试 机场日志、飞机日志 飞行器电量低 等待充电至30%以上,重新下发任务"),
E514104(514104, "飞行器电池开始充电失败,请重启机场后重试 充电时请保持飞机舱关闭。另外,请检查HMS中是否有任何过热警报。过热也会导致充电异常。"),
E514105(514105, "飞行器电池停止充电失败,请重启机场后重试 机场日志、飞机日志 1、内部逻辑异常 2、充电链路通讯异常 1、升级最新固件 2、重启机场和飞行器 3、拉取机场和飞行器日志联系售后分析"),
E514106(514106, "飞行器电源控制异常,请重启机场后重试"),
E514107(514107, "舱盖开启失败,请检查舱盖周围是否存在异物,或重启机场后重试 机场日志、飞机日志 1、舱盖卡住或重物覆盖导致堵转 2、电机刹车异常,无法正常解锁 3、主控模块异常 4、电机减速机损坏卡死 5、驱动器损坏 6、电机线圈短路 7、位置反馈磁环位置发生移动 1、机场上电,手动按下解锁按钮,检查是否有“咔哒”的解锁声音,手动开启舱盖,检查是否可以正常开启或关闭舱盖以及是否有异响。 2、若无,则可能为刹车损坏或刹车连接器接触不良,需卸下摆臂把舱盖取下并掀开停机坪,排查主控模块刹车接口供电,更换主控模块或电机进行交叉测试。 3、若有解锁声音但无法开启舱盖,则可能电机卡死损坏,需更换电机。 4、若手动可正常开启但APP控制不动作,则可能是驱动器或电机损坏。 5、使用APP重新标定舱盖位置。"),
E514108(514108, "舱盖关闭失败,请检查舱盖周围是否存在异物,或重启机场后重试 机场日志、飞机日志 1、舱盖卡住或重物覆盖导致堵转 2、磁环位置发生移动 3、主控模块损坏 4、电机减速机损坏卡死 5、驱动器损坏 6、霍尔传感器异常 1、机场上电,手动按下解锁按钮,检查是否有“咔哒”的解锁声音,手动开启舱盖,检查是否可以正常开启或关闭舱盖以及是否有异响。 2、若无,则可能为刹车损坏或刹车连接器接触不良,需卸下摆臂把舱盖取下并掀开停机坪,排查主控模块刹车接口供电,再测量刹车线圈电阻,根据测量结果更换主控模块或电机。 3、若有解锁声音但无法开启舱盖,则可能电机卡死损坏,需更换电机。 4、若手动可正常开启但APP控制不动作,则可能是驱动器或电机损坏,或主控损坏。 5、使用APP重新标定舱盖位置。"),
E514109(514109, "飞行器开机失败,请检查飞行器电池是否安装到位且电量是否正常,或重启机场后重试 机场日志、飞机日志 1、飞行器电池电量低 2、电池固件不兼容 3、充电连接器通讯异常 1、检查飞机电池电量是否大于30% 2、升级至最新机场和飞机固件 3、修复以上问题后重启机场重试"),
E514110(514110, "飞行器关机失败,请重启机场后重试 机场日志、飞机日志 1、固件版本过低 2、充电连接器通讯异常 1、升级飞行器和机场固件至最新版本 2、重启后重试 3、检查充电连接器金属片是否插入飞行器"),
E514111(514111, "飞行器慢转收桨控制异常,请重启机场后重试"),
E514112(514112, "飞行器慢转收桨控制异常,请重启机场后重试"),
E514113(514113, "机场与飞行器无法建立有线连接,请检查飞行器是否在舱内,推杆闭合时是否被卡住,充电连接器是否脏污或损坏 机场日志、飞机日志 1、停机坪下充电连接线断裂 2、飞机不在机场停机坪上 3、推杆片簧金属片没有插入飞机 1、检查飞行器是否在停机坪上 2、检查左右充电线连接是否正常且无断裂 3、远程调试是否可控制飞行器开关机或充电 4、检查充电连接器金属片是否插入飞行器"),
E514114(514114, "获取飞行器电源状态失败,请重启机场后重试"),
E514116(514116, "无法执行当前操作,机场正在执行其他控制指令,请稍后重试 机场日志、飞机日志 指令冲突 等待上一步操作执行完毕后再进行操作"),
E514117(514117, "舱盖开启或关闭未到位,请重启机场后重试"),
E514118(514118, "推杆展开或闭合未到位,请重启机场后重试"),
E514120(514120, "机场与飞行器断连,请重启机场后重试或重新对频 机场和无人机之间的图传链路断开了,可以尝试重启机场"),
E514121(514121, "机场急停按钮被按下,请释放急停按钮 机场日志、飞机日志 急停按钮被按下 向外拔出急停按钮"),
E514122(514122, "获取飞行器充电状态失败,请重启机场后重试"),
E514123(514123, "飞行器电池电量过低无法开机"),
E514124(514124, "获取飞行器电池信息失败,无法执行飞行任务,请重启机场后重试 机场日志 1、电池未插到位 2、电池电量低,进入休眠状态 1、检查双电池是否插入到位 2、确认电池电量是否为0 3、打开远程调试,给飞机充电至40%以上后重试下发任务"),
E514125(514125, "飞行器电池电量已接近满电状态,无法开始充电,请使用至95%以下再进行充电"),
E514126(514126, "获取bid失败,请检查发送的MQTT命令是否缺少bid字段"),
E514134(514134, "雨量过大,机场无法执行飞行任务,请稍后重试 机场日志 大雨无法飞行 等待雨量减小后再下发任务"),
E514135(514135, "风速过大(≥12m/s),机场无法执行飞行任务,请稍后重试 机场日志 大风无法飞行 等待风速降低后再下发任务"),
E514136(514136, "机场供电断开,机场无法执行飞行任务,请恢复机场供电后重试 机场日志 1、无市电输入 2、ACDC损坏 3、ACDC与主控模块连接线缆断开 1、检查市电供电是否正常 2、检查ACDC输出是否正常 3、检查ACDC与主控模块连接线缆 4、更换ACDC或主控模块"),
E514137(514137, "环境温度过低于-20℃(-4°F),机场无法执行飞行任务,请稍后重试"),
E514138(514138, "飞行器电池正在保养中,机场无法执行飞行任务,请等待保养结束后重试"),
E514139(514139, "飞行器电池无法执行保养指令,飞行器电池无需保养"),
E514140(514140, "飞行器电池无法执行保养指令,飞行器电池无需保养"),
E514141(514141, "机场系统运行异常,请重启机场后重试 机场日志、飞机日志 设备逻辑异常 远程重启机场和飞行器后重新下发任务,若仍存在问题,请拉取机场和飞行器日志联系售后分析"),
E514142(514142, "飞行器起飞前,机场与飞行器无法建立有线连接,请检查飞行器是否在舱内,推杆闭合时是否被卡住,充电连接器是否脏污或损坏 机场日志、飞机日志 1、起飞前检查充电连接器通讯异常 2、飞机不在机场停机坪上 3、推杆片簧金属片没有插入飞机 4、检查并修复以上异常后,重启机场 1、远程调试是否可控制飞行器开关机或充电 2、检查飞行器是否在停机坪上 3、检查充电连接器金属片是否已插入飞行器 4、检查停机坪下方充电连接线是否连接正常"),
E514143(514143, "推杆未闭合或闭合不到位,请稍后重试或重启机场后重试 机场日志 1、停机坪与主控模块电源线连接不良 2、推杆舵机损坏 3、推杆被异物卡住 4、检查并修复以上异常后,重启机场 1、远程调试控制推杆运动,查看是否正常运行 2、通过机场监控摄像头查看推杆是否有异物卡住 3、机场断电后手动推动推杆,检查是否卡住 4、可能硬件损坏:停机坪与主控模块电源线连接不良/推杆舵机损坏"),
E514144(514144, "舱盖未关闭或关闭不到位,请稍后重试或重启机场后重试"),
E514145(514145, "机场处于现场调试中,无法执行当前操作或飞行任务,请断开遥控器与机场数据线后重试 机场日志 处于现场调试无法作业"),
E514146(514146, "机场处于远程调试中,无法执行飞行任务,请退出远程调试后重试 机场日志 处于远程调试无法作业"),
E514147(514147, "设备升级中,无法进行远程调试或执行飞行任务,请等待升级完成后重试 机场日志 处于升级状态无法作业"),
E514148(514148, "机场已经在作业中,无法进行远程调试或再次执行飞行任务,请等待当前任务执行完成后重试"),
E514149(514149, "机场系统运行异常,无法执行飞行任务,请重启机场后重试"),
E514150(514150, "设备重启中,无法执行飞行任务,请等待重启完成后重试 机场日志 机场重启中 等待重启完成"),
E514151(514151, "设备升级中,无法执行设备重启指令,请等待升级完成后重试"),
E514153(514153, "机场已退出远程调试模式,无法执行当前操作"),
E514154(514154, "获取内循环出风口温度失败,请稍后再试"),
E514156(514156, "飞机不在舱内,请立即检查飞行器是否已安全降落并将飞行器放回至机场"),
E514157(514157, "执行开机失败,无线充电线圈业务繁忙,请重启机场后再试 1、检查市电是否断开"),
E514158(514158, "无法起飞,机场RTK业务异常,请重启机场后再试 机器RTK异常。模拟飞行需要RTK正常收敛。"),
E514159(514159, "任务失败,降落机场检测到飞行器,请确保降落机场没有飞行器后再试"),
E514162(514162, "飞机和机场连接失败,请关闭机场舱盖或重启机场后再试"),
E514163(514163, "电池功能异常,请确保飞行器电池插入到位或重启飞行器后再试"),
E514164(514164, "设备重启失败,请稍后重试,如果仍报错请联系大疆售后。"),
E514165(514165, "设备重启失败,请稍后重试,如果仍报错请联系大疆售后。"),
E514170(514170, "机场系统初始化中,无法执行当前操作或指令,请等待机场系统初始化完成后重试"),
E514171(514171, "云端下发给机场的命令不符合格式要求,机场无法执行"),
E514172(514172, "飞行器无法关机,蓝牙连接状态为未连接,请尝试重启飞行器和机场,或去现场重新对频飞行器与机场后再试"),
E514173(514173, "由于天气原因(环境温度低于5℃并且降雨大于等于中雨),可能导致桨叶结冰影响作业安全,暂无法执行任务"),
E514174(514174, "飞行器充电失败,机场舱盖开启或关闭未到位,请关闭舱盖后再试"),
E514180(514180, "停止空调制冷或停止空调制热失败,请稍后重试"),
E514181(514181, "开启空调制冷失败,请稍后重试"),
E514182(514182, "开启空调制热失败,请稍后重试"),
E514183(514183, "开启空调除湿失败,请稍后重试"),
E514184(514184, "当前温度低于 0 ℃(32°F),无法开启空调制冷"),
E514185(514185, "当前温度高于 45 ℃(115°F),无法开启空调制热"),
E514300(514300, "网关异常"),
E514301(514301, "请求超时,连接断开 1、为了保证DRC链路不断开,每分钟需要至少发送一次心跳命令给机场。"),
E514302(514302, "网络证书异常,连接失败"),
E514303(514303, "机场网络波动导致DRC连接丢失 需检查DRC连接状态是否为已连接 1、可通过监控Topic:thing/product/{gateway_sn}/events,method为drc_status_notify上报的状态是否为2(已连接) 2、若未上报可监控机场OSD状态上报的drc_state:2(已连接)做补偿。"),
E328145(328145, "禁飞等问题"),
E328074(328074, "无人机定位问题"),
UNKNOWN(-1, "UNKNOWN"),
;
private final String msg;
private final int code;
ErrorCodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public String getMessage() {
return this.msg;
}
@Override
public Integer getCode() {
return this.code;
}
/**
* @param code error code
* @return enumeration object
*/
public static ErrorCodeEnum find(int code) {
return Arrays.stream(values()).filter(codeEnum -> codeEnum.code == code).findAny().orElse(UNKNOWN);
}
}

29
dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/map/api/AbstractOfflineMapService.java

@ -10,12 +10,12 @@ import org.dromara.common.sdk.config.version.CloudSDKVersionEnum;
import org.dromara.common.sdk.config.version.GatewayManager;
import org.dromara.common.sdk.config.version.GatewayTypeEnum;
import org.dromara.common.sdk.mqtt.ChannelName;
import org.dromara.common.sdk.mqtt.MqttGatewayPublish;
import org.dromara.common.sdk.mqtt.MqttReply;
import org.dromara.common.sdk.mqtt.TopicConst;
import org.dromara.common.sdk.mqtt.requests.TopicRequestsRequest;
import org.dromara.common.sdk.mqtt.requests.TopicRequestsResponse;
import org.dromara.common.sdk.mqtt.services.ServicesPublish;
import org.dromara.common.sdk.mqtt.services.ServicesReplyData;
import org.dromara.common.sdk.mqtt.services.TopicServicesResponse;
import org.dromara.common.sdk.mqtt.services.*;
import org.dromara.common.sdk.mqtt.state.TopicStateRequest;
import org.dromara.common.sdk.mqtt.state.TopicStateResponse;
import jakarta.annotation.Resource;
@ -23,6 +23,11 @@ import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import java.util.Objects;
import java.util.UUID;
import static org.springframework.integration.context.IntegrationContextUtils.DEFAULT_TIMEOUT;
/**
* @author sean
@ -34,6 +39,10 @@ public abstract class AbstractOfflineMapService {
@Resource
private ServicesPublish servicesPublish;
@Resource
private MqttGatewayPublish gatewayPublish;
/**
* When the offline map is closed, offline map synchronization will no longer automatically synchronize.
* @param request data
@ -78,10 +87,20 @@ public abstract class AbstractOfflineMapService {
* @param request data
* @param headers The headers for a {@link Message}.
* @return events_reply
* TopicRequestsResponse<MqttReply<OfflineMapGetResponse>>
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_OFFLINE_MAP_GET, outputChannel = ChannelName.OUTBOUND_REQUESTS)
@CloudSDKVersion(since = CloudSDKVersionEnum.V1_0_1, include = GatewayTypeEnum.DOCK2)
public TopicRequestsResponse<MqttReply<OfflineMapGetResponse>> offlineMapGet(TopicRequestsRequest<OfflineMapGetRequest> request, MessageHeaders headers) {
throw new UnsupportedOperationException("offlineMapGet not implemented");
public void offlineMapGet(TopicRequestsRequest<OfflineMapGetRequest> request, MessageHeaders headers) {
MqttReply success = MqttReply.success();
String topic = TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT + Objects.requireNonNull(request.getGateway()) + TopicConst.SERVICES_SUF;
gatewayPublish.publish(
topic,0, new TopicServicesRequest<>()
.setTid(UUID.randomUUID().toString())
.setBid(null)
.setTimestamp(System.currentTimeMillis())
.setMethod("offline_map_get")
.setData(success));
//throw new UnsupportedOperationException("offlineMapGet not implemented");
}
}

6
dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/psdk/PsdkWidgetValue.java

@ -35,7 +35,7 @@ public class PsdkWidgetValue {
private PsdkSpeaker psdkSpeaker;
@JsonProperty("values")
private List<String> values;
private List<Object> values;
public PsdkWidgetValue() {
}
@ -99,11 +99,11 @@ public class PsdkWidgetValue {
return this;
}
public List<String> getValues() {
public List<Object> getValues() {
return values;
}
public PsdkWidgetValue setValues(List<String> values) {
public PsdkWidgetValue setValues(List<Object> values) {
this.values = values;
return this;
}

2
dk-common/common-mybatis/src/main/resources/common-mybatis.yml

@ -23,7 +23,7 @@ mybatis-plus:
dbConfig:
# 主键类型
# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
idType: ASSIGN_ID
idType: AUTO
# 逻辑已删除值(框架表均使用此值 禁止随意修改)
logicDeleteValue: 2
# 逻辑未删除值

6
dk-common/common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java

@ -363,6 +363,11 @@ public class OssClient {
return url;
}
//自定义上传prefix路径
public UploadResult uploadPrefix(byte[] data, String prefix, String suffix,String fileName, String contentType) {
return upload(new ByteArrayInputStream(data), getPath(prefix, suffix,fileName), Long.valueOf(data.length), contentType);
}
/**
* 上传 byte[] 数据到 Amazon S3使用指定的后缀构造对象键
*
@ -649,4 +654,5 @@ public class OssClient {
return policy.replaceAll("bucketName", bucketName);
}
}

28
dk-modules/business/pom.xml

@ -121,6 +121,34 @@
<artifactId>common-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- html转pdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>

160
dk-modules/business/src/main/java/org/dromara/business/controller/BusinessAlertConstructInfoOssController.java

@ -0,0 +1,160 @@
package org.dromara.business.controller;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import org.dromara.business.utils.MinioUntil;
import org.dromara.business.utils.constants.MinIOConstants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.MimeTypeUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.business.domain.bo.BusinessAlertConstructInfoOssBo;
import org.dromara.business.service.IBusinessAlertConstructInfoOssService;
import org.dromara.business.domain.vo.BusinessAlertConstructInfoOssVo;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.springframework.web.multipart.MultipartFile;
/**
* 预警任务-施工信息-oss
* 前端访问路由地址为:/business/businessAlertConstructInfoOss
*
* @author szs
* @date 2025-06-04
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/alertConstructInfoOss")
public class BusinessAlertConstructInfoOssController extends BaseController {
private final IBusinessAlertConstructInfoOssService businessAlertConstructInfoOssService;
/**
* 查询预警任务-施工信息-oss列表
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:list")
@GetMapping("/list")
public TableDataInfo<BusinessAlertConstructInfoOss> list(BusinessAlertConstructInfoOssBo bo, PageQuery pageQuery) {
TableDataInfo<BusinessAlertConstructInfoOss> businessAlertConstructInfoOssVoTableDataInfo = businessAlertConstructInfoOssService.queryPageList(bo, pageQuery);
return businessAlertConstructInfoOssVoTableDataInfo;
}
/**
* 预警任务-施工信息-oss - 上传
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:upload")
// @Log(title = "预警任务-施工信息-oss", businessType = BusinessType.EXPORT)
@PostMapping("/upload")
public R<BusinessAlertConstructInfoOssBo> upload(@RequestPart("file") MultipartFile file, BusinessAlertConstructInfoOssBo bo, HttpServletResponse response) {
if (ObjectUtil.isNull(file)) {
return R.fail("上传文件不能为空");
}
if(ObjectUtil.isNull(bo.getAlertConstructInfoId())){
return R.fail("施工信息ID不能为空!");
}
//文件上传
// OssClient storage = OssFactory.instance(MinIOConstants.BUCKET_DKCY);
OssClient storage = OssFactory.instance(MinIOConstants.BUCKET_NANTONG);
String originalfileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
UploadResult uploadResult;
try {
uploadResult = storage.uploadPrefix(file.getBytes(),"construct", suffix, originalfileName, file.getContentType());
} catch (IOException e) {
throw new ServiceException(e.getMessage());
}
//保存记录
BusinessAlertConstructInfoOssBo businessAlertConstructInfoOssBo = new BusinessAlertConstructInfoOssBo();
businessAlertConstructInfoOssBo.setAlertConstructInfoId(bo.getAlertConstructInfoId());
businessAlertConstructInfoOssBo.setFileName(file.getName());
businessAlertConstructInfoOssBo.setOriginalName(originalfileName);
businessAlertConstructInfoOssBo.setFileSuffix(suffix);
businessAlertConstructInfoOssBo.setUrl(uploadResult.getFilename()); //格式:construct/2025/06/05/46e26e2df3a94a2dabb0d445ad3438f2DJI_20250602104843_0001_V.jpeg
businessAlertConstructInfoOssBo.setService(storage.getConfigKey());
businessAlertConstructInfoOssService.insertByBo(businessAlertConstructInfoOssBo);
return R.ok(businessAlertConstructInfoOssBo);
}
/**
* 导出预警任务-施工信息-oss列表
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:export")
// @Log(title = "预警任务-施工信息-oss", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(BusinessAlertConstructInfoOssBo bo, HttpServletResponse response) {
List<BusinessAlertConstructInfoOssVo> list = businessAlertConstructInfoOssService.queryList(bo);
ExcelUtil.exportExcel(list, "预警任务-施工信息-oss", BusinessAlertConstructInfoOssVo.class, response);
}
/**
* 获取预警任务-施工信息-oss详细信息
*
* @param id 主键
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:query")
@GetMapping("/{id}")
public R<BusinessAlertConstructInfoOssVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(businessAlertConstructInfoOssService.queryById(id));
}
/**
* 新增预警任务-施工信息-oss
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:add")
// @Log(title = "预警任务-施工信息-oss", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody BusinessAlertConstructInfoOssBo bo) {
return toAjax(businessAlertConstructInfoOssService.insertByBo(bo));
}
/**
* 修改预警任务-施工信息-oss
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:edit")
// @Log(title = "预警任务-施工信息-oss", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody BusinessAlertConstructInfoOssBo bo) {
return toAjax(businessAlertConstructInfoOssService.updateByBo(bo));
}
/**
* 删除预警任务-施工信息-oss
*
* @param ids 主键串
*/
// @SaCheckPermission("business:businessAlertConstructInfoOss:remove")
// @Log(title = "预警任务-施工信息-oss", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
Boolean result = businessAlertConstructInfoOssService.deleteWithValidByIds(List.of(ids), true);
return toAjax(result);
}
}

127
dk-modules/business/src/main/java/org/dromara/business/controller/BusinessAlertController.java

@ -1,38 +1,31 @@
package org.dromara.business.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.client.utils.TenantUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.business.api.domain.RemoteBusinessAlertRequest;
import org.dromara.business.domain.BusinessAlert;
import org.dromara.business.domain.bo.BusinessAlertBo;
import org.dromara.business.domain.vo.BusinessAlertVo;
import org.dromara.business.service.IBusinessAlertService;
import org.dromara.business.utils.MinioUntil;
import org.dromara.business.utils.constants.MinIOConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.api.RemoteNoticeService;
import org.dromara.system.api.RemoteSubmailConfigService;
import org.dromara.system.api.domain.bo.RemoteNoticeBo;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.io.IOException;
import java.util.List;
/**
@ -121,41 +114,16 @@ public class BusinessAlertController extends BaseController {
@Operation(summary ="预警推送-实时预警模块专用",description = "预警推送-实时预警模块专用")
@GetMapping("/pushAlert")
public R pushAlert(Long alertId,@RequestParam(required = false) String deptId,@RequestParam(required = false)String deptName) {
BusinessAlert businessAlert= businessAlertService.getBusinessAlert(alertId);
if(!ObjectUtil.hasEmpty(deptId,deptName)){
businessAlert.setDeptName(deptName);
businessAlert.setDeptId(deptId);
}
businessAlert.setCreateTime(new Date());
//businessAlert.setJobName(deptName + businessAlert.getLabelCn() + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",businessAlert.getCreateTime()));
businessAlertService.updateBusinessAlert(businessAlert);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(String.valueOf(businessAlert.getId()));
startProcess.setFlowCode("alertChz");
remoteWorkflowService.startWorkFlowBatch(List.of(startProcess));
RemoteNoticeBo remoteNoticeBo = new RemoteNoticeBo();
remoteNoticeBo.setNoticeTitle(businessAlert.getDeptName()+"产生预警,预警类型["+businessAlert.getLabelCn()+"],请立即查看");
remoteNoticeBo.setNoticeType("3");
remoteNoticeBo.setNoticeContent(businessAlert.getDeptName()+"产生预警,预警类型["+businessAlert.getLabelCn()+"],请立即查看");
remoteNoticeBo.setStatus("0");
remoteNoticeBo.setIsRead(0);
remoteNoticeBo.setCreateBy(1L);
remoteNoticeBo.setCreateDept(1L);
remoteNoticeBo.setCreateTime(businessAlert.getCreateTime());
if (businessAlert.getBusinessType() == 2){
businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, businessAlert.getImages(), 3600).toString());
}
remoteNoticeBo.setDeviceSn(businessAlert.getDeviceSn());
businessAlert.setDeviceSn(businessAlert.getDeviceSn());
remoteNoticeBo.setParam(JSON.toJSONString(businessAlert));
remoteNoticeService.saveNotice(remoteNoticeBo);
remoteSubmailConfigService.remoteCmdSend("smsMultixsend", JSON.toJSONString(businessAlert));
businessAlertService.pushAlert(alertId,deptId,deptName);
return R.ok();
}
/**
* 查询全部预警/待办/已完成/忽略
* 前端视频画框
*/
@Operation(summary ="ai实时流预警保存",description = "ai实时流预警保存")
@PostMapping("/saveAlertList")
@ -186,34 +154,53 @@ public class BusinessAlertController extends BaseController {
}
@Operation(summary ="ai实时流预警保存-用于演示",description = "ai实时流预警保存-用于演示")
@PostMapping("/saveAlert")
public R selectAlert(@RequestBody BusinessAlertVo vo) {
vo.setBusinessType(2);
BusinessAlert businessAlert = businessAlertService.addBusinessAlert(vo);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(String.valueOf(businessAlert.getId()));
startProcess.setFlowCode("alertChz");
remoteWorkflowService.startWorkFlowBatch(List.of(startProcess));
RemoteNoticeBo remoteNoticeBo = new RemoteNoticeBo();
remoteNoticeBo.setNoticeTitle(vo.getDeptName()+"产生预警,预警类型["+vo.getLabelCn()+"],请立即查看");
remoteNoticeBo.setNoticeType("3");
remoteNoticeBo.setNoticeContent(vo.getDeptName()+"产生预警,预警类型["+vo.getLabelCn()+"],请立即查看");
remoteNoticeBo.setStatus("0");
remoteNoticeBo.setIsRead(0);
remoteNoticeBo.setCreateBy(1L);
remoteNoticeBo.setCreateDept(1L);
remoteNoticeBo.setCreateTime(businessAlert.getCreateTime());
if (businessAlert.getBusinessType() == 2){
businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, vo.getImages(), 3600).toString());
/**
* 导出预警数据
* @param bo
*/
@Operation(summary ="导出预警数据",description = "导出预警数据")
@GetMapping("/alert/export")
public void exportBusinessAlert(BusinessAlertBo bo, HttpServletResponse response) throws IOException {
businessAlertService.exportAlert(bo,response);
}
remoteNoticeBo.setDeviceSn(vo.getDeviceSn());
businessAlert.setDeviceSn(vo.getDeviceSn());
remoteNoticeBo.setParam(JSON.toJSONString(businessAlert));
remoteNoticeService.saveNotice(remoteNoticeBo);
remoteSubmailConfigService.remoteCmdSend("smsMultixsend", JSON.toJSONString(vo));
return R.ok();
@PostMapping("/saveBusinessAlert")
// public Boolean saveBusinessAlert(List<RemoteBusinessAlertVo> alertVoList, String activeProfile) {
// public Boolean saveBusinessAlert(@RequestBody RemoteBusinessAlertRequest requestObj) {
public Boolean saveBusinessAlert(@RequestBody JSONObject requestJSON) {
// return businessAlertService.batchAddBusinessAlert(alertVoList, activeProfile);
RemoteBusinessAlertRequest requestObj = JSONUtil.toBean(requestJSON, RemoteBusinessAlertRequest.class);
return businessAlertService.batchAddBusinessAlert(requestObj.getAlertVoList(), requestObj.getActiveProfile());
}
// @Operation(summary ="ai实时流预警保存-用于演示",description = "ai实时流预警保存-用于演示")
// @PostMapping("/saveAlert")
// public R selectAlert(@RequestBody BusinessAlertVo vo) {
// vo.setBusinessType(2);
// BusinessAlert businessAlert = businessAlertService.addBusinessAlert(vo);
// RemoteStartProcess startProcess = new RemoteStartProcess();
// startProcess.setBusinessId(String.valueOf(businessAlert.getId()));
// startProcess.setFlowCode("alertChz");
// remoteWorkflowService.startWorkFlowBatch(List.of(startProcess));
// RemoteNoticeBo remoteNoticeBo = new RemoteNoticeBo();
// remoteNoticeBo.setNoticeTitle(vo.getDeptName()+"产生预警,预警类型["+vo.getLabelCn()+"],请立即查看");
// remoteNoticeBo.setNoticeType("3");
// remoteNoticeBo.setNoticeContent(vo.getDeptName()+"产生预警,预警类型["+vo.getLabelCn()+"],请立即查看");
// remoteNoticeBo.setStatus("0");
// remoteNoticeBo.setIsRead(0);
// remoteNoticeBo.setCreateBy(1L);
// remoteNoticeBo.setCreateDept(1L);
// remoteNoticeBo.setCreateTime(businessAlert.getCreateTime());
// if (businessAlert.getBusinessType() == 2){
// businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, vo.getImages(), 3600).toString());
// }
// remoteNoticeBo.setDeviceSn(vo.getDeviceSn());
// businessAlert.setDeviceSn(vo.getDeviceSn());
// remoteNoticeBo.setParam(JSON.toJSONString(businessAlert));
// remoteNoticeService.saveNotice(remoteNoticeBo);
// remoteSubmailConfigService.remoteCmdSend("smsMultixsend", JSON.toJSONString(vo));
// return R.ok();
// }
}

89
dk-modules/business/src/main/java/org/dromara/business/controller/BusinessLayerController.java

@ -0,0 +1,89 @@
package org.dromara.business.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.business.domain.bo.BusinessLayerBo;
import org.dromara.business.domain.vo.BusinessLayerVo;
import org.dromara.business.service.IBusinessLayerService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@Tag(name = "图层模块")
@RequestMapping("/layer")
public class BusinessLayerController extends BaseController {
private final IBusinessLayerService businessLayerService;
/**
* 图层模块列表
*/
@Operation(summary ="图层模块列表",description = "图层模块列表")
// @SaCheckPermission("business:layer:list")
@GetMapping("/list")
public R<TableDataInfo<BusinessLayerVo>> list(BusinessLayerBo bo, PageQuery pageQuery) {
return R.ok(businessLayerService.queryPageList(bo, pageQuery));
}
@Operation(summary ="图层下拉列表",description = "图层下拉列表")
@GetMapping("/optionSelect")
public R<List<BusinessLayerVo>> optionSelect() {
return R.ok(businessLayerService.optionSelect());
}
/**
* 图层新增
*/
@Operation(summary ="图层新增",description = "图层新增")
// @SaCheckPermission("business:layer:add")
@Log(title = "图层新增", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody BusinessLayerBo bo) {
return toAjax(businessLayerService.insert(bo));
}
/**
* 图层修改
*/
// @SaCheckPermission("business:layer:edit")
@Operation(summary ="图层修改",description = "图层修改")
@Log(title = "图层修改", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody BusinessLayerBo bo) {
return toAjax(businessLayerService.update(bo));
}
/**
* 删除
*
* @param id 主键
*/
// @SaCheckPermission("business:task:remove")
@Operation(summary ="图层删除",description = "图层删除")
@Log(title = "图层删除", businessType = BusinessType.DELETE)
@GetMapping("/delete")
public R<Void> remove(@RequestParam("id") Long id) {
return toAjax(businessLayerService.delete(id));
}
}

32
dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlert.java

@ -257,4 +257,36 @@ public class BusinessAlert {
//预警扩展施工信息
@TableField(exist = false)
private BusinessAlertConstructInfoVo alertConstructInfoVo;
/**
* 指南针
*/
@TableField(exist = false)
private String icon;
@TableField(exist = false)
private String postCategory; //类别编码,用来过滤预警查询返回值(南通的查询南通类,丰县查询丰县)
/**
* 无人机方向
*/
private String direction;
/**
* 无人机云台偏航角
*/
private String gimbalYaw;
/**
* 无人机高
*/
private String height;
/**
* 无人机俯视角
*/
private String gimbalPitch;
}

6
dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlertConstructInfo.java

@ -4,8 +4,10 @@ import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import java.io.Serial;
import java.util.List;
/**
* 预警任务-施工信息对象 business_alert_construct_info
@ -83,4 +85,8 @@ public class BusinessAlertConstructInfo extends TenantEntity {
private String remark;
@TableField(exist = false)
private List<BusinessAlertConstructInfoOss> alertConstructInfoOssList;
}

74
dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlertConstructInfoOss.java

@ -0,0 +1,74 @@
package org.dromara.business.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 预警任务-施工信息-oss对象 business_alert_construct_info_oss
*
* @author szs
* @date 2025-06-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("business_alert_construct_info_oss")
public class BusinessAlertConstructInfoOss extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 施工信息ID
*/
private Long alertConstructInfoId;
/**
* 施工信息
*/
private Long alertConstructInfoName;
/**
* 文件名
*/
private String fileName;
/**
* 原名
*/
private String originalName;
/**
* 文件后缀名
*/
private String fileSuffix;
/**
* URL地址
*/
private String url;
@TableField(exist = false)
private String previewUrl;
/**
* 备注
*/
private String remark;
/**
* 服务商
*/
private String service;
}

70
dk-modules/business/src/main/java/org/dromara/business/domain/BusinessLayer.java

@ -0,0 +1,70 @@
package org.dromara.business.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import java.io.Serial;
import java.util.Date;
@Data
@TableName(value = "business_layer", autoResultMap = true)
public class BusinessLayer extends BaseEntity {
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String layerName;
/*0:禁用 1:启用*/
private Boolean enable;
/**
* 0菜单 1三维 2矢量 3影像
*/
private Integer layerType;
@TableField(exist = false)
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "layerType", other = "layer_type")
private String layerTypeName;
/**
* 图层url
*/
private String layerUrl;
/**
* 部门id
*/
private Long deptId;
/**
* 部门名称
*/
private String deptName;
/**
* 备注
*/
private String remark;
/**
* 排序
*/
private Integer sort;
/**
* 父类id
*/
private Long parentId;
}

27
dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java

@ -247,4 +247,31 @@ public class BusinessAlertBo {
*/
private String caseNumber;
/**
* 不传的话默认world
*/
private String exportType = "world";
/**
* 无人机方向
*/
private String direction;
/**
* 无人机云台偏航角
*/
private String gimbalYaw;
/**
* 无人机高
*/
private String height;
/**
* 无人机俯视角
*/
private String gimbalPitch;
private String postCategory; //类别编码,用来过滤预警查询返回值(南通的查询南通类,丰县查询丰县)
}

73
dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertConstructInfoOssBo.java

@ -0,0 +1,73 @@
package org.dromara.business.domain.bo;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 预警任务-施工信息-oss业务对象 business_alert_construct_info_oss
*
* @author szs
* @date 2025-06-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = BusinessAlertConstructInfoOss.class, reverseConvertGenerate = false)
public class BusinessAlertConstructInfoOssBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
private Long id;
/**
* 施工信息ID
*/
@NotNull(message = "施工信息ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long alertConstructInfoId;
/**
* 施工信息
*/
private Long alertConstructInfoName;
/**
* 文件名
*/
@NotBlank(message = "文件名不能为空", groups = { AddGroup.class, EditGroup.class })
private String fileName;
/**
* 原名
*/
private String originalName;
/**
* 文件后缀名
*/
private String fileSuffix;
/**
* URL地址
*/
private String url;
/**
* 备注
*/
private String remark;
/**
* 服务商
*/
@NotBlank(message = "服务商不能为空", groups = { AddGroup.class, EditGroup.class })
private String service;
}

68
dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessLayerBo.java

@ -0,0 +1,68 @@
package org.dromara.business.domain.bo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.business.domain.BusinessLayer;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import java.io.Serial;
import java.util.Date;
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = BusinessLayer.class,reverseConvertGenerate = false)
public class BusinessLayerBo {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private Long id;
@NotNull(message = "图层名称不能为空", groups = { AddGroup.class})
private String layerName;
/*0:禁用 1:启用*/
private Boolean enable;
/**
* 时间
* */
private Date createTime;
/**
* 0目录 1地址
*/
@NotNull(message = "图层类型不能为空", groups = { AddGroup.class})
private Integer layerType;
/**
* 图层url
*/
private String layerUrl;
private String tenantId;
@NotNull(message = "部门id不能为空", groups = { AddGroup.class})
private Long deptId;
@NotNull(message = "部门名称不能为空", groups = { AddGroup.class})
private String deptName;
private String remark;
//排序
private Integer sort;
//父部门id
private Long parentId;
private String startTime;
private String endTime;
}

23
dk-modules/business/src/main/java/org/dromara/business/domain/model/enums/LayerTypeEnum.java

@ -0,0 +1,23 @@
package org.dromara.business.domain.model.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum LayerTypeEnum {
menu(0,"目录"),
threeDimensional(1,"三维"),
vector(2,"矢量"),
image(3,"影像");
private Integer type;
private String desc;
}

88
dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessAlertConstructInfoOssVo.java

@ -0,0 +1,88 @@
package org.dromara.business.domain.vo;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 预警任务-施工信息-oss视图对象 business_alert_construct_info_oss
*
* @author szs
* @date 2025-06-04
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = BusinessAlertConstructInfoOss.class)
public class BusinessAlertConstructInfoOssVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 施工信息ID
*/
@ExcelProperty(value = "施工信息ID")
private Long alertConstructInfoId;
/**
* 施工信息
*/
@ExcelProperty(value = "施工信息")
private Long alertConstructInfoName;
/**
* 文件名
*/
@ExcelProperty(value = "文件名")
private String fileName;
/**
* 原名
*/
@ExcelProperty(value = "原名")
private String originalName;
/**
* 文件后缀名
*/
@ExcelProperty(value = "文件后缀名")
private String fileSuffix;
/**
* URL地址
*/
@ExcelProperty(value = "URL地址")
private String url;
private String previewUrl;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 服务商
*/
@ExcelProperty(value = "服务商")
private String service;
}

5
dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessAlertConstructInfoVo.java

@ -7,11 +7,12 @@ import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
@ -100,5 +101,7 @@ public class BusinessAlertConstructInfoVo implements Serializable {
@ExcelProperty(value = "备注")
private String remark;
private List<BusinessAlertConstructInfoOss> alertConstructInfoOssList;//文件列表
}

33
dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessAlertVo.java

@ -211,4 +211,37 @@ public class BusinessAlertVo implements Serializable {
* 案件号
*/
private String caseNumber;
/**
* 无人机方向
*/
private String direction;
/**
* 无人机云台偏航角
*/
private String gimbalYaw;
/**
* 无人机高
*/
private String height;
/**
* 无人机俯视角
*/
private String gimbalPitch;
/**
* 画框的四个角度参数
*/
private Integer lx;
private Integer ly;
private Integer rx;
private Integer ry;
}

76
dk-modules/business/src/main/java/org/dromara/business/domain/vo/BusinessLayerVo.java

@ -0,0 +1,76 @@
package org.dromara.business.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.business.domain.BusinessLayer;
import org.dromara.business.domain.BusinessTask;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import java.io.Serial;
import java.util.Date;
import java.util.List;
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = BusinessLayer.class)
public class BusinessLayerVo {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private Long id;
/**
* 用于前端渲染
*/
private Long key;
private String layerName;
/*0:禁用 1:启用*/
private Boolean enable;
/**
* 0菜单 1三维 2矢量 3影像
*/
private Integer layerType;
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "layerType", other = "layer_type")
private String layerTypeName;
private String tenantId;
private Long deptId;
/**
* 图层url
*/
private String layerUrl;
private String deptName;
private String remark;
//排序
private Integer sort;
//父id
private Long parentId;
private List<BusinessLayerVo> children;
//用于前端回显
private List<Long> deptIdList;
}

8
dk-modules/business/src/main/java/org/dromara/business/dubbo/RemoteBusinessAlertServiceImpl.java

@ -1,6 +1,7 @@
package org.dromara.business.dubbo;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.business.api.RemoteBusinessAlertService;
import org.dromara.business.api.domain.bo.RemoteBusinessAlertBo;
@ -9,6 +10,8 @@ import org.dromara.business.domain.vo.BusinessAlertVo;
import org.dromara.business.service.IBusinessAlertService;
import org.dromara.business.utils.MinioUntil;
import org.dromara.business.utils.constants.MinIOConstants;
import org.dromara.system.api.RemoteSubmailConfigService;
import org.dromara.system.api.RemoteUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@ -26,7 +29,8 @@ import java.util.stream.Collectors;
public class RemoteBusinessAlertServiceImpl implements RemoteBusinessAlertService {
private final IBusinessAlertService businessAlertService;
@DubboReference(timeout = 30000)
private RemoteSubmailConfigService remoteSubmailConfigService;
@Override
public Boolean saveBusinessAlert(List<RemoteBusinessAlertVo> alertVoList, String activeProfile) {
@ -84,5 +88,7 @@ public class RemoteBusinessAlertServiceImpl implements RemoteBusinessAlertServic
}).toList();
businessAlertService.batchUpdateDept(alertVoList);
//短信推送
remoteSubmailConfigService.remoteSend("smsMultixsend", alertList);
}
}

4
dk-modules/business/src/main/java/org/dromara/business/feign/FeignDeviceGroup.java

@ -22,4 +22,8 @@ public interface FeignDeviceGroup {
@GetMapping("/device/flight/count")
public Map<String,Integer> getDevices();
@GetMapping("/media/api/v1/files/degree")
public Double getGimbalYawDegree(@RequestParam("fileId") String fileId);
}

20
dk-modules/business/src/main/java/org/dromara/business/mapper/BusinessAlertConstructInfoOssMapper.java

@ -0,0 +1,20 @@
package org.dromara.business.mapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import org.dromara.business.domain.vo.BusinessAlertConstructInfoOssVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 预警任务-施工信息-ossMapper接口
*
* @author szs
* @date 2025-06-04
*/
public interface BusinessAlertConstructInfoOssMapper extends BaseMapperPlus<BusinessAlertConstructInfoOss, BusinessAlertConstructInfoOssVo> {
Page<BusinessAlertConstructInfoOss> selectVoPageData(@Param("page") Page<BusinessAlertConstructInfoOss> page,@Param("ew") QueryWrapper<BusinessAlertConstructInfoOss> qw);
}

5
dk-modules/business/src/main/java/org/dromara/business/mapper/BusinessAlertMapper.java

@ -121,4 +121,9 @@ public interface BusinessAlertMapper extends BaseMapperPlus<BusinessAlert, Busin
Integer selectCurrentAlertCount(@Param("currentDate") String currentDate);
void batchUpdateCaseNumber(@Param("list") List<BusinessAlertVo> alertVoList);
@DataPermission(
@DataColumn(key = "deptName", value = "t.dept_id")
)
List<BusinessAlert> exportAlert(@Param("ew") QueryWrapper<BusinessAlert> ew, @Param("tbPrefix") ProjectTablePrefixConfig tbPrefix);
}

20
dk-modules/business/src/main/java/org/dromara/business/mapper/BusinessLayerMapper.java

@ -0,0 +1,20 @@
package org.dromara.business.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.business.domain.BusinessLayer;
import org.dromara.business.domain.bo.BusinessLayerBo;
import org.dromara.business.domain.bo.BusinessTaskBo;
import org.dromara.business.domain.vo.BusinessLayerVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
public interface BusinessLayerMapper extends BaseMapperPlus<BusinessLayer, BusinessLayerVo> {
Page<BusinessLayerVo> queryPageList(@Param("page") Page<?> page, @Param("bo") BusinessLayerBo bo);
List<BusinessLayerVo> selectInfoByParent(@Param("parentId") Long parentId);
}

69
dk-modules/business/src/main/java/org/dromara/business/service/IBusinessAlertConstructInfoOssService.java

@ -0,0 +1,69 @@
package org.dromara.business.service;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import org.dromara.business.domain.vo.BusinessAlertConstructInfoOssVo;
import org.dromara.business.domain.bo.BusinessAlertConstructInfoOssBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 预警任务-施工信息-ossService接口
*
* @author szs
* @date 2025-06-04
*/
public interface IBusinessAlertConstructInfoOssService {
/**
* 查询预警任务-施工信息-oss
*
* @param id 主键
* @return 预警任务-施工信息-oss
*/
BusinessAlertConstructInfoOssVo queryById(Long id);
/**
* 分页查询预警任务-施工信息-oss列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 预警任务-施工信息-oss分页列表
*/
TableDataInfo<BusinessAlertConstructInfoOss> queryPageList(BusinessAlertConstructInfoOssBo bo, PageQuery pageQuery);
/**
* 查询符合条件的预警任务-施工信息-oss列表
*
* @param bo 查询条件
* @return 预警任务-施工信息-oss列表
*/
List<BusinessAlertConstructInfoOssVo> queryList(BusinessAlertConstructInfoOssBo bo);
/**
* 新增预警任务-施工信息-oss
*
* @param bo 预警任务-施工信息-oss
* @return 是否新增成功
*/
Boolean insertByBo(BusinessAlertConstructInfoOssBo bo);
/**
* 修改预警任务-施工信息-oss
*
* @param bo 预警任务-施工信息-oss
* @return 是否修改成功
*/
Boolean updateByBo(BusinessAlertConstructInfoOssBo bo);
/**
* 校验并批量删除预警任务-施工信息-oss信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

7
dk-modules/business/src/main/java/org/dromara/business/service/IBusinessAlertService.java

@ -1,5 +1,6 @@
package org.dromara.business.service;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.business.api.domain.bo.RemoteBusinessAlertBo;
import org.dromara.business.api.domain.vo.RemoteBusinessAlertVo;
import org.dromara.business.domain.BusinessAlert;
@ -8,6 +9,7 @@ import org.dromara.business.domain.vo.BusinessAlertVo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@ -102,4 +104,9 @@ public interface IBusinessAlertService {
Boolean updateBusinessAlert(BusinessAlert businessAlert);
TableDataInfo<BusinessAlertVo> listAiVerifyAlert(BusinessAlertVo vo,PageQuery pageQuery);
void exportAlert(BusinessAlertBo bo, HttpServletResponse response) throws IOException;
void pushAlert(Long alertId, String deptId, String deptName);
}

27
dk-modules/business/src/main/java/org/dromara/business/service/IBusinessLayerService.java

@ -0,0 +1,27 @@
package org.dromara.business.service;
import org.dromara.business.domain.bo.BusinessLayerBo;
import org.dromara.business.domain.vo.BusinessLayerVo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import java.util.List;
public interface IBusinessLayerService {
/**
* 分页查询工单预约列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 工单预约分页列表
*/
TableDataInfo<BusinessLayerVo> queryPageList(BusinessLayerBo bo, PageQuery pageQuery);
Boolean insert(BusinessLayerBo bo);
Boolean update(BusinessLayerBo bo);
Boolean delete(Long id);
List<BusinessLayerVo> optionSelect();
}

193
dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertConstructInfoOssServiceImpl.java

@ -0,0 +1,193 @@
package org.dromara.business.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.business.domain.BusinessAlert;
import org.dromara.business.service.IBusinessAlertConstructInfoOssService;
import org.dromara.business.utils.MinioUntil;
import org.dromara.business.utils.constants.MinIOConstants;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import org.dromara.business.domain.bo.BusinessAlertConstructInfoOssBo;
import org.dromara.business.domain.vo.BusinessAlertConstructInfoOssVo;
import org.dromara.business.mapper.BusinessAlertConstructInfoOssMapper;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 预警任务-施工信息-ossService业务层处理
*
* @author szs
* @date 2025-06-04
*/
@RequiredArgsConstructor
@Service
public class BusinessAlertConstructInfoOssServiceImpl implements IBusinessAlertConstructInfoOssService {
private final BusinessAlertConstructInfoOssMapper baseMapper;
/**
* 查询预警任务-施工信息-oss
*
* @param id 主键
* @return 预警任务-施工信息-oss
*/
@Override
public BusinessAlertConstructInfoOssVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询预警任务-施工信息-oss列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 预警任务-施工信息-oss分页列表
*/
@Override
public TableDataInfo<BusinessAlertConstructInfoOss> queryPageList(BusinessAlertConstructInfoOssBo bo, PageQuery pageQuery) {
QueryWrapper<BusinessAlertConstructInfoOss> wrapper = buildQueryWrapperQuery(bo);
Page<BusinessAlertConstructInfoOss> result = baseMapper.selectVoPageData(pageQuery.build(), wrapper);
result.getRecords().forEach(item -> {
item.setPreviewUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_NANTONG, item.getUrl(), 3600).toString());
});
return TableDataInfo.build(result);
}
/**
* 查询符合条件的预警任务-施工信息-oss列表
*
* @param bo 查询条件
* @return 预警任务-施工信息-oss列表
*/
@Override
public List<BusinessAlertConstructInfoOssVo> queryList(BusinessAlertConstructInfoOssBo bo) {
LambdaQueryWrapper<BusinessAlertConstructInfoOss> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<BusinessAlertConstructInfoOss> buildQueryWrapper(BusinessAlertConstructInfoOssBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<BusinessAlertConstructInfoOss> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getAlertConstructInfoId() != null, BusinessAlertConstructInfoOss::getAlertConstructInfoId, bo.getAlertConstructInfoId());
lqw.like(bo.getAlertConstructInfoName() != null, BusinessAlertConstructInfoOss::getAlertConstructInfoName, bo.getAlertConstructInfoName());
lqw.like(StringUtils.isNotBlank(bo.getFileName()), BusinessAlertConstructInfoOss::getFileName, bo.getFileName());
lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), BusinessAlertConstructInfoOss::getOriginalName, bo.getOriginalName());
lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), BusinessAlertConstructInfoOss::getFileSuffix, bo.getFileSuffix());
lqw.eq(StringUtils.isNotBlank(bo.getUrl()), BusinessAlertConstructInfoOss::getUrl, bo.getUrl());
lqw.eq(StringUtils.isNotBlank(bo.getService()), BusinessAlertConstructInfoOss::getService, bo.getService());
return lqw;
}
private QueryWrapper<BusinessAlertConstructInfoOss> buildQueryWrapperQuery(BusinessAlertConstructInfoOssBo bo) {
QueryWrapper<BusinessAlertConstructInfoOss> wrapper = new QueryWrapper<>();
if(ObjectUtil.isNotEmpty(bo.getId())){
wrapper.eq("t.id", bo.getId());
}
if(ObjectUtil.isNotEmpty(bo.getAlertConstructInfoId())){
wrapper.eq("t.alert_construct_info_id", bo.getAlertConstructInfoId());
}
if(ObjectUtil.isNotEmpty(bo.getAlertConstructInfoName())){
wrapper.eq("t.alert_construct_info_name", bo.getAlertConstructInfoName());
}
if(ObjectUtil.isNotEmpty(bo.getFileName())){
wrapper.eq("t.file_name", bo.getFileName());
}
if(ObjectUtil.isNotEmpty(bo.getOriginalName())){
wrapper.eq("t.original_name", bo.getOriginalName());
}
if(ObjectUtil.isNotEmpty(bo.getFileSuffix())){
wrapper.eq("t.file_suffix", bo.getFileSuffix());
}
if(ObjectUtil.isNotEmpty(bo.getUrl())){
wrapper.eq("t.url", bo.getUrl());
}
if(ObjectUtil.isNotEmpty(bo.getCreateDept())){
wrapper.eq("t.create_dept", bo.getCreateDept());
}
if(ObjectUtil.isNotEmpty(bo.getCreateTime())){
wrapper.eq("t.create_time", bo.getCreateTime());
}
if(ObjectUtil.isNotEmpty(bo.getCreateBy())){
wrapper.eq("t.create_by", bo.getCreateBy());
}
if(ObjectUtil.isNotEmpty(bo.getUpdateTime())){
wrapper.eq("t.update_time", bo.getUpdateTime());
}
if(ObjectUtil.isNotEmpty(bo.getUpdateBy())){
wrapper.eq("t.update_by", bo.getUpdateBy());
}
if(ObjectUtil.isNotEmpty(bo.getRemark())){
wrapper.eq("t.remark", bo.getRemark());
}
if(ObjectUtil.isNotEmpty(bo.getService())){
wrapper.eq("t.service", bo.getService());
}
return wrapper;
}
/**
* 新增预警任务-施工信息-oss
*
* @param bo 预警任务-施工信息-oss
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(BusinessAlertConstructInfoOssBo bo) {
BusinessAlertConstructInfoOss add = MapstructUtils.convert(bo, BusinessAlertConstructInfoOss.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改预警任务-施工信息-oss
*
* @param bo 预警任务-施工信息-oss
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(BusinessAlertConstructInfoOssBo bo) {
BusinessAlertConstructInfoOss update = MapstructUtils.convert(bo, BusinessAlertConstructInfoOss.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(BusinessAlertConstructInfoOss entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除预警任务-施工信息-oss信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

412
dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java

@ -1,30 +1,40 @@
package org.dromara.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itextpdf.text.DocumentException;
import freemarker.template.TemplateException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.business.api.domain.bo.RemoteBusinessAlertBo;
import org.dromara.business.api.domain.vo.RemoteBusinessAlertConstructInfo;
import org.dromara.business.api.domain.vo.RemoteBusinessAlertVo;
import org.dromara.business.config.ProjectTablePrefixConfig;
import org.dromara.business.domain.BusinessAlert;
import org.dromara.business.domain.BusinessAlertConstructInfo;
import org.dromara.business.domain.bo.BusinessAlertBo;
import org.dromara.business.domain.vo.BusinessAlertConstructInfoVo;
import org.dromara.business.domain.vo.BusinessAlertVo;
import org.dromara.business.feign.FeignDeviceGroup;
import org.dromara.business.mapper.BusinessAlertConstructInfoMapper;
import org.dromara.business.mapper.BusinessAlertMapper;
import org.dromara.business.service.IBusinessAlertService;
import org.dromara.business.utils.BatchProcessorUtil;
import org.dromara.business.utils.MinioUntil;
import org.dromara.business.utils.*;
import org.dromara.business.utils.constants.MinIOConstants;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.enums.FormatsType;
@ -34,18 +44,25 @@ import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.business.utils.MinioUtil;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.RemoteLabelPostService;
import org.dromara.resource.api.RemoteMessageService;
import org.dromara.system.api.*;
import org.dromara.system.api.domain.bo.RemoteNoticeBo;
import org.dromara.system.api.domain.vo.RemoteAiLabelPostVo;
import org.dromara.system.api.domain.vo.RemoteUserVo;
import org.dromara.business.domain.BusinessAlertConstructInfoOss;
import org.dromara.business.mapper.BusinessAlertConstructInfoOssMapper;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@ -54,9 +71,16 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.util.Base64;
/**
* 预警任务Service业务层处理
*
@ -66,13 +90,19 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
@Slf4j
@DubboService
public class BusinessAlertServiceImpl implements IBusinessAlertService {
private final BusinessAlertMapper baseMapper;
@DubboReference(timeout = 30000)
private RemoteSubmailConfigService remoteSubmailConfigService;
@Autowired
private BusinessAlertConstructInfoMapper businessAlertConstructInfoMapper;
@Autowired
private BusinessAlertConstructInfoOssMapper businessAlertConstructInfoOssMapper;
@DubboReference(timeout = 30000)
RemoteWorkflowService remoteWorkflowService;
@ -82,6 +112,22 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
@Autowired
private ProjectTablePrefixConfig ptPrefix;
@DubboReference
private RemoteUserService remoteUserService;
@Autowired
FeignDeviceGroup feignDeviceGroup;
@DubboReference
private final RemoteMessageService remoteMessageService;
@DubboReference
private RemoteConfigService remoteConfigService;
@DubboReference(timeout = 30000)
private RemoteNoticeService remoteNoticeService;
/**
* 新增预警任务
*
@ -92,7 +138,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
public BusinessAlert addBusinessAlert(BusinessAlertVo param) {
BusinessAlert alert = MapstructUtils.convert(param, BusinessAlert.class);
alert.setCreateTime(new Date());
alert.setJobName(alert.getLabelCn()+ DateUtils.getTime());
// alert.setJobName(alert.getLabelCn()+ DateUtils.getTime());
//创建案件号
try {
incrementalAlertCount(alert);
@ -129,18 +175,58 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
@Override
public void addBusinessAlertList(List<BusinessAlertVo> alertVoList) {
if(!alertVoList.isEmpty()) {
if (ObjectUtil.isEmpty(alertVoList)){
throw new ServiceException("参数为空!");
}
try {
incrementalCount(alertVoList);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
//用于短信推送
List<Map<String, Object>> noticeList=new ArrayList<>();
List<RemoteStartProcess> remoteStartProcessList = new ArrayList<>();
for (BusinessAlertVo alertVo : alertVoList) {
Map<String,Object>map=new HashMap<>();
alertVo.setBusinessType(2);
alertVo.setHandleType(BusinessStatusEnum.WAITING.getStatus());
//构建pixel
JSONObject pixelJson = new JSONObject();
pixelJson.put("lef_x",alertVo.getLx());
pixelJson.put("lef_y",alertVo.getLy());
pixelJson.put("right_x",alertVo.getRx());
pixelJson.put("right_y",alertVo.getRy());
alertVo.setPixelCoordinate(pixelJson.toJSONString());
BusinessAlert alert = addBusinessAlert(alertVo);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(String.valueOf(alert.getId()));
startProcess.setFlowCode("alertChz");
String flowCode = remoteWorkflowService.getFlowCode(alertVo.getLabelEn());
log.info("flowCode:{}",flowCode);
startProcess.setFlowCode(flowCode);
map.put("deptId",alert.getDeptId());
map.put("deptName",alert.getDeptName());
map.put("labelCn",alert.getLabelCn());
map.put("labelEn",alert.getLabelEn());
map.put("jobName",alert.getJobName());
noticeList.add(map);
remoteStartProcessList.add(startProcess);
//推送消息-基于部门-找用户 发送json格式
ArrayList<Long> deptIds = new ArrayList<>();
deptIds.add(Long.parseLong(alert.getDeptId()));
List<RemoteUserVo> remoteUserVos = remoteUserService.selectUsersByDeptIds(deptIds);
List<Long> userIds = remoteUserVos.stream().map(RemoteUserVo::getUserId).collect(Collectors.toList());
String imagePreviewUrl = MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, alertVo.getImages(), 3600).toString();
JSONObject jsonObject = setupBusinessAlertSSEObj( alert, imagePreviewUrl);
remoteMessageService.publishMessage(userIds, jsonObject.toString() );
System.out.println("已发送:"+ "预警内容:"+ jsonObject.toString());
}
int startIndex = 0; // 从第 0 条开始
@ -149,8 +235,30 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
//批量新增部门区域数据
remoteWorkflowService.startWorkFlowBatch(batch);
});
remoteSubmailConfigService.remoteSend("smsMultixsend",noticeList);
//推送消息-基于部门-找用户-批量
// List<String> deptStrIds = alertVoList.stream().map(BusinessAlertVo::getDeptId).distinct().collect(Collectors.toList());
// List<Long> deptIds = deptStrIds.stream().map(Long::parseLong).collect(Collectors.toList());
// List<RemoteUserVo> remoteUserVos = remoteUserService.selectUsersByDeptIds(deptIds);
// List<Long> userIds = remoteUserVos.stream().map(RemoteUserVo::getUserId).collect(Collectors.toList());
//
// remoteMessageService.publishMessage(userIds, "预警");
}
/** 预警信息转jsonObj给前台提示预警 **/
private static JSONObject setupBusinessAlertSSEObj( BusinessAlert alert, String imagePreviewUrl) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("deptId", alert.getDeptId());
jsonObject.put("deptName", alert.getDeptName());
jsonObject.put("images", imagePreviewUrl);
jsonObject.put("labelCn", alert.getLabelCn());
jsonObject.put("lat", alert.getLat());
jsonObject.put("lng", alert.getLng());
jsonObject.put("createTime", ObjectUtil.isNotEmpty(alert.getCreateTime()) ? alert.getCreateTime() : new Date());
jsonObject.put("jobName", alert.getJobName());
return jsonObject;
}
/**
@ -165,9 +273,11 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
alert.setCreateTime(new Date());
alert.setHandleType(BusinessStatusEnum.VERIFY.getStatus());
RemoteBusinessAlertConstructInfo remoteAlertConstructInfo = alert.getRemoteAlertConstructInfo();
if(BeanUtil.isNotEmpty(remoteAlertConstructInfo)){
BusinessAlertConstructInfoVo alertConstructInfoVo = new BusinessAlertConstructInfoVo();
BeanUtils.copyProperties(alert.getRemoteAlertConstructInfo(), alertConstructInfoVo);
BeanUtils.copyProperties(remoteAlertConstructInfo, alertConstructInfoVo);
businessAlert.setAlertConstructInfoVo(alertConstructInfoVo);
}
BeanUtils.copyProperties(alert, businessAlert);
if(!StrUtil.equals("default", activeProfile)){
businessAlert.setBusinessType(2);
@ -181,6 +291,22 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
}).toList();
boolean b = this.baseMapper.insertBatch(businessAlerts);
//推送消息-基于部门-找用户 发送json格式 --此时没有deptId,无效预警
for (BusinessAlert alert : businessAlerts) {
if(ObjectUtil.isEmpty(alert.getDeptId())){
continue;
}
ArrayList<Long> deptIds = new ArrayList<>();
deptIds.add(Long.parseLong(alert.getDeptId()));
List<RemoteUserVo> remoteUserVos = remoteUserService.selectUsersByDeptIds(deptIds);
List<Long> userIds = remoteUserVos.stream().map(RemoteUserVo::getUserId).collect(Collectors.toList());
String imagePreviewUrl = MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, alert.getImages(), 3600).toString();
JSONObject jsonObject = setupBusinessAlertSSEObj(alert, imagePreviewUrl);
remoteMessageService.publishMessage(userIds, jsonObject.toString() );
}
/*List<BusinessAlertConstructInfo> alertConstructInfoList = businessAlerts.stream().map(alert -> {
BusinessAlertConstructInfoVo alertConstructInfoVo = alert.getAlertConstructInfoVo();
BusinessAlertConstructInfo businessAlertConstructInfo = new BusinessAlertConstructInfo();
@ -190,6 +316,19 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
}).collect(Collectors.toList());
businessAlertConstructInfoMapper.insertBatch(alertConstructInfoList);*/
//基于系统参数判断是否要自动提交
boolean submitFlag = remoteConfigService.selectXingluoAutoSubmit();
if(submitFlag){
System.out.println("记录内容提交");
String collect = alertVoList.stream().map(RemoteBusinessAlertVo::getLabelCn).collect(Collectors.joining(","));
System.out.println(collect);
for (BusinessAlert businessAlert : businessAlerts) {
// this.pushAlert(businessAlert.getAlertId(),);
}
}
return b;
}
@ -271,10 +410,12 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
QueryWrapper<BusinessAlert> wrapper = buildQueryWrapper(bo);
if (ObjectUtil.isEmpty(wrapper)){
return new TableDataInfo<>();
return TableDataInfo.build();
}
Page<BusinessAlert> page = this.baseMapper.pageBusinessAlert(pageQuery.build(), wrapper, ptPrefix);
//拼接-预警扩展施工信息
setupConstructInfo(page.getRecords(), page);
try {//预警管理查询图片
page.getRecords().forEach(businessAlertVo->{
@ -306,13 +447,15 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
QueryWrapper<BusinessAlert> wrapper = buildQueryWrapper(bo);
if (ObjectUtil.isEmpty(wrapper)){
return new TableDataInfo<>();
return TableDataInfo.build();
}
wrapper.in("t.flowStatus", BusinessStatusEnum.CANCEL.getStatus());
Page<BusinessAlert> page = this.baseMapper.pageBusinessAlertCancel(pageQuery.build(), wrapper, ptPrefix);
//拼接-预警扩展施工信息
setupConstructInfo(page.getRecords(), page);
try {
page.getRecords().forEach(businessAlertVo->{
if (businessAlertVo.getBusinessType() == 2){
@ -343,7 +486,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
QueryWrapper<BusinessAlert> wrapper = buildQueryWrapper(bo);
if (ObjectUtil.isEmpty(wrapper)){
return new TableDataInfo<>();
return TableDataInfo.build();
}
wrapper.eq("t.handle_type",BusinessStatusEnum.FINISH.getStatus());
@ -351,6 +494,9 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
Page<BusinessAlert> page = this.baseMapper.pageBusinessAlertFinish(pageQuery.build(), wrapper, ptPrefix);
//拼接-预警扩展施工信息
setupConstructInfo(page.getRecords(), page);
try {
page.getRecords().forEach(businessAlertVo->{
if (businessAlertVo.getBusinessType() == 2){
@ -380,7 +526,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
QueryWrapper<BusinessAlert> wrapper = buildQueryWrapper(bo);
if (ObjectUtil.isEmpty(wrapper)){
return new TableDataInfo<>();
return TableDataInfo.build();
}
wrapper.eq("t.node_type", 1);
@ -402,6 +548,9 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
});
}
//拼接-预警扩展施工信息
setupConstructInfo(records, page);
try {
page.getRecords().forEach(businessAlertVo->{
if (businessAlertVo.getBusinessType() == 2){
@ -425,7 +574,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
QueryWrapper<BusinessAlert> wrapper = buildQueryWrapper(bo);
if (ObjectUtil.isEmpty(wrapper)){
return new TableDataInfo<>();
return TableDataInfo.build();
}
String tableWorkflow = ptPrefix.getTableWorkflow(); // eg: "dk_workflow"
@ -436,6 +585,9 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
Page<BusinessAlert> page = this.baseMapper.pageBusinessAlertHandle(pageQuery.build(), wrapper, ptPrefix);
//拼接-预警扩展施工信息
setupConstructInfo(page.getRecords(), page);
try {
page.getRecords().forEach(businessAlertVo->{
businessAlertVo.setHandleType(null);
@ -455,6 +607,35 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
return TableDataInfo.build(page);
}
private void setupConstructInfo(List<BusinessAlert> records, Page<BusinessAlert> page) {
List<Long> alertIds = records.stream().map(BusinessAlert::getId).collect(Collectors.toList());
if(alertIds.isEmpty()){
return;
}
LambdaQueryWrapper<BusinessAlertConstructInfo> qw = new LambdaQueryWrapper<BusinessAlertConstructInfo>();
qw.in(BusinessAlertConstructInfo::getBusinessAlertId, alertIds);
List<BusinessAlertConstructInfoVo> constructInfoVoList = businessAlertConstructInfoMapper.selectVoList(qw,BusinessAlertConstructInfoVo.class);
List<Long> constructInfoIds = constructInfoVoList.stream().map(BusinessAlertConstructInfoVo::getId).collect(Collectors.toList());
List<BusinessAlertConstructInfoOss> alertConstructInfoOssList = new ArrayList<>();
if(!constructInfoIds.isEmpty()){
LambdaQueryWrapper<BusinessAlertConstructInfoOss> alertConstructOssQw = new LambdaQueryWrapper<>();
alertConstructOssQw.in(BusinessAlertConstructInfoOss::getAlertConstructInfoId,constructInfoIds);
alertConstructInfoOssList = businessAlertConstructInfoOssMapper.selectVoList(alertConstructOssQw, BusinessAlertConstructInfoOss.class);
}
for (BusinessAlert record : page.getRecords()) {
BusinessAlertConstructInfoVo businessAlertConstructInfoVo = constructInfoVoList.stream().filter(item -> item.getBusinessAlertId().equals(record.getId())).findFirst().orElse(null);
if(ObjectUtil.isNotNull(businessAlertConstructInfoVo)){
List<BusinessAlertConstructInfoOss> constructInfoOssList = alertConstructInfoOssList.stream().filter(item -> item.getAlertConstructInfoId().equals(businessAlertConstructInfoVo.getId())).collect(Collectors.toList());
businessAlertConstructInfoVo.setAlertConstructInfoOssList(constructInfoOssList);
}
record.setAlertConstructInfoVo(businessAlertConstructInfoVo);
}
}
/**
* 构建wrapper
@ -532,7 +713,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
} catch (Exception e) {
e.printStackTrace();
}
return null;
return TableDataInfo.build();
}
@ -759,6 +940,180 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
return TableDataInfo.build(businessAlertVos);
}
@Override
public void exportAlert(BusinessAlertBo bo, HttpServletResponse response) throws IOException {
Map<String,Object> resultMap = new HashMap<>();
if (ObjectUtil.hasEmpty(bo.getStartTime(),bo.getEndTime())) {
bo.setStartTime(DateUtils.getDate());
bo.setEndTime(DateUtils.getDate());
}
//获取所有的用户信息
List<RemoteUserVo> remoteUserVos = remoteUserService.selectUserByUserIds(List.of());
Map<Long, List<RemoteUserVo>> userIdMap = remoteUserVos.stream().collect(Collectors.groupingBy(RemoteUserVo::getUserId));
QueryWrapper<BusinessAlert> wrapper = buildQueryWrapper(bo);
if (ObjectUtil.isEmpty(wrapper)){
throw new RuntimeException("没有可查看的预警数据!");
}
wrapper.eq("t.business_type",1);
//根据前端查询条件查询
List<BusinessAlert> alertList = this.baseMapper.exportAlert(wrapper,ptPrefix);
alertList = alertList.stream().filter(p-> !p.getHandleType().equalsIgnoreCase("cancel")).toList();
long todoCount = alertList.stream().filter(p -> p.getHandleType().equalsIgnoreCase("waiting")).count();
long finishCount = alertList.stream().filter(p -> p.getHandleType().equalsIgnoreCase("finish")).count();
//构建预警数量
resultMap.put("total",alertList.size());
resultMap.put("todo",todoCount);
resultMap.put("finish",finishCount);
//构建预警时间
resultMap.put("startTime",bo.getStartTime());
resultMap.put("endTime",bo.getEndTime());
long startMillis = System.currentTimeMillis();
alertList.parallelStream().forEach(businessAlert->{
try {
if (ObjectUtil.isNotEmpty(businessAlert.getAssignUserId()) && ObjectUtil.isNotEmpty(userIdMap.get(Long.valueOf(businessAlert.getAssignUserId())))){
businessAlert.setAssignUserName(userIdMap.get(Long.valueOf(businessAlert.getAssignUserId())).get(0).getNickName());
}
businessAlert.setHandleType(businessAlert.getHandleType().equalsIgnoreCase("waiting")?"未处理":businessAlert.getHandleType().equalsIgnoreCase("finish")?"已完结":businessAlert.getHandleType().equalsIgnoreCase("cancel")?"已忽略":"待验证");
if (businessAlert.getBusinessType() == 1){
businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString());
businessAlert.setMaxImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxImages(), 3600).toString());
businessAlert.setMaxMateSourceImgUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxMateSourceImgUrl(), 3600).toString());
businessAlert.setMateSourceImgUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMateSourceImgUrl(), 3600).toString());
}else {
businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString());
}
//获取指南针
// Double gimbalYawDegree = feignDeviceGroup.getGimbalYawDegree(businessAlert.getTaskImageId());
// if (ObjectUtil.isNotEmpty(gimbalYawDegree) && gimbalYawDegree != -1.0){
// if (gimbalYawDegree < 0){
// gimbalYawDegree = gimbalYawDegree - 180;
// }else {
// gimbalYawDegree = 180 - gimbalYawDegree;
// }
//
// log.info("旋转角度${}",gimbalYawDegree);
//
// String rotatedAndOverlayImage = ImageRotator.rotateAndOverlayImage(null, null, gimbalYawDegree);
// businessAlert.setIcon(rotatedAndOverlayImage);
// }
} catch (Exception e) {
log.error(e.getMessage(),e);
}
});
long endMillis = System.currentTimeMillis();
System.out.println("消耗时长:" + (endMillis-startMillis));
resultMap.put("alertList",alertList);
if (bo.getExportType().equalsIgnoreCase("world")){
//生成word
FreemarkerUtil.renderTplFileToWord("预警导出.docx","alert.ftl",resultMap,response);
} else if (bo.getExportType().equalsIgnoreCase("pdf")) {
try {
HtmlConvertPdfHelper.renderTplFileToPDF("预警导出.pdf","pdfAlert.ftl",resultMap,response);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
}
}
@Override
public void pushAlert(Long alertId, String deptId, String deptName) {
BusinessAlert businessAlert= this.getBusinessAlert(alertId);
if(!ObjectUtil.hasEmpty(deptId,deptName)){
businessAlert.setDeptName(deptName);
businessAlert.setDeptId(deptId);
}
businessAlert.setCreateTime(new Date());
//businessAlert.setJobName(deptName + businessAlert.getLabelCn() + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",businessAlert.getCreateTime()));
this.updateBusinessAlert(businessAlert);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(String.valueOf(businessAlert.getId()));
startProcess.setFlowCode("alertChz");
remoteWorkflowService.startWorkFlowBatch(List.of(startProcess));
RemoteNoticeBo remoteNoticeBo = new RemoteNoticeBo();
remoteNoticeBo.setNoticeTitle(businessAlert.getDeptName()+"产生预警,预警类型["+businessAlert.getLabelCn()+"],请立即查看");
remoteNoticeBo.setNoticeType("3");
remoteNoticeBo.setNoticeContent(businessAlert.getDeptName()+"产生预警,预警类型["+businessAlert.getLabelCn()+"],请立即查看");
remoteNoticeBo.setStatus("0");
remoteNoticeBo.setIsRead(0);
remoteNoticeBo.setCreateBy(1L);
remoteNoticeBo.setCreateDept(1L);
remoteNoticeBo.setCreateTime(businessAlert.getCreateTime());
if (businessAlert.getBusinessType() == 2){
businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, businessAlert.getImages(), 3600).toString());
}
remoteNoticeBo.setDeviceSn(businessAlert.getDeviceSn());
businessAlert.setDeviceSn(businessAlert.getDeviceSn());
remoteNoticeBo.setParam(JSON.toJSONString(businessAlert));
remoteNoticeService.saveNotice(remoteNoticeBo);
remoteSubmailConfigService.remoteCmdSend("smsMultixsend", JSON.toJSONString(businessAlert));
}
// 压缩图片方法
private static BufferedImage compressImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
Image resizedImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
BufferedImage bufferedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(resizedImage, 0, 0, null);
g.dispose();
return bufferedImage;
}
// 下载图片并转换为Base64
public static String imageToBase64(String imageUrl) throws Exception {
int targetWidth = 800; // 你可以调整这个值来控制图片压缩的程度
int targetHeight = 600;
// 创建URL对象
URL url = new URL(imageUrl);
// 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
// 获取输入流
InputStream inputStream = connection.getInputStream();
// 读取图片
BufferedImage originalImage = ImageIO.read(inputStream);
// 压缩图片
BufferedImage compressedImage = compressImage(originalImage, targetWidth, targetHeight);
// 将压缩后的图片转换为字节数组
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(compressedImage, "jpg", byteArrayOutputStream); // 将图片写为JPEG格式
byte[] imageBytes = byteArrayOutputStream.toByteArray();
// 将字节数组编码为Base64
String base64Encoded = Base64.getEncoder().encodeToString(imageBytes);
return base64Encoded;
}
@Override
public Boolean deleteAlert(List<Long> alertIdList) {
if (ObjectUtil.isEmpty(alertIdList)) {
@ -768,8 +1123,21 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
LambdaUpdateWrapper<BusinessAlert> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(BusinessAlert::getHandleType,BusinessStatusEnum.VERIFY.getStatus());
wrapper.in(BusinessAlert::getId, alertIdList);
List<BusinessAlert> businessAlerts = this.baseMapper.selectList(wrapper);
// 删除文件 - 仅处理ai识别文件删除
for (BusinessAlert businessAlert : businessAlerts) {
if(businessAlert.getBusinessType().equals(2)){
try {
MinioUtil.deleteFile(businessAlert.getImages(), MinIOConstants.BUCKET_DKCY);
} catch (Exception e) {
log.error(e.getMessage(),e);
// throw new RuntimeException(e);
}
}
}
return this.baseMapper.delete(wrapper) > 0;
boolean b = this.baseMapper.delete(wrapper) > 0;
return b;
}
@Override
@ -782,6 +1150,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
//更新number
this.baseMapper.batchUpdateCaseNumber(alertVoList);
} catch (Exception e) {
log.error(e.getMessage(),e);
}
@ -873,6 +1242,13 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
List<BusinessAlert> businessAlerts = this.baseMapper.listTodoAlert(wrapper, ptPrefix);
BusinessAlert businessAlert = businessAlerts.stream().filter(p -> p.getId().equals(alertId)).findFirst().get();
//拼接-预警扩展施工信息
QueryWrapper<BusinessAlertConstructInfo> qw = new QueryWrapper<BusinessAlertConstructInfo>();
qw.eq("business_alert_id", businessAlert.getId());
List<BusinessAlertConstructInfoVo> constructInfoVoList = businessAlertConstructInfoMapper.selectVoList(qw);
if(!constructInfoVoList.isEmpty()){
businessAlert.setAlertConstructInfoVo(constructInfoVoList.getFirst());
}
try {
if (businessAlert.getBusinessType() == 2){
@ -902,7 +1278,8 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
MinioUtil.deleteFile(businessAlert.getImages(), MinIOConstants.BUCKET_DKCY);
MinioUtil.deleteFile(businessAlert.getImages(), MinIOConstants.BUCKET_ALERT);
} catch (Exception e) {
throw new RuntimeException(e);
log.error(e.getMessage(),e);
// throw new RuntimeException(e);
}
return this.baseMapper.update(wrapper) > 0;
@ -963,6 +1340,5 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
public static void main(String[] args) {
System.out.println(getLastSixDays());
}
}

16
dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertStatisticsServiceImpl.java

@ -428,6 +428,10 @@ public class BusinessAlertStatisticsServiceImpl implements IBusinessAlertStatist
//查询所有的职能岗位
List<RemotePostVo> postVoList = remotePostService.listPost();
postVoList = postVoList.stream().filter(item -> StrUtil.equals("0",item.getStatus())).toList();//剔除禁用规则
//基于类别编码postCategory过滤返回值:区分南通 / 丰县等部门数据 【postCategory不能为空再过滤数据】
if(StrUtil.isNotEmpty(businessAlertBo.getPostCategory()) ){
postVoList = postVoList.stream().filter(item -> StrUtil.equals(businessAlertBo.getPostCategory(), item.getPostCategory())).toList();
}
if (ObjectUtil.isEmpty(postVoList)) {
return ListUtil.empty();
@ -457,6 +461,10 @@ public class BusinessAlertStatisticsServiceImpl implements IBusinessAlertStatist
//查询所有的职能岗位
List<RemotePostVo> postVoList = remotePostService.listPost();
postVoList = postVoList.stream().filter(item -> StrUtil.equals("0",item.getStatus())).toList();//剔除禁用规则
//基于类别编码postCategory过滤返回值:区分南通 / 丰县等部门数据 【postCategory不能为空再过滤数据】
if(StrUtil.isNotEmpty(businessAlertBo.getPostCategory()) ){
postVoList = postVoList.stream().filter(item -> StrUtil.equals(businessAlertBo.getPostCategory(), item.getPostCategory())).toList();
}
List<StatObj> result = new ArrayList<>();
@ -507,6 +515,10 @@ public class BusinessAlertStatisticsServiceImpl implements IBusinessAlertStatist
//查询所有的职能岗位
List<RemotePostVo> postVoList = remotePostService.listPost();
postVoList = postVoList.stream().filter(item -> StrUtil.equals("0",item.getStatus())).toList();//剔除禁用规则
//基于类别编码postCategory过滤返回值:区分南通 / 丰县等部门数据 【postCategory不能为空再过滤数据】
if(StrUtil.isNotEmpty(businessAlertBo.getPostCategory()) ){
postVoList = postVoList.stream().filter(item -> StrUtil.equals(businessAlertBo.getPostCategory(), item.getPostCategory())).toList();
}
List<StatObj> result = new ArrayList<>();
if (ObjectUtil.isEmpty(postVoList)) {
@ -547,6 +559,10 @@ public class BusinessAlertStatisticsServiceImpl implements IBusinessAlertStatist
//查询所有的职能岗位
List<RemotePostVo> postVoList = remotePostService.listPost();
postVoList = postVoList.stream().filter(item -> StrUtil.equals("0",item.getStatus())).toList();//剔除禁用规则
//基于类别编码postCategory过滤返回值:区分南通 / 丰县等部门数据 【postCategory不能为空再过滤数据】
if(StrUtil.isNotEmpty(businessAlertBo.getPostCategory()) ){
postVoList = postVoList.stream().filter(item -> StrUtil.equals(businessAlertBo.getPostCategory(), item.getPostCategory())).toList();
}
List<String> monthList = getLastSixMonths();

143
dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessLayerServiceImpl.java

@ -0,0 +1,143 @@
package org.dromara.business.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.impl.MapConverter;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.business.domain.BusinessLayer;
import org.dromara.business.domain.bo.BusinessLayerBo;
import org.dromara.business.domain.model.enums.LayerTypeEnum;
import org.dromara.business.domain.vo.BusinessLayerVo;
import org.dromara.business.mapper.BusinessLayerMapper;
import org.dromara.business.service.IBusinessLayerService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.api.RemoteDeptService;
import org.dromara.system.api.domain.vo.RemoteDeptVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.*;
@Slf4j
@RequiredArgsConstructor
@Service
public class BusinessLayerServiceImpl implements IBusinessLayerService {
private final BusinessLayerMapper baseMapper;
@DubboReference(timeout = 30000)
RemoteDeptService remoteDeptService;
@Override
public TableDataInfo<BusinessLayerVo> queryPageList(BusinessLayerBo bo, PageQuery pageQuery) {
Page<BusinessLayerVo> result = baseMapper.queryPageList(pageQuery.build(), bo);
result.getRecords().forEach(businessLayerVo -> {
List<RemoteDeptVo> deptList = remoteDeptService.listTreeDeptByChild(businessLayerVo.getDeptId());
LinkedList<Long> deptIdList = new LinkedList<>();
deptList.forEach(deptVo -> {
deptIdList.add(deptVo.getDeptId());
});
List<BusinessLayerVo> layerVoList = baseMapper.selectInfoByParent(businessLayerVo.getId());
businessLayerVo.setChildren(buildTree(layerVoList,businessLayerVo.getId()));
businessLayerVo.setDeptIdList(deptIdList);
});
return TableDataInfo.build(result);
}
@Override
public Boolean insert(BusinessLayerBo bo) {
BusinessLayer layerVo = Convert.convert( BusinessLayer.class,bo);
RemoteDeptVo remoteDeptVo = remoteDeptService.selectDeptById(layerVo.getDeptId());
layerVo.setDeptName(remoteDeptVo.getDeptName());
return baseMapper.insert(layerVo)>0;
}
@Override
public Boolean update(BusinessLayerBo bo) {
BusinessLayer businessLayer = baseMapper.selectById(bo.getId());
//判断是否修改部门
if (!businessLayer.getDeptId().equals(bo.getDeptId())) {
RemoteDeptVo remoteDeptVo = remoteDeptService.selectDeptById(bo.getDeptId());
bo.setDeptName(remoteDeptVo.getDeptName());
}
BeanUtils.copyProperties(bo,businessLayer);
return baseMapper.updateById(businessLayer)>0;
}
@Override
public Boolean delete(Long id) {
return baseMapper.deleteById(id)>0;
}
@Override
public List<BusinessLayerVo> optionSelect() {
List<BusinessLayerVo> layerVoList = baseMapper.selectInfoByParent(0L);
if (ObjectUtil.isEmpty(layerVoList)){
return List.of();
}
return layerVoList.stream().filter(p-> p.getLayerType().equals(LayerTypeEnum.menu.getType())).toList();
}
/**
* 构建树
* @param allNodes
* @return
*/
public List<BusinessLayerVo> buildTree(List<BusinessLayerVo> allNodes, Long parentId) {
// 创建一个Map来存储所有节点,键为ID,值为节点
Map<Long, BusinessLayerVo> nodeMap = new HashMap<>();
for (BusinessLayerVo node : allNodes) {
nodeMap.put(node.getId(), node);
}
// 用来存储根节点(即 parentId 为传入值的节点)
List<BusinessLayerVo> rootNodes = new ArrayList<>();
// 遍历所有节点,将子节点添加到父节点的 children 列表中
for (BusinessLayerVo node : allNodes) {
List<RemoteDeptVo> deptList = remoteDeptService.listTreeDeptByChild(node.getDeptId());
LinkedList<Long> deptIdList = new LinkedList<>();
deptList.forEach(deptVo -> {
deptIdList.add(deptVo.getDeptId());
});
node.setDeptIdList(deptIdList);
if (node.getParentId().equals(parentId)) {
rootNodes.add(node); // 当前节点的 parentId 与传入的 parentId 匹配,作为根节点
} else {
BusinessLayerVo parentNode = nodeMap.get(node.getParentId());
if (parentNode != null) {
// 确保父节点的 children 列表已初始化
if (parentNode.getChildren() == null) {
parentNode.setChildren(new ArrayList<>());
}
parentNode.getChildren().add(node); // 将当前节点添加到父节点的 children 列表中
}
}
}
return rootNodes;
}
}

264
dk-modules/business/src/main/java/org/dromara/business/utils/FreemarkerUtil.java

@ -0,0 +1,264 @@
package org.dromara.business.utils;
import cn.hutool.extra.spring.SpringUtil;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import freemarker.template.Template;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
public class FreemarkerUtil {
/**
* Freemarker的配置类模板目录默认 resources下的 templates
*/
private static FreeMarkerConfigurer freeMarkerConfigurer = SpringUtil.getBean(FreeMarkerConfigurer.class);
/**
* 将模板文件填充数据后转为String
*
* @param templateName ftl模板文件名
* @param datas 数据集合
* @return
*/
public static String renderTplFileToStr(String templateName, Map<String, Object> datas) {
try {
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName, "UTF-8");
StringWriter out = new StringWriter();
template.process(datas, out);
out.flush();
out.close();
return out.getBuffer().toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将模板文件填充数据后导出为文件导出html,word文件都使用此方法
*
* @param templateName ftl模板文件名
* @param datas 数据集合
* @param outFile 导出的文件路径名称
*/
public static void renderTplFileToLocalFile(String templateName, Map<String, Object> datas, ByteArrayOutputStream fos) {
Writer out = null;
OutputStreamWriter oWriter = null;
try {
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName, "UTF-8");
oWriter = new OutputStreamWriter(fos, "UTF-8");
// 这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
out = new BufferedWriter(new OutputStreamWriter(fos));
out = new BufferedWriter(oWriter);
template.process(datas, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (oWriter != null) {
oWriter.close();
}
if (fos != null) {
fos.close();
}
if (out != null) {
out.close();
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
/**
* 根据word模板获取输入流
*
* @param templateName
* @param datas
* @return
* @throws IOException
*/
public static InputStream renderTplFileToWordInputStream(String templateName, Map<String, Object> datas) throws IOException {
Document doc = null;
DataInputStream in = null;
try {
in = renderTplFileToIOFile(templateName, datas);
doc = new Document();
doc.loadFromStream(in, FileFormat.Auto);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.saveToStream(baos, FileFormat.Docx);
ByteArrayOutputStream byteArrayOutputStream = ZipStreamUtil.copyStream(baos);
//输出流转为输入流
InputStreamSource inputStreamSource = new ByteArrayResource(byteArrayOutputStream.toByteArray());
return inputStreamSource.getInputStream();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
if (doc != null) {
doc.close();
}
}
return null;
}
/**
* 将模板文件填充数据后返回文件流
*
* @param templateName ftl模板文件名
* @param datas 数据集合
*/
public static DataInputStream renderTplFileToIOFile(String templateName, Map<String, Object> datas) throws Exception {
ByteArrayInputStream in = null;
Writer out = null;
try {
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName, "UTF-8");
out = new StringWriter();
template.process(datas, out);
String out1 = out.toString().replace("&", "&amp;");//替换非法字符
in = new ByteArrayInputStream(out1.getBytes("UTF-8"));
return new DataInputStream(in);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
}
return null;
}
/**
* 根据word模板获取输入流
*
* @param templateName
* @param datas
* @return
* @throws IOException
*/
public static void renderTplFileToWord(String documentName , String templateName, Map<String, Object> datas, HttpServletResponse response) throws IOException {
response.setContentType("application/x-msdownload;");
response.setHeader("Content-disposition", "attachment; filename=" + documentName);
Document doc = null;
DataInputStream in = null;
try {
in = renderTplFileToIOFile(templateName, datas);
doc = new Document();
doc.loadFromStream(in, FileFormat.Auto);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.saveToStream(baos, FileFormat.Docx);
ByteArrayOutputStream byteArrayOutputStream = ZipStreamUtil.copyStream(baos);
// 将生成的文档写入到响应的输出流中
response.reset(); // 重置响应
response.getOutputStream().write(byteArrayOutputStream.toByteArray());
response.getOutputStream().flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
if (doc != null) {
doc.close();
}
}
}
/**
* 根据word模板获取输入流
*
* @param templateName
* @param datas
* @return
* @throws IOException
*/
public static void renderTplFileToPDF(String fileName ,String templateName, Map<String, Object> datas,HttpServletResponse response) throws IOException {
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); // 字符集编码
response.setContentType("application/pdf;");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.addHeader("Access-Control-Allow-Origin", "*"); // 实现跨域
Document doc = null;
DataInputStream in = null;
try {
in = renderTplFileToIOFile(templateName, datas);
doc = new Document();
doc.loadFromStream(in, FileFormat.Auto);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
doc.saveToStream(baos, FileFormat.PDF);
// 将生成的文档写入到响应的输出流中
response.reset(); // 重置响应
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String encodeImageToBase64(String imageUrl) throws Exception {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
try (InputStream in = connection.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
byte[] imageBytes = baos.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
}
}
}

101
dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java

@ -0,0 +1,101 @@
package org.dromara.business.utils;
import cn.hutool.extra.spring.SpringUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import freemarker.template.TemplateException;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* Html转换Pdf
*
* @author Mall
* @date Created in 2022-04-25
*/
public class HtmlConvertPdfHelper {
/**
* Freemarker的配置类模板目录默认 resources下的 templates
*/
private static FreeMarkerConfigurer freeMarkerConfigurer = SpringUtil.getBean(FreeMarkerConfigurer.class);
public static void renderTplFileToPDF(String fileName , String templateName, Map<String, Object> datas, HttpServletResponse response) {
try {
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); // 字符集编码
response.setContentType("application/pdf;");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.addHeader("Access-Control-Allow-Origin", "*"); // 实现跨域
byte[] bytes = htmlConvertPDF(datas, templateName);
// 将生成的文档写入到响应的输出流中
response.reset(); // 重置响应
response.getOutputStream().write(bytes);
response.getOutputStream().flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* freemarker转PDF
*
* @param templateName ftl文件名称需要在resources/templates目录下
* @return
* @throws IOException
*/
public static byte[] htmlConvertPDF(Object map,String templateName) throws IOException, TemplateException, DocumentException {
String htmlText = FreeMarkerTemplateUtils.processTemplateIntoString(freeMarkerConfigurer.getConfiguration().getTemplate(templateName), map);
return htmlConvertPDF(htmlText);
}
/**
* 根据HTML内容转Image
*
* @param htmText HTML文本字符串
*/
public static byte[] htmlConvertPDF(String htmText) throws DocumentException, IOException {
//最终返回的byte流
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//第一步,创建一个 iTextSharp.text.Document对象的实例:
Document document = new Document();
//第二步,为该Document创建一个Writer实例:
PdfWriter writer = PdfWriter.getInstance(document, byteArrayOutputStream);
//第三步,打开当前Document
document.open();
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmText.getBytes()), null, Charset.defaultCharset(), new AsianFontProvider());
document.close();
return byteArrayOutputStream.toByteArray();
}
}
/**
* 用于中文显示的Provider
*/
class AsianFontProvider extends XMLWorkerFontProvider {
@Override
public Font getFont(final String fontname, String encoding, float size, int style) {
try {
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
return new Font(bfChinese, size, style);
} catch (Exception e) {
}
return super.getFont(fontname, encoding, size, style);
}
}

127
dk-modules/business/src/main/java/org/dromara/business/utils/ImageRotator.java

@ -0,0 +1,127 @@
package org.dromara.business.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Base64;
public class ImageRotator {
/**
* 旋转图片并叠加到另一个图片上
* @param sourceImagePath 源图片路径
* @param targetImagePath 目标图片路径
* @param angle 旋转角度顺时针
* @return 处理后的图片的Base64字符串
*/
public static String rotateAndOverlayImage(String sourceImagePath, String targetImagePath, double angle) {
try {
URL resourceUrl = ImageRotator.class.getClassLoader().getResource("templates/1.png");
URL targetUrl = ImageRotator.class.getClassLoader().getResource("templates/2.png");
// 读取源图片和目标图片
BufferedImage sourceImage = ImageIO.read(new File(resourceUrl.getPath()));
BufferedImage targetImage = ImageIO.read(new File(targetUrl.getPath()));
// 创建旋转后的图片
BufferedImage rotatedImage = rotateImage(sourceImage, angle);
// 创建新的画布,使用目标图片的尺寸
BufferedImage resultImage = new BufferedImage(
targetImage.getWidth(),
targetImage.getHeight(),
BufferedImage.TYPE_INT_ARGB
);
// 创建图形上下文
Graphics2D g2d = resultImage.createGraphics();
// 绘制目标图片
g2d.drawImage(targetImage, 0, 0, null);
// 计算旋转图片的位置(居中)
int x = (targetImage.getWidth() - rotatedImage.getWidth()) / 2;
int y = (targetImage.getHeight() - rotatedImage.getHeight()) / 2;
// 绘制旋转后的图片
g2d.drawImage(rotatedImage, x, y, null);
// 释放图形上下文
g2d.dispose();
// 转换为Base64
return convertToBase64(resultImage);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 旋转图片
* @param image 要旋转的图片
* @param angle 旋转角度顺时针
* @return 旋转后的图片
*/
private static BufferedImage rotateImage(BufferedImage image, double angle) {
double rads = Math.toRadians(angle);
double sin = Math.abs(Math.sin(rads));
double cos = Math.abs(Math.cos(rads));
int w = image.getWidth();
int h = image.getHeight();
int newWidth = (int) Math.floor(w * cos + h * sin);
int newHeight = (int) Math.floor(h * cos + w * sin);
BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = rotated.createGraphics();
g2d.translate((newWidth - w) / 2, (newHeight - h) / 2);
g2d.rotate(rads, w / 2, h / 2);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return rotated;
}
/**
* 将图片转换为Base64字符串
* @param image 要转换的图片
* @return Base64字符串
*/
private static String convertToBase64(BufferedImage image) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", outputStream);
byte[] imageBytes = outputStream.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// 使用示例
public static void main(String[] args) {
String sourceImagePath = "C:\\Users\\Administrator\\Desktop\\1.png"; // 源图片路径
String targetImagePath = "C:\\Users\\Administrator\\Desktop\\2.png"; // 目标图片路径
double angle = 45.0; // 旋转角度
String base64Result = rotateAndOverlayImage(sourceImagePath, targetImagePath, angle);
if (base64Result != null) {
System.out.println("处理成功,Base64结果:" + base64Result);
} else {
System.out.println("处理失败");
}
}
}

283
dk-modules/business/src/main/java/org/dromara/business/utils/ZipStreamUtil.java

@ -0,0 +1,283 @@
package org.dromara.business.utils;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.util.function.BiFunction;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import static java.util.zip.ZipEntry.STORED;
import static java.util.zip.ZipOutputStream.DEFLATED;
public class ZipStreamUtil {
public static void main(String[] args) {
/* String srcPath = "E:\\360极速浏览器下载\\Linksla生产 (1).docx";
String outPath = "E:\\360极速浏览器下载\\Linksla生产2.docx";
try (FileInputStream is = new FileInputStream(srcPath)) {
try (FileOutputStream os = new FileOutputStream(outPath)) {
ZipStreamUtil.zipEntryCopyStream(os, is, new BiFunction<ZipEntry, ZipInputStream, byte[]>() {
@Override
public byte[] apply(ZipEntry se, ZipInputStream zis) {
byte[] rt = null;
String name = se.getName();
if (null == name) return rt;
String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)",
se.getName(), (se.isDirectory()) ? 1 : 0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment());
System.out.println(line);
if (name.endsWith("word/document.xml")) {
try {
byte[] oldBytes = ZipStreamUtil.toByteArray(zis);
String str = (new String(oldBytes));
String appendString = str.replace("Evaluation Warning: The document was created with Spire.Doc for JAVA.", "");
//rt = str.getBytes();
// 为了避免多余的编码转换, 改成下面的代码更好.
try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) {
//ZipStreamUtil.copyStream(buf, zis);
buf.write(appendString.getBytes());
rt = buf.toByteArray();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return rt;
}
});
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("ZipTxtAppendTest done." + outPath);*/
}
/**
* 过滤word 水印
*
* @param baos
* @return
* @throws IOException
*/
public static ByteArrayOutputStream copyStream(ByteArrayOutputStream baos) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ByteArrayOutputStream baoss = new ByteArrayOutputStream();
try {
ZipStreamUtil.zipEntryCopyStream(baoss, bais, new BiFunction<ZipEntry, ZipInputStream, byte[]>() {
@Override
public byte[] apply(ZipEntry se, ZipInputStream zis) {
byte[] rt = null;
String name = se.getName();
if (null == name) return rt;
String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)",
se.getName(), (se.isDirectory()) ? 1 : 0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment());
System.out.println(line);
if (name.endsWith("word/document.xml")) {
try {
byte[] oldBytes = ZipStreamUtil.toByteArray(zis);
String str = (new String(oldBytes));
String appendString = str.replace("Evaluation Warning: The document was created with Spire.Doc for JAVA.", "");
try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) {
buf.write(appendString.getBytes());
rt = buf.toByteArray();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return rt;
}
});
} finally {
bais.close();
baoss.close();
}
return baoss;
}
public static byte[] toByteArray(InputStream in) throws IOException {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
copyStream(out, in);
return out.toByteArray();
}
}
public static void copyStream(OutputStream os, InputStream is) throws IOException {
copyStream(os, is, 0);
}
public static void copyStream(OutputStream os, InputStream is, int bufsize) throws IOException {
if (bufsize <= 0) bufsize = 4096;
int len;
byte[] bytes = new byte[bufsize];
while ((len = is.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
}
/**
* 基于ZIP项目的复制Zip流.
*
* @param dst The output stream of the destination zip.
* @param src Source zip.
* @param transform 转换处理. 可以为null, 不转换. 该回调函数的原型为`byte[] transform(ZipEntry zipEntry, ZipInputStream zis)`, 当返回值为 null时保留原值, 为非null时用返回值替换当前ZipEntry对应的流数据.
* @return 返回转换次数.
* @throws IOException
*/
public static int zipEntryCopyStreamZip(ZipOutputStream zos, ZipInputStream zis, BiFunction<ZipEntry, ZipInputStream, byte[]> transform) throws IOException {
int rt = 0;
ZipEntry se;
while ((se = zis.getNextEntry()) != null) {
if (null == se) continue;
//String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)",
// se.getName(), (se.isDirectory())?1:0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment());
//System.out.println(line);
byte[] dstBytes = null;
if (null != transform) {
dstBytes = transform.apply(se, zis);
}
// choose by dstBytes.
if (null == dstBytes) {
ZipEntry de = new ZipEntry(se);
de.setCompressedSize(-1); // 重新压缩后, csize 可能不一致, 故需要恢复为默认值.
zos.putNextEntry(de);
copyStream(zos, zis);
zos.closeEntry();
} else {
++rt;
//ZipEntry de = new ZipEntry(se);
//de.setCompressedSize(-1);
//de.setCrc(-1);
// == fix IllegalArgumentException.
ZipEntry de = new ZipEntry(se.getName());
//System.out.println(se.getTime());
//final long timeNone = 312739200000L;
//if (timeNone!=se.getTime() && null!=se.getLastModifiedTime()) { // 发现会被自动改为当前时间.
if (null != se.getLastModifiedTime()) {
de.setLastModifiedTime(se.getLastModifiedTime());
}
if (null != se.getLastAccessTime()) {
de.setLastAccessTime(se.getLastAccessTime());
}
if (null != se.getCreationTime()) {
de.setCreationTime(se.getCreationTime());
}
de.setSize(dstBytes.length);
//de.setCompressedSize(se.getCompressedSize()); // changed.
//de.setCrc(se.getCrc()); // changed.
int method = se.getMethod();
if (method != STORED && method != DEFLATED) {
// No setMethod .
} else {
de.setMethod(method);
}
de.setExtra(se.getExtra());
de.setComment(se.getComment());
zos.putNextEntry(de);
zos.write(dstBytes);
zos.closeEntry();
}
}
return rt;
}
/**
* 基于ZIP项目的复制流.
*
* @param dst The output stream of the destination zip.
* @param src Source zip.
* @param transform 转换处理. 可以为null, 不转换. 该回调函数的原型为`byte[] transform(ZipEntry zipEntry, ZipInputStream zis)`, 当返回值为 null时保留原值, 为非null时用返回值替换当前ZipEntry对应的流数据.
* @return 返回转换次数.
* @throws IOException
*/
public static int zipEntryCopyStream(OutputStream os, InputStream is, BiFunction<ZipEntry, ZipInputStream, byte[]> transform) throws IOException {
try (ZipInputStream zis = new ZipInputStream(is)) {
try (ZipOutputStream zos = new ZipOutputStream(os)) {
return zipEntryCopyStreamZip(zos, zis, transform);
}
}
}
public static void saveImageToFile(String imageUrl, File destination) throws IOException {
try (InputStream in = new URL(imageUrl).openStream()) {
Files.copy(in, destination.toPath());
}
}
public static void addFolderToZip(File sourceFolder, String baseFolderName, ZipOutputStream zos) throws IOException {
for (File file : sourceFolder.listFiles()) {
if (file.isDirectory()) {
addFolderToZip(file, baseFolderName + "/" + file.getName(), zos);
} else {
try (InputStream in = Files.newInputStream(file.toPath())) {
ZipEntry zipEntry = new ZipEntry(baseFolderName + "/" + file.getName());
zos.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) >= 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
}
}
}
}
public static void deleteDirectory(File directory) {
for (File file : directory.listFiles()) {
if (file.isDirectory()) {
deleteDirectory(file);
}
file.delete();
}
directory.delete();
}
// Helper method to add image to zip stream
public static void addImageToZip(String imageUrl, File targetFile, String folderName, ZipOutputStream zos) throws IOException {
if (imageUrl == null || imageUrl.isEmpty()) {
throw new IllegalArgumentException("The image URL cannot be null or empty.");
}
URL url;
try {
url = new URL(imageUrl);
} catch (MalformedURLException e) {
throw new IOException("Invalid URL format: " + imageUrl, e);
}
try (InputStream imageStream = url.openStream()) {
// Create zip entry for image
String zipEntryName = folderName + "/" + targetFile.getName();
ZipEntry zipEntry = new ZipEntry(zipEntryName);
zos.putNextEntry(zipEntry);
// Write image content to zip stream
byte[] buffer = new byte[8192]; // 8KB buffer for optimal performance
int bytesRead;
while ((bytesRead = imageStream.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
} catch (IOException e) {
// Log the error and rethrow the exception for higher-level handling
System.err.println("Error processing image from URL: " + imageUrl);
e.printStackTrace();
throw e;
}
}
}

3
dk-modules/business/src/main/java/org/dromara/business/utils/constants/MinIOConstants.java

@ -17,4 +17,7 @@ public interface MinIOConstants {
String BUCKET_ALERT = "alert";
//桶名称 图斑
String BUCKET_PATTERN = "pattern";
//南通-丰县Buskcet
String BUCKET_NANTONG = "nantongsitebucket";
}

12
dk-modules/business/src/main/resources/mapper/business/BusinessAlertConstructInfoOssMapper.xml

@ -0,0 +1,12 @@
<?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="org.dromara.business.mapper.BusinessAlertConstructInfoOssMapper">
<select id="selectVoPageData" resultType="org.dromara.business.domain.BusinessAlertConstructInfoOss">
select t.* from business_alert_construct_info_oss t
${ew.getCustomSqlSegment}
</select>
</mapper>

7
dk-modules/business/src/main/resources/mapper/business/BusinessAlertMapper.xml

@ -967,4 +967,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</update>
<select id="exportAlert" resultType="org.dromara.business.domain.BusinessAlert">
select t.* from (select
ba.*
from ${tbPrefix.tableBusiness}.business_alert ba) t
${ew.getCustomSqlSegment}
</select>
</mapper>

76
dk-modules/business/src/main/resources/mapper/business/BusinessLayerMapper.xml

@ -0,0 +1,76 @@
<?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="org.dromara.business.mapper.BusinessLayerMapper">
<select id="queryPageList" resultType="org.dromara.business.domain.vo.BusinessLayerVo">
SELECT
t.id,
t.id as 'key',
t.layer_name as layerName,
t.enable,
t.remark,
t.layer_type as layerType,
t.layer_url as layerUrl,
t.dept_id as deptId,
t.dept_name AS deptName,
t.tenant_id as tenantId,
t.create_time AS createTime,
t.sort,
t.parent_id AS parentId
FROM
business_layer t
<where>
t.parent_id = 0
<if test="bo.parentId != null and bo.parentId != ''">
and t.parent_id = #{bo.parentId}
</if>
<if test="bo.layerType != null and bo.layerType != ''">
and t.layer_type = #{bo.layerType}
</if>
<if test="bo.deptId != null and bo.deptId != ''">
and t.dept_id = #{bo.deptId}
</if>
<if test="bo.enable != null and bo.enable != ''">
and t.enable = #{bo.enable}
</if>
<if test="bo.layerName != null and bo.layerName != ''">
and t.layer_name like CONCAT(#{bo.layerName}, '%')
</if>
<if test="bo.deptName != null and bo.deptName != ''">
and t.dept_name like CONCAT(#{bo.deptName}, '%')
</if>
<choose>
<when test="bo.startTime != null and bo.endTime != null">
and t.create_time between #{bo.startTime} and #{bo.endTime}
</when>
<when test="bo.startTime != null">
and t.create_time &gt;= #{bo.startTime}
</when>
<when test="bo.endTime != null">
and t.create_time &lt;= #{bo.endTime}
</when>
</choose>
</where>
order by t.parent_id , t.sort
</select>
<select id="selectInfoByParent" resultType="org.dromara.business.domain.vo.BusinessLayerVo">
WITH RECURSIVE business_hierarchy AS (
SELECT bl.*,bl.id as 'key'
FROM business_layer bl
WHERE parent_id = #{parentId}
UNION ALL
-- 递归查询,选择当前节点的子项
SELECT bla.*,bla.id as 'key'
FROM business_layer bla
JOIN business_hierarchy bh ON bla.parent_id = bh.id
)
-- 最终查询
SELECT * FROM business_hierarchy;
</select>
</mapper>

BIN
dk-modules/business/src/main/resources/templates/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
dk-modules/business/src/main/resources/templates/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

1943
dk-modules/business/src/main/resources/templates/alert.ftl

File diff suppressed because it is too large

125
dk-modules/business/src/main/resources/templates/pdfAlert.ftl

@ -0,0 +1,125 @@
<!DOCTYPE html>
<html>
<head>
<title>Early Warning Record</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
text-align: center;
}
h2, p {
text-align: left;
margin-top: 40px;
margin-left: 60px;
}
table {
margin: 40px auto;
width: 100%;
}
h2 {
color: #1b5aa1;
}
td {
word-wrap: break-word;
word-break: break-all;
}
</style>
</head>
<body>
<h2>一、报表日期</h2>
<p>${startTime?if_exists}~${endTime?if_exists}</p>
<h2>二、数据情况</h2>
<p>预警信息总计:${total?if_exists}条;未处理:${todo?if_exists}条; 已完结:${finish?if_exists}条。</p>
<p>详情如下</p>
<table>
<!-- 使用 colgroup 和 col 标签为每一列设置不同宽度 -->
<colgroup>
<col style="width: 5%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
</colgroup>
<tbody>
<tr>
<td>序号</td>
<td>预警名称</td>
<td>所属部门</td>
<td>预警状态</td>
<td>经纬度</td>
<td>预警时间</td>
</tr>
<#if (alertList?size gt 0) && alertList??>
<#list alertList as item>
<tr>
<td>${item_index + 1}</td>
<td>${item.jobName?if_exists}</td>
<td>${item.deptName?if_exists}</td>
<td>${item.handleType?if_exists}</td>
<td>${item.lng?if_exists} ${item.lat?if_exists}</td>
<td>${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')}</td>
</tr>
</#list>
</#if>
</tbody>
</table>
<script>
</script>
<#if (alertList?size gt 0) && alertList??>
<#list alertList as item>
<div style="page-break-before: always;"></div>
<h2>(${item_index + 1})预警信息:${item.jobName?if_exists}</h2>
<table>
<colgroup>
<col style="width: 50%;"/>
<col style="width: 50%;"/>
</colgroup>
<tbody>
<tr>
<td style="height: 50px;">前期影像</td>
<td style="height: 50px;">后期影像</td>
</tr>
<tr>
<td><img src="${item.mateSourceImgUrl?if_exists}" alt="前期影像1" style="width: 330px; height: 290px;"/></td>
<td><img src="${item.images?if_exists}" alt="前期影像2" style="width: 330px; height: 290px;"/></td>
</tr>
<tr>
<td><img src="${item.maxMateSourceImgUrl?if_exists}" alt="后期影像1" style="width: 330px; height: 290px;"/></td>
<td><img src="${item.maxImages?if_exists}" alt="后期影像2" style="width: 330px; height: 290px;"/></td>
</tr>
</tbody>
</table>
<#if item.assignUserId??>
<h2>处置内容</h2>
<table style="border-collapse: collapse; border: none; margin-top: 50px;width: 50%;height: 50%;">
<tbody>
<tr>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">识别类型:${item.labelCn?if_exists}</td>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">指派人员: ${item.assignUserName?if_exists}</td>
</tr>
<tr>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">预警时间: ${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')}</td>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">指派时间:
<#if item.assignDate??>
${item.assignDate?datetime?string('yyyy-MM-dd HH:mm:ss')}
</#if>
</td>
</tr>
<tr>
<td colspan="2" style="border: none; text-align: left; height: 40px;width: 50%; vertical-align: top;" >任务内容: ${item.reason?if_exists}</td>
</tr>
</tbody>
</table>
</#if>
</#list>
</#if>
</body>
</html>

16
dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteBusinessAlertFeign.java

@ -0,0 +1,16 @@
package org.dromara.sample.feign;
import cn.hutool.json.JSONObject;
import org.dromara.business.api.domain.RemoteBusinessAlertRequest;
import org.dromara.common.core.domain.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = "gateway",path = "business")
public interface RemoteBusinessAlertFeign {
@PostMapping("/saveBusinessAlert")
// public R<Boolean> saveBusinessAlert(@RequestBody RemoteBusinessAlertRequest requestObj);
public R<Boolean> saveBusinessAlert(@RequestBody JSONObject requestObj);
}

18
dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteConfigFeign.java

@ -0,0 +1,18 @@
package org.dromara.sample.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(name = "gateway",path = "system")
public interface RemoteConfigFeign {
@GetMapping("/config/configKeyFeign/{configKey}")
String getConfigKey(@PathVariable String configKey);
}

4
dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteSystemFeign.java

@ -3,6 +3,7 @@ package org.dromara.sample.feign;
import org.dromara.common.core.domain.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -13,4 +14,7 @@ public interface RemoteSystemFeign {
@GetMapping("/config/selectStreamType")
public List<String> selectStreamType(@RequestParam String deviceSn);
@GetMapping(value = "/config/configKeyFeign/{configKey}")
public String getConfigKeyFeign(@PathVariable String configKey);
}

32
dk-modules/sample/src/main/java/org/dromara/sample/manage/config/XingluoApiConfig.java

@ -0,0 +1,32 @@
package org.dromara.sample.manage.config;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import io.minio.*;
import io.minio.http.Method;
import lombok.Data;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.HashMap;
@Data
@Component
@ConfigurationProperties(prefix="xingluoapi")
public class XingluoApiConfig {
@Value("${xingluoapi.engineLogin:http://60.204.247.65:8100/Third/Login}")
private String engineLogin;
@Value("${xingluoapi.engineCallbackUrl:http://121.237.178.63:11100/sample/manage/api/v1/saEngineRecord/some}")
private String engineCallbackUrl;
@Value("${xingluoapi.engineStart:http://60.204.247.65:8100/Third/Engine/Start}")
private String engineStart;
@Value("${xingluoapi.engineStop:http://60.204.247.65:8100/Third/Engine/Stop}")
private String engineStop;
}

82
dk-modules/sample/src/main/java/org/dromara/sample/manage/config/XingluoApiEnum.java

@ -0,0 +1,82 @@
package org.dromara.sample.manage.config;
public enum XingluoApiEnum {
//2022 秸秆焚烧(烟、火、焚后痕迹) fire ----------
FIRE(2022, "可见光","秸秆焚烧","秸秆燃烧预警","2010_12",2022, 1899717400907046931l,"fire","秸秆燃烧"),
//2023 烟火识别 ------
FIREWORKS(2022, "可见光","烟火识别","烟火识别预警","2010_13",2023, 1899717400907046931l,"fire","烟火识别"),
//2003 佩戴安全带 ------ A null object appeared
SAFETY_HARNESS(2003, "可见光","是否佩戴安全带","安全带预警","2003_ext",2003, 1899717400907046940l,"SafetyHarness","安全带"),
//2024 安全帽 ------- A null object appeared
SAFETY_HELMET(2004, "可见光","是否佩戴安全帽","安全帽预警","2004_ext",2004, 1899717400907046939l,"SafetyHelmet","安全帽"),
//2034 路面车辆计数
CARCOUNT(2034, "可见光","路面车辆计数","路面车辆计数","2010_24",2034, 1899717400907046953l,"carCount","路面车辆计数"),
//2015 多类型车辆计数
CARCOUNTMULTITYPE(2015, "可见光","多类型车辆计数","多类型车辆计数","2010_5",2015, 1899717400907046953l,"carCountMultiType","多类型车辆计数"),
//2016 多类型车辆拥堵聚集
CARMULTITYPEJAM(2016, "可见光","多类型车辆拥堵聚集","多类型车辆拥堵聚集","2010_6",2016, 1899717400907046955l,"carMultiTypeJam","多类型车辆拥堵聚集"),
//2039 无人机安全帽检测 ---------
SAFETY_HELMET_NEW(2039, "可见光","无人机安全帽检测","安全帽预警","2010_29",2039, 1899717400907046939l,"SafetyHelmet","安全帽");
private final Integer id;
private final String sence;
private final String type;
private final String typeStr; //类型描述
private final String extraType;
private final Integer senceId;
private final Long aiLabelId; //ailabel对照数据
private final String aiType;
private final String aiName;
XingluoApiEnum(Integer id, String sence, String type, String typeStr, String extraType, Integer senceId, Long aiLabelId,String aiType, String aiName) {
this.id = id;
this.sence = sence;
this.type = type;
this.typeStr = typeStr;
this.extraType = extraType;
this.senceId = senceId;
this.aiLabelId = aiLabelId;
this.aiType = aiType;
this.aiName = aiName;
}
public Integer getId() {
return id;
}
public String getSence() {
return sence;
}
public String getType() {
return type;
}
public String getTypeStr() {
return typeStr;
}
public String getExtraType() {
return extraType;
}
public Integer getSenceId() {
return senceId;
}
public Long getAiLabelId() {
return aiLabelId;
}
public String getAiType() {
return aiType;
}
public String getAiName() {
return aiName;
}
}

110
dk-modules/sample/src/main/java/org/dromara/sample/manage/config/xingluoApiType.json

@ -0,0 +1,110 @@
{
"code": 200,
"message": "操作成功",
"data": [
{
"id": 2022,
"sence": "可见光",
"type": "秸秆焚烧(烟、火、焚后痕迹)",
"extra_type": "2010_12",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2022,
"conf": 0.7,
"aiConfig": 0
},
{
"id": 2023,
"sence": "可见光",
"type": "烟火识别",
"extra_type": "2010_13",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2023,
"conf": 0.7,
"aiConfig": 0
},
{
"id": 2003,
"sence": "可见光",
"type": "是否佩戴安全绳",
"extra_type": "2003_ext",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2003,
"conf": 0.7,
"aiConfig": 0
},
{
"id": 2004,
"sence": "可见光",
"type": "是否佩戴安全帽",
"extra_type": "2004_ext",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2004,
"conf": 0.7,
"aiConfig": 1
},
{
"id": 2034,
"sence": "可见光",
"type": "路面车辆计数",
"extra_type": "2010_24",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2034,
"conf": 0.7,
"aiConfig": 0
},
{
"id": 2015,
"sence": "可见光",
"type": "多类型车辆计数",
"extra_type": "2010_5",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2015,
"conf": 0.7,
"aiConfig": 0
},
{
"id": 2016,
"sence": "可见光",
"type": "多类型车辆拥堵聚集",
"extra_type": "2010_6",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2016,
"conf": 0.7,
"aiConfig": 0
},
{
"id": 2039,
"sence": "可见光",
"type": "无人机安全帽检测",
"extra_type": "2010_29",
"model": "01",
"user": "xuzhou_ai",
"difficult": 0,
"if_open": 1,
"sence_id": 2039,
"conf": 0.7,
"aiConfig": 0
}
]
}

2
dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceQrtzController.java

@ -47,7 +47,7 @@ public class DeviceQrtzController extends BaseController {
* */
@SaCheckPermission("devict:qrtz:list")
@GetMapping(value = "/page")
public TableDataInfo<DeviceQrtzEntity> queryPageDept(@RequestParam(name="pageNum", defaultValue="1") Integer pageNum,
public TableDataInfo<DeviceQrtzEntity> queryPageDept(@RequestParam(name="pageNo", defaultValue="1") Integer pageNum,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize, DeviceQrtzDTO deviceQrtzDTO) {
Page<DeviceQrtzEntity> page = new Page(pageNum,pageSize);
return deviceQrtzService.listManageDeviceQrtz(page, deviceQrtzDTO);

80
dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/SampleEngineRecordController.java

@ -1,30 +1,62 @@
package org.dromara.sample.manage.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.business.api.RemoteBusinessAlertService;
import org.dromara.business.api.domain.vo.RemoteBusinessAlertVo;
import org.dromara.common.core.utils.file.MimeTypeUtils;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.common.sdk.common.HttpResultResponse;
import org.dromara.sample.feign.RemoteSystemFeign;
import org.dromara.sample.manage.config.XingluoApiEnum;
import org.dromara.sample.manage.mapper.ITaskJobMapper;
import org.dromara.sample.manage.model.dto.CallBackDTO;
import org.dromara.sample.manage.model.dto.DeviceDTO;
import org.dromara.sample.manage.model.dto.EventsDTO;
import org.dromara.sample.manage.model.dto.ObjectsDTO;
import org.dromara.sample.manage.model.entity.TaskJobEntity;
import org.dromara.sample.manage.model.entity.WarningRecordEntity;
import org.dromara.sample.manage.service.IDeviceService;
import org.dromara.sample.manage.service.ISampleEngineRecordService;
import org.dromara.sample.manage.service.ISampleWarningRecordService;
import org.dromara.sample.media.constant.MinIOConstants;
import org.dromara.sample.wayline.mapper.IWaylineJobMapper;
import org.dromara.sample.wayline.model.entity.WaylineJobEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author sean.zhou
* @version 0.1
* @date 2021/11/15
*/
//@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("${url.manage.prefix}${url.manage.version}/saEngineRecord")
@ -35,7 +67,21 @@ public class SampleEngineRecordController {
private ISampleEngineRecordService sampleEngineRecordService;
@Autowired
private ISampleWarningRecordService sampleWarningRecordService;
private IDeviceService deviceService;
@Autowired
private RemoteSystemFeign remoteSystemFeign;
/**
* 获取场景算法
* @param objectMap
* @return
*/
@PostMapping("/extractType")
@Operation(summary = "获取星逻引擎类型。", description = "获取星罗引擎算法")
public HttpResultResponse<Map<String,Object>> extractType(@RequestBody Map<String,Object> objectMap) {
return HttpResultResponse.success(sampleEngineRecordService.extractType(objectMap));
}
/**
* 启动星罗引擎
@ -55,23 +101,23 @@ public class SampleEngineRecordController {
return HttpResultResponse.success();
}
// @Resource
// ITaskJobMapper taskJobMapper;
/**
* 回调数据
*{"events":[{"algoId":2022,"eventId":"NMwuELxmSA","extraType":"2010_12","frame":{"height":1080,"width":1920},"objects":[{"attrImage":"","attrName":"","attrText":"","classId":"3399529","trackId":"576g4","x":829,"y":638}],"picUrl":"https://dispatch-base-test.oss-cn-shanghai.aliyuncs.com/ai/report/29847/rsISeqAgsK/BzSdPemeNi/events/NMwuELxmSA.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20250607T102241Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=LTAI5tLSJ1Jd91LeBLkeuQJx%2F20250607%2Fcn-shanghai%2Fs3%2Faws4_request&X-Amz-Signature=d7cf99add75296a285854bbf2bb8a112b80d76a46a7653a350c26ba154c82865"}],"taskId":"rsISeqAgsK"}
*
* @param resObject
*/
@PostMapping("/some")
@Operation(summary = "存储推流的预警(对外接口)。", description = "存储推流的预警(对外接口)。")
public void some(@RequestBody CallBackDTO callBackVo){
WarningRecordEntity warningRecord = new WarningRecordEntity();
List<WarningRecordEntity> list = new ArrayList<>();
if (CollectionUtils.isNotEmpty(callBackVo.getEvents())){
for (EventsDTO eventsVo :callBackVo.getEvents()){
warningRecord.setTaskId(callBackVo.getTaskId());
warningRecord.setAlgoId(eventsVo.getAlgoId());
warningRecord.setEventId(eventsVo.getEventId());
warningRecord.setExtraType(eventsVo.getExtraType());
warningRecord.setPicUrl(eventsVo.getPicUrl());
warningRecord.setTimestamp(eventsVo.getTimestamp());
list.add(warningRecord);
}
sampleWarningRecordService.saveBatch(list);
System.out.println(callBackVo);
}
// public void some(@RequestBody CallBackDTO callBackVo){
public void some(@RequestBody JSONObject resObject){
Integer insertCount = sampleEngineRecordService.dealAlertData(resObject);
}
}

17
dk-modules/sample/src/main/java/org/dromara/sample/manage/model/entity/EngineRecordEntity.java

@ -30,12 +30,23 @@ public class EngineRecordEntity implements Serializable {
@TableField(value = "device_sn")
private String deviceSn;
/**
* 算法类型
*/
@TableField(value = "extra_type")
private String extraType;
//引擎任务id 格式:qMx86W2tE
@TableField(value = "task_id")
private String taskId;
//任务批次号 格式: WX20250526918312
//(是调用其他接口中的关键字, 也就是飞行所关联的业务逻辑单据号)
@TableField(value = "mission_batch")
private String missionBatch;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@ -45,4 +56,10 @@ public class EngineRecordEntity implements Serializable {
@TableField(value = "push_url")
private String pushUrl;
@TableField(value = "stop_res_data")
private String stopResData;
@TableField(value = "stop_res_data_str")
private String stopResDataStr;
}

5
dk-modules/sample/src/main/java/org/dromara/sample/manage/model/entity/TaskJobEntity.java

@ -30,4 +30,9 @@ public class TaskJobEntity implements Serializable {
private String jobId;
private String deviceSn;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
}

17
dk-modules/sample/src/main/java/org/dromara/sample/manage/model/entity/WarningRecordEntity.java

@ -1,14 +1,12 @@
package org.dromara.sample.manage.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 设备对象-用于存储设备对象 iot_device
@ -21,7 +19,6 @@ import java.io.Serializable;
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class WarningRecordEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private String id;
@ -44,4 +41,14 @@ public class WarningRecordEntity implements Serializable {
@TableField(value = "timestamp")
private Integer timestamp;//事件时间戳,单位:毫秒")
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(value = "track_ids")
private String trackIds;
@TableField(value = "remark")
private String remark;
}

2
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceService.java

@ -77,6 +77,8 @@ public interface IDeviceService {
*/
void spliceDeviceTopo(DeviceDTO device);
String getChildDeviceStreamUrlByDeviceSn(String childDeviceSn);
/**
* Query the information of the device according to the sn of the device.
* @param sn device sn

6
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/ISampleEngineRecordService.java

@ -1,9 +1,15 @@
package org.dromara.sample.manage.service;
import cn.hutool.json.JSONObject;
import java.util.Map;
public interface ISampleEngineRecordService {
Map<String,Object> startEngine(Map<String,Object> objectMap);
void closeEngine(Map<String,Object> objectMap);
Map<String, Object> extractType(Map<String, Object> objectMap);
Integer dealAlertData(JSONObject resObject);
}

46
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceFlightRecordsServiceImpl.java

@ -9,9 +9,7 @@ import org.dromara.sample.manage.service.IDeviceFlightRecordsService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
@Service
@ -19,18 +17,30 @@ public class DeviceFlightRecordsServiceImpl extends ServiceImpl<DeviceFlightReco
@Override
public void saveDeviceFlight(DeviceFlightRecordsEntity deviceFlightRecords) {
public void saveDeviceFlight(DeviceFlightRecordsEntity currentFlightRecord) {
//查询之前的数据
DeviceFlightRecordsEntity deviceFlightRecordsEntities = this.baseMapper.selectOne(new LambdaQueryWrapper<DeviceFlightRecordsEntity>().eq(DeviceFlightRecordsEntity::getDeviceSn,deviceFlightRecords.getDeviceSn()));
DeviceFlightRecordsEntity deviceFlightRecordsEntities = this.baseMapper.selectOne(new LambdaQueryWrapper<DeviceFlightRecordsEntity>().eq(DeviceFlightRecordsEntity::getDeviceSn,currentFlightRecord.getDeviceSn()));
//不为空
if (ObjectUtil.isNotEmpty(deviceFlightRecordsEntities)) {
deviceFlightRecordsEntities.setFlyCount(deviceFlightRecordsEntities.getFlyCount() + deviceFlightRecords.getFlyCount());
deviceFlightRecordsEntities.setFlyAccTime(deviceFlightRecordsEntities.getFlyAccTime() + deviceFlightRecords.getFlyAccTime());
//飞行总架次大于等于表中数据替换 否则累加
if (currentFlightRecord.getFlyCount() >= deviceFlightRecordsEntities.getFlyCount()){
deviceFlightRecordsEntities.setFlyCount(currentFlightRecord.getFlyCount());
}else {
deviceFlightRecordsEntities.setFlyCount(deviceFlightRecordsEntities.getFlyCount() + currentFlightRecord.getFlyCount());
}
//飞行总时长大于等于表中数据替换 否则累加
if (currentFlightRecord.getFlyAccTime() >= deviceFlightRecordsEntities.getFlyAccTime()){
deviceFlightRecordsEntities.setFlyAccTime(currentFlightRecord.getFlyAccTime());
}else {
deviceFlightRecordsEntities.setFlyAccTime(deviceFlightRecordsEntities.getFlyAccTime() + currentFlightRecord.getFlyAccTime());
}
this.updateById(deviceFlightRecordsEntities);
}else {
this.save(deviceFlightRecords);
this.save(currentFlightRecord);
}
}
@ -40,18 +50,28 @@ public class DeviceFlightRecordsServiceImpl extends ServiceImpl<DeviceFlightReco
List<DeviceFlightRecordsEntity> deviceFlightRecordsEntities = this.baseMapper.selectList(new LambdaQueryWrapper<>());
int flyCount = deviceFlightRecordsEntities.stream()
int flyCount = Optional.ofNullable(deviceFlightRecordsEntities)
.map(list -> list.stream()
.map(DeviceFlightRecordsEntity::getFlyCount)
.reduce(0, Integer::sum);
.reduce(0, Integer::sum))
.orElse(0);
// int flyAccTime = deviceFlightRecordsEntities.stream()
// .map(DeviceFlightRecordsEntity::getFlyAccTime)
// .reduce(0, Integer::sum);
int flyAccTime = deviceFlightRecordsEntities.stream()
int flyAccTime = Optional.ofNullable(deviceFlightRecordsEntities)
.map(list -> list.stream()
.map(DeviceFlightRecordsEntity::getFlyAccTime)
.reduce(0, Integer::sum);
.reduce(0, Integer::sum))
.orElse(0);
int flyAccTimeHour = (int) Math.round(flyAccTime / 3600.0);
resultMap.put("flyCount",flyCount);
resultMap.put("flyAccTime",flyAccTime);
resultMap.put("flyAccTime",flyAccTimeHour);
return resultMap;
}

13
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceServiceImpl.java

@ -57,6 +57,7 @@ import org.springframework.util.StringUtils;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@ -247,6 +248,9 @@ public class DeviceServiceImpl implements IDeviceService {
if(proIds == null){
proIds = deviceProService.listDeviceGroup(loginUser.getUserId());
}
if(ObjectUtil.isEmpty(proIds)){
return new ArrayList<DeviceDTO>();
}
List<DeviceDTO> devicesList = this.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
@ -289,6 +293,15 @@ public class DeviceServiceImpl implements IDeviceService {
subDevice.setPayloadsList(payloadService.getDevicePayloadEntitiesByDeviceSn(gateway.getChildDeviceSn()));
}
@Override
public String getChildDeviceStreamUrlByDeviceSn(String childDeviceSn) {
DeviceDTO subDevice = getDevicesByParams(DeviceQueryParam.builder().deviceSn(childDeviceSn).build()).get(0);
String deviceVideoEnum = DeviceVideoEnum.find(subDevice.getDeviceName()).getDevice();
// String string = new VideoId(subDevice.getDeviceSn() + SLASH + deviceVideoEnum + SLASH + VideoTypeEnum.NORMAL.getType() + DASH + DeviceTypeVideoEnum.ZERO.getVideoType()).toString();
String childDeviceUrl = subDevice.getDeviceSn() + DASH + deviceVideoEnum; //1581F6Q8X254K00G085K-81-0-0
return childDeviceUrl;
}
@Override
public Optional<TopologyDeviceDTO> getDeviceTopoForPilot(String sn) {
if (!StringUtils.hasText(sn)) {

12
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/EngineRecordServiceImpl.java

@ -95,6 +95,7 @@ public class EngineRecordServiceImpl implements IEngineRecordService {
JSONObject jsonObj = new JSONObject();
jsonObj.put("username", sanitize("xuzhou_ai")); // sanitize函数见下文
jsonObj.put("password", sanitize(md5));
//{"code":200,"message":"操作成功","data":{"token":"eyJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3NDc5NjY2NzksImV4cCI6MTc1MDU1ODY3OSwidWlkIjoiT2tUV0NyWWxZSSIsInRoaXJkIjoxfQ.lkOSgcWES1ViKmeVht6b1AKuw6MbxPxsmGVeuahy4QZfWkv8y8Ac80bkvZMVBQD_-DmcwK3HXOslrWI5_uHDuBRO2phB6BGXzqkb4GKvLsZMGI-Wrc4tHyZ-ojQ67uhWVUgnjFK4OnMsf5U9LxAxe0XJZQWwrm8KAh9Zb0iD4gY"}}
String responseBody = PostRequest(jsonObj, "http://60.204.247.65:8100/Third/Login");
JSONObject jsonObject = new JSONObject(responseBody);
// 逐层获取 data -> token
@ -107,14 +108,16 @@ public class EngineRecordServiceImpl implements IEngineRecordService {
try {
URI uri = new URIBuilder("http://60.204.247.65:8100/V2/AI/WX/User/Scene")
.build();
//{"code":200,"message":"操作成功","data":[{"scene":"可见光","id":2}]}
sceneResponseBody = GetRequest(uri, token);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
log.error("星逻算法-场景查询异常",e);
}
JSONObject jsonObject1 = new JSONObject(sceneResponseBody);
// 逐层获取 data -> token
JSONObject data1 = jsonObject.getJSONObject("data");
String scene = data1.getString("scene");
// String scene = jsonObject1.getJSONArray("data").getJSONObject(0).getString("scene");
//查询场景算法
List<String> extra_type_list = new ArrayList<>();
@ -125,6 +128,7 @@ public class EngineRecordServiceImpl implements IEngineRecordService {
.build();
algorithmResponseBody = GetRequest(uri, token);
ObjectMapper mapper = new ObjectMapper();
//ExtraTypeResponse(code=200, message=操作成功, data=[ExtraType(id=2022, sence=可见光, type=秸秆焚烧(烟、火、焚后痕迹), extra_type=2010_12, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2022, conf=0.7, aiConfig=0), ExtraType(id=2023, sence=可见光, type=烟火识别, extra_type=2010_13, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2023, conf=0.7, aiConfig=0), ExtraType(id=2003, sence=可见光, type=是否佩戴安全绳, extra_type=2003_ext, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2003, conf=0.7, aiConfig=0), ExtraType(id=2004, sence=可见光, type=是否佩戴安全帽, extra_type=2004_ext, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2004, conf=0.7, aiConfig=1), ExtraType(id=2034, sence=可见光, type=路面车辆计数, extra_type=2010_24, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2034, conf=0.7, aiConfig=0), ExtraType(id=2015, sence=可见光, type=多类型车辆计数, extra_type=2010_5, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2015, conf=0.7, aiConfig=0), ExtraType(id=2016, sence=可见光, type=多类型车辆拥堵聚集, extra_type=2010_6, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2016, conf=0.7, aiConfig=0)])
ExtraTypeResponse response = mapper.readValue(algorithmResponseBody,ExtraTypeResponse.class);
List<ExtraType> list = response.getData();
for (ExtraType extraType : list) {
@ -132,7 +136,7 @@ public class EngineRecordServiceImpl implements IEngineRecordService {
break;
}
} catch (URISyntaxException | JsonProcessingException e) {
throw new RuntimeException(e);
log.error("星逻算法-算法列表查询失败",e);
}
JSONObject jsonObj2 = new JSONObject();
@ -147,7 +151,7 @@ public class EngineRecordServiceImpl implements IEngineRecordService {
try {
response = mapper1.readValue(responseBody2, EngineResponse.class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
log.error("星逻算法-引擎启动失败",e);
}
objectMap.put("task_id",response.getData().getTask_id());
record.setPushUrl(objectMap.get("push_url").toString());
@ -181,7 +185,7 @@ public class EngineRecordServiceImpl implements IEngineRecordService {
if(dataObj != null && dataObj instanceof Integer) {
int data = (Integer) dataObj;
if (data ==1){
mapper.delete(new LambdaQueryWrapper<EngineRecordEntity>().eq(EngineRecordEntity::getDeviceSn, objectMap.get("device_sn")));
mapper.delete(new LambdaQueryWrapper<EngineRecordEntity>().eq(EngineRecordEntity::getDeviceSn, objectMap.get("deviceSn")));
}else {
throw new RuntimeException("关闭引擎失败!");
}

36
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/LiveStreamServiceImpl.java

@ -1,29 +1,27 @@
package org.dromara.sample.manage.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.dromara.common.rocketmq.producer.MessageProducerUtil;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.sdk.cloudapi.device.DeviceDomainEnum;
import org.dromara.common.sdk.cloudapi.device.VideoId;
import org.dromara.common.sdk.cloudapi.livestream.*;
import org.dromara.common.sdk.cloudapi.livestream.api.AbstractLivestreamService;
import org.dromara.common.sdk.cloudapi.wayline.FlighttaskProgress;
import org.dromara.common.sdk.common.HttpResultResponse;
import org.dromara.common.sdk.common.SDKManager;
import org.dromara.common.sdk.mqtt.CommonTopicRequest;
import org.dromara.common.sdk.mqtt.MqttGatewayPublish;
import org.dromara.common.sdk.mqtt.services.ServicesReplyData;
import org.dromara.common.sdk.mqtt.services.TopicServicesResponse;
import org.dromara.sample.component.mqtt.model.EventsReceiver;
import org.dromara.sample.feign.RemoteSystemFeign;
import org.dromara.sample.manage.model.dto.*;
import org.dromara.sample.manage.model.entity.DeviceEntity;
import org.dromara.sample.manage.model.param.DeviceQueryParam;
import org.dromara.sample.manage.service.*;
import org.dromara.sample.wayline.model.dto.WaylineJobDTO;
import org.dromara.sample.wayline.service.IWaylineJobService;
import org.dromara.sample.wayline.service.IWaylineRedisService;
import org.dromara.system.api.RemoteDictService;
import org.dromara.system.api.domain.vo.RemoteDictDataVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -70,6 +68,9 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
@Resource
private RemoteSystemFeign remoteSystemFeign;
@DubboReference
private RemoteDictService remoteDictService;
@Override
public List<CapacityDeviceDTO> getLiveCapacity(String workspaceId) {
@ -290,6 +291,25 @@ public class LiveStreamServiceImpl implements ILiveStreamService {
return agoraUrl.setSn(videoId.getDroneSn());
case RTMP:
LivestreamRtmpUrl rtmpUrl = (LivestreamRtmpUrl) url.clone();
//南通设备指定固定rtmpl路径 功能关闭
/* List<RemoteDictDataVo> dictDataVoList = remoteDictService.selectDictDataByType("drone_stream_rtmp");
for (RemoteDictDataVo remoteDictDataVo : dictDataVoList) {
if(JSONUtil.isTypeJSON(remoteDictDataVo.getRemark())){
JSONArray jsonArr = JSONUtil.parseArray(remoteDictDataVo.getRemark());
for (Object obj : jsonArr) {
JSONObject entries = new JSONObject(obj);
String droneSnStr = entries.getStr("droneSn");
String rtmpUrlStr = entries.getStr("rtmpUrl");
if(videoId.getDroneSn().equals(droneSnStr) ){
rtmpUrl.setUrl(rtmpUrlStr);
}
}
}
}*/
// if(videoId.getDroneSn().equals("7CTXN2T00B07C5") || videoId.getDroneSn().equals("1581F6Q8X24CC00G02JB")){
// rtmpUrl.setUrl("rtmp://106.13.57.190/live/livesteam/");
// }
return rtmpUrl.setUrl(rtmpUrl.getUrl() + videoId.getDroneSn() + "-" + videoId.getPayloadIndex().toString());
case GB28181:
String random = String.valueOf(Math.abs(videoId.getDroneSn().hashCode()) % 1000);

483
dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/SampleEngineRecordServiceImpl.java

@ -1,12 +1,19 @@
package org.dromara.sample.manage.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.seata.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
@ -15,48 +22,96 @@ import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dromara.business.api.domain.RemoteBusinessAlertRequest;
import org.dromara.business.api.domain.vo.RemoteBusinessAlertVo;
import org.dromara.common.core.utils.file.MimeTypeUtils;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.sample.common.util.Md5Utils;
import org.dromara.sample.feign.RemoteBusinessAlertFeign;
import org.dromara.sample.feign.RemoteConfigFeign;
import org.dromara.sample.feign.RemoteSystemFeign;
import org.dromara.sample.manage.config.XingluoApiConfig;
import org.dromara.sample.manage.config.XingluoApiEnum;
import org.dromara.sample.manage.mapper.ISampleEngineRecordMapper;
import org.dromara.sample.manage.mapper.ITaskJobMapper;
import org.dromara.sample.manage.mapper.SampleWarningRecordMapper;
import org.dromara.sample.manage.model.dto.*;
import org.dromara.sample.manage.model.entity.EngineRecordEntity;
import org.dromara.sample.manage.model.entity.TaskJobEntity;
import org.dromara.sample.manage.model.entity.WarningRecordEntity;
import org.dromara.sample.manage.service.IDeviceService;
import org.dromara.sample.manage.service.ISampleEngineRecordService;
import org.dromara.system.api.RemoteConfigService;
import org.dromara.sample.media.constant.MinIOConstants;
import org.dromara.sample.wayline.mapper.IWaylineJobMapper;
import org.dromara.sample.wayline.model.entity.WaylineJobEntity;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;
import static org.apache.commons.compress.utils.ArchiveUtils.sanitize;
@RequiredArgsConstructor
@Service
@Slf4j
@Transactional
public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService {
@Resource
ISampleEngineRecordMapper mapper;
ISampleEngineRecordMapper engineRecordMapper;
@Resource
ITaskJobMapper taskJobMapper;
@DubboReference
private RemoteConfigService remoteConfigService;
@Resource
SampleWarningRecordMapper sampleWarningRecordMapper;
@Autowired
private XingluoApiConfig xingluoApiConfig;
@Autowired
private IDeviceService deviceService;
// @Autowired
// private ISampleWarningRecordService sampleWarningRecordService;
// @Autowired
private final IWaylineJobMapper waylineJobMapper;
@Resource
private RemoteConfigFeign remoteConfigFeign;
@Resource
private RemoteSystemFeign remoteSystemFeign;
@Resource
private RemoteBusinessAlertFeign remoteBusinessAlertFeign;
@Override
public Map<String, Object> startEngine(Map<String, Object> objectMap){
public Map<String, Object> extractType(Map<String, Object> objectMap) {
EngineRecordEntity record = new EngineRecordEntity();
String ip = remoteConfigService.selectStreamIp();
//获取token
//设置请求Header和Body(如JSON)
String md5 = Md5Utils.hash("xuzhou_ai");
JSONObject jsonObj = new JSONObject();
jsonObj.put("username", sanitize("xuzhou_ai")); // sanitize函数见下文
jsonObj.put("password", sanitize(md5));
//{"code":200,"message":"操作成功","data":{"token":"eyJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3NDc5NjY2NzksImV4cCI6MTc1MDU1ODY3OSwidWlkIjoiT2tUV0NyWWxZSSIsInRoaXJkIjoxfQ.lkOSgcWES1ViKmeVht6b1AKuw6MbxPxsmGVeuahy4QZfWkv8y8Ac80bkvZMVBQD_-DmcwK3HXOslrWI5_uHDuBRO2phB6BGXzqkb4GKvLsZMGI-Wrc4tHyZ-ojQ67uhWVUgnjFK4OnMsf5U9LxAxe0XJZQWwrm8KAh9Zb0iD4gY"}}
String responseBody = PostRequest(jsonObj, "http://60.204.247.65:8100/Third/Login","");
JSONObject jsonObject = new JSONObject(responseBody);
// 逐层获取 data -> token
@ -66,87 +121,151 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
String algorithmResponseBody = null;
//查询用户开通的场景
if (StringUtils.isNotEmpty(token)){
// try {
// URI uri = new URIBuilder("http://60.204.247.65:8100/V2/AI/WX/User/Scene")
// .build();
// sceneResponseBody = GetRequest(uri, token);
// } catch (URISyntaxException e) {
// throw new RuntimeException(e);
// }
// EngineTypeResponse engineTypeResponse = null;
// try {
// ObjectMapper mapper = new ObjectMapper();
// engineTypeResponse = mapper.readValue(sceneResponseBody, EngineTypeResponse.class);
// } catch (JsonProcessingException e) {
// throw new RuntimeException(e);
// }
//// JSONObject jsonObject1 = new JSONObject(sceneResponseBody);
// // 逐层获取 data -> token
//// JSONObject data1 = jsonObject1.getJSONObject("data");
// String scene = engineTypeResponse.getData().getScene();
//
// //查询场景算法
// List<String> extra_type_list = new ArrayList<>();
// try {
// URI uri = new URIBuilder("http://60.204.247.65:8100/V2/AI/WX/User/ExtraType/Get")
// .addParameter("scene",scene)
// .addParameter("if_open","1")
// .build();
// algorithmResponseBody = GetRequest(uri, token);
// ObjectMapper mapper = new ObjectMapper();
// ExtraTypeResponse response = mapper.readValue(algorithmResponseBody,ExtraTypeResponse.class);
// List<ExtraType> list = response.getData();
// for (ExtraType extraType : list) {
// extra_type_list.add(extraType.getExtra_type());
// break;
// }
// } catch (URISyntaxException | JsonProcessingException e) {
// throw new RuntimeException(e);
// }
try {
URI uri = new URIBuilder("http://60.204.247.65:8100/V2/AI/WX/User/Scene")
.build();
//{"code":200,"message":"操作成功","data":[{"scene":"可见光","id":2}]}
sceneResponseBody = GetRequest(uri, token);
} catch (URISyntaxException e) {
log.error("星逻算法-场景查询异常",e);
}
JSONObject jsonObject1 = new JSONObject(sceneResponseBody);
// 逐层获取 data -> token
JSONObject data1 = jsonObject.getJSONObject("data");
// String scene = data1.getString("scene");
// String scene = jsonObject1.getJSONArray("data").getJSONObject(0).getString("scene");
//查询场景算法
List<String> extra_type_list = new ArrayList<>();
try {
URI uri = new URIBuilder("http://60.204.247.65:8100/V2/AI/WX/User/ExtraType/Get")
.addParameter("scene","可见光")
.addParameter("if_open","1")
.build();
algorithmResponseBody = GetRequest(uri, token);
ObjectMapper mapper = new ObjectMapper();
//ExtraTypeResponse(code=200, message=操作成功, data=[ExtraType(id=2022, sence=可见光, type=秸秆焚烧(烟、火、焚后痕迹), extra_type=2010_12, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2022, conf=0.7, aiConfig=0), ExtraType(id=2023, sence=可见光, type=烟火识别, extra_type=2010_13, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2023, conf=0.7, aiConfig=0), ExtraType(id=2003, sence=可见光, type=是否佩戴安全绳, extra_type=2003_ext, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2003, conf=0.7, aiConfig=0), ExtraType(id=2004, sence=可见光, type=是否佩戴安全帽, extra_type=2004_ext, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2004, conf=0.7, aiConfig=1), ExtraType(id=2034, sence=可见光, type=路面车辆计数, extra_type=2010_24, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2034, conf=0.7, aiConfig=0), ExtraType(id=2015, sence=可见光, type=多类型车辆计数, extra_type=2010_5, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2015, conf=0.7, aiConfig=0), ExtraType(id=2016, sence=可见光, type=多类型车辆拥堵聚集, extra_type=2010_6, model=01, user=xuzhou_ai, difficult=0, if_open=1, sence_id=2016, conf=0.7, aiConfig=0)])
ExtraTypeResponse response = mapper.readValue(algorithmResponseBody,ExtraTypeResponse.class);
System.out.println(JSONUtil.toJsonStr(response));
List<ExtraType> list = response.getData();
for (ExtraType extraType : list) {
extra_type_list.add(extraType.getExtra_type());
break;
}
} catch (URISyntaxException | JsonProcessingException e) {
log.error("星逻算法-算法列表查询失败",e);
}
}
return null;
}
@Override
public Map<String, Object> startEngine(Map<String, Object> objectMap){
System.out.println("objectMap" + objectMap);
// String configKey = remoteSystemFeign.getConfigKey("xingluo.auto.submit");//通
// System.out.println("configKey"+configKey);
EngineRecordEntity record = new EngineRecordEntity();
// String ip = remoteConfigService.selectStreamIp();
String ip = remoteConfigFeign.getConfigKey("stream");
System.out.println(ip);
ip = "121.237.182.235";//服务器使用ip
String md5 = Md5Utils.hash("xuzhou_ai"); //获取token + 设置请求Header和Body(如JSON)
JSONObject jsonObj = new JSONObject();
jsonObj.put("username", sanitize("xuzhou_ai")); // sanitize函数见下文
jsonObj.put("password", sanitize(md5));
String responseBody = PostRequest(jsonObj, xingluoApiConfig.getEngineLogin(),""); //"http://60.204.247.65:8100/Third/Login"
JSONObject jsonObject = new JSONObject(responseBody);
// 逐层获取 data -> token
JSONObject data = jsonObject.getJSONObject("data");
String token = data.getString("token");
String sceneResponseBody = null;
String algorithmResponseBody = null;
String taskId = "";
String missionBatch = "";
String deviceSn = MapUtil.getStr(objectMap, "deviceSn", "");
//获取rtmpUrl
String rtmpUrl = "";
DeviceDTO deviceDTO = deviceService.getDeviceBySn(deviceSn).orElse(null);
if (deviceDTO != null) {
String childDeviceRtmpUrl = deviceService.getChildDeviceStreamUrlByDeviceSn(deviceDTO.getChildDeviceSn());
rtmpUrl = childDeviceRtmpUrl;
}
//查询用户开通的场景
Object rtmpUrlParam = objectMap.get("rtmpUrl");
String pushUrl = "rtmp://" + ip + "/live/livesteam/" + rtmpUrl + "ai1";
if (StringUtils.isNotEmpty(token)){
JSONObject jsonObj2 = new JSONObject();
String type = objectMap.get("type").toString();
if (StringUtils.isNotEmpty(type)){
if (StringUtils.isNotEmpty(type)){ //2004_ext 算法名称
List<String> list = Arrays.asList(type.split(","));
jsonObj2.put("scene", "可见光"); // sanitize函数见下文
jsonObj2.put("callback_url", "http://114.235.183.162:9888/ces/iot/deviceLog/some");
jsonObj2.put("callback_url", xingluoApiConfig.getEngineCallbackUrl());//"http://121.237.178.63:11100/sample/manage/api/v1/saEngineRecord/some"
jsonObj2.put("extra_type_list",new JSONArray(list));
jsonObj2.put("input_url","http://"+ip+":19008/live/livesteam/"+objectMap.get("rtmpUrl")+".flv");
jsonObj2.put("push_url", "rtmp://"+ip+"/live/livesteam/"+objectMap.get("rtmpUrl")+"ai1");
// jsonObj2.put("play_url", objectMap.get("play_url"));
String responseBody2 = PostRequest(jsonObj2, "http://60.204.247.65:8100/Third/Engine/Start",token);
// jsonObj2.put("input_url","http://"+ip+":19008/live/livesteam/"+objectMap.get("rtmpUrl")+".flv");
jsonObj2.put("input_url", "rtmp://"+ip+"/live/livesteam/"+ rtmpUrl);//预览接口必须要传rtmp,不能是flv
jsonObj2.put("push_url", pushUrl); //推流接口有时候不稳定,需要检查SRS服务
// live.setUrl(url.toString().replace("rtmp", "webrtc"));
// jsonObj2.put("play_url", objectMap.get("play_url")); //play_url不必传, play和push是一对, play 其实是冗余的, 方便记录更详细的日志
/**
* {"code":500,"message":"任务启动错误:can not open input stream http://114.235.183.163:19008/live/livesteam/7CTXN2T00B07C5-165-0-7.flv","data":null}
* {"code":500,"message":"AI开启失败","data":null}
* {"code":500,"message":"任务启动错误:can not open output rtmp://114.235.183.163/live/livesteam/7CTXN2T00B07C5-165-0-7ai1","data":null}
* {"code":200,"message":"操作成功","data":{"task_id":"NOZGoIIubQ","mission_batch":"WX1748254304635"}}
*/
//测试环境,直接接收url,跳过无人机
// Object rtmpUrlParam = objectMap.get("inputUrl");
// jsonObj2.put("input_url", "rtmp://114.235.183.163/live/livesteam/1581F6Q8X24CE00G02S4-81-0-0");//预览接口必须要传rtmp,不能是flv
// jsonObj2.put("push_url", "rtmp://114.235.183.163/live/livesteam/1581F6Q8X24CE00G02S4-81-0-0ai1");//预览接口必须要传rtmp,不能是flv
System.out.println(jsonObj2.toString());
String responseBody2 = PostRequest(jsonObj2, xingluoApiConfig.getEngineStart(),token); //"http://60.204.247.65:8100/Third/Engine/Start"
System.out.println(responseBody2);
ObjectMapper mapper1 = new ObjectMapper();
EngineResponse response = null;
try {
response = mapper1.readValue(responseBody2, EngineResponse.class);
if (response.getCode() != 200){
throw new RuntimeException("第三方接口调用失败!");
log.error("第三方接口调用失败!");
}
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
log.error("星逻算法-引擎启动失败",e);
}
taskId = response.getData().getTask_id();
missionBatch = response.getData().getMission_batch();
objectMap.put("task_id",response.getData().getTask_id());
record.setPushUrl(objectMap.get("rtmpUrl").toString());
record.setTaskId(MapUtil.getStr(objectMap,"task_id",""));
record.setDeviceSn(MapUtil.getStr(objectMap,"deviceSn",""));
record.setTaskId(response.getData().getTask_id());
record.setDeviceSn(deviceSn);
record.setExtraType(objectMap.get("type").toString());
record.setPushUrl(rtmpUrl.toString());
record.setTaskId(taskId); //MapUtil.getStr(objectMap,"task_id","")
record .setMissionBatch(missionBatch);
record.setPushUrl(pushUrl);
System.out.print(objectMap);
}
}
Map<String, Object> map = new HashMap();
map.put("push_url", "http://"+ip+":1985/rtc/v1/whep/?app=live/livesteam&stream="+objectMap.get("rtmpUrl")+"ai1");
map.put("task_id", objectMap.get("task_id"));
//添加启动引擎记录
mapper.insert(record);
engineRecordMapper.insert(record);
Map<String, Object> map = new HashMap();
// map.put("push_url", "http://"+ip+":1985/rtc/v1/whep/?app=live/livesteam&stream="+ rtmpUrl +"ai1");
// live.setUrl(url.toString().replace("rtmp", "webrtc"));
map.put("push_url", pushUrl.replaceFirst("rtmp", "webrtc"));
map.put("task_id", taskId);//objectMap.get("task_id")
//添加任务id和jobid关联关系
TaskJobEntity taskJobEntity = new TaskJobEntity();
taskJobEntity.setJobId(objectMap.get("jobId").toString());
String jobIdStr = MapUtil.getStr(objectMap, "jobId");
jobIdStr = StrUtil.isEmpty(jobIdStr) ? "-1" : jobIdStr; //没有航线,默认-1
taskJobEntity.setJobId(jobIdStr);
taskJobEntity.setTaskId(objectMap.get("task_id").toString());
taskJobEntity.setDeviceSn(deviceSn);
taskJobMapper.insert(taskJobEntity);
return map;
}
@ -154,7 +273,14 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
@Override
public void closeEngine(Map<String, Object> objectMap) {
JSONObject jsonObj2 = new JSONObject();
EngineRecordEntity record = mapper.selectOne(new LambdaQueryWrapper<EngineRecordEntity>().eq(EngineRecordEntity::getDeviceSn, objectMap.get("deviceSn")));
// String taskId = (String)objectMap.get("taskId");
String deviceSn = (String)objectMap.get("deviceSn");
LambdaQueryWrapper<EngineRecordEntity> engineRecordQW = new LambdaQueryWrapper<EngineRecordEntity>();
// engineRecordQW.eq(EngineRecordEntity::getTaskId, taskId);
engineRecordQW.eq(EngineRecordEntity::getDeviceSn,deviceSn);
engineRecordQW.orderByDesc(EngineRecordEntity::getCreateTime);
engineRecordQW.last("limit 1");
EngineRecordEntity record = engineRecordMapper.selectOne(engineRecordQW);
if (record == null){
// throw new RuntimeException("关闭引擎失败!");
}else {
@ -164,18 +290,40 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
JSONObject jsonObj = new JSONObject();
jsonObj.put("username", sanitize("xuzhou_ai")); // sanitize函数见下文
jsonObj.put("password", sanitize(md5));
String responseBody = PostRequest(jsonObj, "http://60.204.247.65:8100/Third/Login","");
//{"code":200,"message":"操作成功","data":{"token":"eyJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3NDgyNDM0MDgsImV4cCI6MTc1MDgzNTQwOCwidWlkIjoiT2tUV0NyWWxZSSIsInRoaXJkIjoxfQ.LZI1jEl7wyUquXJrApynEE7aUdpqiiqy8VD_3nm215I0dgkGTtDWa3PO26pDWFzw40kNPI5JwWuZBjEtroLAOEQtmhsI9BId5aw605D5jGQ69U6JTa7q095eJxIT2I7rMwAjMGqOtxDfRyw_U-GJPTA4nE4uy98yCXG56FBnrY8"}}
String responseBody = PostRequest(jsonObj, xingluoApiConfig.getEngineLogin(),"");//"http://60.204.247.65:8100/Third/Login"
JSONObject jsonObject = new JSONObject(responseBody);
// 逐层获取 data -> token
JSONObject data = jsonObject.getJSONObject("data");
String token = data.getString("token");
jsonObj2.put("task_id", record.getTaskId()); // sanitize函数见下文
String responseBody2 = PostRequest(jsonObj2, "http://60.204.247.65:8100/Third/Engine/Stop",token);
//{"code":200,"message":"操作成功","data":0}
String responseBody2 = PostRequest(jsonObj2, xingluoApiConfig.getEngineStop(),token); //"http://60.204.247.65:8100/Third/Engine/Stop"
JSONObject json = new JSONObject(responseBody2);
String resData = json.getString("data");
String resDataStr = "";
// String resDataStr = StrUtil.equals(resData,"1") ? "停止成功" : "停止失败";
switch (resData){
case "":
resDataStr = "停止成功(长时间未关闭)";
break;
case "0":
resDataStr = "停止失败";
break;
case "1":
resDataStr = "停止成功";
break;
}
EngineRecordEntity engineRecordUpdate = new EngineRecordEntity();
engineRecordUpdate.setId(record.getId());
engineRecordUpdate.setStopResData(resData);
engineRecordUpdate.setStopResDataStr(resDataStr);
engineRecordMapper.updateById(engineRecordUpdate);
// 方式2:安全获取(先判空再转换)
Object dataObj = json.get("data");
/* Object dataObj = json.get("data");
if(dataObj != null && dataObj instanceof Integer) {
int data1 = (Integer) dataObj;
if (data1 ==1){
@ -185,16 +333,201 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
}
} else {
throw new RuntimeException("关闭引擎失败!");
}*/
}
}
@Override
public Integer dealAlertData(cn.hutool.json.JSONObject resObject) {
cn.hutool.json.JSONObject entries = new cn.hutool.json.JSONObject(resObject);
CallBackDTO callBackVo = JSONUtil.toBean(resObject, CallBackDTO.class);
String taskIdStr = entries.getStr("taskId");
if(StrUtil.isBlank(taskIdStr)){return 0;} //无任务ID拦截
if(callBackVo.getEvents().isEmpty()){ return 0;}
//基于历史记录,找相同设备- trackId是否相同,不同才保存, (每次记录中eventId都不同,所以不做参考)
//同一图片上传可能包含多个物体,传值可能是 h1v93,或者fdi32,或者h1v93,fdi32, 只要trackIds不同,就保存记录
List<WarningRecordEntity> warningRecordList = new ArrayList<>();
// String fileUrlStr = "mediafile/e5b8ce3a-3562-40e0-b244-91554d9c17ad/DJI_202505211323_001_e5b8ce3a-3562-40e0-b244-91554d9c17ad/DJI_20250521132610_0001_V.jpeg";
// String fileUrl = fileService.getObjectUrlOne(MinIOConstants.BUCKET_DKCY, fileUrlStr, 360000).toString();
if (CollectionUtils.isEmpty(callBackVo.getEvents())){return 0;} //空事件拦截
/** 传值转WarningRecord记录 **/
for (EventsDTO eventsVo : callBackVo.getEvents()){ //一个事件一个图片
String extraTypeStr = eventsVo.getExtraType();
String trackIds = eventsVo.getObjects().stream().map(ObjectsDTO::getTrackId).collect(Collectors.joining(","));
// Long count = sampleWarningRecordService.lambdaQuery()
// .eq(WarningRecordEntity::getTaskId, taskIdStr)
// .eq(WarningRecordEntity::getExtraType, extraTypeStr)
// .eq(WarningRecordEntity::getTrackIds, trackIds)
// .count();
LambdaQueryWrapper<WarningRecordEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WarningRecordEntity::getTaskId, taskIdStr)
.eq(WarningRecordEntity::getExtraType, extraTypeStr)
.eq(WarningRecordEntity::getTrackIds, trackIds);
Long count = sampleWarningRecordMapper.selectCount(queryWrapper);
if(count > 0){continue;}
WarningRecordEntity warningRecord = new WarningRecordEntity();
warningRecord.setTaskId(callBackVo.getTaskId());
warningRecord.setAlgoId(eventsVo.getAlgoId());
warningRecord.setEventId(eventsVo.getEventId());
warningRecord.setExtraType(eventsVo.getExtraType());
warningRecord.setPicUrl(eventsVo.getPicUrl());
// warningRecord.setPicUrl("http://114.235.183.147:9090/api/v1/download-shared-object/aHR0cDovLzEyNy4wLjAuMTo5MDAwL2RrY3kvbWVkaWFmaWxlL2U1YjhjZTNhLTM1NjItNDBlMC1iMjQ0LTkxNTU0ZDljMTdhZC9ESklfMjAyNTA1MjExMzIzXzAwMV9lNWI4Y2UzYS0zNTYyLTQwZTAtYjI0NC05MTU1NGQ5YzE3YWQvREpJXzIwMjUwNTIxMTMyNjEwXzAwMDFfVi5qcGVnP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QVI5MEk5QkxXWVZBWkRLOUowVjElMkYyMDI1MDUyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA1MjJUMTUxNzAxWiZYLUFtei1FeHBpcmVzPTQzMjAwJlgtQW16LVNlY3VyaXR5LVRva2VuPWV5SmhiR2NpT2lKSVV6VXhNaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpoWTJObGMzTkxaWGtpT2lKQlVqa3dTVGxDVEZkWlZrRmFSRXM1U2pCV01TSXNJbVY0Y0NJNk1UYzBOemsyT0RneE9Dd2ljR0Z5Wlc1MElqb2lZV1J0YVc0aWZRLkh1N1VaVkhuS19EUWhfR1lnLVB0cVhBNFpJTHpPTk1vTkZ3by1YalI0N0R3U3VnZ2NyRC1EdXkxeEdfM3FmWXdRQmdPd29Ca2xGVTRYLWpvNncxY0lRJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZ2ZXJzaW9uSWQ9bnVsbCZYLUFtei1TaWduYXR1cmU9MjNmZjdhZWViNTJlZjk4ZWFmMTg5OTg4MjQzNDk5ZTRiYzgwNzI5ZWU1MzJkM2M2MTdlMDFmM2U3ODZlZDA1OQ");
warningRecord.setTimestamp(eventsVo.getTimestamp());
String objJsonStr = JSONUtil.toJsonStr(eventsVo.getObjects());
warningRecord.setRemark(objJsonStr);
warningRecord.setTrackIds(trackIds);
// System.out.println(JSONUtil.toJsonStr(eventsVo.getObjects()));
warningRecordList.add(warningRecord);
}
// sampleWarningRecordService.saveBatch(warningRecordList);
sampleWarningRecordMapper.insert(warningRecordList);
/** WarningRecord转 businessAlert记录 **/
//保存数据到BusinessAlert
String activeProfile = "w_nantong";
ArrayList<RemoteBusinessAlertVo> alertVoList = new ArrayList<>();
for (WarningRecordEntity warningRecordEntity : warningRecordList) {
RemoteBusinessAlertVo remoteBusinessAlertVo = new RemoteBusinessAlertVo();
if(ObjectUtil.isEmpty(warningRecordEntity.getTaskId())){ continue;} //空数据跳过
setupLabelInfo(warningRecordEntity, remoteBusinessAlertVo);//设置标签信息
//查找最新任务TaskJob
LambdaQueryWrapper<TaskJobEntity> taskJobquery = new LambdaQueryWrapper<>(TaskJobEntity.class)
.eq(TaskJobEntity::getTaskId, warningRecordEntity.getTaskId())
.orderByDesc(TaskJobEntity::getCreateTime)
.last("limit 1");
TaskJobEntity taskJobEntity = taskJobMapper.selectOne(taskJobquery);
String deviceSn = "";
if(BeanUtil.isNotEmpty(taskJobEntity)){
String jobId = taskJobEntity.getJobId();
deviceSn = taskJobEntity.getDeviceSn();
if(StrUtil.equals("-1",jobId)){ //没有jobId,给个默认名称
remoteBusinessAlertVo.setJobId("-1");
remoteBusinessAlertVo.setJobName("手动飞行" + "-" +remoteBusinessAlertVo.getLabelCn()+ DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
} else if(StrUtil.isNotEmpty(jobId)){
LambdaQueryWrapper<WaylineJobEntity> waylineJobQuery = new LambdaQueryWrapper<>();
waylineJobQuery.eq(WaylineJobEntity::getJobId,jobId); //jobId是unique唯一
WaylineJobEntity waylineJobEntity = waylineJobMapper.selectOne(waylineJobQuery);
if(BeanUtil.isEmpty(waylineJobEntity)){continue;} //找不到航线-不处理预警
remoteBusinessAlertVo.setJobId(waylineJobEntity.getJobId());
remoteBusinessAlertVo.setJobName(waylineJobEntity.getName());
}
}
remoteBusinessAlertVo.setLat("");
remoteBusinessAlertVo.setLng("");
if(StrUtil.isNotEmpty(deviceSn)){
Optional<DeviceDTO> deviceBySn = deviceService.getDeviceBySn(deviceSn);
DeviceDTO deviceDTO = deviceBySn.isPresent() ? deviceBySn.get() : null;
remoteBusinessAlertVo.setLat(deviceDTO.getLatitude()+ ""); //34.20912175973148
remoteBusinessAlertVo.setLng(deviceDTO.getLongitude()+ "");//117.2260332850499
}
//预警基础信息扩展
// remoteBusinessAlertVo.setAlertType("1"); //1:图片比对预警 2:AI实时预警
remoteBusinessAlertVo.setAssign(false);
String minioUrl = saveAliyunPreviewToMinio(warningRecordEntity.getPicUrl(),deviceSn, MinIOConstants.BUCKET_DKCY);
remoteBusinessAlertVo.setImages(minioUrl);
// remoteBusinessAlertVo.setMaxImages("");//mateFileUrl
// remoteBusinessAlertVo.setMateSourceImgUrl("");//mateFileUrl
remoteBusinessAlertVo.setTaskContent("");
remoteBusinessAlertVo.setHandleType("waiting");
// remoteBusinessAlertVo.setDeptId(aiCompareEntity.getCreateDept()+"");//暂时没有
// remoteBusinessAlertVo.setDeptName(aiCompareEntity.getDeptName());
remoteBusinessAlertVo.setHandleNum(0);
//businessAlertConstructInfo数据
alertVoList.add(remoteBusinessAlertVo);
}
// businessAlertService.saveBusinessAlert(alertVoList,activeProfile); //远程触发预警消息
RemoteBusinessAlertRequest remoteBusinessAlertRequest = new RemoteBusinessAlertRequest();
remoteBusinessAlertRequest.setAlertVoList(alertVoList);
remoteBusinessAlertRequest.setActiveProfile(activeProfile);
cn.hutool.json.JSONObject requestObj = new cn.hutool.json.JSONObject(remoteBusinessAlertRequest);
remoteBusinessAlertFeign.saveBusinessAlert(requestObj);
return callBackVo.getEvents().size();
}
//基于算法名称赋值
private static void setupLabelInfo(WarningRecordEntity warningRecordEntity, RemoteBusinessAlertVo remoteBusinessAlertVo) {
// String extraType = XingluoApiEnum.SAFETY_HARNESS.getExtraType();
switch (warningRecordEntity.getExtraType()){
case "2010_12": //秸秆焚烧 ------
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.FIRE.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.FIRE.getAiType());
break;
case "2010_13": //烟火识别
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.FIREWORKS.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.FIREWORKS.getAiType());
break;
case "2003_ext": //安全带预警 ------
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.SAFETY_HARNESS.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.SAFETY_HARNESS.getAiType());
break;
case "2004_ext"://安全帽预警 -----
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.SAFETY_HELMET.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.SAFETY_HELMET.getAiType());
break;
case "2010_24"://路面车辆计数
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.CARCOUNT.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.CARCOUNT.getAiType());
break;
case "2010_5"://多类型车辆计数
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.CARCOUNTMULTITYPE.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.CARCOUNTMULTITYPE.getAiType());
break;
case "2010_6"://多类型车辆拥堵聚集
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.CARMULTITYPEJAM.getTypeStr());
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.CARMULTITYPEJAM.getAiType());
break;
case "2010_29": //无人机安全帽检测 ------
remoteBusinessAlertVo.setLabelCn(XingluoApiEnum.SAFETY_HELMET_NEW.getTypeStr());//安全帽预警-新
remoteBusinessAlertVo.setLabelEn(XingluoApiEnum.SAFETY_HELMET_NEW.getAiType()); //SafetyHelmet
break;
}
}
public String saveAliyunPreviewToMinio(String aliyunUrl,String deviceSn, String minioBucket) {
try {
URL url = new URL(aliyunUrl);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(3_500);
conn.setReadTimeout(3_500);
InputStream inputStream = conn.getInputStream();
long fileSize = conn.getContentLengthLong();
String fileName = FileUtil.getName(url.getPath());
String path = url.getPath().replace(fileName, deviceSn+ fileName); // eg: /ai/report/29847/{deviceSn+xxx.jpg}
String originalFileName = path.substring(path.lastIndexOf("/") + 1); // qwfbGaBixI.jpg
String suffix = originalFileName.contains(".") ? originalFileName.substring(originalFileName.lastIndexOf(".")) : ".jpg"; // fallback
// String newFileName = IdUtils.fastUUID() + suffix;
OssClient minioClient = OssFactory.instance(minioBucket);
UploadResult result = minioClient.upload(inputStream, path, fileSize, MimeTypeUtils.IMAGE_JPG);
// MinioUtil.uploadFile(path,inputStream,);
inputStream.close();
return path; // 返回 MinIO 的访问地址
} catch (IOException e) {
throw new RuntimeException("上传图片失败", e);
}
}
public String PostRequest( JSONObject jsonObj, String url, String token
) {
//通用提交
public String PostRequest( JSONObject jsonObj, String url, String token) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 1. 创建POST请求对象
HttpPost post = new HttpPost(url);
@ -209,7 +542,7 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
if (response.getStatusLine().getStatusCode() == 200) {
return responseBody;
} else {
throw new RuntimeException("第三方接口调用失败!");
log.error("第三方接口调用失败!");
}
}
} catch (Exception e) {
@ -219,8 +552,7 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
}
public String GetRequest(URI uri, String token
) {
public String GetRequest(URI uri, String token) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// URI uri = new URIBuilder("https://api.example.com/data")
// .addParameter("param1", "value1")
@ -236,7 +568,8 @@ public class SampleEngineRecordServiceImpl implements ISampleEngineRecordService
if (response.getStatusLine().getStatusCode() == 200){
return responseBody;
}else {
throw new RuntimeException("第三方接口调用失败!");
log.error("星逻算法-第三方接口调用失败");
// throw new RuntimeException("第三方接口调用失败!");
}
}
} catch (Exception e) {

11
dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java

@ -85,4 +85,15 @@ public class FileController {
}
return HttpResultResponse.success(filesList);
}
/**
* 根据文件id查询图片的偏航角
* @param fileId
* @return
*/
@GetMapping("/degree")
@Operation(summary = "根据文件id查询图片的偏航角", description = "根据文件id查询图片的偏航角")
public Double getGimbalYawDegree(@RequestParam("fileId") String fileId) {
return fileService.getGimbalYawDegree(fileId);
}
}

3
dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java

@ -88,4 +88,7 @@ public interface IFileService {
List<MediaFileDTO> getMediaFileDTO( String jobId,String fileType);
String copyFile(String sourceBucket, String originFileUrl, String targetBucket);
String copyFileHttp(String fileUrl, String originFileUrl, String bucketDkcy);
Double getGimbalYawDegree(String fileId);
}

48
dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java

@ -1,11 +1,14 @@
package org.dromara.sample.media.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dromara.common.core.utils.file.MimeTypeUtils;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.common.redis.utils.RedisOpsUtils;
import org.dromara.common.satoken.utils.LoginHelper;
@ -29,8 +32,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;
@ -195,12 +201,52 @@ public class FileServiceImpl implements IFileService {
MinioUtil.copyFile(originFileUrl,originFileUrl,sourceBucket,targetBucket);//列表图片
MinioUtil.copyFile(originFileUrl,originFileUrl,sourceBucket,MinIOConstants.BUCKET_ALERT);//预览图片
} catch (Exception e) {
throw new RuntimeException(e);
e.printStackTrace();
}
return fileUrl;
}
@Override
public String copyFileHttp(String aliyunUrl, String originFileUrl, String minioBucket) {
try {
URL url = new URL(aliyunUrl);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(3_500);
conn.setReadTimeout(3_500);
InputStream inputStream = conn.getInputStream();
long fileSize = conn.getContentLengthLong();
String fileName = FileUtil.getName(url.getPath());
// String path = url.getPath().replace(fileName, deviceSn+ fileName); // eg: /ai/report/29847/{deviceSn+xxx.jpg}
// String originalFileName = path.substring(path.lastIndexOf("/") + 1); // qwfbGaBixI.jpg
// String suffix = originalFileName.contains(".") ? originalFileName.substring(originalFileName.lastIndexOf(".")) : ".jpg"; // fallback
// String newFileName = IdUtils.fastUUID() + suffix;
OssClient minioClient = OssFactory.instance(minioBucket);
UploadResult result = minioClient.upload(inputStream, originFileUrl, fileSize, MimeTypeUtils.IMAGE_JPG);
// MinioUtil.uploadFile(path,inputStream,);
inputStream.close();
return result.getUrl(); // 返回 MinIO 的访问地址
} catch (IOException e) {
throw new RuntimeException("上传图片失败", e);
}
}
@Override
public Double getGimbalYawDegree(String fileId) {
LambdaQueryWrapper<MediaFileEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(MediaFileEntity::getFileId, fileId);
List<MediaFileEntity> mediaFileEntities = mapper.selectList(wrapper);
if (ObjectUtil.isNotEmpty(mediaFileEntities)){
return mediaFileEntities.get(0).getGimbalYawDegree();
}
return -1.0;
}
/**
* Convert the received file object into a database entity object.
* @param file

7
dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java

@ -154,4 +154,11 @@ public class WaylineJobController {
}
}
//根据设备sn查询jobname
@GetMapping("/{workspace_id}/getJobByDockSn")
@Operation(summary = "根据设备sn查询jobname。", description = "根据设备sn查询jobname。")
public HttpResultResponse getJobByDockSn( @RequestParam(name = "device_sn") String deviceSn) {
return HttpResultResponse.success(waylineJobService.getJobByDockSn(deviceSn));
}
}

2
dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/dto/WaylineJobDTO.java

@ -58,6 +58,8 @@ public class WaylineJobDTO {
private Integer code;
private String codeName;
private Integer rthAltitude;
private OutOfControlActionEnum outOfControlAction;

2
dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java

@ -87,4 +87,6 @@ public interface IWaylineJobService {
* @param fileType 图片类型 "jpeg,mp4"
* */
List<MediaFileDTO> getMediaFileDTO(String jobId, String fileType);
WaylineJobDTO getJobByDockSn(String dockSn);
}

15
dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/AiCompareServiceImpl.java

@ -214,7 +214,7 @@ public class AiCompareServiceImpl implements IAiCompareService {
aiCompareEntity.setId(frameDTO.getCompareId());
aiCompareMapper.updateById(aiCompareEntity);
frameDTO.setJobName(aiCompareEntity.getJobName());
String originFileUrl = frameDTO.getFileUrl();
String originFileUrl = frameDTO.getFileUrl();//waiwang/b0c5dc04-6232-4762-b748-16f8e6ea04ed/DJI_202506010857_001_b0c5dc04-6232-4762-b748-16f8e6ea04ed/DJI_20250601085925_0001_V.jpeg
String fileUrl = fileService.getObjectUrlOne(MinIOConstants.BUCKET_MEDIAFILE, originFileUrl, 3600).toString();
frameDTO.setFileUrl(fileUrl);
String originMateFileUrl = frameDTO.getMateFileUrl();
@ -234,9 +234,20 @@ public class AiCompareServiceImpl implements IAiCompareService {
//图片处理
// fileService.get(MinIOConstants.BUCKET_MEDIAFILE, originMateFileUrl, 3600);
//复制原图到指定bucket
//复制原图到指定bucket //mediafile
// originMateFileUrl:waiwang/b9e5ae94-e290-43af-9f66-12031580aba1/DJI_202506020949_001_b9e5ae94-e290-43af-9f66-12031580aba1/DJI_20250602095106_0001_V.jpeg
String linkType = "";
if(StrUtil.startWith(fileUrl,"http")){
linkType = "http";
//http://yq-dajiang.oss-cn-hangzhou.aliyuncs.com/waiwang/56055519-3189-4af9-b4ea-56fe06df3082/DJI_202506010952_001_56055519-3189-4af9-b4ea-56fe06df3082/DJI_20250601100131_0001_V.jpeg
String fileUrlStr = fileService.copyFileHttp(fileUrl, originFileUrl, MinIOConstants.BUCKET_DKCY);
String fileMateUrlStr = fileService.copyFileHttp(mateFileUrl, originMateFileUrl, MinIOConstants.BUCKET_DKCY);
}else{
String copyFileUrl = fileService.copyFile(MinIOConstants.BUCKET_MEDIAFILE, originMateFileUrl, MinIOConstants.BUCKET_DKCY);
// String copyFileUrl = fileService.copyFile(MinIOConstants.BUCKET_MEDIAFILE, originFileUrl, MinIOConstants.BUCKET_ALERT);
}
ArrayList<RemoteBusinessAlertVo> alertVoList = new ArrayList<>();
//手动简化逻辑,上传图片
int frameCount =0;

24
dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java

@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dromara.common.redis.config.RedisConst;
import org.dromara.common.redis.utils.RedisOpsUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sdk.cloudapi.debug.DebugErrorCodeEnum;
import org.dromara.common.sdk.cloudapi.debug.ErrorCodeEnum;
import org.dromara.common.sdk.cloudapi.device.DockModeCodeEnum;
import org.dromara.common.sdk.cloudapi.device.DroneModeCodeEnum;
import org.dromara.common.sdk.cloudapi.device.OsdDock;
@ -265,6 +267,26 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
return fileService.getMediaFileDTO(jobId,fileType);
}
@Override
public WaylineJobDTO getJobByDockSn(String dockSn) {
LambdaQueryWrapper<WaylineJobEntity> queryWrapper = new LambdaQueryWrapper<WaylineJobEntity>()
.eq(WaylineJobEntity::getStatus, 2)
.eq(WaylineJobEntity::getDockSn, dockSn);
//降序查询
queryWrapper.orderByDesc(WaylineJobEntity::getCreateTime);
List<WaylineJobEntity> waylineJobEntities = mapper.selectList(queryWrapper);
if (ObjectUtil.isEmpty(waylineJobEntities)){
return new WaylineJobDTO();
}
return entity2Dto(waylineJobEntities.getFirst());
}
private WaylineJobDTO entity2Dto(WaylineJobEntity entity) {
if (entity == null) {
return null;
@ -297,6 +319,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.rthAltitude(entity.getRthAltitude())
.outOfControlAction(OutOfControlActionEnum.find(entity.getOutOfControlAction()))
.mediaCount(entity.getMediaCount())
.codeName(entity.getErrorCode()!=null?ErrorCodeEnum.find(entity.getErrorCode()).getMessage():null)
.breakPoint(entity.getBreakPoint());
@ -337,5 +360,4 @@ public class WaylineJobServiceImpl implements IWaylineJobService {
.uploadedCount(uploadedSize).build());
return builder.build();
}
}

1
dk-modules/system/pom.xml

@ -135,7 +135,6 @@
<artifactId>gt-shapefile</artifactId>
<version>29.5</version>
</dependency>
</dependencies>
<build>

2
dk-modules/system/src/main/java/org/dromara/system/DKSystemApplication.java

@ -4,6 +4,7 @@ import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* 系统模块
@ -12,6 +13,7 @@ import org.springframework.boot.context.metrics.buffering.BufferingApplicationSt
*/
@EnableDubbo
@SpringBootApplication
@EnableAsync
public class DKSystemApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(DKSystemApplication.class);

6
dk-modules/system/src/main/java/org/dromara/system/config/ProjectTablePrefixConfig.java

@ -14,12 +14,12 @@ import org.springframework.context.annotation.Configuration;
@ConfigurationProperties(prefix = "projecttableprefix")
public class ProjectTablePrefixConfig {
@Value("${projectTablePrefix.tableBusiness:dk_business")
@Value("${projectTablePrefix.tableBusiness:dk_business}")
private String tableBusiness;
@Value("${projectTablePrefix.tableCloud:dk_cloud")
@Value("${projectTablePrefix.tableCloud:dk_cloud}")
private String tableCloud;
@Value("${projectTablePrefix.tableWorkflow:dk_workflow")
@Value("${projectTablePrefix.tableWorkflow:dk_workflow}")
private String tableWorkflow;
}

5
dk-modules/system/src/main/java/org/dromara/system/controller/system/SysConfigController.java

@ -73,6 +73,11 @@ public class SysConfigController extends BaseController {
return R.ok("操作成功", configService.selectConfigByKey(configKey));
}
@GetMapping(value = "/configKeyFeign/{configKey}")
public String getConfigKeyFeign(@PathVariable String configKey) {
return configService.selectConfigByKey(configKey);
}
/**
* 新增参数配置
*/

37
dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java

@ -5,19 +5,18 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysDepartBoundary ;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.SysDepartBoundary;
import org.dromara.system.domain.bo.SysDepartBoundaryBo;
import org.dromara.system.service.ISysDepartBoundaryService;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* 部门区域
@ -40,7 +39,6 @@ public class SysDepartBoundaryController extends BaseController {
@Operation(summary ="查询部门的地理位置",description = "查询部门的地理位置")
@GetMapping(value = "/listJson")
public R<List<SysDepartBoundaryBo>> listJson(SysDepartBoundary departBoundary) {
// departBoundary.setDeptId(String.valueOf(LoginHelper.getDeptId()));
List<SysDepartBoundaryBo> listJson = departBoundaryService.listJson(departBoundary);
return R.ok("查询成功!",listJson);
}
@ -61,22 +59,27 @@ public class SysDepartBoundaryController extends BaseController {
* 解析shp文件
* @return
*/
@Operation(summary ="批量新增部门区域",description = "批量新增部门区域")
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public R<Void> uploadShpFile(@RequestParam("file") MultipartFile file,@RequestParam("areaType") Integer areaType) {
return toAjax(departBoundaryService.uploadShpFile(file,areaType));
@RepeatSubmit()
@Operation(summary ="新增部门区域",description = "新增部门区域(areaType: 0:市级 1:区级(县) 2:镇级(街道) 3:村级)")
@RequestMapping(value = "/{areaType}/{parentId}/upload", method = RequestMethod.POST)
public R<Void> uploadShpFile(@RequestParam("file") MultipartFile file,
@PathVariable Integer areaType,
@PathVariable Long parentId) {
return toAjax(departBoundaryService.uploadShpFile(file,areaType,parentId));
}
/**
* 编辑
*
* @param
* 根据经纬度查询部门信息
* @param latlng
* @return
*/
@Operation(summary ="编辑部门区域",description = "编辑部门区域")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public R<Void> updateDepartBoundary(@RequestBody SysDepartBoundary departBoundary) {
return toAjax(departBoundaryService.updateDepartBoundary(departBoundary));
@Operation(summary ="根据经纬度查询部门信息",description = "根据经纬度查询部门信息")
@GetMapping(value = "/location/list")
public R<List<SysDepartBoundary>> listDepartBoundaryByLngAndLat(@RequestParam("lat") Double lat,
@RequestParam("lng") Double lng) {
List<SysDepartBoundary> listJson = departBoundaryService.listDepartBoundaryByLngAndLat(lng,lat);
return R.ok(listJson);
}
@ -91,8 +94,4 @@ public class SysDepartBoundaryController extends BaseController {
public R<Void> deleteDepartBoundary(@RequestParam(name = "id") String id) {
return toAjax(departBoundaryService.deleteDepartBoundary(id));
}
}

12
dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDictDataController.java

@ -14,12 +14,14 @@ import org.dromara.system.domain.bo.SysDictDataBo;
import org.dromara.system.domain.vo.SysDictDataVo;
import org.dromara.system.service.ISysDictDataService;
import org.dromara.system.service.ISysDictTypeService;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 数据字典信息
@ -80,6 +82,16 @@ public class SysDictDataController extends BaseController {
return R.ok(data);
}
@PostMapping(value = "/selectDataByType")
public R<List<String>> selectDataByType(@RequestParam String dictType) {
List<SysDictDataVo> data = dictTypeService.selectDictDataByType(dictType);
List<String> collect = data.stream().map(SysDictDataVo::getRemark).collect(Collectors.toList());
if (ObjectUtil.isNull(data)) {
data = new ArrayList<>();
}
return R.ok(collect);
}
/**
* 新增字典类型
*/

12
dk-modules/system/src/main/java/org/dromara/system/controller/system/SysRoleController.java

@ -26,6 +26,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
@ -237,10 +239,18 @@ public class SysRoleController extends BaseController {
@GetMapping(value = "/user/list")
public R<List<SysUser>> listRoleUser() {
String roleName = "dispose";
String roleJiuLiName = "jiulihu_dipose";
List<SysUser> resultlist = new ArrayList<>();
List<SysUser> userList = roleService.getUserIno(roleName);
List<SysUser> userjiuliList = roleService.getUserIno(roleJiuLiName);
resultlist.addAll(userjiuliList);
resultlist.addAll(userList);
return R.ok(userList);
return R.ok(resultlist);
}
}

10
dk-modules/system/src/main/java/org/dromara/system/controller/system/SysUserController.java

@ -274,6 +274,16 @@ public class SysUserController extends BaseController {
return toAjax(userService.updateUserStatus(user.getUserId(), user.getStatus()));
}
/**
* 状态修改
*/
@SaCheckPermission("system:user:edit")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/noticeType")
public R<Void> noticeType(@RequestBody SysUserBo user) {
return toAjax(userService.updateUserNoticeType(user.getUserId(), user.getNoticeType()));
}
/**
* 根据用户编号获取授权角色
*

44
dk-modules/system/src/main/java/org/dromara/system/domain/SysDepartBoundary.java

@ -1,6 +1,7 @@
package org.dromara.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@ -23,55 +24,34 @@ public class SysDepartBoundary extends BaseEntity {
/**ID*/
@TableId(type = IdType.AUTO)
private String id;
/**
* 租户Id
*/
private String tenantId;
private Long id;
/**机构ID*/
private String deptId;
private Long deptId;
/**机构/部门名称*/
private String deptName;
/**是否显示0显示,1不显示*/
private Integer type;
/**边界*/
private String communityName;
/**部门全路径*/
private String namePath;
/**边界*/
private String boundary;
/**
* 周长
*/
private Double perimeter;
/**
* 面积平方公里
* 区域类别 areaType: 0市级 1区级() 2镇级(街道) 3村级
*/
private Double area;
/**
* 面积亩
*/
private Double areaMu;
/**
* 编号
*/
private String shpNo;
private Integer areaType;
/**
* 区域类别
* 父类id
*/
private Integer areaType;
private Long parentId;
/**删除状态(0,正常,1已删除)*/
private String delFlag;
private List<String> deptIds;
@TableField(exist = false)
private List<Long> deptIds;
}

1
dk-modules/system/src/main/java/org/dromara/system/domain/SysUser.java

@ -98,6 +98,7 @@ public class SysUser extends TenantEntity {
*/
private Date loginDate;
private Integer noticeType;
/**
* 备注
*/

1
dk-modules/system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java

@ -108,6 +108,7 @@ public class SysUserBo extends BaseEntity {
*/
private String excludeUserIds;
private Integer noticeType;
/**
* 平台名称
*/

25
dk-modules/system/src/main/java/org/dromara/system/domain/kmz/KmzResult.java

@ -0,0 +1,25 @@
package org.dromara.system.domain.kmz;
import lombok.Data;
import java.util.Map;
@Data
public class KmzResult {
private String name;
private Map<String, String> attributes;
private String wkt;
public KmzResult(String name, Map<String, String> attributes, String wkt) {
this.name = name;
this.attributes = attributes;
this.wkt = wkt;
}
public KmzResult() {
}
}

15
dk-modules/system/src/main/java/org/dromara/system/domain/kmz/Placemark.java

@ -0,0 +1,15 @@
package org.dromara.system.domain.kmz;
import lombok.Data;
import java.util.Map;
@Data
public class Placemark {
private String name;
private String coordinates;
private Map<String, String> attributes;
}

1
dk-modules/system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java

@ -47,6 +47,7 @@ public class SysUserVo implements Serializable {
* 用户账号
*/
private String userName;
private Integer noticeType;
/**
* 用户昵称

5
dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteConfigServiceImpl.java

@ -38,6 +38,11 @@ public class RemoteConfigServiceImpl implements RemoteConfigService {
return ip;
}
@Override
public boolean selectXingluoAutoSubmit() {
return sysConfigService.selectXingluoAutoSubmit();
}
// @Override
// public List<String> selectStreamType(String deviceSn) {
// List<String> list =sysConfigService.selectStreamType(deviceSn);

11
dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteDeptServiceImpl.java

@ -50,8 +50,8 @@ public class RemoteDeptServiceImpl implements RemoteDeptService {
}
@Override
public List<Map<String,Object>> getNamePathList() {
return sysDeptService.getNamePathList();
public List<Map<String,Object>> getNamePathList(Long deptId) {
return sysDeptService.getNamePathList(deptId);
}
@Override
@ -66,4 +66,11 @@ public class RemoteDeptServiceImpl implements RemoteDeptService {
SysDeptVo sysDeptVo = sysDeptService.getByParentId(deptId);
return BeanUtil.copyProperties(sysDeptVo, RemoteDeptVo.class);
}
@Override
public List<RemoteDeptVo> listTreeDeptByChild(Long deptId) {
List<SysDeptVo> deptVoList = sysDeptService.listTreeDeptByChild(deptId);
return BeanUtil.copyToList(deptVoList, RemoteDeptVo.class);
}
}

1
dk-modules/system/src/main/java/org/dromara/system/dubbo/RemotePostServiceImpl.java

@ -41,6 +41,7 @@ public class RemotePostServiceImpl implements RemotePostService {
remotePostVo.setPostName(aiLabel.getPostName());
remotePostVo.setPostCode(aiLabel.getPostCode());
remotePostVo.setStatus(aiLabel.getStatus());
remotePostVo.setPostCategory(aiLabel.getPostCategory());
return remotePostVo;
})
.collect(Collectors.toList());

41
dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteSubmailConfigServiceImpl.java

@ -1,17 +1,28 @@
package org.dromara.system.dubbo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.common.core.domain.R;
import org.dromara.system.api.RemoteClientService;
import org.dromara.system.api.RemoteSubmailConfigService;
import org.dromara.system.api.domain.vo.RemoteClientVo;
import org.dromara.system.domain.vo.SysClientVo;
import org.dromara.system.service.ISysClientService;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysSubmailConfigService;
import org.dromara.system.service.ISysUserService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 客户端服务
*
@ -25,6 +36,7 @@ public class RemoteSubmailConfigServiceImpl implements RemoteSubmailConfigServic
private final ISysSubmailConfigService sysSubmailConfigService;
private final ISysUserService userService;
/**
*
@ -36,4 +48,23 @@ public class RemoteSubmailConfigServiceImpl implements RemoteSubmailConfigServic
public R<String> remoteCmdSend(String code, String multiParam) {
return sysSubmailConfigService.cmdSend(code, multiParam);
}
/**
* 根据部门获取部门下的短信推送人员,进行推送
* */
@Override
@Async
public void remoteSend(String code, List<Map<String, Object>> alertList) {
if(!alertList.isEmpty()){
for (Map<String, Object> map : alertList) {
map.put("createTime",new Date());
Long deptId = Convert.toLong(map.get("deptId"));
List<SysUserVo> sysUserVos = userService.selectUserListByDept(Convert.toLong(deptId));
Set<String> phones = sysUserVos.stream().filter(u -> u.getNoticeType() == 1 && StrUtil.isNotEmpty(u.getPhonenumber())).map(SysUserVo::getPhonenumber).collect(Collectors.toSet());
sysSubmailConfigService.sendPhone(code,phones, JSON.toJSONString(map));
}
}
}
}

1
dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java

@ -26,4 +26,5 @@ public interface SysDepartBoundaryMapper extends BaseMapper<SysDepartBoundary> {
String listJson(@Param("deptId") String deptId);
List<SysDepartBoundary> listDepartBoundaryByLngAndLat(@Param("lng") Double lng,@Param("lat") Double lat);
}

4
dk-modules/system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java

@ -71,7 +71,9 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept, SysDeptVo> {
})
Page<SysDeptVo> selectPageDeptList(@Param("page") Page<SysDeptVo> page, @Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
List<Map<String,Object>> getNamePathList();
List<Map<String,Object>> getNamePathList(@Param("deptId") Long deptId);
List<SysDeptVo> listTreeDept(@Param("deptId") Long deptId, @Param("tbPrefix") ProjectTablePrefixConfig tbPrefix);
List<SysDeptVo> listTreeDeptByChild(@Param("deptId") Long deptId);
}

2
dk-modules/system/src/main/java/org/dromara/system/service/ISysConfigService.java

@ -88,4 +88,6 @@ public interface ISysConfigService {
List<String> selectStreamType(String deviceSn);
boolean selectXingluoAutoSubmit();
}

6
dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java

@ -20,13 +20,15 @@ public interface ISysDepartBoundaryService extends IService<SysDepartBoundary>{
List<SysDepartBoundary> queryByDeptId(String deptId);
boolean uploadShpFile(MultipartFile file,Integer areaType);
boolean uploadShpFile(MultipartFile file,Integer areaType,Long parentId);
boolean deleteDepartBoundary(String id);
boolean deleteDepartBoundary(String deptId);
boolean updateDepartBoundary(SysDepartBoundary departBoundary);
boolean addDepartBoundary(SysDepartBoundary departBoundary);
List<SysDepartBoundaryBo> listJson(SysDepartBoundary departBoundary);
List<SysDepartBoundary> listDepartBoundaryByLngAndLat(Double lng, Double lat);
}

7
dk-modules/system/src/main/java/org/dromara/system/service/ISysDeptService.java

@ -1,6 +1,7 @@
package org.dromara.system.service;
import cn.hutool.core.lang.tree.Tree;
import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.bo.SysDeptBo;
import org.dromara.system.domain.vo.SysDeptVo;
@ -144,7 +145,7 @@ public interface ISysDeptService {
* 查询每个部门的所属的部门全路径
* @return
*/
List<Map<String,Object>> getNamePathList();
List<Map<String,Object>> getNamePathList(Long deptId);
/**
* 根据父级找子级
@ -157,4 +158,8 @@ public interface ISysDeptService {
SysDeptVo getByParentId(String deptId);
List<SysDeptVo> listTreeDept(Long deptId);
SysDept addBoundaryDept(SysDeptBo sysDeptBo);
List<SysDeptVo> listTreeDeptByChild(Long deptId);
}

4
dk-modules/system/src/main/java/org/dromara/system/service/ISysSubmailConfigService.java

@ -10,6 +10,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* 赛邮服务配置Service接口
@ -71,5 +72,8 @@ public interface ISysSubmailConfigService {
R<String> cmdSend(String code, String multiParam);
R<String> sendPhone(String code,Set<String>phones, String multiParam);
String submailSendUtil(SysSubmailConfigBo bo, List<SysSubmailConfigUserVo> configUserVoList);
String submailSendPhone(SysSubmailConfigBo bo, Set<String> phones);
}

1
dk-modules/system/src/main/java/org/dromara/system/service/ISysUserService.java

@ -169,6 +169,7 @@ public interface ISysUserService {
* @return 结果
*/
int updateUserStatus(Long userId, String status);
int updateUserNoticeType(Long userId, Integer noticeType);
/**
* 修改用户基本信息

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save