Преглед изворни кода

Merge branch 'usky-zyj' into server-165

james пре 1 месец
родитељ
комит
88e82681b9
100 измењених фајлова са 3979 додато и 237 уклоњено
  1. 7 0
      pom.xml
  2. 19 0
      service-ai/pom.xml
  3. 27 0
      service-ai/service-ai-api/pom.xml
  4. 88 0
      service-ai/service-ai-biz/pom.xml
  5. 40 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/AIChatApplication.java
  6. 536 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiChatController.java
  7. 43 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiQuestionController.java
  8. 94 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiSessionController.java
  9. 41 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/mapper/AiQuestionMapper.java
  10. 37 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/mapper/AiSessionMapper.java
  11. 70 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiQuestion.java
  12. 51 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiQuestionItem.java
  13. 48 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiSession.java
  14. 14 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/AiChatConfig.java
  15. 19 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/MyGlobalCorsConfig.java
  16. 14 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/WebConfig.java
  17. 22 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/vo/AiStreamOutputVO.java
  18. 24 0
      service-ai/service-ai-biz/src/main/resources/bootstrap.yml
  19. 94 0
      service-ai/service-ai-biz/src/main/resources/logback.xml
  20. 151 0
      service-ai/service-ai-biz/src/main/resources/static/dpsk.html
  21. 150 0
      service-ai/service-ai-biz/src/main/resources/static/tyqw.html
  22. 4 0
      service-alarm/service-alarm-biz/pom.xml
  23. 2 1
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/RuoYiSystemApplication.java
  24. 151 53
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/impl/BaseAlarmNoticeResultServiceImpl.java
  25. 1 0
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/impl/BaseAlarmServiceImpl.java
  26. 20 0
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/mqtt/alarm/Alarm.java
  27. 2 1
      service-eg/service-eg-biz/src/main/java/com/usky/eg/service/impl/EgDeviceServiceImpl.java
  28. 5 0
      service-eg/service-eg-biz/src/main/java/com/usky/eg/service/vo/EgDeviceRequestVO.java
  29. 1 1
      service-eg/service-eg-biz/src/main/resources/logback.xml
  30. 4 0
      service-fire/service-fire-biz/pom.xml
  31. 4 2
      service-fire/service-fire-biz/src/main/java/com/usky/fire/RuoYiSystemApplication.java
  32. 14 5
      service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/DemReportInfoController.java
  33. 15 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/PatrolInspectionSiteController.java
  34. 10 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/DemReportInfo.java
  35. 21 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/ReportResult.java
  36. 4 1
      service-fire/service-fire-biz/src/main/java/com/usky/fire/mapper/PatrolInspectionSiteMapper.java
  37. 7 1
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/DemReportInfoService.java
  38. 5 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/PatrolInspectionSiteService.java
  39. 92 9
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/DemReportInfoServiceImpl.java
  40. 20 4
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionAreaServiceImpl.java
  41. 1 2
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionContentServiceImpl.java
  42. 12 12
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionPlanServiceImpl.java
  43. 2 2
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionRecordServiceImpl.java
  44. 77 14
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionSiteServiceImpl.java
  45. 68 12
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/ReportResultServiceImpl.java
  46. 51 0
      service-fire/service-fire-biz/src/main/java/com/usky/fire/service/vo/PatrolInspectionSiteImportVo.java
  47. 10 0
      service-fire/service-fire-biz/src/main/resources/mapper/fire/PatrolInspectionSiteMapper.xml
  48. 20 0
      service-ids/pom.xml
  49. 27 0
      service-ids/service-ids-api/pom.xml
  50. 89 0
      service-ids/service-ids-biz/pom.xml
  51. 45 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/RuoYiSystemApplication.java
  52. 109 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/MybatisGeneratorUtils.java
  53. 21 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/web/AccessAlarmController.java
  54. 21 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/web/AccessEntryExitRecordController.java
  55. 39 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/web/IdsParkMapController.java
  56. 141 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/domain/AccessAlarm.java
  57. 86 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/domain/AccessEntryExitRecord.java
  58. 61 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/domain/IdsParkMap.java
  59. 16 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/mapper/AccessAlarmMapper.java
  60. 16 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/mapper/AccessEntryExitRecordMapper.java
  61. 16 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/mapper/IdsParkMapMapper.java
  62. 16 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/AccessAlarmService.java
  63. 16 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/AccessEntryExitRecordService.java
  64. 24 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/IdsParkMapService.java
  65. 20 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/impl/AccessAlarmServiceImpl.java
  66. 20 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/impl/AccessEntryExitRecordServiceImpl.java
  67. 44 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/impl/IdsParkMapServiceImpl.java
  68. 136 0
      service-ids/service-ids-biz/src/main/java/com/usky/ids/service/util/HttpClientUtils.java
  69. 25 0
      service-ids/service-ids-biz/src/main/resources/bootstrap.yml
  70. 94 0
      service-ids/service-ids-biz/src/main/resources/logback.xml
  71. 32 0
      service-ids/service-ids-biz/src/main/resources/mapper/ids/AccessAlarmMapper.xml
  72. 21 0
      service-ids/service-ids-biz/src/main/resources/mapper/ids/AccessEntryExitRecordMapper.xml
  73. 16 0
      service-ids/service-ids-biz/src/main/resources/mapper/ids/IdsParkMapMapper.xml
  74. 15 0
      service-ids/service-ids-biz/src/main/resources/smart-doc.json
  75. 16 0
      service-iot/service-iot-api/src/main/java/com/usky/iot/RemoteIotService.java
  76. 0 2
      service-iot/service-iot-api/src/main/java/com/usky/iot/RemoteIotTaskService.java
  77. 40 0
      service-iot/service-iot-api/src/main/java/com/usky/iot/factory/RemoteIotFactory.java
  78. 0 2
      service-iot/service-iot-api/src/main/java/com/usky/iot/factory/RemoteIotTaskFactory.java
  79. 4 0
      service-iot/service-iot-biz/pom.xml
  80. 3 1
      service-iot/service-iot-biz/src/main/java/com/usky/iot/RuoYiSystemApplication.java
  81. 4 4
      service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/api/PmTimedSendingApi.java
  82. 2 1
      service-iot/service-iot-biz/src/main/java/com/usky/iot/mapper/PmWorkContentMapper.java
  83. 1 1
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/DeviceOperate.java
  84. 4 4
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/DingTalkAndMessage.java
  85. 48 49
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/ExecutorConfig.java
  86. 1 7
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/BaseAlarmServiceImpl.java
  87. 3 2
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/BaseAppInfoServiceImpl.java
  88. 11 26
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmProjectServiceImpl.java
  89. 21 11
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkContentServiceImpl.java
  90. 12 6
      service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkReportServiceImpl.java
  91. 2 1
      service-iot/service-iot-biz/src/main/resources/mapper/iot/PmWorkContentMapper.xml
  92. 4 0
      service-issue/service-issue-api/src/main/java/com/usky/issue/RemoteIssueTaskService.java
  93. 4 0
      service-issue/service-issue-api/src/main/java/com/usky/issue/factory/RemoteIssueTaskFactory.java
  94. 5 0
      service-issue/service-issue-biz/pom.xml
  95. 2 0
      service-issue/service-issue-biz/src/main/java/com/usky/issue/RuoYiSystemApplication.java
  96. 50 0
      service-issue/service-issue-biz/src/main/java/com/usky/issue/service/config/mqtt/MqttBaseConfig.java
  97. 48 0
      service-issue/service-issue-biz/src/main/java/com/usky/issue/service/config/mqtt/MqttInConfig.java
  98. 86 0
      service-issue/service-issue-biz/src/main/java/com/usky/issue/service/config/mqtt/MqttOutConfig.java
  99. 175 0
      service-issue/service-issue-biz/src/main/java/com/usky/issue/service/job/JgDataForward.java
  100. 55 0
      service-issue/service-issue-biz/src/main/java/com/usky/issue/service/listener/MqttListener.java

+ 7 - 0
pom.xml

@@ -90,6 +90,13 @@
 
     <module>service-oa</module>
 
+
+    <module>service-ai</module>
+
+    <module>service-pm</module>
+
+    <module>service-ids</module>
+
   </modules>
           
   

+ 19 - 0
service-ai/pom.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>usky-modules</artifactId>
+        <groupId>com.usky</groupId>
+        <version>0.0.1</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>service-ai</artifactId>
+    <packaging>pom</packaging>
+    <version>0.0.1</version>
+
+    <modules>
+        <module>service-ai-biz</module>
+        <module>service-ai-api</module>
+    </modules>
+</project>

+ 27 - 0
service-ai/service-ai-api/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>service-ai</artifactId>
+        <groupId>com.usky</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>service-ai-api</artifactId>
+    <!-- SpringCloud Openfeign -->
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>usky-common-core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>

+ 88 - 0
service-ai/service-ai-biz/pom.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>service-ai</artifactId>
+        <groupId>com.usky</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>service-ai-biz</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>common-cloud-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>service-ai-api</artifactId>
+            <version>0.0.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>ruoyi-common-swagger</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.1.4</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- 阿里dashscope依赖 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dashscope-sdk-java</artifactId>
+            <version>2.14.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.2.6.RELEASE</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.github.shalousun</groupId>
+                <artifactId>smart-doc-maven-plugin</artifactId>
+                <version>2.1.1</version>
+                <configuration>
+                    <!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
+                    <configFile>./src/main/resources/smart-doc.json</configFile>
+                    <!--指定项目名称-->
+                    <projectName>test</projectName>
+                    <!--                    <excludes>-->
+                    <!--                        <exclude>com.bizmatics:product-service-provider</exclude>-->
+                    <!--                        <exclude>cn.afterturn:easypoi-web</exclude>-->
+                    <!--                    </excludes>-->
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 40 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/AIChatApplication.java

@@ -0,0 +1,40 @@
+package com.usky.ai;
+
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
+import org.mybatis.spring.annotation.MapperScan;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+@EnableCustomSwagger2
+@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
+@EnableFeignClients(basePackages = {"com.usky"})
+@MapperScan(value = "com.usky.ai.mapper")
+@ComponentScan(basePackages = {"com.usky"})
+@SpringBootApplication
+public class AIChatApplication {
+        private static final Logger LOGGER = LoggerFactory.getLogger(AIChatApplication.class);
+
+        public static void main (String[]args) throws UnknownHostException {
+        ConfigurableApplicationContext application = SpringApplication.run(AIChatApplication.class, args);
+        Environment env = application.getEnvironment();
+        String ip = InetAddress.getLocalHost().getHostAddress();
+        String port = env.getProperty("server.port");
+        String path = env.getProperty("server.servlet.context-path");
+        LOGGER.info("\n----------------------------------------------------------\n\t" +
+                "Application is running! Access URLs:\n\t" +
+                "Local: \t\thttp://localhost:" + port + (null == path ? "" : path) + "/\n\t" +
+                "External: \thttp://" + ip + ":" + port + (null == path ? "" : path) + "/\n\t" +
+                "Api: \t\thttp://" + ip + ":" + port + (null == path ? "" : path) + "/swagger-ui/index.html\n\t" +
+                "----------------------------------------------------------");
+       }
+}

+ 536 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiChatController.java

@@ -0,0 +1,536 @@
+package com.usky.ai.controller.web;
+
+import com.alibaba.dashscope.aigc.generation.Generation;
+import com.alibaba.dashscope.aigc.generation.GenerationParam;
+import com.alibaba.dashscope.common.Message;
+import com.alibaba.dashscope.common.Role;
+import com.alibaba.dashscope.exception.ApiException;
+import com.alibaba.dashscope.exception.InputRequiredException;
+import com.alibaba.dashscope.exception.NoApiKeyException;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.usky.ai.mapper.AiQuestionMapper;
+import com.usky.ai.mapper.AiSessionMapper;
+import com.usky.ai.service.AiQuestion;
+import com.usky.ai.service.AiQuestionItem;
+import com.usky.ai.service.AiSession;
+import com.usky.ai.service.vo.AiStreamOutputVO;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.security.utils.SecurityUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RestController
+@RequestMapping("/ai")
+public class AiChatController {
+
+    @Value("${ai.api.key}")
+    private String apiKey;
+
+    @Value("${airole}")
+    private String aiRole;
+
+    @Value("${aliTyqw.model}")
+    private String tyqwModel;
+
+    @Value("${aliDpsk.model}")
+    private String dpskModel;
+
+    @Value("${ai.historyLimit}")
+    private int Limit;
+
+    @Value("${ai.millis}")
+    private int millis;
+
+    @Resource
+    private Generation generation;
+
+    @Autowired
+    private AiQuestionMapper aiQuestionMapper;
+
+    @Autowired
+    private AiSessionMapper aiSessionMapper;
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    // 阿里百炼通义千问大模型(修改后)
+    @PostMapping(value = "/aliTyqw", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+    public ResponseEntity<StreamingResponseBody> send1(@RequestBody JSONObject object) throws NoApiKeyException, InputRequiredException {
+        // 获取当前登录用户的信息
+        Long userId = SecurityUtils.getUserId();
+        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
+        String sessionId = null;
+        String content = object.get("content").toString();
+
+        // 如果没有传入 sessionId,则创建一个新的会话ID
+        if (object.containsKey("sessionId")) {
+            sessionId = object.get("sessionId").toString();
+        } else {
+            sessionId = java.util.UUID.randomUUID().toString();
+        }
+
+        // 解析 JSON 并提取 "content" 字段的值
+        String questionText = content;
+
+        // 检查是否已经存在相同的 sessionId
+        boolean exists = aiSessionMapper.existsBySessionId(sessionId);
+
+        if (!exists) {
+            // 创建新的 AiSession 实体并存入数据库
+            AiSession aiSession = new AiSession();
+            aiSession.setSessionId(sessionId);
+            aiSession.setUserId(userId);
+            aiSession.setUserName(userName);
+            aiSession.setQuestion(questionText);
+            aiSession.setAskTime(LocalDateTime.now());
+            aiSessionMapper.save(aiSession);
+        }
+
+        // 构建消息列表,包含角色定义、历史对话记录和用户新消息
+        List<Message> messages = new ArrayList<>();
+
+        // 插入角色定义(在对话历史的开头)
+        Message roleDefinition = Message.builder()
+                .role(Role.SYSTEM.getValue()) // 使用系统角色
+                .content(aiRole) // 定义角色的行为和风格
+                .build();
+        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
+
+        // 从数据库中获取历史对话记录
+        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
+
+        // 如果历史记录超过限制,则只取最近的记录
+        if (questions.size() > Limit) {
+            questions = questions.subList(questions.size() - Limit, questions.size());
+        }
+
+        // 将历史对话记录转换为 AiQuestionItem 列表
+        List<AiQuestionItem> itemList = new ArrayList<>();
+        for (AiQuestion question : questions) {
+            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+            userItem.setId(question.getId());
+            userItem.setSessionId(question.getSessionId());
+            userItem.setUserId(question.getUserId());
+            userItem.setUserName(question.getUserName());
+            userItem.setAskTime(question.getAskTime());
+
+            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
+            assistantItem.setId(question.getId());
+            assistantItem.setSessionId(question.getSessionId());
+            assistantItem.setUserId(question.getUserId());
+            assistantItem.setUserName(question.getUserName());
+            assistantItem.setAskTime(question.getAskTime());
+
+            itemList.add(userItem);
+            itemList.add(assistantItem);
+        }
+
+        // 将 AiQuestionItem 列表转换为消息列表
+        for (AiQuestionItem item : itemList) {
+            Message message = Message.builder()
+                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
+                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
+                    .build();
+            messages.add(message);
+        }
+
+        // 添加用户的新消息
+        Message userMessage = Message.builder()
+                .role(Role.USER.getValue())
+                .content(questionText) // 使用提取的文本
+                .build();
+        messages.add(userMessage);
+
+        // 构建模型调用参数
+        GenerationParam param = GenerationParam.builder()
+                .model(tyqwModel)
+                .messages(messages)
+                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
+                .topP(0.8)
+                .apiKey(apiKey)
+                .incrementalOutput(true) // 开启增量输出
+                .enableSearch(true)  // 联网搜索
+                .build();
+
+        String finalSessionId = sessionId;
+        StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
+        return ResponseEntity.ok()
+                .contentType(MediaType.TEXT_EVENT_STREAM)
+                .body(outputStream -> {
+                    try {
+// 调用流式接口
+                        generation.streamCall(param).blockingForEach(chunk -> {
+                            try {
+                                // 获取每次生成的内容
+                                String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();
+
+                                // 检查内容是否为空,如果为空则跳过
+                                if (partialAnswer == null || partialAnswer.trim().isEmpty()) {
+                                    return; // 如果内容为空,直接返回,不进行后续操作
+                                }
+
+                                // 构建输出对象
+                                AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
+                                aiStreamOutputVO.setSessionId(finalSessionId);
+                                aiStreamOutputVO.setReasoningContent(partialAnswer);
+
+                                // 转换为 JSON 字符串
+                                String newString = objectMapper.writeValueAsString(aiStreamOutputVO);
+
+                                // 写入输出流
+                                outputStream.write(("data: " + newString + "\n\n").getBytes(StandardCharsets.UTF_8));
+                                outputStream.flush(); // 确保立即发送到前端
+
+                                // 累加到完整回答内容中
+                                completeAnswer.append(partialAnswer);
+
+                                // 添加延迟
+                                try {
+                                    Thread.sleep(millis); // 延迟*毫秒
+                                } catch (InterruptedException e) {
+                                    Thread.currentThread().interrupt();
+                                    log.error("Thread interrupted", e);
+                                }
+
+                            } catch (Exception e) {
+                                log.error("Error processing chunk", e);
+                                outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
+                                outputStream.flush();
+                            }
+                        });
+
+                        // 流式接口调用完成后,将完整回答存入数据库
+                        AiQuestion aiQuestion = new AiQuestion();
+                        aiQuestion.setModel(tyqwModel);
+                        aiQuestion.setSessionId(finalSessionId);
+                        aiQuestion.setUserId(userId);
+                        aiQuestion.setUserName(userName);
+                        aiQuestion.setQuestion(questionText);
+                        aiQuestion.setAnswer(completeAnswer.toString());
+                        aiQuestion.setAskTime(LocalDateTime.now());
+                        aiQuestionMapper.save(aiQuestion);
+
+                    } catch (ApiException e) {
+                        log.error("Error processing request", e);
+                        outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
+                        outputStream.flush();
+                    } catch (NoApiKeyException | InputRequiredException e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+    }
+
+    // 阿里百炼DeepSeek大模型
+    @PostMapping(value = "/aliDeepSeek", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+    public ResponseEntity<StreamingResponseBody> send2(@RequestBody JSONObject object )throws NoApiKeyException, InputRequiredException {
+        // 获取当前登录用户的信息
+        Long userId = SecurityUtils.getUserId();
+        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
+        String sessionId = null;
+        String content = object.get("content").toString();
+
+        // 如果没有传入 sessionId,则创建一个新的会话ID
+        if (object.containsKey("sessionId")) {
+            sessionId = object.get("sessionId").toString();
+        } else {
+            sessionId = java.util.UUID.randomUUID().toString();
+        }
+
+        // 解析 JSON 并提取 "content" 字段的值
+        String questionText = content;
+
+        // 检查是否已经存在相同的 sessionId
+        boolean exists = aiSessionMapper.existsBySessionId(sessionId);
+
+        if (!exists) {
+            // 创建新的 AiSession 实体并存入数据库
+            AiSession aiSession = new AiSession();
+            aiSession.setSessionId(sessionId);
+            aiSession.setUserId(userId);
+            aiSession.setUserName(userName);
+            aiSession.setQuestion(questionText);
+            aiSession.setAskTime(LocalDateTime.now());
+            aiSessionMapper.save(aiSession);
+        }
+
+        // 构建消息列表,包含角色定义、历史对话记录和用户新消息
+        List<Message> messages = new ArrayList<>();
+
+        // 插入角色定义(在对话历史的开头)
+        Message roleDefinition = Message.builder()
+                .role(Role.SYSTEM.getValue()) // 使用系统角色
+                .content(aiRole) // 定义角色的行为和风格
+                .build();
+        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
+
+        // 从数据库中获取历史对话记录
+        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
+
+        // 如果历史记录超过限制,则只取最近的记录
+        if (questions.size() > Limit) {
+            questions = questions.subList(questions.size() - Limit, questions.size());
+        }
+
+        // 将历史对话记录转换为 AiQuestionItem 列表
+        List<AiQuestionItem> itemList = new ArrayList<>();
+        for (AiQuestion question : questions) {
+            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+            userItem.setId(question.getId());
+            userItem.setSessionId(question.getSessionId());
+            userItem.setUserId(question.getUserId());
+            userItem.setUserName(question.getUserName());
+            userItem.setAskTime(question.getAskTime());
+
+            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
+            assistantItem.setId(question.getId());
+            assistantItem.setSessionId(question.getSessionId());
+            assistantItem.setUserId(question.getUserId());
+            assistantItem.setUserName(question.getUserName());
+            assistantItem.setAskTime(question.getAskTime());
+
+            itemList.add(userItem);
+            itemList.add(assistantItem);
+        }
+
+        // 将 AiQuestionItem 列表转换为消息列表
+        for (AiQuestionItem item : itemList) {
+            Message message = Message.builder()
+                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
+                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
+                    .build();
+            messages.add(message);
+        }
+
+        // 添加用户的新消息
+        Message userMessage = Message.builder()
+                .role(Role.USER.getValue())
+                .content(questionText) // 使用提取的文本
+                .build();
+        messages.add(userMessage);
+
+        // 构建模型调用参数
+        GenerationParam param = GenerationParam.builder()
+                .model(dpskModel)
+                .messages(messages)
+                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
+                .apiKey(apiKey)
+                .incrementalOutput(true) // 开启增量输出[^1^]
+                .build();
+
+        String finalSessionId = sessionId;
+        StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
+        return ResponseEntity.ok()
+                .contentType(MediaType.TEXT_EVENT_STREAM)
+                .body(outputStream -> {
+                    try {
+                        // 调用流式接口
+                        generation.streamCall(param).blockingForEach(chunk -> {
+                            try {
+                                // 获取每次生成的内容
+                                String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();
+
+                                // 检查内容是否为空,如果为空则跳过
+                                if (partialAnswer == null || partialAnswer.trim().isEmpty()) {
+                                    return; // 如果内容为空,直接返回,不进行后续操作
+                                }
+
+                                // 构建输出对象
+                                AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
+                                aiStreamOutputVO.setSessionId(finalSessionId);
+                                aiStreamOutputVO.setReasoningContent(partialAnswer);
+
+                                // 转换为 JSON 字符串
+                                String newString = objectMapper.writeValueAsString(aiStreamOutputVO);
+
+                                // 写入输出流
+                                outputStream.write(("data: " + newString + "\n\n").getBytes(StandardCharsets.UTF_8));
+                                outputStream.flush(); // 确保立即发送到前端
+
+                                // 累加到完整回答内容中
+                                completeAnswer.append(partialAnswer);
+
+                                // 添加延迟
+                                try {
+                                    Thread.sleep(millis); // 延迟*毫秒
+                                } catch (InterruptedException e) {
+                                    Thread.currentThread().interrupt();
+                                    log.error("Thread interrupted", e);
+                                }
+
+                            } catch (Exception e) {
+                                log.error("Error processing chunk", e);
+                                outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
+                                outputStream.flush();
+                            }
+                        });
+
+                        // 流式接口调用完成后,将完整回答存入数据库
+                        AiQuestion aiQuestion = new AiQuestion();
+                        aiQuestion.setModel(dpskModel);
+                        aiQuestion.setSessionId(finalSessionId);
+                        aiQuestion.setUserId(userId);
+                        aiQuestion.setUserName(userName);
+                        aiQuestion.setQuestion(questionText);
+                        aiQuestion.setAnswer(completeAnswer.toString());
+                        aiQuestion.setAskTime(LocalDateTime.now());
+                        aiQuestionMapper.save(aiQuestion);
+
+                    } catch (ApiException e) {
+                        log.error("Error processing request", e);
+                        outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
+                        outputStream.flush();
+                    } catch (NoApiKeyException | InputRequiredException e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+    }
+
+    @PostMapping(value = "/aliTyqw-test")
+    public ResponseEntity<AiStreamOutputVO> send3(@RequestBody JSONObject object) throws NoApiKeyException, InputRequiredException {
+        // 获取当前登录用户的信息
+        Long userId = SecurityUtils.getUserId();
+        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
+        String sessionId = null;
+        String content = object.get("content").toString();
+
+        // 如果没有传入 sessionId,则创建一个新的会话ID
+        if (object.containsKey("sessionId")) {
+            sessionId = object.get("sessionId").toString();
+        } else {
+            sessionId = java.util.UUID.randomUUID().toString();
+        }
+
+        // 解析 JSON 并提取 "content" 字段的值
+        String questionText = content;
+
+        // 检查是否已经存在相同的 sessionId
+        boolean exists = aiSessionMapper.existsBySessionId(sessionId);
+
+        if (!exists) {
+            // 创建新的 AiSession 实体并存入数据库
+            AiSession aiSession = new AiSession();
+            aiSession.setSessionId(sessionId);
+            aiSession.setUserId(userId);
+            aiSession.setUserName(userName);
+            aiSession.setQuestion(questionText);
+            aiSession.setAskTime(LocalDateTime.now());
+            aiSessionMapper.save(aiSession);
+        }
+
+        // 构建消息列表,包含角色定义、历史对话记录和用户新消息
+        List<Message> messages = new ArrayList<>();
+
+        // 插入角色定义(在对话历史的开头)
+        Message roleDefinition = Message.builder()
+                .role(Role.SYSTEM.getValue()) // 使用系统角色
+                .content(aiRole) // 定义角色的行为和风格
+                .build();
+        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
+
+        // 从数据库中获取历史对话记录
+        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
+
+        // 如果历史记录超过限制,则只取最近的记录
+        if (questions.size() > Limit) {
+            questions = questions.subList(questions.size() - Limit, questions.size());
+        }
+
+        // 将历史对话记录转换为 AiQuestionItem 列表
+        List<AiQuestionItem> itemList = new ArrayList<>();
+        for (AiQuestion question : questions) {
+            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+            userItem.setId(question.getId());
+            userItem.setSessionId(question.getSessionId());
+            userItem.setUserId(question.getUserId());
+            userItem.setUserName(question.getUserName());
+            userItem.setAskTime(question.getAskTime());
+
+            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
+            assistantItem.setId(question.getId());
+            assistantItem.setSessionId(question.getSessionId());
+            assistantItem.setUserId(question.getUserId());
+            assistantItem.setUserName(question.getUserName());
+            assistantItem.setAskTime(question.getAskTime());
+
+            itemList.add(userItem);
+            itemList.add(assistantItem);
+        }
+
+        // 将 AiQuestionItem 列表转换为消息列表
+        for (AiQuestionItem item : itemList) {
+            Message message = Message.builder()
+                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
+                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
+                    .build();
+            messages.add(message);
+        }
+
+        // 添加用户的新消息
+        Message userMessage = Message.builder()
+                .role(Role.USER.getValue())
+                .content(questionText) // 使用提取的文本
+                .build();
+        messages.add(userMessage);
+
+        // 构建模型调用参数
+        GenerationParam param = GenerationParam.builder()
+                .model(tyqwModel)
+                .messages(messages)
+                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
+                .topP(0.8)
+                .apiKey(apiKey)
+                .incrementalOutput(false) // 关闭增量输出
+                .enableSearch(true)  // 联网搜索
+                .build();
+
+        try {
+            // 调用非流式接口
+            String completeAnswer = generation.call(param).getOutput().getChoices().get(0).getMessage().getContent();
+
+            // 将完整回答存入数据库
+            AiQuestion aiQuestion = new AiQuestion();
+            aiQuestion.setModel(tyqwModel);
+            aiQuestion.setSessionId(sessionId);
+            aiQuestion.setUserId(userId);
+            aiQuestion.setUserName(userName);
+            aiQuestion.setQuestion(questionText);
+            aiQuestion.setAnswer(completeAnswer);
+            aiQuestion.setAskTime(LocalDateTime.now());
+            aiQuestionMapper.save(aiQuestion);
+
+            // 构建返回对象
+            AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
+            aiStreamOutputVO.setSessionId(sessionId);
+            aiStreamOutputVO.setReasoningContent(completeAnswer);
+
+            // 返回完整回答给前端
+            return ResponseEntity.ok(aiStreamOutputVO);
+        } catch (ApiException e) {
+            log.error("Error processing request", e);
+
+            // 构建错误返回对象
+            AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
+            aiStreamOutputVO.setSessionId(sessionId);
+            aiStreamOutputVO.setReasoningContent("Error processing request");
+
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(aiStreamOutputVO);
+        } catch (NoApiKeyException | InputRequiredException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 43 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiQuestionController.java

@@ -0,0 +1,43 @@
+package com.usky.ai.controller.web;
+
+import com.usky.ai.mapper.AiQuestionMapper;
+import com.usky.ai.service.AiQuestion;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/questions")
+public class AiQuestionController {
+
+    @Autowired
+    private AiQuestionMapper aiQuestionMapper;
+
+    // 查询所有数据
+    @GetMapping("/all")
+    public List<AiQuestion> getAllQuestions() {
+        return aiQuestionMapper.findAll();
+    }
+
+    // 根据 userId 查询数据
+    @GetMapping("/user/{userId}")
+    public List<AiQuestion> getQuestionsByUserId(@PathVariable Long userId) {
+        return aiQuestionMapper.findByUserId(userId);
+    }
+
+    // 根据 id 删除数据
+    @DeleteMapping("/deleted/{id}")
+    public String deleteQuestion(@PathVariable Long id) {
+        aiQuestionMapper.deleteById(id);
+        return "Question with id " + id + " deleted successfully.";
+    }
+
+    // 根据 sessionId 查询数据
+    @GetMapping("/session/{sessionId}")
+    public List<AiQuestion> getQuestionsBySessionId(@PathVariable String sessionId) {
+        return aiQuestionMapper.findBySessionId(sessionId);
+    }
+}

+ 94 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiSessionController.java

@@ -0,0 +1,94 @@
+package com.usky.ai.controller.web;
+
+import com.usky.ai.mapper.AiQuestionMapper;
+import com.usky.ai.mapper.AiSessionMapper;
+import com.usky.ai.service.AiQuestion;
+import com.usky.ai.service.AiQuestionItem;
+import com.usky.ai.service.AiSession;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.security.utils.SecurityUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/session")
+public class AiSessionController {
+
+    @Autowired
+    private AiSessionMapper aiSessionMapper;
+
+    @Autowired
+    private AiQuestionMapper aiQuestionMapper;
+
+    @GetMapping("/all")
+    public List<AiSession> getAllSessions() {
+        return aiSessionMapper.findAll();
+    }
+
+    @GetMapping("/current")
+    public List<AiSession> getCurrentSessions(@RequestHeader("Authorization") String token) {
+        // 解析 token 获取 userId
+        Long userId = SecurityUtils.getUserId();
+        return getSessionsByUserId(userId);
+    }
+
+    public List<AiSession> getSessionsByUserId(Long userId) {
+        List<AiSession> sessions = aiSessionMapper.findByUserId(userId);
+
+        for (AiSession session : sessions) {
+            List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(session.getSessionId());
+            List<AiQuestionItem> itemList = new ArrayList<>();
+
+            for (AiQuestion question : questions) {
+                AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+                userItem.setId(question.getId());
+                userItem.setSessionId(question.getSessionId());
+                userItem.setUserId(question.getUserId());
+                userItem.setUserName(question.getUserName());
+                userItem.setAskTime(question.getAskTime());
+                // 不设置 reasoningContent,因为 role 是 user
+
+                itemList.add(userItem);
+
+                AiQuestionItem assistantItem = new AiQuestionItem("assistant", null); // 初始化 content 为 null
+                assistantItem.setId(question.getId());
+                assistantItem.setSessionId(question.getSessionId());
+                assistantItem.setUserId(question.getUserId());
+                assistantItem.setUserName(question.getUserName());
+                assistantItem.setAskTime(question.getAskTime());
+                assistantItem.setReasoningContent(question.getAnswer()); // 设置 reasoningContent
+                // 不设置 content,因为 role 是 assistant
+
+                itemList.add(assistantItem);
+            }
+
+            session.setItemList(itemList);
+        }
+
+        return ApiResult.success(sessions).getData();
+    }
+
+    @PostMapping("/update")
+    public ApiResult updateSession(@RequestBody AiSession aiSession) {
+        aiSessionMapper.updateQuestion(aiSession.getSessionId(), aiSession.getQuestion());
+        return ApiResult.success("更新会话成功");
+    }
+
+    @DeleteMapping("/delete")
+    public ApiResult deleteSession(@RequestParam String sessionId) {
+        try {
+            aiSessionMapper.delete(sessionId);
+            aiQuestionMapper.delete(sessionId);
+            return ApiResult.success("删除会话成功");
+        } catch (Exception e) {
+            // 如果出现异常,可以记录日志或者返回错误信息
+            log.error("删除会话失败", e);
+            return ApiResult.error("删除会话失败");
+        }
+    }
+}

+ 41 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/mapper/AiQuestionMapper.java

@@ -0,0 +1,41 @@
+package com.usky.ai.mapper;
+
+import com.usky.ai.service.AiQuestion;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface AiQuestionMapper {
+    @Insert("INSERT INTO ai_questions (model, session_id, user_id, user_name, question, answer, ask_time) " +
+            "VALUES (#{model},  #{sessionId}, #{userId}, #{userName}, #{question}, #{answer}, #{askTime})")
+    void save(AiQuestion aiQuestion);
+
+    // 查询所有数据
+    @Select("SELECT * FROM ai_questions ORDER BY ask_time ASC")
+    List<AiQuestion> findAll();
+
+    // 根据 userId 查询数据
+    @Select("SELECT * FROM ai_questions WHERE user_id = #{userId} ORDER BY ask_time ASC")
+    List<AiQuestion> findByUserId(Long userId);
+
+    // 根据 id 删除数据
+    @Delete("DELETE FROM ai_questions WHERE id = #{id}")
+    void deleteById(Long id);
+
+    // 根据 sessionId 和 userId 查询数据
+    @Select("SELECT * FROM ai_questions WHERE session_id = #{sessionId} AND user_id = #{userId} ORDER BY ask_time ASC")
+    List<AiQuestion> findByUserIdAndSessionId(@Param("sessionId") String sessionId, @Param("userId") Long userId);
+
+    //根据 sessionId查询数据
+    @Select("SELECT * FROM ai_questions WHERE session_id = #{sessionId} ORDER BY ask_time ASC")
+    List<AiQuestion> findBySessionId(String sessionId);
+
+    // 根据 sessionId 查询 ai_questions 表中的数据
+    @Select("SELECT * FROM ai_questions WHERE session_id = #{sessionId} ORDER BY ask_time ASC")
+    List<AiQuestion> findQuestionsBySessionId(String sessionId);
+
+    //标记会话为删除
+    @Update("UPDATE ai_questions SET deleted = true WHERE session_id = #{sessionId}")
+    void delete(String sessionId);
+}

+ 37 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/mapper/AiSessionMapper.java

@@ -0,0 +1,37 @@
+package com.usky.ai.mapper;
+
+import com.usky.ai.service.AiQuestion;
+import com.usky.ai.service.AiSession;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface AiSessionMapper {
+    @Insert("INSERT INTO ai_sessions (session_id, user_id, user_name, question, ask_time) " +
+            "VALUES (#{sessionId}, #{userId}, #{userName}, #{question}, #{askTime})")
+    void save(AiSession aiSession);
+
+    //查询所有数据
+    @Select("SELECT * FROM ai_sessions ORDER BY ask_time DESC")
+    List<AiSession> findAll();
+
+    // 根据 user_id 查询未删除的数据
+    @Select("SELECT * FROM ai_sessions WHERE user_id = #{userId} AND deleted = false ORDER BY ask_time DESC")
+    List<AiSession> findByUserId(Long userId);
+
+    // 检查是否存在指定的 session_id 且未删除
+    @Select("SELECT COUNT(*) FROM ai_sessions WHERE session_id = #{sessionId} ORDER BY ask_time DESC")
+    boolean existsBySessionId(String sessionId);
+
+    @Select("SELECT * FROM ai_questions WHERE session_id = #{sessionId} ORDER BY ask_time DESC")
+    List<AiQuestion> findQuestionsBySessionId(String sessionId);
+
+    // 更新会话主题
+    @Update("UPDATE ai_sessions SET question = #{question} WHERE session_id = #{sessionId}")
+    void updateQuestion(@Param("sessionId") String sessionId, @Param("question") String question);
+
+    //标记会话为删除
+    @Update("UPDATE ai_sessions SET deleted = true WHERE session_id = #{sessionId}")
+    void delete(String sessionId);
+}

+ 70 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiQuestion.java

@@ -0,0 +1,70 @@
+package com.usky.ai.service;
+
+import java.time.LocalDateTime;
+
+public class AiQuestion {
+    private Long id;
+    private String model;
+    private String sessionId;
+    private Long userId; // 添加用户ID字段
+    private String userName; // 添加用户名字段
+    private String question;
+    private String answer;
+    private LocalDateTime askTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getModel() { return model; }
+
+    public void setModel(String model) { this.model = model; }
+
+    public String getSessionId() { return sessionId; }
+
+    public void setSessionId(String sessionId) { this.sessionId = sessionId; }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(String question) {
+        this.question = question;
+    }
+
+    public String getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(String answer) {
+        this.answer = answer;
+    }
+
+    public LocalDateTime getAskTime() {
+        return askTime;
+    }
+
+    public void setAskTime(LocalDateTime askTime) {
+        this.askTime = askTime;
+    }
+}

+ 51 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiQuestionItem.java

@@ -0,0 +1,51 @@
+package com.usky.ai.service;
+
+import java.time.LocalDateTime;
+
+public class AiQuestionItem {
+    private Long id;
+    private String sessionId;
+    private Long userId;
+    private String userName;
+    private String role;
+    private String content;
+    private String reasoningContent;
+    private LocalDateTime askTime;
+
+    public AiQuestionItem(String role, String content) {
+        this.role = role;
+        this.content = content;
+    }
+
+    public Long getId() { return id; }
+
+    public void setId(Long id) { this.id = id; }
+
+    public String getSessionId() { return sessionId; }
+
+    public void setSessionId(String sessionId) { this.sessionId = sessionId; }
+
+    public Long getUserId() { return userId; }
+
+    public void setUserId(Long userId) { this.userId = userId; }
+
+    public String getUserName() { return userName; }
+
+    public void setUserName(String userName) { this.userName = userName; }
+
+    public String getRole() { return role; }
+
+    public void setRole(String role) { this.role = role; }
+
+    public String getContent() { return content; }
+
+    public void setContent(String content) { this.content = content; }
+
+    public String getReasoningContent() { return reasoningContent; }
+
+    public void setReasoningContent(String reasoningContent) { this.reasoningContent = reasoningContent; }
+
+    public LocalDateTime getAskTime() { return askTime; }
+
+    public void setAskTime(LocalDateTime askTime) { this.askTime = askTime; }
+}

+ 48 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiSession.java

@@ -0,0 +1,48 @@
+package com.usky.ai.service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+public class AiSession {
+
+    private Long id;
+    private String sessionId;
+    private Long userId; // 添加用户ID字段
+    private String userName; // 添加用户名字段
+    private String question;
+    private LocalDateTime askTime;
+    private List<AiQuestionItem> itemList;
+    private boolean deleted; // 添加删除标识字段
+
+    public Long getId() { return id; }
+
+    public void setId(Long id) { this.id = id; }
+
+    public String getSessionId() { return sessionId; }
+
+    public void setSessionId(String sessionId) { this.sessionId = sessionId; }
+
+    public Long getUserId() { return userId; }
+
+    public void setUserId(Long userId) { this.userId = userId; }
+
+    public String getUserName() { return userName; }
+
+    public void setUserName(String userName) { this.userName = userName; }
+
+    public String getQuestion() { return question; }
+
+    public void setQuestion(String question) { this.question = question; }
+
+    public LocalDateTime getAskTime() { return askTime; }
+
+    public void setAskTime(LocalDateTime askTime) { this.askTime = askTime; }
+
+    public List<AiQuestionItem> getItemList() { return itemList; }
+
+    public void setItemList(List<AiQuestionItem> itemList) { this.itemList = itemList; }
+
+    public boolean isDeleted() { return deleted; }
+
+    public void setDeleted(boolean deleted) { this.deleted = deleted; }
+}

+ 14 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/AiChatConfig.java

@@ -0,0 +1,14 @@
+package com.usky.ai.service.config;
+
+import com.alibaba.dashscope.aigc.generation.Generation;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AiChatConfig {
+
+    @Bean
+    public Generation generation() {
+        return new Generation();
+    }
+}

+ 19 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/MyGlobalCorsConfig.java

@@ -0,0 +1,19 @@
+package com.usky.ai.service.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class MyGlobalCorsConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**") // 对所有的路径允许跨域请求
+                .allowedOrigins("*") // 允许来自任何源的请求
+                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
+                .allowedHeaders("*") // 允许的请求头
+                .allowCredentials(false) // 是否允许证书(cookies),根据需要设置
+                .maxAge(3600); // 预检请求的缓存时间(秒)
+    }
+}

+ 14 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/WebConfig.java

@@ -0,0 +1,14 @@
+package com.usky.ai.service.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+    @Override
+    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
+        // 设置默认的异步请求超时时间为300秒(单位:毫秒)
+        configurer.setDefaultTimeout(300000);
+    }
+}

+ 22 - 0
service-ai/service-ai-biz/src/main/java/com/usky/ai/service/vo/AiStreamOutputVO.java

@@ -0,0 +1,22 @@
+package com.usky.ai.service.vo;
+
+import lombok.Data;
+
+@Data
+public class AiStreamOutputVO {
+
+    /**
+     * 会话id
+     */
+    private String sessionId;
+
+    /**
+     * 输入内容
+     */
+    private String content;
+
+    /**
+     * 输出内容
+     */
+    private String reasoningContent;
+}

+ 24 - 0
service-ai/service-ai-biz/src/main/resources/bootstrap.yml

@@ -0,0 +1,24 @@
+# Tomcat
+server:
+  port: 9899
+# Spring
+spring: 
+  application:
+    # 应用名称
+    name: service-ai
+  profiles:
+    # 环境配置
+    active: dev
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: usky-cloud-nacos:8848
+      config:
+        # 配置中心地址
+        server-addr: usky-cloud-nacos:8848
+        # 配置文件格式
+        file-extension: yml
+        # 共享配置
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

+ 94 - 0
service-ai/service-ai-biz/src/main/resources/logback.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <!-- 日志存放路径 -->
+    <property name="log.path" value="/var/log/uskycloud/service-ai" />
+    <!-- 日志输出格式 -->
+    <property name="log.pattern" value="%d{MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{26}:%line: %msg%n" />
+    <!--    	<property name="log.pattern" value="%gray(%d{MM-dd HH:mm:ss.SSS}) %highlight(%-5level) &#45;&#45; [%gray(%thread)] %cyan(%logger{26}:%line): %msg%n" />-->
+
+
+    <property name="SQL_PACKAGE" value="com.usky.ai.mapper"/>
+
+    <!-- 控制台输出 -->
+    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="file_sql" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/sql.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sql.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>3</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 系统日志输出 -->
+    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>3</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 系统模块日志级别控制  -->
+    <!--	<logger name="com.usky" level="info" />-->
+    <!-- Spring日志级别控制  -->
+    <!--	<logger name="org.springframework" level="warn" />-->
+
+    <logger name="${SQL_PACKAGE}" additivity="false" level="debug">
+        <appender-ref ref="console"/>
+        <appender-ref ref="file_sql"/>
+    </logger>
+
+    <!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+        <appender-ref ref="console" />
+    </root>
+</configuration>

+ 151 - 0
service-ai/service-ai-biz/src/main/resources/static/dpsk.html

@@ -0,0 +1,151 @@
+<!--
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>小天-AI</title>
+    <style>
+        body {
+            font-family: 'Roboto', Arial, sans-serif;
+            margin: 0;
+            padding: 0;
+            background-color: #f4f4f9;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            height: 100vh;
+        }
+        .container {
+            width: 500px;
+            background-color: #fff;
+            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+            border-radius: 8px;
+            overflow: hidden;
+        }
+        h1 {
+            background-color: #007bff;
+            color: #fff;
+            text-align: center;
+            padding: 15px;
+            margin: 0;
+            font-size: 1.5em;
+        }
+        form {
+            padding: 20px;
+        }
+        label {
+            display: block;
+            margin-bottom: 10px;
+            font-weight: bold;
+        }
+        textarea {
+            width: 100%;
+            height: 100px;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            padding: 10px;
+            resize: none;
+        }
+        button {
+            width: 100%;
+            padding: 10px;
+            background-color: #007bff;
+            color: #fff;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+            transition: background-color 0.3s ease;
+        }
+        button:hover {
+            background-color: #0056b3;
+        }
+        #response {
+            margin-top: 20px;
+            padding: 10px;
+            background-color: #f9f9f9;
+            border-top: 1px solid #ccc;
+            max-height: 200px;
+            overflow-y: auto;
+            font-family: monospace;
+            white-space: pre-wrap;
+        }
+    </style>
+</head>
+<body>
+<div class="container">
+    <h1>小天-AI</h1>
+    <form id="chatForm">
+        <label for="content">你的问题:</label>
+        <textarea id="content" name="content" placeholder="请输入你的问题在这里..."></textarea>
+        <button type="submit">发送</button>
+    </form>
+    <div id="response"></div>
+    <div id="sessionId" style="margin-top: 10px; font-size: 0.9em; color: #666;"></div>
+</div>
+
+<script>
+    document.getElementById('chatForm').addEventListener('submit', function(event) {
+        event.preventDefault();
+
+        const content = document.getElementById('content').value;
+
+        const requestBody = JSON.stringify({content: content});
+
+        const token = "eyJhbGciOiJIUzUxMiJ9.eyIiOjEwMDMsInVzZXJfaWQiOjIxMywidXNlcl9rZXkiOiJlYzUxODMzNjdmYTk0ODgwOGQwZjEwODEyOWVmNjgwOSIsInVzZXJuYW1lIjoi6LW16YeR6ZuoIn0.zWulXcesI1TRcDmiAHuQ9P2WHDE2l7mDmuunx13TmVl6E5Yvs8nZvu1ddtINdw0lrnnR3Q5lZaRH3mJJTaDhig";
+
+        fetch('/ai/aliDeepSeek', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json',
+                'Authorization': `Bearer ${token}`
+            },
+            body: requestBody
+        })
+            .then(response => {
+                if (!response.ok) {
+                    throw new Error('Network response was not ok');
+                }
+                return response.text();
+            })
+            .then(data => {
+                document.getElementById('response').innerText = '';
+
+                // 解析数据,提取 reasoningContent
+                const lines = data.split('\n');
+                let responseLines = [];
+
+                for (let line of lines) {
+                    try {
+                        const parsedLine = JSON.parse(line.replace('data: ', '').trim());
+                        if (parsedLine.reasoningContent !== null) {
+                            responseLines.push(parsedLine.reasoningContent);
+                        }
+                    } catch (e) {
+                        console.error('Error parsing line:', e);
+                    }
+                }
+
+                // 将 reasoningContent 的内容拼接成完整字符串
+                const fullResponse = responseLines.join('');
+
+                // 逐字显示响应内容
+                let index = 0;
+                const responseElement = document.getElementById('response');
+                const interval = setInterval(() => {
+                    if (index < fullResponse.length) {
+                        responseElement.innerText += fullResponse[index];
+                        index++;
+                    } else {
+                        clearInterval(interval);
+                    }
+                }, 50);
+            })
+            .catch(error => {
+                document.getElementById('response').innerText = 'Error: ' + error.message;
+            });
+    })
+</script>
+</body>
+</html>
+-->

+ 150 - 0
service-ai/service-ai-biz/src/main/resources/static/tyqw.html

@@ -0,0 +1,150 @@
+<!--
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>小天-AI</title>
+    <style>
+        body {
+            font-family: 'Roboto', Arial, sans-serif;
+            margin: 0;
+            padding: 0;
+            background-color: #f4f4f9;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            height: 100vh;
+        }
+        .container {
+            width: 500px;
+            background-color: #fff;
+            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+            border-radius: 8px;
+            overflow: hidden;
+        }
+        h1 {
+            background-color: #007bff;
+            color: #fff;
+            text-align: center;
+            padding: 15px;
+            margin: 0;
+            font-size: 1.5em;
+        }
+        form {
+            padding: 20px;
+        }
+        label {
+            display: block;
+            margin-bottom: 10px;
+            font-weight: bold;
+        }
+        textarea {
+            width: 100%;
+            height: 100px;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            padding: 10px;
+            resize: none;
+        }
+        button {
+            width: 100%;
+            padding: 10px;
+            background-color: #007bff;
+            color: #fff;
+            border: none;
+            border-radius: 4px;
+            cursor: pointer;
+            transition: background-color 0.3s ease;
+        }
+        button:hover {
+            background-color: #0056b3;
+        }
+        #response {
+            margin-top: 20px;
+            padding: 10px;
+            background-color: #f9f9f9;
+            border-top: 1px solid #ccc;
+            max-height: 200px;
+            overflow-y: auto;
+            font-family: monospace;
+            white-space: pre-wrap;
+        }
+    </style>
+</head>
+<body>
+<div class="container">
+    <h1>小天-AI</h1>
+    <form id="chatForm">
+        <label for="content">你的问题:</label>
+        <textarea id="content" name="content" placeholder="请输入你的问题在这里..."></textarea>
+        <button type="submit">发送</button>
+    </form>
+    <div id="response"></div>
+    <div id="sessionId" style="margin-top: 10px; font-size: 0.9em; color: #666;"></div>
+</div>
+
+<script>
+    document.getElementById('chatForm').addEventListener('submit', function(event) {
+        event.preventDefault();
+
+        const content = document.getElementById('content').value;
+
+        const requestBody = JSON.stringify({content: content});
+
+        const token = "eyJhbGciOiJIUzUxMiJ9.eyIiOjEwMDMsInVzZXJfaWQiOjIxMywidXNlcl9rZXkiOiJlYzUxODMzNjdmYTk0ODgwOGQwZjEwODEyOWVmNjgwOSIsInVzZXJuYW1lIjoi6LW16YeR6ZuoIn0.zWulXcesI1TRcDmiAHuQ9P2WHDE2l7mDmuunx13TmVl6E5Yvs8nZvu1ddtINdw0lrnnR3Q5lZaRH3mJJTaDhig";
+
+        fetch('/ai/aliTyqw', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json',
+                'Authorization': `Bearer ${token}`
+            },
+            body: requestBody
+        })
+            .then(response => {
+                if (!response.ok) {
+                    throw new Error('Network response was not ok');
+                }
+                return response.text();
+            })
+            .then(data => {
+                document.getElementById('response').innerText = '';
+
+                // 解析数据,提取 reasoningContent
+                const lines = data.split('\n');
+                let responseLines = [];
+
+                for (let line of lines) {
+                    try {
+                        const parsedLine = JSON.parse(line.replace('data: ', '').trim());
+                        if (parsedLine.reasoningContent !== null) {
+                            responseLines.push(parsedLine.reasoningContent);
+                        }
+                    } catch (e) {
+                        console.error('Error parsing line:', e);
+                    }
+                }
+
+                // 将 reasoningContent 的内容拼接成完整字符串
+                const fullResponse = responseLines.join('');
+
+                // 逐字显示响应内容
+                let index = 0;
+                const responseElement = document.getElementById('response');
+                const interval = setInterval(() => {
+                    if (index < fullResponse.length) {
+                        responseElement.innerText += fullResponse[index];
+                        index++;
+                    } else {
+                        clearInterval(interval);
+                    }
+                }, 50);
+            })
+            .catch(error => {
+                document.getElementById('response').innerText = 'Error: ' + error.message;
+            });
+    })
+</script>
+</body>
+</html>-->

+ 4 - 0
service-alarm/service-alarm-biz/pom.xml

@@ -62,6 +62,10 @@
             <version>0.0.1</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>ruoyi-common-swagger</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 2 - 1
service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/RuoYiSystemApplication.java

@@ -1,6 +1,7 @@
 package com.usky.alarm;
 
 
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
 import org.mybatis.spring.annotation.MapperScan;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -20,7 +21,7 @@ import java.net.UnknownHostException;
  * @author ruoyi
  */
 
-
+@EnableCustomSwagger2
 @EnableFeignClients(basePackages = "com.usky")
 @MapperScan(value = "com.usky.alarm.mapper")
 @ComponentScan("com.usky")

+ 151 - 53
service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/impl/BaseAlarmNoticeResultServiceImpl.java

@@ -19,14 +19,16 @@ import com.usky.alarm.service.BaseAlarmNoticeResultService;
 import com.usky.alarm.service.config.voice.VoiceNotice;
 import com.usky.common.core.bean.CommonPage;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.MceRequestVO;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import com.usky.system.RemoteMceService;
 
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -44,77 +46,173 @@ public class BaseAlarmNoticeResultServiceImpl extends AbstractCrudService<BaseAl
     private VoiceNotice voiceNotice;
     @Autowired
     private SysUserMapper sysUserMapper;
+    @Autowired
+    private RemoteMceService remoteMceService;
+
+    private static final String SMS_SIGN_NAME = "上海永天科技股份有限公司";
+    private static final String SMS_TEMPLATE_CODE = "SMS_463791105";
+    private static final String REGION_ID = "cn-beijing";
+    private static final String ACCESS_KEY_ID = "LTAI5tH3VvRL5BUkovCokHJX";
+    private static final String ACCESS_KEY_SECRET = "SaaWUouNqvcA0C746gcNOH9m6SRYN4";
+
+    private static final String INFO_TYPE = "4";
+    private static final String INFO_TITLE = "设备告警";
+    private static final String ALARM_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    private static final String REMARK_TEMPLATE = "设备名称:%s,请及时处理!";
+
 
     @Override
     public CommonPage<BaseAlarmNoticeResult> resultInfo(String receiver, Integer alarmId, Integer current, Integer size) {
         IPage<BaseAlarmNoticeResult> page = new Page<>(current, size);
         LambdaQueryWrapper<BaseAlarmNoticeResult> queryWrapper1 = Wrappers.lambdaQuery();
-        queryWrapper1.like(StringUtils.isNotBlank(receiver),BaseAlarmNoticeResult::getReceiver, receiver)
+        queryWrapper1.like(StringUtils.isNotBlank(receiver), BaseAlarmNoticeResult::getReceiver, receiver)
                 .eq(BaseAlarmNoticeResult::getAlarmId, alarmId);
 //                .eq(BaseAlarmNoticeResult::getTenantId, SecurityUtils.getTenantId());
-        page = this.page(page,queryWrapper1);
-        return new CommonPage<>(page.getRecords(),page.getTotal(),page.getCurrent(),page.getSize());
+        page = this.page(page, queryWrapper1);
+        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize());
     }
 
-    //异步多线程调用
+    // 异步多线程调用
     @Async("asyncServiceExecutor")
     public Integer send(BaseAlarm baseAlarm, List<BaseAlarmNotice> records3, Integer alarmId, List<DmpProduct> records,
                         BaseAlarmType baseAlarmType, List<DmpDevice> records2) throws ClientException {
-        log.info("start asyncServiceExecutor--------------------");
+        log.info("Start asyncServiceExecutor--------------------");
         Integer saveAlarmResult = 0;
-        try{
-            String[] array = records3.get(0).getReceiver1().split(",");
-            for (String s : array) {
-                LambdaQueryWrapper<SysUser> lambdaQuery4 = Wrappers.lambdaQuery();
-                lambdaQuery4.eq(SysUser::getUserId,s)
-                        .eq(SysUser::getDelFlag,0);
-                SysUser sysUser = sysUserMapper.selectOne(lambdaQuery4);
-                BaseAlarmNoticeResult baseAlarmNoticeResult = new BaseAlarmNoticeResult();
-                baseAlarmNoticeResult.setReceiver(sysUser.getNickName());
-                baseAlarmNoticeResult.setReceiverPhone(sysUser.getPhonenumber());
-                baseAlarmNoticeResult.setAlarmId(alarmId);
-                baseAlarmNoticeResult.setNoticeTime(LocalDateTime.now());
-                baseAlarmNoticeResult.setNoticeContent(records.get(0).getProductName()+","+baseAlarmType.getTypeName()+","+baseAlarm.getAlarmTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd " +
-                        "HH:mm:ss")));
-                baseAlarmNoticeResult.setTenantId(records.get(0).getTenantId());
-                if (records3.get(0).getNoticeMethod().contains("电话")){
-                    SingleCallByTtsResponse code = voiceNotice.sendCVoice(sysUser.getPhonenumber(),
-                            records.get(0).getProductName(),baseAlarmType.getTypeName(),
-                            baseAlarm.getAlarmTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd " +
-                                    "HH:mm:ss")));
-                    baseAlarmNoticeResult.setNoticeType(3);
-                    if(code.getCode() != null && code.getCode().equals("OK")) {
-                        //请求成功
-                        baseAlarmNoticeResult.setNoticeResult(1);
-                    }else {
-                        baseAlarmNoticeResult.setNoticeResult(2);
-                    }
+        String templateParam = createTemplateParam(baseAlarm, baseAlarmType, records2.get(0));
+
+        try {
+            String[] receivers = records3.get(0).getReceiver1().split(",");
+            for (String receiver : receivers) {
+                SysUser sysUser = getSysUser(receiver);
+                if (sysUser == null) {
+                    log.warn("查询不到告警接收用户: {}", receiver);
+                    continue;
+                }
+
+                BaseAlarmNoticeResult baseAlarmNoticeResult = createBaseAlarmNoticeResult(sysUser, baseAlarm, baseAlarmType, records.get(0), alarmId);
+
+                if (records3.get(0).getNoticeMethod().contains("电话")) {
+                    handleVoiceNotice(sysUser, baseAlarmNoticeResult, records.get(0), baseAlarmType, baseAlarm);
                     saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
                 }
-                if (records3.get(0).getNoticeMethod().contains("短信")){
-                    DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", "LTAI5tH3VvRL5BUkovCokHJX", "SaaWUouNqvcA0C746gcNOH9m6SRYN4");
-                    IAcsClient client = new DefaultAcsClient(profile);
-                    SendSmsRequest request = new SendSmsRequest();
-                    request.setPhoneNumbers(sysUser.getPhonenumber());//接收短信的手机号码
-                    request.setSignName("上海永天科技股份有限公司");//短信签名名称
-                    request.setTemplateCode("SMS_463791105");//短信模板CODE
-                    request.setTemplateParam("{\"deviceName\":\""+records2.get(0).getDeviceName()+"\","+"\"time\":\""+baseAlarm.getAlarmTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd " +
-                            "HH:mm:ss"))+"\","+
-                            "\"alarmType\":\""+baseAlarmType.getTypeName()+"\","+"\"alarmContent\":\""+baseAlarm.getAlarmContent()+"\"}");
-                    SendSmsResponse code = client.getAcsResponse(request);
-                    baseAlarmNoticeResult.setNoticeType(4);
-                    if(code.getCode() != null && code.getCode().equals("OK")) {
-                        //请求成功
-                        baseAlarmNoticeResult.setNoticeResult(1);
-                    }else {
-                        baseAlarmNoticeResult.setNoticeResult(2);
-                    }
+
+                if (records3.get(0).getNoticeMethod().contains("短信")) {
+                    handleSmsNotice(sysUser, baseAlarmNoticeResult, templateParam);
+                    saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
+                }
+
+                if (records3.get(0).getNoticeMethod().contains("APP")) {
+                    handleMceNotice(sysUser, baseAlarmNoticeResult, baseAlarm, baseAlarmType, records2.get(0), "1");
+                    saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
+                }
+
+                if (records3.get(0).getNoticeMethod().contains("微信")) {
+                    handleMceNotice(sysUser, baseAlarmNoticeResult, baseAlarm, baseAlarmType, records2.get(0), "2");
                     saveAlarmResult = baseMapper.insert(baseAlarmNoticeResult);
                 }
             }
-        }catch (Exception e){
-            e.printStackTrace();
+        } catch (Exception e) {
+            log.error("发送报警通知时异常", e);
         }
         return saveAlarmResult;
     }
+
+    private String createTemplateParam(BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpDevice device) {
+        return "{\"deviceName\":\"" + device.getDeviceName() + "\"," +
+                "\"time\":\"" + formatAlarmTime(baseAlarm.getAlarmTime()) + "\"," +
+                "\"alarmType\":\"" + baseAlarmType.getTypeName() + "\"," +
+                "\"alarmContent\":\"" + baseAlarm.getAlarmContent() + "\"}";
+    }
+
+    private SysUser getSysUser(String userId) {
+        LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(SysUser::getUserId, userId)
+                .eq(SysUser::getDelFlag, 0);
+        return sysUserMapper.selectOne(queryWrapper);
+    }
+
+    private BaseAlarmNoticeResult createBaseAlarmNoticeResult(SysUser sysUser, BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpProduct product, Integer alarmId) {
+        BaseAlarmNoticeResult result = new BaseAlarmNoticeResult();
+        result.setReceiver(sysUser.getNickName());
+        result.setReceiverPhone(sysUser.getPhonenumber());
+        result.setAlarmId(alarmId);
+        result.setNoticeTime(LocalDateTime.now());
+        result.setNoticeContent(product.getProductName() + "," + baseAlarmType.getTypeName() + "," + formatAlarmTime(baseAlarm.getAlarmTime()));
+        result.setTenantId(product.getTenantId());
+        return result;
+    }
+
+    private void handleVoiceNotice(SysUser sysUser, BaseAlarmNoticeResult baseAlarmNoticeResult, DmpProduct product, BaseAlarmType baseAlarmType, BaseAlarm baseAlarm) {
+        baseAlarmNoticeResult.setNoticeType(3);
+        try {
+            SingleCallByTtsResponse response = voiceNotice.sendCVoice(sysUser.getPhonenumber(),
+                    product.getProductName(), baseAlarmType.getTypeName(),
+                    formatAlarmTime(baseAlarm.getAlarmTime()));
+            baseAlarmNoticeResult.setNoticeResult(response.getCode() != null && "OK".equals(response.getCode()) ? 1 : 2);
+        } catch (Exception e) {
+            log.error("用户:{},告警消息电话拨打失败", sysUser.getUserId(), e);
+            baseAlarmNoticeResult.setNoticeResult(2);
+        }
+    }
+
+    private void handleSmsNotice(SysUser sysUser, BaseAlarmNoticeResult baseAlarmNoticeResult, String templateParam) {
+        baseAlarmNoticeResult.setNoticeType(4);
+        try {
+            IAcsClient client = createAcsClient();
+            SendSmsRequest request = new SendSmsRequest();
+            request.setPhoneNumbers(sysUser.getPhonenumber());
+            request.setSignName(SMS_SIGN_NAME);
+            request.setTemplateCode(SMS_TEMPLATE_CODE);
+            request.setTemplateParam(templateParam);
+            SendSmsResponse response = client.getAcsResponse(request);
+            baseAlarmNoticeResult.setNoticeResult(response.getCode() != null && "OK".equals(response.getCode()) ? 1 : 2);
+        } catch (Exception e) {
+            log.error("用户:{},告警消息短信发送失败", sysUser.getUserId(), e);
+            baseAlarmNoticeResult.setNoticeResult(2);
+        }
+    }
+
+    private IAcsClient createAcsClient() {
+        DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
+        return new DefaultAcsClient(profile);
+    }
+
+    // 发送消息中心
+    private void handleMceNotice(SysUser sysUser, BaseAlarmNoticeResult baseAlarmNoticeResult, BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpDevice device, String sendType) {
+        MceRequestVO mceRequestVO = createMceRequestVO(sysUser, baseAlarm, baseAlarmType, device, sendType);
+
+        try {
+            remoteMceService.addMceReceive(mceRequestVO);
+            baseAlarmNoticeResult.setNoticeResult(1);
+        } catch (Exception e) {
+            String noticeType = "1".equals(sendType) ? "APP" : "微信";
+            log.error("用户:{},告警消息{}推送失败:", sysUser.getUserId(), noticeType, e);
+            baseAlarmNoticeResult.setNoticeResult(2);
+        }
+
+        // 设置通知类型
+        baseAlarmNoticeResult.setNoticeType("1".equals(sendType) ? 1 : 2);
+    }
+
+    // 创建消息请求参数
+    private MceRequestVO createMceRequestVO(SysUser sysUser, BaseAlarm baseAlarm, BaseAlarmType baseAlarmType, DmpDevice device, String sendType) {
+        MceRequestVO mceRequestVO = new MceRequestVO();
+        mceRequestVO.setInfoType(INFO_TYPE);
+        mceRequestVO.setInfoTitle(INFO_TITLE);
+        mceRequestVO.setDeviceId(device.getDeviceId());
+        log.info("设备ID:{}", device.getDeviceId());
+        mceRequestVO.setInfoContent(baseAlarmType.getTypeName());
+        mceRequestVO.setAlarmTime(formatAlarmTime(baseAlarm.getAlarmTime()));
+        log.info("告警时间:{}", baseAlarm.getAlarmTime());
+        mceRequestVO.setAlarmSendType(sendType);
+        mceRequestVO.setRemark(String.format(REMARK_TEMPLATE, device.getDeviceName()));
+        mceRequestVO.setUserIds(Collections.singletonList(sysUser.getUserId()));
+        mceRequestVO.setUserName(sysUser.getUserName());
+        mceRequestVO.setId(baseAlarm.getId());
+        return mceRequestVO;
+    }
+
+    private String formatAlarmTime(LocalDateTime alarmTime) {
+        return alarmTime.format(DateTimeFormatter.ofPattern(ALARM_TIME_FORMAT));
+    }
 }

+ 1 - 0
service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/impl/BaseAlarmServiceImpl.java

@@ -115,6 +115,7 @@ public class BaseAlarmServiceImpl extends AbstractCrudService<BaseAlarmMapper, B
                     List<BaseAlarmNotice> records3 = baseAlarmNoticeService.list(lambdaQuery3);
                     if (records3.size()>0){
                         Integer saveAlarmResult = baseAlarmNoticeResultService.send(baseAlarm,records3,alarmId,records,baseAlarmType,records2);
+                        log.info("异步发送告警通知数据: {}", baseAlarm);
                     }
                     return saveResult;
                 }

+ 20 - 0
service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/mqtt/alarm/Alarm.java

@@ -108,6 +108,26 @@ public class Alarm implements MqttStrategy {
             baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
             baseAlarm.setAlarmGrade(2);
             baseAlarm.setAlarmAddress(alarams.get(0).get("deviceName").toString());
+        }else if (alarams.get(0).get("deviceType").equals("131")){
+            baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
+            baseAlarm.setAlarmGrade(1);
+            baseAlarm.setAlarmAddress(alarams.get(0).get("deviceName").toString());
+        }else if (alarams.get(0).get("deviceType").equals("128")){
+            baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
+            baseAlarm.setAlarmGrade(2);
+            baseAlarm.setAlarmAddress(alarams.get(0).get("deviceName").toString());
+        }else if (alarams.get(0).get("deviceType").equals("129")){
+            baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
+            baseAlarm.setAlarmGrade(2);
+            baseAlarm.setAlarmAddress(alarams.get(0).get("deviceName").toString());
+        }else if (alarams.get(0).get("deviceType").equals("130")){
+            baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
+            baseAlarm.setAlarmGrade(2);
+            baseAlarm.setAlarmAddress(alarams.get(0).get("deviceName").toString());
+        }else if (alarams.get(0).get("deviceType").equals("136")){
+            baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
+            baseAlarm.setAlarmGrade(2);
+            baseAlarm.setAlarmAddress(alarams.get(0).get("deviceName").toString());
         }else if (topic.indexOf(code4[2]) != -1 && topic.indexOf(code4[5]) != -1){
             baseAlarm.setAlarmContent(dp.get(0).get("property").toString());
             baseAlarm.setAlarmGrade(2);

+ 2 - 1
service-eg/service-eg-biz/src/main/java/com/usky/eg/service/impl/EgDeviceServiceImpl.java

@@ -68,10 +68,11 @@ public class EgDeviceServiceImpl extends AbstractCrudService<EgDeviceMapper, EgD
                 .like(StringUtils.isNotBlank(requestVO.getInstallAddress()),EgDevice::getInstallAddress,requestVO.getInstallAddress())
                 .eq(null != requestVO.getServiceStatus(),EgDevice::getServiceStatus,requestVO.getServiceStatus())
                 .eq(null != requestVO.getId(),EgDevice::getId,requestVO.getId())
+                .eq(null != requestVO.getDeviceUuid(),EgDevice::getDeviceUuid, requestVO.getDeviceUuid())
                 .eq(EgDevice::getTenantId,tenantId)
                 .orderByDesc(EgDevice::getId);
         page = this.page(page,queryWrapper);
-        if(page.getRecords().size() > 0){
+        if(!page.getRecords().isEmpty()){
 
             LambdaQueryWrapper<MeetingFace> meetingFaceQuery = Wrappers.lambdaQuery();
             meetingFaceQuery.select(MeetingFace::getFid,MeetingFace::getCreateTime,MeetingFace::getVefNum,MeetingFace::getFaceName,MeetingFace::getRemark,MeetingFace::getFaceStatus,MeetingFace::getCardNum,MeetingFace::getBindDevice,MeetingFace::getDeptId,MeetingFace::getTenantId,MeetingFace::getUserId)

+ 5 - 0
service-eg/service-eg-biz/src/main/java/com/usky/eg/service/vo/EgDeviceRequestVO.java

@@ -40,4 +40,9 @@ public class EgDeviceRequestVO implements Serializable {
      * 域名
      */
     private String domain;
+
+    /**
+     * 设备uuid
+     */
+    private String deviceUuid;
 }

+ 1 - 1
service-eg/service-eg-biz/src/main/resources/logback.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration scan="true" scanPeriod="60 seconds" debug="false">
     <!-- 日志存放路径 -->
-	<property name="log.path" value="/var/log/uskycloud/data-transfer" />
+	<property name="log.path" value="/var/log/uskycloud/service-eg"/>
    <!-- 日志输出格式 -->
 	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
 

+ 4 - 0
service-fire/service-fire-biz/pom.xml

@@ -121,6 +121,10 @@
             <version>0.0.1</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>ruoyi-common-swagger</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 4 - 2
service-fire/service-fire-biz/src/main/java/com/usky/fire/RuoYiSystemApplication.java

@@ -1,6 +1,7 @@
 package com.usky.fire;
 
 
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.amqp.rabbit.annotation.EnableRabbit;
 import org.springframework.boot.SpringApplication;
@@ -10,11 +11,12 @@ import org.springframework.context.annotation.ComponentScan;
 
 /**
  * 系统模块
- * 
+ *
  * @author ruoyi
  */
 
 //@EnableRabbit
+@EnableCustomSwagger2
 @EnableFeignClients(basePackages = "com.usky")
 @MapperScan(value = "com.usky.fire.mapper")
 @ComponentScan("com.usky")
@@ -35,4 +37,4 @@ public class RuoYiSystemApplication
                 " |  |  \\    /  \\      /           \n" +
                 " ''-'   `'-'    `-..-'              ");
     }
-}
+}

+ 14 - 5
service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/DemReportInfoController.java

@@ -8,10 +8,7 @@ import com.usky.common.log.enums.BusinessType;
 import com.usky.fire.domain.BaseCompany;
 import com.usky.fire.domain.DemReportInfo;
 import com.usky.fire.service.DemReportInfoService;
-import com.usky.fire.service.vo.CompanyAddVO;
-import com.usky.fire.service.vo.CompanyDataVo;
-import com.usky.fire.service.vo.DemReportInfoIdVo;
-import com.usky.fire.service.vo.DemReportInfoVo;
+import com.usky.fire.service.vo.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -45,7 +42,7 @@ public class DemReportInfoController {
                                                                @RequestParam(value = "sourceType", required = false) String sourceType,
                                                                @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                                                @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
-        return ApiResult.success(demReportInfoService.reportInfoList(companyId,sourceType,pageNum, pageSize));
+        return ApiResult.success(demReportInfoService.reportInfoList(companyId, sourceType, pageNum, pageSize));
     }
 
     /**
@@ -82,5 +79,17 @@ public class DemReportInfoController {
     public ApiResult<List<DemReportInfo>> reportById(@RequestParam(value = "id", required = false) Integer id) {
         return ApiResult.success(demReportInfoService.reportById(id));
     }
+
+    /**
+     * 报告读取状态更新
+     *
+     * @return
+     */
+    @Log(title = "报告读取状态更新", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateReadStatus")
+    public ApiResult<Void> updateReadStatus(@RequestBody DemReportInfoVo vo) {
+        demReportInfoService.updateReadStatus(vo.getId());
+        return ApiResult.success();
+    }
 }
 

+ 15 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/controller/web/PatrolInspectionSiteController.java

@@ -13,6 +13,7 @@ import com.usky.fire.service.vo.PatrolInspectionAreaVo;
 import com.usky.fire.service.vo.PatrolInspectionSiteExportVo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -156,5 +157,19 @@ public class PatrolInspectionSiteController {
         ExcelUtil<PatrolInspectionSiteExportVo> util = new ExcelUtil<PatrolInspectionSiteExportVo>(PatrolInspectionSiteExportVo.class);
         util.exportExcel(response, list, "巡检地点列表", "巡检地点列表");
     }
+
+    /**
+     * 巡检点位-导入
+     *
+     * @param file 导入文件
+     * @return
+     * @throws Exception
+     */
+    @Log(title = "巡检地点", businessType = BusinessType.IMPORT)
+    @PostMapping("/patrolInspectionSiteImport")
+    public ApiResult<Void> patrolInspectionSiteImport(@RequestParam("file") MultipartFile file){
+        patrolInspectionSiteService.patrolInspectionSiteImport(file);
+        return ApiResult.success();
+    }
 }
 

+ 10 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/DemReportInfo.java

@@ -77,5 +77,15 @@ public class DemReportInfo implements Serializable {
      */
     private LocalDateTime sendTime;
 
+    /**
+     * 是否已读
+     */
+    private Integer isRead;
+
+    /**
+     * 读取时间
+     */
+    private LocalDateTime readTime;
+
 
 }

+ 21 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/domain/ReportResult.java

@@ -1,10 +1,15 @@
 package com.usky.fire.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+
 import java.time.LocalDate;
+
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+
 import java.time.LocalDateTime;
 import java.io.Serializable;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
@@ -78,5 +83,21 @@ public class ReportResult implements Serializable {
      */
     private Integer tenantId;
 
+    /**
+     * 报告状态
+     */
+    @TableField(exist = false)
+    private Integer reportStatus;
 
+    /**
+     * 阅读时间
+     */
+    @TableField(exist = false)
+    private LocalDateTime readTime;
+
+    /**
+     * 是否已读
+     */
+    @TableField(exist = false)
+    private Integer isRead;
 }

+ 4 - 1
service-fire/service-fire-biz/src/main/java/com/usky/fire/mapper/PatrolInspectionSiteMapper.java

@@ -2,8 +2,11 @@ package com.usky.fire.mapper;
 
 import com.usky.common.mybatis.core.CrudMapper;
 import com.usky.fire.domain.PatrolInspectionSite;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 /**
  * <p>
  * Mapper 接口
@@ -14,5 +17,5 @@ import org.springframework.stereotype.Repository;
  */
 @Repository
 public interface PatrolInspectionSiteMapper extends CrudMapper<PatrolInspectionSite> {
-
+    int selectSiteCount(@Param("ids") List<Integer> ids);
 }

+ 7 - 1
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/DemReportInfoService.java

@@ -26,7 +26,7 @@ public interface DemReportInfoService extends CrudService<DemReportInfo> {
      * @param pageSize     每页条数
      * @return
      */
-    CommonPage<DemReportInfo> reportInfoList(String companyId, String sourceType,Integer pageNum, Integer pageSize);
+    CommonPage<DemReportInfo> reportInfoList(String companyId, String sourceType, Integer pageNum, Integer pageSize);
 
     /**
      * 生成报告单位信息-列表查询
@@ -51,4 +51,10 @@ public interface DemReportInfoService extends CrudService<DemReportInfo> {
      * @return
      */
     List<DemReportInfo> reportById(Integer id);
+
+    /**
+     * 批量更新已读状态
+     * @param id 主键ID
+     */
+    void updateReadStatus(Integer id);
 }

+ 5 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/PatrolInspectionSiteService.java

@@ -6,6 +6,7 @@ import com.usky.fire.domain.PatrolInspectionSite;
 import com.usky.fire.domain.PatrolInspectionSiteContent;
 import com.usky.fire.service.vo.PatrolInspectionAreaVo;
 import com.usky.fire.service.vo.PatrolInspectionSiteExportVo;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -43,4 +44,8 @@ public interface PatrolInspectionSiteService extends CrudService<PatrolInspectio
      */
     List<Integer> siteIdList(List<Integer> areaIdList);
 
+    void patrolInspectionSiteImport(MultipartFile multipartFile);
+
+    int siteCount(List<Integer> ids);
+
 }

+ 92 - 9
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/DemReportInfoServiceImpl.java

@@ -1,21 +1,26 @@
 package com.usky.fire.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.fire.domain.BaseCompany;
-import com.usky.fire.domain.BaseCompanyAttach1;
 import com.usky.fire.domain.DemReportInfo;
+import com.usky.fire.mapper.BaseCompanyMapper;
 import com.usky.fire.mapper.DemReportInfoMapper;
 import com.usky.fire.service.DemReportInfoService;
 import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.fire.service.vo.CompanyDataVo;
 import com.usky.fire.service.vo.DemReportInfoIdVo;
 import com.usky.fire.service.vo.DemReportInfoVo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -30,21 +35,53 @@ import java.util.*;
  * @author han
  * @since 2023-03-02
  */
+@Slf4j
 @Service
 public class DemReportInfoServiceImpl extends AbstractCrudService<DemReportInfoMapper, DemReportInfo> implements DemReportInfoService {
+
+    @Autowired
+    private BaseCompanyMapper baseCompanyMapper;
+
     @Override
-    public CommonPage<DemReportInfo> reportInfoList(String companyId,String sourceType,Integer pageNum, Integer pageSize) {
+    public CommonPage<DemReportInfo> reportInfoList(String companyId, String sourceType, Integer pageNum, Integer pageSize) {
         IPage<DemReportInfo> page = new Page<>(pageNum, pageSize);
+
+        String organization = null;
+        try {
+            organization = SecurityUtils.getLoginUser().getSysUser().getRemark();
+        } catch (Exception e) {
+            log.error("获取remake失败", e);
+            return ToCommonPage(page);
+        }
+
+        if (StringUtils.isBlank(organization)) {
+            throw new BusinessException("当前登录账号非消防重点单位,请联系管理员!");
+        }
+
+        LambdaQueryWrapper<BaseCompany> queryWrapper3 = Wrappers.lambdaQuery();
+        queryWrapper3.select(BaseCompany::getCompanyId)
+                .eq(BaseCompany::getOrganization, organization);
+        String companyId1 = null;
+        try {
+            companyId1 = baseCompanyMapper.selectOne(queryWrapper3).getCompanyId();
+        } catch (Exception e) {
+            return ToCommonPage(page);
+        }
+
+        if (StringUtils.isBlank(companyId)) {
+            companyId = companyId1;
+        }
+
         LambdaQueryWrapper<DemReportInfo> queryWrapper = Wrappers.lambdaQuery();
-        if ("2".equals(sourceType)){
-            queryWrapper.eq(StringUtils.isNotBlank(companyId), DemReportInfo::getCompanyId, companyId)
-                    .eq(DemReportInfo::getReportStatus, 1)
-                    .orderByDesc(DemReportInfo::getId);
-        }else {
-            queryWrapper.eq(StringUtils.isNotBlank(companyId), DemReportInfo::getCompanyId, companyId)
+        queryWrapper.eq(DemReportInfo::getCompanyId, companyId);
+        if ("2".equals(sourceType)) {
+            queryWrapper.eq(DemReportInfo::getReportStatus, 1)
                     .orderByDesc(DemReportInfo::getId);
+        } else {
+            queryWrapper.orderByDesc(DemReportInfo::getId);
         }
         page = this.page(page, queryWrapper);
+
         return ToCommonPage(page);
     }
 
@@ -62,7 +99,7 @@ public class DemReportInfoServiceImpl extends AbstractCrudService<DemReportInfoM
             LambdaQueryWrapper<DemReportInfo> queryWrapper1 = Wrappers.lambdaQuery();
             queryWrapper1.select(DemReportInfo::getId, DemReportInfo::getCompanyId)
                     .in(DemReportInfo::getCompanyId, companyIdList)
-                    .eq(DemReportInfo::getStatisticsTime, now.get(Calendar.YEAR)+"-"+now.get(Calendar.MONTH)).groupBy(DemReportInfo::getCompanyId);
+                    .eq(DemReportInfo::getStatisticsTime, now.get(Calendar.YEAR) + "-" + now.get(Calendar.MONTH)).groupBy(DemReportInfo::getCompanyId);
             list2 = this.list(queryWrapper1);
             for (int i = 0; i < companyList.size(); i++) {
                 for (int j = 0; j < list2.size(); j++) {
@@ -102,4 +139,50 @@ public class DemReportInfoServiceImpl extends AbstractCrudService<DemReportInfoM
         List<DemReportInfo> list2 = this.list(queryWrapper1);
         return list2;
     }
+
+    @Override
+    public void updateReadStatus(Integer id) {
+        String remark = null;
+        try {
+            remark = SecurityUtils.getLoginUser().getSysUser().getRemark();
+        } catch (NullPointerException e) {
+            log.error("获取remake失败", e);
+            return;
+        }
+
+        String companyId = null;
+        LambdaQueryWrapper<BaseCompany> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(BaseCompany::getCompanyId)
+                .eq(BaseCompany::getOrganization, remark);
+        BaseCompany baseCompany = baseCompanyMapper.selectOne(queryWrapper);
+        if (baseCompany != null) {
+            companyId = baseCompany.getCompanyId();
+        } else {
+            log.warn("未查询到与组织[{}]匹配的公司信息", remark);
+            return;
+        }
+
+        DemReportInfo report = this.getOne(Wrappers.<DemReportInfo>lambdaQuery()
+                .eq(DemReportInfo::getId, id));
+        if (report == null) {
+            log.warn("报告ID[{}]不存在,无法更新已读状态", id);
+            return;
+        }
+
+        String reportCompanyId = report.getCompanyId();
+        if (!Objects.equals(reportCompanyId, companyId)) {
+            log.warn("报告ID[{}]所属公司[{}]与当前用户公司[{}]不匹配,无权限更新",
+                    id, reportCompanyId, companyId);
+            return;
+        }
+
+        if (report.getIsRead() == 0) {
+            report.setReadTime(LocalDateTime.now());
+            report.setIsRead(1);
+            this.updateById(report);
+            log.info("报告ID[{}]已更新为已读状态", id);
+        } else {
+            log.info("报告ID[{}]非第一次阅读,无需更新", id);
+        }
+    }
 }

+ 20 - 4
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionAreaServiceImpl.java

@@ -9,7 +9,9 @@ import com.usky.common.core.exception.BusinessException;
 import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.common.security.utils.SecurityUtils;
 import com.usky.fire.domain.PatrolInspectionArea;
+import com.usky.fire.domain.PatrolInspectionSite;
 import com.usky.fire.mapper.PatrolInspectionAreaMapper;
+import com.usky.fire.mapper.PatrolInspectionSiteMapper;
 import com.usky.fire.service.BaseCompanyService;
 import com.usky.fire.service.PatrolInspectionAreaService;
 import com.usky.fire.service.vo.PatrolInspectionAreaVo;
@@ -42,6 +44,9 @@ public class PatrolInspectionAreaServiceImpl extends AbstractCrudService<PatrolI
     @Autowired
     private RemoteDeptService remoteDeptService;
 
+    @Autowired
+    private PatrolInspectionSiteMapper patrolInspectionSiteMapper;
+
     /**
      * 巡查自检-巡检区域-新增
      *
@@ -161,18 +166,29 @@ public class PatrolInspectionAreaServiceImpl extends AbstractCrudService<PatrolI
         LambdaQueryWrapper<PatrolInspectionArea> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.eq(PatrolInspectionArea::getEnable, 1).eq(PatrolInspectionArea::getAreaFid, id);
         List<PatrolInspectionArea> patrolInspectionArealist = this.list(queryWrapper);
+        List<Integer> areaIdList = new ArrayList<>();
+        int siteNum = 0;
         if (null != patrolInspectionArealist && !patrolInspectionArealist.isEmpty()) {
+            for (int j = 0; j < patrolInspectionArealist.size(); j++) {
+                areaIdList.add(patrolInspectionArealist.get(j).getId());
+            }
+            areaIdList.add(id);
+            siteNum = patrolInspectionSiteMapper.selectSiteCount(areaIdList);
+        }
+        if (siteNum>0){
             for (int i = 0; i < patrolInspectionArealist.size(); i++) {
                 PatrolInspectionArea patrolInspectionAreaz = new PatrolInspectionArea();
                 patrolInspectionAreaz.setId(patrolInspectionArealist.get(i).getId());
                 patrolInspectionAreaz.setEnable(0);
                 this.updateById(patrolInspectionAreaz);
             }
+            PatrolInspectionArea patrolInspectionArea = new PatrolInspectionArea();
+            patrolInspectionArea.setId(id);
+            patrolInspectionArea.setEnable(0);
+            this.updateById(patrolInspectionArea);
+        }else {
+            throw new BusinessException("区域下有绑定的点位,请解绑后再删除!");
         }
-        PatrolInspectionArea patrolInspectionArea = new PatrolInspectionArea();
-        patrolInspectionArea.setId(id);
-        patrolInspectionArea.setEnable(0);
-        this.updateById(patrolInspectionArea);
     }
 
     /**

+ 1 - 2
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionContentServiceImpl.java

@@ -102,8 +102,7 @@ public class PatrolInspectionContentServiceImpl extends AbstractCrudService<Patr
                 PatrolInspectionContentOption contentOption = new PatrolInspectionContentOption();
                 contentOption.setOptionName(patrolInspectionContentVo.getContentOptionList().get(i).getOptionName());
                 contentOption.setContentId(patrolInspectionContentVo.getId());
-                if (patrolInspectionContentVo.getContentOptionList().get(i).getId() != 0 &&
-                        patrolInspectionContentVo.getContentOptionList().get(i).getId() != null) {
+                if (patrolInspectionContentVo.getContentOptionList().get(i).getId() != null && patrolInspectionContentVo.getContentOptionList().get(i).getId() != 0) {
                     contentOption.setId(patrolInspectionContentVo.getContentOptionList().get(i).getId());
                     contentOption.setEnable(1);
                     contentOptionService.updateById(contentOption);

+ 12 - 12
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionPlanServiceImpl.java

@@ -291,12 +291,12 @@ public class PatrolInspectionPlanServiceImpl extends AbstractCrudService<PatrolI
     @Override
     @Transactional
     public void updatePatrolInspectionPlan(PatrolInspectionPlanVo patrolInspectionPlanVo) {
-        LambdaQueryWrapper<PatrolInspectionRecord> queryWrapperSix = Wrappers.lambdaQuery();
-        queryWrapperSix.eq(PatrolInspectionRecord::getPlanId, patrolInspectionPlanVo.getId());
-        List<PatrolInspectionRecord> patrolInspectionRecordList = patrolInspectionRecordService.list(queryWrapperSix);
-        if (patrolInspectionRecordList.size() > 0) {
-            throw new BusinessException("巡检计划已执行中不可修改");
-        }
+//        LambdaQueryWrapper<PatrolInspectionRecord> queryWrapperSix = Wrappers.lambdaQuery();
+//        queryWrapperSix.eq(PatrolInspectionRecord::getPlanId, patrolInspectionPlanVo.getId());
+//        List<PatrolInspectionRecord> patrolInspectionRecordList = patrolInspectionRecordService.list(queryWrapperSix);
+//        if (patrolInspectionRecordList.size() > 0) {
+//            throw new BusinessException("巡检计划已执行中不可修改");
+//        }
         Integer planCycle = patrolInspectionPlanVo.getPlanCycle();
         String timeStr = patrolInspectionPlanVo.getStartDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
         Date startDate = OnlineMethod.getDate(timeStr);
@@ -575,12 +575,12 @@ public class PatrolInspectionPlanServiceImpl extends AbstractCrudService<PatrolI
     @Override
     @Transactional
     public void delPatrolInspectionPlan(Integer id) {
-        LambdaQueryWrapper<PatrolInspectionRecord> queryWrapperSix = Wrappers.lambdaQuery();
-        queryWrapperSix.eq(PatrolInspectionRecord::getPlanId, id);
-        List<PatrolInspectionRecord> patrolInspectionRecordList = patrolInspectionRecordService.list(queryWrapperSix);
-        if (patrolInspectionRecordList.size() > 0) {
-            throw new BusinessException("巡检计划已执行中不可删除");
-        }
+//        LambdaQueryWrapper<PatrolInspectionRecord> queryWrapperSix = Wrappers.lambdaQuery();
+//        queryWrapperSix.eq(PatrolInspectionRecord::getPlanId, id);
+//        List<PatrolInspectionRecord> patrolInspectionRecordList = patrolInspectionRecordService.list(queryWrapperSix);
+//        if (patrolInspectionRecordList.size() > 0) {
+//            throw new BusinessException("巡检计划已执行中不可删除");
+//        }
         PatrolInspectionPlan patrolInspectionPlan = new PatrolInspectionPlan();
         patrolInspectionPlan.setId(id);
         patrolInspectionPlan.setEnable(0);

+ 2 - 2
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionRecordServiceImpl.java

@@ -276,7 +276,7 @@ public class PatrolInspectionRecordServiceImpl extends AbstractCrudService<Patro
         }
         List<Integer> planSonidListTwo = this.getPlanSon(null, null);
         if (planSonidListTwo.size() > 0) {
-            siteCount = this.getPlanSiteSonCount(planSonidListTwo, 0);
+            siteCount = this.getPlanSiteSonCount(planSonidListTwo, 2);
             siteCountLeak = this.getPlanSiteSonCount(planSonidListTwo, 1);
         }
         RecordStatisticsVo recordStatisticsVo = new RecordStatisticsVo();
@@ -300,7 +300,7 @@ public class PatrolInspectionRecordServiceImpl extends AbstractCrudService<Patro
     public Integer getPlanSiteSonCount(List<Integer> planSonidList, Integer inspectionStatus) {
         LambdaQueryWrapper<PatrolInspectionPlanSiteSon> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.in(PatrolInspectionPlanSiteSon::getPlanId, planSonidList);
-        if (inspectionStatus != 0 && inspectionStatus != null) {
+        if (inspectionStatus.equals(1)||inspectionStatus.equals(2)){
             queryWrapper.eq(PatrolInspectionPlanSiteSon::getInspectionStatus, inspectionStatus);
         }
         Integer taskCount = planSiteSonService.count(queryWrapper);

+ 77 - 14
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/PatrolInspectionSiteServiceImpl.java

@@ -1,12 +1,15 @@
 package com.usky.fire.service.impl;
 
-import com.alibaba.nacos.common.utils.CollectionUtils;
+import cn.afterturn.easypoi.excel.ExcelImportUtil;
+import cn.afterturn.easypoi.excel.entity.ImportParams;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.common.datascope.annotation.DataScope;
 import com.ruoyi.common.datascope.context.DataScopeContextHolder;
 import com.usky.common.core.bean.CommonPage;
 import com.usky.common.core.exception.BusinessException;
+import com.usky.common.core.util.BeanMapperUtils;
 import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.common.security.utils.SecurityUtils;
 import com.usky.fire.domain.*;
@@ -19,17 +22,18 @@ import com.usky.fire.service.util.OnlineMethod;
 import com.usky.fire.service.vo.DataCountVo;
 import com.usky.fire.service.vo.PatrolInspectionAreaVo;
 import com.usky.fire.service.vo.PatrolInspectionSiteExportVo;
+import com.usky.fire.service.vo.PatrolInspectionSiteImportVo;
 import com.usky.system.model.LoginUser;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -194,16 +198,24 @@ public class PatrolInspectionSiteServiceImpl extends AbstractCrudService<PatrolI
     @Override
     @Transactional
     public void addSiteContent(List<PatrolInspectionSiteContent> siteContentList) {
-        LambdaQueryWrapper<PatrolInspectionSiteContent> queryWrapper = Wrappers.lambdaQuery();
-        queryWrapper.eq(PatrolInspectionSiteContent::getSiteId, siteContentList.get(0).getSiteId());
-        List<PatrolInspectionSiteContent> siteContenListOne = siteContentService.list(queryWrapper);
-        if (siteContenListOne.size() > 0) {
-            for (int i = 0; i < siteContenListOne.size(); i++) {
-                siteContentService.removeById(siteContenListOne.get(i).getId());
+        List<Integer> list = new ArrayList<>();
+        List<Integer> list2 = new ArrayList<>();
+        if (siteContentList.size()>0){
+            for (int i = 0; i < siteContentList.size(); i++) {
+                list.add(siteContentList.get(i).getSiteId());
+            }
+            list2 = removeDuplicatesUsingHashSet(list);
+            LambdaQueryWrapper<PatrolInspectionSiteContent> queryWrapper = Wrappers.lambdaQuery();
+            queryWrapper.in(PatrolInspectionSiteContent::getSiteId, list2);
+            List<PatrolInspectionSiteContent> siteContenListOne = siteContentService.list(queryWrapper);
+            if (siteContenListOne.size() > 0) {
+                for (int i = 0; i < siteContenListOne.size(); i++) {
+                    siteContentService.removeById(siteContenListOne.get(i).getId());
+                }
+            }
+            for (int i = 0; i < siteContentList.size(); i++) {
+                siteContentService.save(siteContentList.get(i));
             }
-        }
-        for (int i = 0; i < siteContentList.size(); i++) {
-            siteContentService.save(siteContentList.get(i));
         }
     }
 
@@ -285,4 +297,55 @@ public class PatrolInspectionSiteServiceImpl extends AbstractCrudService<PatrolI
         }
         return siteIdList;
     }
+
+    @Override
+    public void patrolInspectionSiteImport(MultipartFile multipartFile) {
+        ImportParams params = new ImportParams();
+        params.setHeadRows(1);
+        String err="文件导入失败";
+        try {
+            List<PatrolInspectionSiteImportVo> patrolInspectionSiteImportVos =
+                    ExcelImportUtil.importExcel(multipartFile.getInputStream(),
+                    PatrolInspectionSiteImportVo.class, params);
+            if (CollectionUtils.isNotEmpty(patrolInspectionSiteImportVos)){
+                int rot=0;
+                for (PatrolInspectionSiteImportVo patrolInspectionSiteImportVo:patrolInspectionSiteImportVos) {
+                    PatrolInspectionSite patrolInspectionSite = BeanMapperUtils.map(patrolInspectionSiteImportVo, PatrolInspectionSite.class);
+                    patrolInspectionSite.setEnable(1);
+                    patrolInspectionSite.setCreator(SecurityUtils.getUsername());
+                    patrolInspectionSite.setCollector(SecurityUtils.getLoginUser().getSysUser().getNickName());
+                    patrolInspectionSite.setCreateTime(LocalDateTime.now());
+                    patrolInspectionSite.setTenantId(SecurityUtils.getTenantId());
+                    patrolInspectionSite.setSiteType(2);
+                    try{
+                        this.save(patrolInspectionSite);
+                    }catch (Exception e){
+                        int h=rot+2;
+                        err="文件导入失败,第"+h+"行数据导入失败";
+                        throw  new BusinessException(err);
+                    }
+                    rot++;
+                }
+            }else {
+                err="文件不能为空";
+                throw new BusinessException(err);
+            }
+        }catch (Exception e){
+            throw  new BusinessException(e.getMessage());
+        }
+    }
+    public static <T> List<T> removeDuplicatesUsingHashSet(List<T> list) {
+        Set<T> set = new HashSet<>(list);
+        return new ArrayList<>(set);
+    }
+
+    @Override
+    public int siteCount(List<Integer> ids){
+        LambdaQueryWrapper<PatrolInspectionSite> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(PatrolInspectionSite::getEnable, 1)
+                .in(PatrolInspectionSite::getAreaId, ids);
+        int siteCounts = this.count(queryWrapper);
+        List<Integer> siteIdList = new ArrayList<>();
+        return siteCounts;
+    }
 }

+ 68 - 12
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/impl/ReportResultServiceImpl.java

@@ -6,9 +6,9 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.usky.common.core.bean.CommonPage;
-import com.usky.fire.domain.BaseCompanyPerson;
-import com.usky.fire.domain.ReportConfig;
-import com.usky.fire.domain.ReportResult;
+import com.usky.fire.domain.*;
+import com.usky.fire.mapper.BaseCompanyMapper;
+import com.usky.fire.mapper.DemReportInfoMapper;
 import com.usky.fire.mapper.ReportResultMapper;
 import com.usky.fire.service.ReportConfigService;
 import com.usky.fire.service.ReportResultService;
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -33,23 +34,78 @@ import java.util.Map;
 public class ReportResultServiceImpl extends AbstractCrudService<ReportResultMapper, ReportResult> implements ReportResultService {
     @Autowired
     private ReportConfigService reportConfigService;
+    @Autowired
+    private BaseCompanyMapper baseCompanyMapper;
+    @Autowired
+    private DemReportInfoMapper demReportInfoMapper;
 
     @Override
-    public CommonPage<ReportResult> reportResultList(Integer companyId, String sourceType, Integer pageNum,
-                                                     Integer pageSize) {
-        IPage<ReportResult> page = new Page<>(pageNum, pageSize);
+    public CommonPage<ReportResult> reportResultList(Integer companyId, String sourceType, Integer pageNum, Integer pageSize) {
+        Page<ReportResult> page = new Page<>(pageNum, pageSize);
+
         LambdaQueryWrapper<ReportResult> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.eq(ReportResult::getObjectId, companyId)
-                    .orderByDesc(ReportResult::getId);
-        page = this.page(page, queryWrapper);
-        return ToCommonPage(page);
+                .orderByDesc(ReportResult::getId);
+        IPage<ReportResult> resultPage = this.page(page, queryWrapper);
+        List<ReportResult> resultList = resultPage.getRecords();
+
+        List<Integer> objectIdList = resultList.stream()
+                .map(ReportResult::getObjectId)
+                .distinct()
+                .collect(Collectors.toList());
+
+        if (objectIdList.isEmpty()) {
+            return ToCommonPage(resultPage);
+        }
+
+        LambdaQueryWrapper<BaseCompany> baseCompanyQuery = Wrappers.lambdaQuery();
+        baseCompanyQuery.select(BaseCompany::getId, BaseCompany::getCompanyId)
+                .in(BaseCompany::getId, objectIdList);
+        List<BaseCompany> baseCompanyList = baseCompanyMapper.selectList(baseCompanyQuery);
+
+        List<String> companyIdList = baseCompanyList.stream()
+                .map(BaseCompany::getCompanyId)
+                .distinct()
+                .collect(Collectors.toList());
+
+        if (companyIdList.isEmpty()) {
+            return ToCommonPage(resultPage);
+        }
+
+        LambdaQueryWrapper<DemReportInfo> demReportQuery = Wrappers.lambdaQuery();
+        demReportQuery.select(DemReportInfo::getIsRead, DemReportInfo::getReadTime, DemReportInfo::getCompanyId, DemReportInfo::getReportStatus)
+                .in(DemReportInfo::getCompanyId, companyIdList);
+        List<DemReportInfo> demReportInfoList = demReportInfoMapper.selectList(demReportQuery);
+
+        Map<String, DemReportInfo> demReportMap = demReportInfoList.stream()
+                .collect(Collectors.toMap(DemReportInfo::getCompanyId, info -> info, (existing, replacement) -> existing));
+
+        Map<Integer, String> baseCompanyMap = baseCompanyList.stream()
+                .collect(Collectors.toMap(BaseCompany::getId, BaseCompany::getCompanyId, (existing, replacement) -> existing));
+
+        for (ReportResult reportResult : resultList) {
+            Integer objectId = reportResult.getObjectId();
+            String relatedCompanyId = baseCompanyMap.get(objectId);
+
+            if (relatedCompanyId != null) {
+                DemReportInfo demReportInfo = demReportMap.get(relatedCompanyId);
+                if (demReportInfo != null) {
+                    reportResult.setReportStatus(demReportInfo.getReportStatus());
+                    reportResult.setReadTime(demReportInfo.getReadTime());
+                    reportResult.setIsRead(demReportInfo.getIsRead());
+                }
+            }
+        }
+
+        return ToCommonPage(resultPage);
     }
+
     @Override
     public CommonPage<Object> newReportResultList(String reportObject, Integer pageNum, Integer pageSize) {
         List<Object> list = new ArrayList<>();
         IPage<ReportResult> page = new Page<>(pageNum, pageSize);
         LambdaQueryWrapper<ReportResult> queryWrapper = Wrappers.lambdaQuery();
-        queryWrapper.like(StringUtils.isNotBlank(reportObject),ReportResult::getReportObject, reportObject)
+        queryWrapper.like(StringUtils.isNotBlank(reportObject), ReportResult::getReportObject, reportObject)
                 .orderByDesc(ReportResult::getId);
         page = this.page(page, queryWrapper);
         LambdaQueryWrapper<ReportConfig> queryWrapper1 = Wrappers.lambdaQuery();
@@ -61,8 +117,8 @@ public class ReportResultServiceImpl extends AbstractCrudService<ReportResultMap
                 map.put("reportObject", page.getRecords().get(i).getReportObject());
                 map.put("overallScore", page.getRecords().get(i).getOverallScore());
                 map.put("createDate", page.getRecords().get(i).getCreateDate());
-                for (int j = 0; j < list1.size(); j++){
-                    if (page.getRecords().get(i).getConfigId().equals(list1.get(j).getId())){
+                for (int j = 0; j < list1.size(); j++) {
+                    if (page.getRecords().get(i).getConfigId().equals(list1.get(j).getId())) {
                         map.put("reportName", list1.get(j).getReportName());
                     }
                 }

+ 51 - 0
service-fire/service-fire-biz/src/main/java/com/usky/fire/service/vo/PatrolInspectionSiteImportVo.java

@@ -0,0 +1,51 @@
+package com.usky.fire.service.vo;
+
+import cn.afterturn.easypoi.excel.annotation.Excel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author han
+ * @since 2025-04-24
+ */
+@Data
+public class PatrolInspectionSiteImportVo{
+
+    /**
+     * 地点名称
+     */
+    @Excel(name = "地点名称")
+    private String siteName;
+
+    /**
+     * 地点号码
+     */
+    @Excel(name = "地点号码")
+    private String siteNubmber;
+
+    /**
+     * 经度
+     */
+    @Excel(name = "经度")
+    private String longitude;
+
+    /**
+     * 纬度
+     */
+    @Excel(name = "纬度")
+    private String latitude;
+
+    /**
+     * 图片地址
+     */
+    @Excel(name = "图片地址")
+    private String pictureUrl;
+
+}

+ 10 - 0
service-fire/service-fire-biz/src/main/resources/mapper/fire/PatrolInspectionSiteMapper.xml

@@ -23,4 +23,14 @@
         <result column="company_id" property="companyId" />
     </resultMap>
 
+    <select id="selectSiteCount" resultType="java.lang.Integer">
+        select count(*)
+        from patrol_inspection_site AS a
+        <where>
+            <if test="ids != null">
+                and a.area_id in #{ids}
+            </if>
+        </where>
+    </select>
+
 </mapper>

+ 20 - 0
service-ids/pom.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>usky-modules</artifactId>
+        <groupId>com.usky</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>service-ids</artifactId>
+
+    <packaging>pom</packaging>
+    <version>0.0.1</version>
+
+    <modules>
+        <module>service-ids-biz</module>
+        <module>service-ids-api</module>
+    </modules>
+</project>

+ 27 - 0
service-ids/service-ids-api/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>service-ids</artifactId>
+        <groupId>com.usky</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>service-ids-api</artifactId>
+    <!-- SpringCloud Openfeign -->
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>usky-common-core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>

+ 89 - 0
service-ids/service-ids-biz/pom.xml

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>service-ids</artifactId>
+        <groupId>com.usky</groupId>
+        <version>0.0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>service-ids-biz</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>common-cloud-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-spring-boot-starter</artifactId>
+            <version>4.1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.5.16</version>
+        </dependency>
+
+        <!--语音依赖-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dyvmsapi</artifactId>
+            <version>1.2.2</version>
+        </dependency>
+
+        <!--短信依赖-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+            <version>1.1.0</version>
+        </dependency>
+
+        <!--MQTT依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-integration</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.integration</groupId>
+            <artifactId>spring-integration-mqtt</artifactId>
+        </dependency>
+        <!--websocket依赖-->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-websocket</artifactId>
+            <version>5.2.8.RELEASE</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.github.shalousun</groupId>
+                <artifactId>smart-doc-maven-plugin</artifactId>
+                <version>2.1.1</version>
+                <configuration>
+                    <!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
+                    <configFile>./src/main/resources/smart-doc.json</configFile>
+                    <!--指定项目名称-->
+                    <projectName>test</projectName>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 45 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/RuoYiSystemApplication.java

@@ -0,0 +1,45 @@
+package com.usky.ids;
+
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * 系统模块
+ * 
+ * @author ruoyi
+ */
+
+
+@EnableFeignClients(basePackages = "com.usky")
+@MapperScan(value = "com.usky.ids.mapper")
+@ComponentScan("com.usky")
+@SpringBootApplication
+public class RuoYiSystemApplication
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger(RuoYiSystemApplication.class);
+
+    public static void main(String[] args) throws UnknownHostException {
+        ConfigurableApplicationContext application = SpringApplication.run(RuoYiSystemApplication.class, args);
+        Environment env = application.getEnvironment();
+        String ip = InetAddress.getLocalHost().getHostAddress();
+        String port = env.getProperty("server.port");
+        String path = env.getProperty("server.servlet.context-path");
+        LOGGER.info("\n----------------------------------------------------------\n\t" +
+                "Application is running! Access URLs:\n\t" +
+                "Local: \t\thttp://localhost:" + port + (null==path?"":path) + "/\n\t" +
+                "External: \thttp://" + ip + ":" + port + (null==path?"":path) + "/\n\t" +
+                "Api: \t\thttp://" + ip + ":" + port + (null==path?"":path) + "/swagger-ui/index.html\n\t" +
+                "----------------------------------------------------------");
+    }
+}

+ 109 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/MybatisGeneratorUtils.java

@@ -0,0 +1,109 @@
+package com.usky.ids.controller;//package com.usky.iot.controller;//package com.usky.dm.controller.web.business;
+// package com.usky.dm.controller.web;
+
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.generator.AutoGenerator;
+import com.baomidou.mybatisplus.generator.InjectionConfig;
+import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author han
+ * @date 2025/1/18 13:19
+ */
+public class MybatisGeneratorUtils {
+    public static void main(String[] args) {
+
+            shell("service-ids","service-ids-biz");
+    }
+
+    private static void shell(String parentName,String model) {
+
+        AutoGenerator mpg = new AutoGenerator();
+        //1、全局配置
+        GlobalConfig gc = new GlobalConfig();
+//        File file = new File(model);
+//        String path = file.getAbsolutePath();
+        String projectPath = System.getProperty("user.dir");
+        projectPath+="/"+parentName;
+        projectPath+="/"+model;
+        gc.setOutputDir(projectPath+ "/src/main/java");  //生成路径(一般都是生成在此项目的src/main/java下面)
+        //修改为自己的名字
+        gc.setAuthor("han"); //设置作者
+        gc.setOpen(false);
+        gc.setFileOverride(true); //第二次生成会把第一次生成的覆盖掉
+        gc.setServiceName("%sService"); //生成的service接口名字首字母是否为I,这样设置就没有
+        gc.setBaseResultMap(true); //生成resultMap
+        mpg.setGlobalConfig(gc);
+
+        //2、数据源配置
+        //修改数据源
+        DataSourceConfig dsc = new DataSourceConfig();
+        dsc.setUrl("jdbc:mysql://192.168.10.165:3306/usky-cloud?useUnicode=true&serverTimezone=GMT&useSSL=false&characterEncoding=utf8");
+        dsc.setDriverName("com.mysql.jdbc.Driver");
+        dsc.setUsername("root");
+        dsc.setPassword("yt123456");
+        mpg.setDataSource(dsc);
+
+        // 3、包配置
+        PackageConfig pc = new PackageConfig();
+        pc.setParent("com.usky.ids");
+        pc.setController("controller.web");
+        pc.setEntity("domain");
+        pc.setMapper("mapper");
+        pc.setService("service");
+        pc.setServiceImpl("service.impl");
+//        pc.setXml("mapper.demo");
+        //pc.setModuleName("test");
+        mpg.setPackageInfo(pc);
+
+        // 4、策略配置
+        StrategyConfig strategy = new StrategyConfig();
+        strategy.setNaming(NamingStrategy.underline_to_camel);
+        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
+        strategy.setSuperMapperClass("com.usky.common.mybatis.core.CrudMapper");
+        strategy.setSuperServiceClass("com.usky.common.mybatis.core.CrudService");
+        strategy.setSuperServiceImplClass("com.usky.common.mybatis.core.AbstractCrudService");
+        // strategy.setTablePrefix("t_"); // 表名前缀
+        strategy.setEntityLombokModel(true); //使用lombok
+        //修改自己想要生成的表
+        strategy.setInclude("ids_park_map");  // 逆向工程使用的表   如果要生成多个,这里可以传入String[]
+        mpg.setStrategy(strategy);
+
+        // 关闭默认 xml 生成,调整生成 至 根目录
+        //修改对应的模块名称
+        TemplateConfig tc = new TemplateConfig();
+        // 自定义配置
+        InjectionConfig cfg = new InjectionConfig() {
+            @Override
+            public void initMap() {
+                // to do nothing
+            }
+        };
+        //如果模板引擎是 velocity
+        String templatePath = "/templates/mapper.xml.vm";
+        // 自定义输出配置
+        List<FileOutConfig> focList = new ArrayList<>();
+        // 自定义配置会被优先输出
+        String finalProjectPath = projectPath;
+        focList.add(new FileOutConfig(templatePath) {
+            @Override
+            public String outputFile(TableInfo tableInfo) {
+                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
+                return finalProjectPath + "/src/main/resources/mapper/ids" + "/"
+                        + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
+            }
+        });
+        cfg.setFileOutConfigList(focList);
+        mpg.setCfg(cfg);
+        tc.setXml(null);
+        mpg.setTemplate(tc);
+        //5、执行
+        mpg.execute();
+    }
+}

+ 21 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/web/AccessAlarmController.java

@@ -0,0 +1,21 @@
+package com.usky.ids.controller.web;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 报警信息表 前端控制器
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-10
+ */
+@Controller
+@RequestMapping("/accessAlarm")
+public class AccessAlarmController {
+
+}
+

+ 21 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/web/AccessEntryExitRecordController.java

@@ -0,0 +1,21 @@
+package com.usky.ids.controller.web;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.stereotype.Controller;
+
+/**
+ * <p>
+ * 车辆进出记录 前端控制器
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-26
+ */
+@Controller
+@RequestMapping("/accessEntryExitRecord")
+public class AccessEntryExitRecordController {
+
+}
+

+ 39 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/controller/web/IdsParkMapController.java

@@ -0,0 +1,39 @@
+package com.usky.ids.controller.web;
+
+
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.ids.domain.IdsParkMap;
+import com.usky.ids.service.IdsParkMapService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author han
+ * @since 2025-01-18
+ */
+@RestController
+@RequestMapping("/idsParkMap")
+public class IdsParkMapController {
+    @Autowired
+    private IdsParkMapService idsParkMapService;
+    /**
+     * 获取车位信息
+     * @return
+     */
+    @GetMapping("mapList")
+    ApiResult<Object> mapList(){
+        return ApiResult.success(idsParkMapService.mapList());
+    }
+}
+

+ 141 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/domain/AccessAlarm.java

@@ -0,0 +1,141 @@
+package com.usky.ids.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 报警信息表
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-10
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class AccessAlarm implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 报警ID
+     */
+    @TableId(value = "alarm_id", type = IdType.AUTO)
+    private Long alarmId;
+
+    /**
+     * 报警等级
+     */
+    private String alarmLevel;
+
+    /**
+     * 报警详情
+     */
+    private String alarmDetails;
+
+    /**
+     * 报警位置
+     */
+    private String alarmLocation;
+
+    /**
+     * 报警区域
+     */
+    private String regionIndexCode;
+
+    /**
+     * 监控点名称
+     */
+    private String cameraName;
+
+    /**
+     * 监控点唯一编码
+     */
+    private String cameraIndexCode;
+
+    /**
+     * 报警来源算法类型
+     */
+    private String alarmSourceAlgorithmType;
+
+    /**
+     * 报警图片 
+     */
+    private String alarmPhoto;
+
+    /**
+     * 报警视频 
+     */
+    private String alarmVideo;
+
+    /**
+     * 报警类型(1车辆违停2车辆拥堵 3车辆违停占道 4吸烟 5人员摔倒 6杂物堆放 7人员聚集 8火焰识别算法)
+     */
+    private String alarmType;
+
+    /**
+     * 状态(0未处理 1已处理)
+     */
+    private String alarmStatus;
+
+    /**
+     * 处理时间
+     */
+    private LocalDateTime processTime;
+
+    /**
+     * 拥堵等级(1绿色 2黄色 3红色)
+     */
+    private Integer congestionLevel;
+
+    /**
+     * 报警时间
+     */
+    private LocalDateTime alarmTime;
+
+    /**
+     * 报警消除时间(算法自动识别)
+     */
+    private LocalDateTime cleanAlarmTime;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 已读状态(0 未读 1 已读)
+     */
+    private String readStatus;
+
+    /**
+     * 已读时间
+     */
+    private LocalDateTime readTime;
+
+
+}

+ 86 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/domain/AccessEntryExitRecord.java

@@ -0,0 +1,86 @@
+package com.usky.ids.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 车辆进出记录
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class AccessEntryExitRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 车辆进出记录ID
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 车辆颜色
+     */
+    private String carColor;
+
+    /**
+     * 车牌
+     */
+    private String licensePlate;
+
+    /**
+     * 进出场类型(1进 2出)
+     */
+    private String actionDirection;
+
+    /**
+     * 监控点唯一编码
+     */
+    private String cameraIndexCode;
+
+    /**
+     * 监控点名称
+     */
+    private String cameraName;
+
+    /**
+     * 进/出场时间
+     */
+    private LocalDateTime recordTime;
+
+    /**
+     * 创建者
+     */
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新者
+     */
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 61 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/domain/IdsParkMap.java

@@ -0,0 +1,61 @@
+package com.usky.ids.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author han
+ * @since 2025-01-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class IdsParkMap implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 楼层车位统计信息
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 楼层名称
+     */
+    private String mapName;
+
+    /**
+     * 使用中数量
+     */
+    private Integer usingCount;
+
+    /**
+     * 空闲数量
+     */
+    private Integer freeCount;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    /**
+     * 租户id
+     */
+    private Integer tenantId;
+
+
+}

+ 16 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/mapper/AccessAlarmMapper.java

@@ -0,0 +1,16 @@
+package com.usky.ids.mapper;
+
+import com.usky.ids.domain.AccessAlarm;
+import com.usky.common.mybatis.core.CrudMapper;
+
+/**
+ * <p>
+ * 报警信息表 Mapper 接口
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-10
+ */
+public interface AccessAlarmMapper extends CrudMapper<AccessAlarm> {
+
+}

+ 16 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/mapper/AccessEntryExitRecordMapper.java

@@ -0,0 +1,16 @@
+package com.usky.ids.mapper;
+
+import com.usky.ids.domain.AccessEntryExitRecord;
+import com.usky.common.mybatis.core.CrudMapper;
+
+/**
+ * <p>
+ * 车辆进出记录 Mapper 接口
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-26
+ */
+public interface AccessEntryExitRecordMapper extends CrudMapper<AccessEntryExitRecord> {
+
+}

+ 16 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/mapper/IdsParkMapMapper.java

@@ -0,0 +1,16 @@
+package com.usky.ids.mapper;
+
+import com.usky.ids.domain.IdsParkMap;
+import com.usky.common.mybatis.core.CrudMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author han
+ * @since 2025-01-18
+ */
+public interface IdsParkMapMapper extends CrudMapper<IdsParkMap> {
+
+}

+ 16 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/AccessAlarmService.java

@@ -0,0 +1,16 @@
+package com.usky.ids.service;
+
+import com.usky.ids.domain.AccessAlarm;
+import com.usky.common.mybatis.core.CrudService;
+
+/**
+ * <p>
+ * 报警信息表 服务类
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-10
+ */
+public interface AccessAlarmService extends CrudService<AccessAlarm> {
+
+}

+ 16 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/AccessEntryExitRecordService.java

@@ -0,0 +1,16 @@
+package com.usky.ids.service;
+
+import com.usky.ids.domain.AccessEntryExitRecord;
+import com.usky.common.mybatis.core.CrudService;
+
+/**
+ * <p>
+ * 车辆进出记录 服务类
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-26
+ */
+public interface AccessEntryExitRecordService extends CrudService<AccessEntryExitRecord> {
+
+}

+ 24 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/IdsParkMapService.java

@@ -0,0 +1,24 @@
+package com.usky.ids.service;
+
+import com.usky.ids.domain.IdsParkMap;
+import com.usky.common.mybatis.core.CrudService;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author han
+ * @since 2025-01-18
+ */
+public interface IdsParkMapService extends CrudService<IdsParkMap> {
+    Object mapList();
+//    /**
+//     * 定时同步智泊反寻系统停车场数据到巡检异常记录表中
+//     *
+//     * @return
+//     */
+//    void addPatrolInspectionAbnormalData();
+}

+ 20 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/impl/AccessAlarmServiceImpl.java

@@ -0,0 +1,20 @@
+package com.usky.ids.service.impl;
+
+import com.usky.ids.domain.AccessAlarm;
+import com.usky.ids.mapper.AccessAlarmMapper;
+import com.usky.ids.service.AccessAlarmService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 报警信息表 服务实现类
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-10
+ */
+@Service
+public class AccessAlarmServiceImpl extends AbstractCrudService<AccessAlarmMapper, AccessAlarm> implements AccessAlarmService {
+
+}

+ 20 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/impl/AccessEntryExitRecordServiceImpl.java

@@ -0,0 +1,20 @@
+package com.usky.ids.service.impl;
+
+import com.usky.ids.domain.AccessEntryExitRecord;
+import com.usky.ids.mapper.AccessEntryExitRecordMapper;
+import com.usky.ids.service.AccessEntryExitRecordService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 车辆进出记录 服务实现类
+ * </p>
+ *
+ * @author han
+ * @since 2025-03-26
+ */
+@Service
+public class AccessEntryExitRecordServiceImpl extends AbstractCrudService<AccessEntryExitRecordMapper, AccessEntryExitRecord> implements AccessEntryExitRecordService {
+
+}

+ 44 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/impl/IdsParkMapServiceImpl.java

@@ -0,0 +1,44 @@
+package com.usky.ids.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.ids.domain.IdsParkMap;
+import com.usky.ids.mapper.IdsParkMapMapper;
+import com.usky.ids.service.IdsParkMapService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.ids.service.util.HttpClientUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author han
+ * @since 2025-01-18
+ */
+@Service
+public class IdsParkMapServiceImpl extends AbstractCrudService<IdsParkMapMapper, IdsParkMap> implements IdsParkMapService {
+    @Override
+    public Object mapList(){
+        HashMap map = new HashMap();
+        map.put("key", "A10001");
+        map.put("timestamp", "20241231111111");
+        map.put("version", "v3.20.0.2");
+        map.put("sign", "f1c0a78dddb4f4591f04b32cc2151ea7");
+        String resultString = HttpClientUtils.doPost("http://172.18.0.25:8180/mpgs/api/v3/parkingLot/getParkingLotInfo",map);
+        JSONObject resultVO = JSONObject.parseObject(resultString);
+        String resultData = resultVO.get("data").toString();
+        JSONObject resultVO1 = JSONObject.parseObject(resultData);
+        Object mapList = resultVO1.get("mapList");
+        System.out.println(mapList);
+        return mapList;
+    }
+}

+ 136 - 0
service-ids/service-ids-biz/src/main/java/com/usky/ids/service/util/HttpClientUtils.java

@@ -0,0 +1,136 @@
+package com.usky.ids.service.util;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ 1. 跨域请求工具类
+ */
+public class HttpClientUtils {
+
+    public static String doGet(String url, Map<String, String> param) {
+
+        // 创建Httpclient对象
+        CloseableHttpClient httpclient = HttpClients.createDefault();
+
+        String resultString = "";
+        CloseableHttpResponse response = null;
+        try {
+            // 创建uri
+            URIBuilder builder = new URIBuilder(url);
+            if (param != null) {
+                for (String key : param.keySet()) {
+                    builder.addParameter(key, param.get(key));
+                }
+            }
+            URI uri = builder.build();
+
+            // 创建http GET请求
+            HttpGet httpGet = new HttpGet(uri);
+
+            // 执行请求
+            response = httpclient.execute(httpGet);
+            // 判断返回状态是否为200
+            if (response.getStatusLine().getStatusCode() == 200) {
+                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (response != null) {
+                    response.close();
+                }
+                httpclient.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return resultString;
+    }
+
+    public static String doGet(String url) {
+        return doGet(url, null);
+    }
+
+    public static String doPost(String url, Map<String, String> param) {
+        // 创建Httpclient对象
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        String resultString = "";
+        try {
+            // 创建Http Post请求
+            HttpPost httpPost = new HttpPost(url);
+            // 创建参数列表
+            if (param != null) {
+                List<NameValuePair> paramList = new ArrayList<>();
+                for (String key : param.keySet()) {
+                    paramList.add(new BasicNameValuePair(key, param.get(key)));
+                }
+                // 模拟表单
+                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
+                httpPost.setEntity(entity);
+            }
+            // 执行http请求
+            response = httpClient.execute(httpPost);
+            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return resultString;
+    }
+
+    public static String doPost(String url) {
+        return doPost(url, null);
+    }
+
+    public static String doPostJson(String url, String json) {
+        // 创建Httpclient对象
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        String resultString = "";
+        try {
+            // 创建Http Post请求
+            HttpPost httpPost = new HttpPost(url);
+            // 创建请求内容
+            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
+            httpPost.setEntity(entity);
+            // 执行http请求
+            response = httpClient.execute(httpPost);
+            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                response.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return resultString;
+    }
+}

+ 25 - 0
service-ids/service-ids-biz/src/main/resources/bootstrap.yml

@@ -0,0 +1,25 @@
+# Tomcat
+server:
+  port: 9892
+
+# Spring
+spring: 
+  application:
+    # 应用名称
+    name: service-ids
+  profiles:
+    # 环境配置
+    active: dev
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: usky-cloud-nacos:8848
+      config:
+        # 配置中心地址
+        server-addr: usky-cloud-nacos:8848
+        # 配置文件格式
+        file-extension: yml
+        # 共享配置
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

+ 94 - 0
service-ids/service-ids-biz/src/main/resources/logback.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <!-- 日志存放路径 -->
+    <property name="log.path" value="/var/log/uskycloud/service-ids" />
+    <!-- 日志输出格式 -->
+    <property name="log.pattern" value="%d{MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{26}:%line: %msg%n" />
+    <!--    	<property name="log.pattern" value="%gray(%d{MM-dd HH:mm:ss.SSS}) %highlight(%-5level) &#45;&#45; [%gray(%thread)] %cyan(%logger{26}:%line): %msg%n" />-->
+
+
+    <property name="SQL_PACKAGE" value="com.usky.ids.mapper"/>
+
+    <!-- 控制台输出 -->
+    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="file_sql" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/sql.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sql.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>3</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 系统日志输出 -->
+    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>3</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 系统模块日志级别控制  -->
+    <!--	<logger name="com.usky" level="info" />-->
+    <!-- Spring日志级别控制  -->
+    <!--	<logger name="org.springframework" level="warn" />-->
+
+    <logger name="${SQL_PACKAGE}" additivity="false" level="debug">
+        <appender-ref ref="console"/>
+        <appender-ref ref="file_sql"/>
+    </logger>
+
+    <!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+        <appender-ref ref="console" />
+    </root>
+</configuration>

+ 32 - 0
service-ids/service-ids-biz/src/main/resources/mapper/ids/AccessAlarmMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.ids.mapper.AccessAlarmMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.ids.domain.AccessAlarm">
+        <id column="alarm_id" property="alarmId" />
+        <result column="alarm_level" property="alarmLevel" />
+        <result column="alarm_details" property="alarmDetails" />
+        <result column="alarm_location" property="alarmLocation" />
+        <result column="region_index_code" property="regionIndexCode" />
+        <result column="camera_name" property="cameraName" />
+        <result column="camera_index_code" property="cameraIndexCode" />
+        <result column="alarm_source_algorithm_type" property="alarmSourceAlgorithmType" />
+        <result column="alarm_photo" property="alarmPhoto" />
+        <result column="alarm_video" property="alarmVideo" />
+        <result column="alarm_type" property="alarmType" />
+        <result column="alarm_status" property="alarmStatus" />
+        <result column="process_time" property="processTime" />
+        <result column="congestion_level" property="congestionLevel" />
+        <result column="alarm_time" property="alarmTime" />
+        <result column="clean_alarm_time" property="cleanAlarmTime" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="remark" property="remark" />
+        <result column="read_status" property="readStatus" />
+        <result column="read_time" property="readTime" />
+    </resultMap>
+
+</mapper>

+ 21 - 0
service-ids/service-ids-biz/src/main/resources/mapper/ids/AccessEntryExitRecordMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.ids.mapper.AccessEntryExitRecordMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.ids.domain.AccessEntryExitRecord">
+        <id column="id" property="id" />
+        <result column="car_color" property="carColor" />
+        <result column="license_plate" property="licensePlate" />
+        <result column="action_direction" property="actionDirection" />
+        <result column="camera_index_code" property="cameraIndexCode" />
+        <result column="camera_name" property="cameraName" />
+        <result column="record_time" property="recordTime" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="remark" property="remark" />
+    </resultMap>
+
+</mapper>

+ 16 - 0
service-ids/service-ids-biz/src/main/resources/mapper/ids/IdsParkMapMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.ids.mapper.IdsParkMapMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.ids.domain.IdsParkMap">
+        <id column="id" property="id" />
+        <result column="map_name" property="mapName" />
+        <result column="using_count" property="usingCount" />
+        <result column="free_count" property="freeCount" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>

+ 15 - 0
service-ids/service-ids-biz/src/main/resources/smart-doc.json

@@ -0,0 +1,15 @@
+{
+  "outPath":"./src/main/resources/doc",
+  "serverUrl": "http:10.23.39.1:9887/",
+  "isStrict": false,
+  "coverOld": true,
+  "allInOne": true,
+  "packageFilters": "com.usky.iot.controller.web",
+  "requestExample":"false",
+  "responseExample":"true",
+  "projectName": "iot项目",
+  "appKey": "20211216921084883495813120",
+  "appToken":"967031b0cc6f474aaf73616cbf2b25c2",
+  "secret": "N@Pd,KXAHki*BW3=zK.XPNykf!=CM79J",
+  "openUrl": "http://101.133.214.75:7700/api"
+}

+ 16 - 0
service-iot/service-iot-api/src/main/java/com/usky/iot/RemoteIotService.java

@@ -0,0 +1,16 @@
+package com.usky.iot;
+
+
+import com.usky.iot.factory.RemoteIotFactory;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@FeignClient(contextId = "remoteIotService", value = "service-iot" , fallbackFactory = RemoteIotFactory.class)
+public interface RemoteIotService {
+
+    @GetMapping("/executeTimedSendingOld")
+    void executeTimedSendingOld();
+
+    @GetMapping("/reportSubmissionReminderOld")
+    void reportSubmissionReminderOld();
+}

+ 0 - 2
service-iot/service-iot-api/src/main/java/com/usky/iot/RemoteIotTaskService.java

@@ -2,8 +2,6 @@ package com.usky.iot;
 
 
 import com.usky.iot.factory.RemoteIotTaskFactory;
-import com.usky.iot.factory.RemotePmFactory;
-import org.apache.ibatis.annotations.Param;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;

+ 40 - 0
service-iot/service-iot-api/src/main/java/com/usky/iot/factory/RemoteIotFactory.java

@@ -0,0 +1,40 @@
+package com.usky.iot.factory;
+
+import com.usky.common.core.exception.FeignBadRequestException;
+import com.usky.iot.RemoteIotService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 用户服务降级处理
+ *
+ * @author ruoyi
+ */
+@Component
+public class RemoteIotFactory implements FallbackFactory<RemoteIotService>
+{
+    private static final Logger log = LoggerFactory.getLogger(RemoteIotFactory.class);
+
+    @Override
+    public RemoteIotService create(Throwable throwable)
+    {
+        return new RemoteIotService()
+        {
+            @Override
+            public void executeTimedSendingOld() {
+                log.error("工作报告定时发送异常:{}", throwable.getMessage());
+                throw new FeignBadRequestException(500,"工作报告定时发送异常"+throwable.getMessage());
+            }
+
+            @Override
+            public void reportSubmissionReminderOld() {
+                log.error("工作报告提交提醒发送异常:{}", throwable.getMessage());
+                throw new FeignBadRequestException(500,"工作报告提交提醒发送异常"+throwable.getMessage());
+            }
+
+        };
+    }
+}

+ 0 - 2
service-iot/service-iot-api/src/main/java/com/usky/iot/factory/RemoteIotTaskFactory.java

@@ -2,8 +2,6 @@ package com.usky.iot.factory;
 
 import com.usky.common.core.exception.FeignBadRequestException;
 import com.usky.iot.RemoteIotTaskService;
-import com.usky.iot.RemotePmService;
-import org.apache.ibatis.annotations.Param;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cloud.openfeign.FallbackFactory;

+ 4 - 0
service-iot/service-iot-biz/pom.xml

@@ -117,6 +117,10 @@
             <artifactId>alibaba-dingtalk-service-sdk</artifactId>
             <version>2.0.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>ruoyi-common-swagger</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 3 - 1
service-iot/service-iot-biz/src/main/java/com/usky/iot/RuoYiSystemApplication.java

@@ -2,6 +2,7 @@ package com.usky.iot;
 
 
 
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
 import com.usky.iot.constant.constant;
 import io.swagger.annotations.SwaggerDefinition;
 import lombok.val;
@@ -31,12 +32,13 @@ import java.net.UnknownHostException;
  */
 
 //@EnableSwagger2
+@EnableCustomSwagger2
 @EnableFeignClients(basePackages = "com.usky")
 @MapperScan(value = "com.usky.iot.mapper")
 @ComponentScan("com.usky")
 @SpringBootApplication
 //开启异步
-@EnableAsync
+//@EnableAsync
 //@EnableRabbit
 public class RuoYiSystemApplication
 {

+ 4 - 4
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/api/PmTimedSendingApi.java

@@ -1,6 +1,6 @@
 package com.usky.iot.controller.api;
 
-import com.usky.iot.RemotePmService;
+import com.usky.iot.RemoteIotService;
 import com.usky.iot.service.PmWorkReportService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RestController;
@@ -15,19 +15,19 @@ import java.time.LocalDateTime;
  * @author f
  */
 @RestController
-public class PmTimedSendingApi implements RemotePmService {
+public class PmTimedSendingApi implements RemoteIotService {
 
     @Autowired
     private PmWorkReportService pmWorkReportService;
 
     @Override
-    public void executeTimedSending() {
+    public void executeTimedSendingOld() {
         LocalDateTime now = LocalDateTime.now();
         pmWorkReportService.timedSending(now);
     }
 
     @Override
-    public void reportSubmissionReminder() {
+    public void reportSubmissionReminderOld() {
         pmWorkReportService.reportSubmissionReminder();
     }
 

+ 2 - 1
service-iot/service-iot-biz/src/main/java/com/usky/iot/mapper/PmWorkContentMapper.java

@@ -27,7 +27,8 @@ public interface PmWorkContentMapper extends CrudMapper<PmWorkContent> {
 
     List<PmProjectWorkTimeVo> workTimeCount(@Param("startTime") LocalDateTime startTime,
                                             @Param("endTime") LocalDateTime endTime,
-                                            @Param("userId") Long userId);
+                                            @Param("userId") Long userId,
+                                            @Param("tenantId") Integer tenantId);
 
 /*    List<WorkHoursStatisticsVO> workHoursStatistics(@Param("startTime") LocalDate startTime,
                                                     @Param("endTime") LocalDate endTime,

+ 1 - 1
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/DeviceOperate.java

@@ -36,7 +36,7 @@ public class DeviceOperate {
     @Autowired
     DmpDeviceStatusService dmpDeviceStatusService;
 
-    @Async
+    @Async("asyncServiceExecutor")
     public void updateDeviceStatus(){
         log.info("定时同步设备状态数据 start");
         ApiResult<List<Map<String,Object>>> list = remoteTsdbProxyService.getAllDeviceRealTime();

+ 4 - 4
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/DingTalkAndMessage.java

@@ -207,8 +207,8 @@ public class DingTalkAndMessage {
         return sysUserMapper.selectOne(phoneQuery);
     }
 
-    @Async// 异步发送
-//    @Async("asyncServiceExecutor")// 异步发送
+    //@Async// 异步发送
+    @Async("asyncServiceExecutor")// 异步发送
     public void sendDingTalkDailyReport(PmWorkReport workReport, List<PmWorkContent> workContents) {
         String userName = workReport.getCreateBy();
         log.info(userName + "的工作报告开始发送钉钉-----------------------------------");
@@ -303,8 +303,8 @@ public class DingTalkAndMessage {
     }
 
 
-    @Async
-//    @Async("asyncServiceExecutor")
+    //@Async
+    @Async("asyncServiceExecutor")
     public void sendAsyncMessage(PmWorkReport newReport) {
         String username = newReport.getCreateBy();
         Long submitterId = newReport.getSubmitterId();

+ 48 - 49
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/ExecutorConfig.java

@@ -1,49 +1,48 @@
-//package com.usky.iot.service.config;
-//
-//import lombok.extern.slf4j.Slf4j;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.scheduling.annotation.EnableAsync;
-//import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-//
-//import java.util.concurrent.Executor;
-//import java.util.concurrent.ThreadPoolExecutor;
-//
-//@Configuration
-//@EnableAsync
-//@Slf4j
-//public class ExecutorConfig {
-//
-//    /** 核心线程数(默认线程数) */
-//    private int corePoolSize = 10;
-//    /** 最大线程数 */
-//    private int maxPoolSize = 20;
-//    /** 允许线程空闲时间(单位:默认为秒) */
-//    private static final int keepAliveTime = 60;
-//    /** 缓冲队列大小 */
-//    private int queueCapacity = 10;
-//
-//    @Bean(name = "asyncServiceExecutor")
-//    public Executor asyncServiceExecutor(){
-//        log.info("start asyncServiceExecutor++++++++++++++++++++++");
-//        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
-//        //配置核心线程数
-//        executor.setCorePoolSize(corePoolSize);
-//        //配置最大线程数
-//        executor.setMaxPoolSize(maxPoolSize);
-//        //配置空闲时间
-//        executor.setKeepAliveSeconds(keepAliveTime);
-//        //配置队列大小
-//        executor.setQueueCapacity(queueCapacity);
-//        //配置线程前缀名
-//        executor.setThreadNamePrefix("async-service-");
-//
-//        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
-//        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
-//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
-//
-//        //执行初始化
-//        executor.initialize();
-//        return executor;
-//    }
-//}
+package com.usky.iot.service.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@EnableAsync
+@Slf4j
+public class ExecutorConfig {
+
+   /** 核心线程数(默认线程数) */
+   private int corePoolSize = 20;
+   /** 最大线程数 */
+   private int maxPoolSize = 100;
+   /** 允许线程空闲时间(单位:默认为秒) */
+   private static final int keepAliveTime = 60;
+   /** 缓冲队列大小 */
+   private int queueCapacity = 100;
+
+   @Bean(name = "asyncServiceExecutor")
+   public Executor asyncServiceExecutor(){
+       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+       //配置核心线程数
+       executor.setCorePoolSize(corePoolSize);
+       //配置最大线程数
+       executor.setMaxPoolSize(maxPoolSize);
+       //配置空闲时间
+       executor.setKeepAliveSeconds(keepAliveTime);
+       //配置队列大小
+       executor.setQueueCapacity(queueCapacity);
+       //配置线程前缀名
+       executor.setThreadNamePrefix("async-service-");
+
+       // rejection-policy:当pool已经达到max size的时候,如何处理新任务
+       // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
+       executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+
+       //执行初始化
+       executor.initialize();
+       return executor;
+   }
+}

+ 1 - 7
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/BaseAlarmServiceImpl.java

@@ -14,9 +14,6 @@ import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.bean.CommonPage;
 import com.usky.common.core.exception.BusinessException;
 import com.usky.common.security.utils.SecurityUtils;
-import com.usky.demo.RemoteTsdbProxyService;
-import com.usky.demo.domain.LastInnerQueryVO;
-import com.usky.demo.domain.LastInnerResultVO;
 import com.usky.iot.domain.*;
 import com.usky.iot.mapper.BaseAlarmMapper;
 import com.usky.iot.mapper.DmpDeviceTypeMapper;
@@ -73,9 +70,6 @@ public class BaseAlarmServiceImpl extends AbstractCrudService<BaseAlarmMapper, B
     @Autowired
     private DataQueryClient dataQueryClient;
 
-    @Autowired
-    private RemoteTsdbProxyService remoteTsdbProxyService;
-
     @Autowired
     private DmpDeviceStatusService dmpDeviceStatusService;
 
@@ -635,7 +629,7 @@ public class BaseAlarmServiceImpl extends AbstractCrudService<BaseAlarmMapper, B
         }
     }
 
-    @Async
+    @Async("asyncServiceExecutor")
     public void deviceAlarm(List<StatusVO> list, List<DmpDeviceInfo> devInfoList, List<BaseAlarm> baseUnAlarmList){
         log.info("定时同步设备告警数据 start");
         if(CollectionUtils.isNotEmpty(devInfoList)){

+ 3 - 2
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/BaseAppInfoServiceImpl.java

@@ -119,11 +119,12 @@ public class BaseAppInfoServiceImpl extends AbstractCrudService<BaseAppInfoMappe
         IPage<BaseAppInfo> page = new Page<>(appInfoRequest.getCurrent(), appInfoRequest.getSize());
         QueryWrapper<BaseAppInfo> queryWrapper = Wrappers.query();
         queryWrapper.eq(StringUtils.isNotBlank(appInfoRequest.getDeviceId()),"device_id",appInfoRequest.getDeviceId())
+                .eq("tenant_id",SecurityUtils.getTenantId())
                 .inSql("id","SELECT MAX(id) AS id FROM base_app_info GROUP BY device_id")
                 .orderByDesc("id");
         page = this.page(page,queryWrapper);
-        if (page.getSize()>0){
-            for (int i = 0; i < page.getSize(); i++) {
+        if (page.getRecords().size()>0){
+            for (int i = 0; i < page.getRecords().size(); i++) {
                 if (page.getRecords().get(i).getCheckStatus().equals(1)){
                     LocalDateTime endTime = LocalDateTime.now();
                     long seconds = ChronoUnit.SECONDS.between(page.getRecords().get(i).getUpdateTime(), endTime);

+ 11 - 26
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmProjectServiceImpl.java

@@ -75,7 +75,7 @@ public class PmProjectServiceImpl extends AbstractCrudService<PmProjectMapper, P
         String projectName = project.getProjectName();
         if (StringUtils.isBlank(projectName)) {
             throw new BusinessException("项目名称不能为空!");
-        }else if (projectName.length() > 50) {
+        } else if (projectName.length() > 50) {
             throw new BusinessException("项目名称长度不能超过50个字符!");
         }
 
@@ -88,7 +88,7 @@ public class PmProjectServiceImpl extends AbstractCrudService<PmProjectMapper, P
         Integer projectType = project.getProjectType();
         if (projectType == null) {
             throw new BusinessException("项目类型不能为空且");
-        }else if (projectType < 1 || projectType > 6) {
+        } else if (projectType < 1 || projectType > 6) {
             throw new BusinessException("项目类型传参有误!");
         }
 
@@ -96,7 +96,7 @@ public class PmProjectServiceImpl extends AbstractCrudService<PmProjectMapper, P
         Integer projectStatus = project.getProjectStatus();
         if (projectStatus == null) {
             throw new BusinessException("项目状态不能为空且!");
-        }else if (projectStatus < 1 || projectStatus > 5) {
+        } else if (projectStatus < 1 || projectStatus > 5) {
             throw new BusinessException("项目状态传参有误!");
         }
 
@@ -249,43 +249,26 @@ public class PmProjectServiceImpl extends AbstractCrudService<PmProjectMapper, P
 
         LambdaQueryWrapper<PmProject> lambdaQuery = Wrappers.lambdaQuery();
         lambdaQuery.eq(PmProject::getTenantId, tenantId)
-                .eq(PmProject::getDelFlag, 0)
-                .eq(visibleRange != null, PmProject::getVisibleRange, visibleRange);
+                .eq(PmProject::getDelFlag, 0);
 
         if (projectId != null && projectId != 0) {
             lambdaQuery.eq(PmProject::getId, projectId);
-            page = this.page(page, lambdaQuery);
-            return new CommonPage<>(page.getRecords(), page.getTotal(), pageSize, pageNum);
         }
 
         switch (projectAscription) {
             case 0:
-                if (StringUtils.isNotBlank(projectName) || projectType != null || projectStatus != null) {
-                    lambdaQuery.eq(PmProject::getDelFlag, 0)
-                            .like(StringUtils.isNotBlank(projectName), PmProject::getProjectName, projectName)
-                            .eq(projectType != null, PmProject::getProjectType, projectType)
-                            .eq(projectStatus != null, PmProject::getProjectStatus, projectStatus)
+                if (visibleRange == null) {
+                    lambdaQuery.and(wrapper -> wrapper
                             .and(qw -> qw
                                     .eq(PmProject::getProjectHead, userId)
                                     .or()
                                     .apply("FIND_IN_SET('" + userId + "', project_member) > 0")
                                     .or()
-                                    .eq(PmProject::getCreateBy, username));
-                }
-                if (visibleRange == null) {
-                    lambdaQuery.eq(PmProject::getDelFlag, 0)
-                            .and(wrapper -> wrapper
-                                    .eq(PmProject::getVisibleRange, 2)
-                                    .and(qw -> qw
-                                            .eq(PmProject::getProjectHead, userId)
-                                            .or()
-                                            .apply("FIND_IN_SET('" + userId + "', project_member) > 0")
-                                            .or()
-                                            .eq(PmProject::getCreateBy, username))
+                                    .eq(PmProject::getCreateBy, username)
                             )
                             .or()
                             .eq(PmProject::getVisibleRange, 1)
-                            .eq(PmProject::getDelFlag, 0);
+                    );
                 } else if (visibleRange == 2) {
                     lambdaQuery.and(wrapper -> wrapper
                             .eq(PmProject::getProjectHead, userId)
@@ -314,7 +297,9 @@ public class PmProjectServiceImpl extends AbstractCrudService<PmProjectMapper, P
             default:
                 throw new BusinessException("查询项目列表参数错误");
         }
-        lambdaQuery.orderByDesc(PmProject::getCreateTime);
+
+        lambdaQuery.eq(visibleRange != null, PmProject::getVisibleRange, visibleRange)
+                .orderByDesc(PmProject::getCreateTime);
         List<PmProject> pmProjects = pmProjectMapper.selectList(lambdaQuery);
         if (pmProjects.isEmpty()) {
             return new CommonPage<>(pmProjects, 0, pageSize, pageNum);

+ 21 - 11
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkContentServiceImpl.java

@@ -465,6 +465,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             }
         }
         Integer tenantId = SecurityUtils.getTenantId();
+        Long nowUserId = SecurityUtils.getUserId();
         LocalDate start = null;
         LocalDate end = null;
         List<Integer> reportIds = new ArrayList<>();
@@ -475,6 +476,8 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         Set<Integer> reportIdsByProject = new HashSet<>();
         Set<Integer> reportIdsSet = new HashSet<>();
 
+        LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
+
         if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
             DateTimeFormatter formatter = null;
             try {
@@ -486,7 +489,6 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             end = LocalDate.parse(endDate, formatter);
             startDateTime = start.atStartOfDay();
             endDateTime = end.atTime(23, 59, 59);
-            LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
             reportQuery.select(PmWorkReport::getId).eq(PmWorkReport::getReportStatus, 1).between(PmWorkReport::getSubmitDate, startDateTime, endDateTime);
             reportIdsByDate = pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toSet());
         }
@@ -498,8 +500,8 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         }
 
         if (userId != null) {
-            LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
-            reportQuery.eq(PmWorkReport::getSubmitterId, userId);
+            reportQuery.eq(PmWorkReport::getSubmitterId, userId)
+                    .and(wrappers -> wrappers.apply("FIND_IN_SET(" + nowUserId + ", cc_to) > 0"));
             reportIdsByUser = pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toSet());
             if (reportIdsByProject.isEmpty() && reportIdsByUser.isEmpty()) {
                 return returnPage;
@@ -538,8 +540,16 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         } else if (!reportIdsByDate.isEmpty()) {
             reportIdsSet.addAll(reportIdsByDate);
         }
+
         reportIds = new ArrayList<>(reportIdsSet);
 
+        if (projectAscription == 1) {
+            LambdaQueryWrapper<PmWorkReport> headerQuery = Wrappers.lambdaQuery();
+            headerQuery.in(!reportIds.isEmpty(), PmWorkReport::getId, reportIds)
+                    .and(wrappers -> wrappers.apply("FIND_IN_SET(" + nowUserId + ", cc_to) > 0"));
+            reportIds = pmWorkReportMapper.selectList(headerQuery).stream().map(PmWorkReport::getId).collect(Collectors.toList());
+        }
+
         List<PmWorkContent> pmWorkContentList = new ArrayList<>();
         Long userId2 = SecurityUtils.getUserId();
         List<Long> userIds = new ArrayList<>();
@@ -588,22 +598,22 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
 
         List<Integer> reportIds2 = pmWorkContentList.stream().distinct().map(PmWorkContent::getReportId).collect(Collectors.toList());
 
-        LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
-        reportQuery.eq(PmWorkReport::getTenantId, tenantId).eq(PmWorkReport::getReportStatus, 1);
+        LambdaQueryWrapper<PmWorkReport> reportQuery1 = Wrappers.lambdaQuery();
+        reportQuery1.eq(PmWorkReport::getTenantId, tenantId).eq(PmWorkReport::getReportStatus, 1);
         if (reportId != null && reportId != 0) {
-            reportQuery.eq(PmWorkReport::getId, reportId);
+            reportQuery1.eq(PmWorkReport::getId, reportId);
         } else {
-            reportQuery.in(PmWorkReport::getId, reportIds2);
+            reportQuery1.in(PmWorkReport::getId, reportIds2);
             // 判断上下滑动以及数量
             if (upOrDown != null && slideSum != null && submitDateTime != null) {
                 if (slideSum > 0) {
                     // 向下滑动
                     if (upOrDown == 0) {
-                        reportQuery.lt(PmWorkReport::getSubmitDate, submitDateTime).orderByDesc(PmWorkReport::getSubmitDate);
+                        reportQuery1.lt(PmWorkReport::getSubmitDate, submitDateTime).orderByDesc(PmWorkReport::getSubmitDate);
                     }
                     // 向上滑动
                     else if (upOrDown == 1) {
-                        reportQuery.gt(PmWorkReport::getSubmitDate, submitDateTime).orderByAsc(PmWorkReport::getSubmitDate);
+                        reportQuery1.gt(PmWorkReport::getSubmitDate, submitDateTime).orderByAsc(PmWorkReport::getSubmitDate);
                     } else {
                         throw new BusinessException("上下滑动参数异常");
                     }
@@ -614,11 +624,11 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
                     throw new BusinessException("滑动数量参数必须是大于0正整数");
                 }
             } else {
-                reportQuery.orderByDesc(PmWorkReport::getSubmitDate);
+                reportQuery1.orderByDesc(PmWorkReport::getSubmitDate);
             }
         }
 
-        reportPage = pmWorkReportMapper.selectPage(new Page<>(pageNum, pageSize), reportQuery);
+        reportPage = pmWorkReportMapper.selectPage(new Page<>(pageNum, pageSize), reportQuery1);
         reportList = reportPage.getRecords();
 
         // 查询已读状态

+ 12 - 6
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkReportServiceImpl.java

@@ -95,6 +95,9 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
      */
     @Override
     public List<Map<String, List<PmWorkReport>>> weekWork(String startDate, String endDate, Integer reportId) {
+        Long userId = SecurityUtils.getUserId();
+        Integer tenantId = SecurityUtils.getTenantId();
+
         List<Map<String, List<PmWorkReport>>> returnList = new ArrayList<>();
         List<PmWorkReport> report = new ArrayList<>();
         Map<String, List<PmWorkReport>> weekData = new HashMap<>();
@@ -114,9 +117,10 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             dates.add(tempDate);
             tempDate = tempDate.plusDays(1);
         }
+
         // 返回最新的一条数据给前端填充
         LambdaQueryWrapper<PmWorkReport> wrapper2 = Wrappers.lambdaQuery();
-        wrapper2.eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
+        wrapper2.eq(PmWorkReport::getSubmitterId, userId)
                 .orderByDesc(PmWorkReport::getSubmitDate)
                 .last("LIMIT 1");
         report = baseMapper.selectList(wrapper2);
@@ -127,9 +131,11 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             List<PmWorkContent> contents1 = pmWorkContentMapper.selectList(wrapper);
             report.get(0).setWorkContents(contents1);
         }
+
         // 固定返回七条数据,没有内容也要设置时间给前端渲染
         LambdaQueryWrapper<PmWorkReport> queryWrapperR = Wrappers.lambdaQuery();
-        queryWrapperR.eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
+        queryWrapperR.eq(PmWorkReport::getTenantId, tenantId)
+                .eq(PmWorkReport::getSubmitterId, userId)
                 .between(reportId == 0, PmWorkReport::getReportDate, startDate1, endDate1)
                 .eq(reportId != 0, PmWorkReport::getId, reportId)
                 .orderByAsc(PmWorkReport::getReportDate);
@@ -174,7 +180,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         if (reports.size() == 7 || reportId != 0) {
             weekData.put("weekData", reports);
             LambdaQueryWrapper<PmWorkReport> wrapper1 = Wrappers.lambdaQuery();
-            wrapper1.eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
+            wrapper1.eq(PmWorkReport::getSubmitterId, userId)
                     .orderByDesc(PmWorkReport::getReportDate)
                     .last("LIMIT 1");
             report = this.list(wrapper1);
@@ -499,7 +505,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         LocalDateTime endTime = stringLocalDateTimeMap.get("end");
         BigDecimal totalWorkTime = BigDecimal.ZERO;
 
-        List<PmProjectWorkTimeVo> week = pmWorkContentMapper.workTimeCount(startTime, endTime, SecurityUtils.getUserId());
+        List<PmProjectWorkTimeVo> week = pmWorkContentMapper.workTimeCount(startTime, endTime, SecurityUtils.getUserId(), SecurityUtils.getTenantId());
         if (week.isEmpty()) {
             projectTotalWorkTimeVo.setTotalWorkTime(totalWorkTime);
             projectTotalWorkTimeVo.setProjectWorkTime(week);
@@ -601,7 +607,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
      * @param: [time] 开始时间
      * @return: void
      **/
-    @Async
+    @Async("asyncServiceExecutor")
     @Override
     public void timedSending(LocalDateTime time) {
         log.info("定时报告任务开始---------------------------");
@@ -740,7 +746,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         return timedReports;
     }
 
-    @Async
+    @Async("asyncServiceExecutor")
     @Override
     public void reportSubmissionReminder() {
         Integer tenantId = SecurityUtils.getTenantId();

+ 2 - 1
service-iot/service-iot-biz/src/main/resources/mapper/iot/PmWorkContentMapper.xml

@@ -21,9 +21,10 @@
     <select id="workTimeCount" resultType="com.usky.iot.service.vo.PmProjectWorkTimeVo">
         SELECT pc.project_name, SUM(pc.work_time) as workTime
         FROM pm_work_content pc
-            JOIN pm_work_report pr ON pc.report_id = pr.id
+                 JOIN pm_work_report pr ON pc.report_id = pr.id
         WHERE pr.submitter_id = #{userId}
           AND pr.report_date BETWEEN #{startTime} AND #{endTime}
+          AND pr.tenant_id = #{tenantId}
         GROUP BY pc.project_name
     </select>
 

+ 4 - 0
service-issue/service-issue-api/src/main/java/com/usky/issue/RemoteIssueTaskService.java

@@ -0,0 +1,4 @@
+package com.usky.issue;
+
+public interface RemoteIssueTaskService {
+}

+ 4 - 0
service-issue/service-issue-api/src/main/java/com/usky/issue/factory/RemoteIssueTaskFactory.java

@@ -0,0 +1,4 @@
+package com.usky.issue.factory;
+
+public class RemoteIssueTaskFactory {
+}

+ 5 - 0
service-issue/service-issue-biz/pom.xml

@@ -61,6 +61,11 @@
             <artifactId>spring-websocket</artifactId>
             <version>5.2.8.RELEASE</version>
         </dependency>
+        <dependency>
+            <groupId>com.usky</groupId>
+            <artifactId>ruoyi-common-swagger</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 2 - 0
service-issue/service-issue-biz/src/main/java/com/usky/issue/RuoYiSystemApplication.java

@@ -2,6 +2,7 @@ package com.usky.issue;
 
 
 
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
 import org.mybatis.spring.annotation.MapperScan;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -22,6 +23,7 @@ import java.net.UnknownHostException;
  */
 
 //@EnableSwagger2
+@EnableCustomSwagger2
 @EnableFeignClients(basePackages = "com.usky")
 @MapperScan(value = "com.usky.issue.mapper")
 @ComponentScan("com.usky")

+ 50 - 0
service-issue/service-issue-biz/src/main/java/com/usky/issue/service/config/mqtt/MqttBaseConfig.java

@@ -0,0 +1,50 @@
+package com.usky.issue.service.config.mqtt;
+
+import lombok.Data;
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
+import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
+import org.springframework.stereotype.Component;
+
+@ConditionalOnProperty(prefix = "mqtt", value = {"enabled"}, havingValue = "true")
+@Data
+@Component
+@ConfigurationProperties(prefix = "mqtt")
+public class MqttBaseConfig {
+
+    @Value("${mqtt.username}")
+    private String username;
+
+    @Value("${mqtt.password}")
+    private String password;
+
+    @Value("${mqtt.url}")
+    private String hostUrl;
+
+    @Value("${mqtt.sub-topics}")
+    private String msgTopic;
+
+    @Value("${mqtt.keep-alive-interval}")
+    //心跳间隔
+    private int keepAliveInterval;
+    @Value("${mqtt.completionTimeout}")
+    //心跳间隔
+    private int completionTimeout;
+
+
+    @Bean
+    public MqttPahoClientFactory mqttClientFactory() {
+        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
+        MqttConnectOptions options = new MqttConnectOptions();
+        options.setServerURIs(new String[]{this.getHostUrl()});
+        options.setUserName(this.getUsername());
+        options.setPassword(this.getPassword().toCharArray());
+        factory.setConnectionOptions(options);
+        return factory;
+    }
+
+}

+ 48 - 0
service-issue/service-issue-biz/src/main/java/com/usky/issue/service/config/mqtt/MqttInConfig.java

@@ -0,0 +1,48 @@
+package com.usky.issue.service.config.mqtt;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.channel.DirectChannel;
+import org.springframework.integration.core.MessageProducer;
+import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
+import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
+import org.springframework.messaging.MessageChannel;
+
+/**
+ * @author han
+ * @date 2025/03/20 14:30
+ */
+@ConditionalOnProperty(prefix = "mqtt", value = {"enabled"}, havingValue = "true")
+@Configuration
+public class MqttInConfig {
+    @Autowired
+    private MqttBaseConfig mqttBaseConfig;
+
+    public static final String CHANNEL_NAME_INPUT = "mqttInputChannel";
+
+    @Bean(name = CHANNEL_NAME_INPUT)
+    public MessageChannel mqttInputChannel() {
+        return new DirectChannel();
+    }
+
+
+    /**
+     * 消息订阅绑定-消费者
+     *
+     * @return
+     */
+    @Bean
+    public MessageProducer inbound() {
+        String[] tops = mqttBaseConfig.getMsgTopic().split(",");
+        String clientId = "h-agbox-mqtt-in-" + System.currentTimeMillis();
+        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId,
+                mqttBaseConfig.mqttClientFactory(), tops);
+        adapter.setCompletionTimeout(mqttBaseConfig.getCompletionTimeout());
+        adapter.setConverter(new DefaultPahoMessageConverter());
+        adapter.setQos(2);
+        adapter.setOutputChannel(mqttInputChannel());
+        return adapter;
+    }
+}

+ 86 - 0
service-issue/service-issue-biz/src/main/java/com/usky/issue/service/config/mqtt/MqttOutConfig.java

@@ -0,0 +1,86 @@
+package com.usky.issue.service.config.mqtt;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.annotation.MessagingGateway;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.channel.DirectChannel;
+import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.handler.annotation.Header;
+
+/**
+ * @author han
+ * @date 2025/03/20 14:31
+ */
+@ConditionalOnProperty(prefix = "mqtt", value = {"enabled"}, havingValue = "true")
+@Configuration
+public class MqttOutConfig {
+    @Autowired
+    public MqttBaseConfig mqttBaseConfig;
+
+    public static final String CHANNEL_NAME_OUT = "mqttOutboundChannel";
+
+    public static final String MESSAGE_NAME = "messageOut";
+
+    public static final String DEFAULT_TOPIC = "testTopic";
+
+    /**
+     * 连接通道
+     *
+     * @return
+     */
+    @Bean(name = CHANNEL_NAME_OUT)
+    public MessageChannel mqttOutboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory
+     *
+     * @return
+     */
+    @Bean(name = MESSAGE_NAME)
+    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
+    public MessageHandler outbound() {
+        // 在这里进行mqttOutboundChannel的相关设置
+        String clientId = "h-backend-mqtt-in-" + System.currentTimeMillis();
+        MqttPahoMessageHandler messageHandler =
+                new MqttPahoMessageHandler(clientId, mqttBaseConfig.mqttClientFactory());
+        //如果设置成true,发送消息时将不会阻塞。
+        messageHandler.setAsync(true);
+        messageHandler.setDefaultTopic(DEFAULT_TOPIC);
+        return messageHandler;
+    }
+
+    @MessagingGateway(defaultRequestChannel = CHANNEL_NAME_OUT)
+    public interface MqttGateway {
+        /**
+         * 发送消息
+         *
+         * @param payload
+         */
+        void sendToMqtt(String payload);
+
+        /**
+         * 指定top发送消息
+         *
+         * @param topic
+         * @param payload
+         */
+        void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);
+
+        /**
+         * 指定队列和qos
+         *
+         * @param topic
+         * @param qos
+         * @param payload
+         */
+        void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
+    }
+}

+ 175 - 0
service-issue/service-issue-biz/src/main/java/com/usky/issue/service/job/JgDataForward.java

@@ -0,0 +1,175 @@
+package com.usky.issue.service.job;
+
+import com.alibaba.fastjson.JSONObject;
+import com.usky.issue.service.util.HttpClientUtils;
+import com.usky.issue.service.vo.RtuAttributeVO;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 外滩27号介谷物管家平台消息转发
+ */
+@Component
+public class JgDataForward {
+    public JSONObject addHeart(String requestBody) {
+        String resultString = "";
+        JSONObject map = new JSONObject();
+        JSONObject eventVO = JSONObject.parseObject(requestBody);
+        JSONObject resultVO = new JSONObject();
+        List<Map<String, Object>> devs = (List) JSONObject.parseArray(JSONObject.toJSONString(eventVO.get("devs")));
+        List<Map<String, Object>> dp = (List) JSONObject.parseArray(JSONObject.toJSONString(devs.get(0).get("dp")));
+        String battery = "";
+        String devSignal = "";
+        String waterPressure = "";
+        List<RtuAttributeVO> mapList = new ArrayList<>();
+        RtuAttributeVO rtuAttributeVO1 = new RtuAttributeVO();
+        RtuAttributeVO rtuAttributeVO2 = new RtuAttributeVO();
+        RtuAttributeVO rtuAttributeVO3 = new RtuAttributeVO();
+        RtuAttributeVO rtuAttributeVO4 = new RtuAttributeVO();
+        RtuAttributeVO rtuAttributeVO5 = new RtuAttributeVO();
+        if (devs.get(0).get("deviceType").equals("6")){
+            if (eventVO.get("devId").equals("4023383030393834")){
+                for (int i = 0; i < dp.size(); i++) {
+                    if (dp.get(i).get("serial").equals("601")){
+                        rtuAttributeVO1.setPowerAlarm(dp.get(i).get("value").equals("00")?0:1);
+                        rtuAttributeVO2.setPowerAlarm(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("602")){
+                        rtuAttributeVO1.setManualAct(dp.get(i).get("value").equals("00")?0:1);
+                        rtuAttributeVO2.setManualAct(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("603")){
+                        rtuAttributeVO1.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("604")){
+                        rtuAttributeVO2.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("605")){
+                        rtuAttributeVO1.setDevAlarm(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("606")){
+                        rtuAttributeVO2.setDevAlarm(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("607")){
+                        rtuAttributeVO3.setPowerAlarm(dp.get(i).get("value").equals("00")?0:1);
+                        rtuAttributeVO4.setPowerAlarm(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("608")){
+                        rtuAttributeVO3.setManualAct(dp.get(i).get("value").equals("00")?0:1);
+                        rtuAttributeVO4.setManualAct(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("609")){
+                        rtuAttributeVO3.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("610")){
+                        rtuAttributeVO4.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("611")){
+                        rtuAttributeVO3.setDevAlarm(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("612")){
+                        rtuAttributeVO4.setDevAlarm(dp.get(i).get("value").equals("00")?0:1);
+                    }
+                }
+                mapList.add(rtuAttributeVO1);
+                mapList.add(rtuAttributeVO2);
+                mapList.add(rtuAttributeVO3);
+                mapList.add(rtuAttributeVO4);
+                for (int j = 0; j < mapList.size(); j++) {
+                    int k = j+1;
+                    map.put("deviceId", "YHYH"+eventVO.get("devId")+k);
+                    map.put("dataJson",
+                            "{\"powerAlarm\":"+mapList.get(j).getPowerAlarm()+",\"devWorking\":"+mapList.get(j).getDevWorking()+
+                                    ",\"manualAct\":"+mapList.get(j).getManualAct()+ "," + "\"devAlarm\":"+mapList.get(j).getDevAlarm()+"}");
+                    resultString = HttpClientUtils.doPostJson("http://adaptor.dbmcloud.tech:8802/dbm/iot/receive/data/all"
+                            ,map.toJSONString());
+                    System.out.print("发送数据"+map.toJSONString());
+                    resultVO = JSONObject.parseObject(resultString);
+                    System.out.print("返回数据"+resultString);
+                }
+            }else if (eventVO.get("devId").equals("4023383030393835")){
+                for (int i = 0; i < dp.size(); i++) {
+                    if (dp.get(i).get("serial").equals("601")){
+                        rtuAttributeVO1.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("602")){
+                        rtuAttributeVO2.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("603")){
+                        rtuAttributeVO3.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("604")){
+                        rtuAttributeVO4.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }else if (dp.get(i).get("serial").equals("605")){
+                        rtuAttributeVO5.setDevWorking(dp.get(i).get("value").equals("00")?0:1);
+                    }
+                }
+                mapList.add(rtuAttributeVO1);
+                mapList.add(rtuAttributeVO2);
+                mapList.add(rtuAttributeVO3);
+                mapList.add(rtuAttributeVO4);
+                mapList.add(rtuAttributeVO5);
+                for (int j = 0; j < mapList.size(); j++) {
+                    int k = j+1;
+                    map.put("deviceId", "YHYH"+eventVO.get("devId")+k);
+                    map.put("dataJson",
+                            "{\"devWorking\":"+mapList.get(j).getDevWorking()+"}");
+                    resultString = HttpClientUtils.doPostJson("http://adaptor.dbmcloud.tech:8802/dbm/iot/receive/data/all"
+                            ,map.toJSONString());
+                    System.out.print("发送数据"+map.toJSONString());
+                    resultVO = JSONObject.parseObject(resultString);
+                    System.out.print("返回数据"+resultString);
+                }
+            }
+        }else {
+            map.put("deviceId", "YHYH"+eventVO.get("devId"));
+            if (devs.get(0).get("deviceType").equals("2")||devs.get(0).get("deviceType").equals("5")){
+                for (int i = 0; i < dp.size(); i++) {
+                    if (dp.get(i).get("serial").equals("201")){
+                        battery = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("202")){
+                        devSignal = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("203")){
+                        waterPressure = dp.get(i).get("value").toString();
+                    }
+                }
+                if (devs.get(0).get("deviceType").equals("2")){
+                    map.put("dataJson", "{\"battery\":"+battery+",\"devSignal\":"+devSignal+",\"waterPressure\":"+waterPressure+"," +
+                            "\"devStatus\":"+0+"}");
+                }else {
+                    map.put("dataJson", "{\"battery\":"+battery+",\"devSignal\":"+devSignal+",\"waterLevel\":"+waterPressure+"," +
+                            "\"devStatus\":"+0+"}");
+                }
+            }else if (devs.get(0).get("deviceType").equals("7")){
+                String voltageA = "";
+                String voltageB = "";
+                String voltageC = "";
+                String currentA = "";
+                String currentB = "";
+                String currentC = "";
+                String temperatureA = "";
+                String temperatureB = "";
+                String temperatureC = "";
+                for (int i = 0; i < dp.size(); i++) {
+                    if (dp.get(i).get("serial").equals("65")){
+                        voltageA = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("66")){
+                        voltageB = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("67")){
+                        voltageC = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("68")){
+                        currentA = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("69")){
+                        currentB = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("70")){
+                        currentC = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("71")){
+                        temperatureA = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("72")){
+                        temperatureB = dp.get(i).get("value").toString();
+                    }else if (dp.get(i).get("serial").equals("73")){
+                        temperatureC = dp.get(i).get("value").toString();
+                    }
+                }
+                map.put("dataJson", "{\"voltageA\":"+voltageA+",\"voltageB\":"+voltageB+",\"voltageC\":"+voltageC+"," +
+                        "\"currentA\":"+currentA+",\"currentB\":"+currentB+",\"currentC\":"+currentC+",\"temperatureA\":"+temperatureA+",\"temperatureB\":"+temperatureB+",\"temperatureC\":"+temperatureC+"," +
+                        "\"devStatus\":"+0+"}");
+            }
+            resultString = HttpClientUtils.doPostJson("http://adaptor.dbmcloud.tech:8802/dbm/iot/receive/data/all"
+                    ,map.toJSONString());
+            System.out.print("发送数据"+map.toJSONString());
+            resultVO = JSONObject.parseObject(resultString);
+            System.out.print("返回数据"+resultString);
+        }
+        return resultVO;
+    }
+}

+ 55 - 0
service-issue/service-issue-biz/src/main/java/com/usky/issue/service/listener/MqttListener.java

@@ -0,0 +1,55 @@
+package com.usky.issue.service.listener;
+
+import com.usky.issue.service.config.mqtt.MqttInConfig;
+import com.usky.issue.service.mqtt.SimpleContext;
+import com.usky.issue.service.vo.MqttBaseVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author han
+ * @date 2025/03/20 14:41
+ */
+@ConditionalOnProperty(prefix = "mqtt", value = {"enabled"}, havingValue = "true")
+@Slf4j
+@Component
+public class MqttListener {
+    public static final String MESSAGE_NAME = "messageInput";
+
+    @Autowired
+    private SimpleContext simpleContext;
+
+    /**
+     * 处理消息-消费者
+     *
+     * @return
+     */
+    @Bean(MESSAGE_NAME)
+    @ServiceActivator(inputChannel = MqttInConfig.CHANNEL_NAME_INPUT)
+    public MessageHandler handler() {
+        return message -> {
+            String payload = message.getPayload().toString();
+            //进行接口推送
+            Object mqttReceivedTopic = message.getHeaders().get("mqtt_receivedTopic");
+            if (null != mqttReceivedTopic) {
+                String topic = mqttReceivedTopic.toString();
+                MqttBaseVO mqttBaseVO = new MqttBaseVO();
+                mqttBaseVO.setTopic(topic);
+                if (topic.indexOf("info") != -1 ) {
+                    mqttBaseVO.setDescribe("info");
+                    mqttBaseVO.setData(payload);
+                }else if(topic.indexOf("event") != -1 ) {
+                    mqttBaseVO.setDescribe("event");
+                    mqttBaseVO.setData(payload);
+                }
+                //统一处理数据
+                simpleContext.getResource(mqttBaseVO);
+            }
+        };
+    }
+}

Неке датотеке нису приказане због велике количине промена