Browse Source

Merge branch 'han' of http://47.111.81.118:3000/uskycloud/usky-modules into han

hanzhengyi 6 days ago
parent
commit
8803785dfd
100 changed files with 3010 additions and 2840 deletions
  1. 3 1
      pom.xml
  2. 1 0
      service-agbox/service-agbox-biz/pom.xml
  3. 15 16
      service-agbox/service-agbox-biz/src/main/java/com/usky/agbox/service/job/patrolAgbox.java
  4. 1 6
      service-agbox/service-agbox-biz/src/main/java/com/usky/agbox/service/mqtt/event/event.java
  5. 1 1
      service-agbox/service-agbox-biz/src/main/java/com/usky/agbox/service/util/HttpClientUtils.java
  6. 1 1
      service-agbox/service-agbox-biz/src/main/resources/logback.xml
  7. 19 0
      service-ai/pom.xml
  8. 27 0
      service-ai/service-ai-api/pom.xml
  9. 88 0
      service-ai/service-ai-biz/pom.xml
  10. 40 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/AIChatApplication.java
  11. 536 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiChatController.java
  12. 43 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiQuestionController.java
  13. 94 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiSessionController.java
  14. 41 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/mapper/AiQuestionMapper.java
  15. 37 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/mapper/AiSessionMapper.java
  16. 70 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiQuestion.java
  17. 51 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiQuestionItem.java
  18. 48 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/AiSession.java
  19. 14 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/AiChatConfig.java
  20. 19 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/MyGlobalCorsConfig.java
  21. 14 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/config/WebConfig.java
  22. 22 0
      service-ai/service-ai-biz/src/main/java/com/usky/ai/service/vo/AiStreamOutputVO.java
  23. 24 0
      service-ai/service-ai-biz/src/main/resources/bootstrap.yml
  24. 94 0
      service-ai/service-ai-biz/src/main/resources/logback.xml
  25. 151 0
      service-ai/service-ai-biz/src/main/resources/static/dpsk.html
  26. 150 0
      service-ai/service-ai-biz/src/main/resources/static/tyqw.html
  27. 5 0
      service-alarm/service-alarm-biz/pom.xml
  28. 2 1
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/RuoYiSystemApplication.java
  29. 151 53
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/impl/BaseAlarmNoticeResultServiceImpl.java
  30. 1 0
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/impl/BaseAlarmServiceImpl.java
  31. 7 2
      service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/mqtt/alarm/Alarm.java
  32. 9 0
      service-cdi/service-cdi-api/src/main/java/com/usky/cdi/RemotecdiTaskService.java
  33. 22 1
      service-cdi/service-cdi-api/src/main/java/com/usky/cdi/factory/RemotecdiTaskFactory.java
  34. 7 0
      service-cdi/service-cdi-biz/pom.xml
  35. 2 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/RuoYiSystemApplication.java
  36. 15 12
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/IotDataController.java
  37. 4 4
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/MybatisGeneratorUtils.java
  38. 25 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/api/RemotecdiTaskApi.java
  39. 22 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/web/DmpProductController.java
  40. 141 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/domain/DmpProduct.java
  41. 16 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/mapper/DmpProductMapper.java
  42. 16 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/DmpProductService.java
  43. 20 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/impl/DmpProductServiceImpl.java
  44. 514 159
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/impl/IotDataTransferService.java
  45. 225 94
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/util/DeviceDataQuery.java
  46. 41 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/util/DeviceDataSyncService.java
  47. 28 0
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/vo/IotDataTransferVO.java
  48. 1 1
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/vo/base/BaseEnvMonitorPushVO.java
  49. 0 11
      service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/vo/base/ElectricityLoadVO.java
  50. 1 1
      service-cdi/service-cdi-biz/src/main/resources/bootstrap.yml
  51. 2 2
      service-cdi/service-cdi-biz/src/main/resources/logback.xml
  52. 0 30
      service-cdi/service-cdi-biz/src/main/resources/mapper.cdi/DmpDeviceMapper.xml
  53. 32 0
      service-cdi/service-cdi-biz/src/main/resources/mapper/cdi/DmpProductMapper.xml
  54. 3 3
      service-cdi/service-cdi-biz/src/main/resources/smart-doc.json
  55. 0 13
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/ServletInitializer.java
  56. 0 116
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/base/BaseController.java
  57. 0 24
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/CorsConfig.java
  58. 0 16
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/DateStringConvert.java
  59. 0 20
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/MybatisPlusConfig.java
  60. 0 16
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/StringDateConverter.java
  61. 0 72
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/V2Config.java
  62. 0 104
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/domain/AjaxResult.java
  63. 0 84
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/domain/ResultTable.java
  64. 0 50
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/domain/Tablepar.java
  65. 0 21
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/interceptor/Interceptor.java
  66. 0 31
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/interceptor/WebMvcConfig.java
  67. 0 371
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/FileController.java
  68. 0 254
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/GoviewProjectController.java
  69. 0 21
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/Indexcontroller.java
  70. 0 19
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/SysUserController.java
  71. 0 18
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/GoviewProjectDataMapper.java
  72. 0 16
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/GoviewProjectMapper.java
  73. 0 19
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/SysFileMapper.java
  74. 0 16
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/SysUserMapper.java
  75. 0 48
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/GoviewProject.java
  76. 0 39
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/GoviewProjectData.java
  77. 0 119
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/SysFile.java
  78. 0 39
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/SysUser.java
  79. 0 119
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/vo/GoviewProjectVo.java
  80. 0 70
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/vo/SysFileVo.java
  81. 0 19
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/IGoviewProjectDataService.java
  82. 0 17
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/IGoviewProjectService.java
  83. 0 20
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/ISysFileService.java
  84. 0 17
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/ISysUserService.java
  85. 0 31
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/GoviewProjectDataServiceImpl.java
  86. 0 20
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/GoviewProjectServiceImpl.java
  87. 0 30
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/SysFileServiceImpl.java
  88. 0 20
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/SysUserServiceImpl.java
  89. 0 252
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/util/ConvertUtil.java
  90. 0 73
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/util/SaTokenUtil.java
  91. 0 155
      service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/util/SnowflakeIdWorker.java
  92. 0 5
      service-cockpit/service-cockpit-biz/src/main/resources/mapper/GoviewProjectDataMapper.xml
  93. 0 5
      service-cockpit/service-cockpit-biz/src/main/resources/mapper/GoviewProjectMapper.xml
  94. 0 5
      service-cockpit/service-cockpit-biz/src/main/resources/mapper/SysFileMapper.xml
  95. 0 5
      service-cockpit/service-cockpit-biz/src/main/resources/mapper/SysUserMapper.xml
  96. 4 2
      service-eg/service-eg-biz/src/main/java/com/usky/eg/controller/web/EgDeviceController.java
  97. 12 0
      service-eg/service-eg-biz/src/main/java/com/usky/eg/domain/EgDevice.java
  98. 3 1
      service-eg/service-eg-biz/src/main/java/com/usky/eg/service/EgDeviceService.java
  99. 68 29
      service-eg/service-eg-biz/src/main/java/com/usky/eg/service/impl/EgDeviceServiceImpl.java
  100. 7 0
      service-eg/service-eg-biz/src/main/java/com/usky/eg/service/impl/EgRecordServiceImpl.java

+ 3 - 1
pom.xml

@@ -90,8 +90,10 @@
 
     <module>service-oa</module>
 
-    <module>service-cockpit</module>
 
+    <module>service-ai</module>
+
+    <module>service-pm</module>
 
     <module>service-ids</module>
 

+ 1 - 0
service-agbox/service-agbox-biz/pom.xml

@@ -74,6 +74,7 @@
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.2.6.RELEASE</version>
                 <executions>
                     <execution>
                         <goals>

+ 15 - 16
service-agbox/service-agbox-biz/src/main/java/com/usky/agbox/service/job/patrolAgbox.java

@@ -104,24 +104,23 @@ public class patrolAgbox {
         map.put("json", "{\"jsonrpc\":\"2.0\",\"method\":\"addEvent\",\"params\":{\"deviceId\":\""+eventVO.get("deviceId").toString()+"\"," +
                 "\"triggerTime\":\""+eventVO.get("triggerTime").toString()+"\",\"eventCode\":"+eventVO.get("eventCode")+",\"name" +
                 "\":\""+eventVO.get("name").toString()+"\",\"certifiedNo\":\""+eventVO.get("certifiedNo").toString()+"\"}}");
-        System.out.println("FEvent收到消息: " + map.toString());
         String resultString = HttpClientUtils.doPost(list.get(0).getAgboxUrl(),map);
         JSONObject resultVO = JSONObject.parseObject(resultString);
-//        LocalDateTime now = LocalDateTime.now();
-////        String host = "127.0.0.1";
-//        int port = 5901;
-//        String xmlData = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>  \n" +
-//                "<Agent ID=\"SGT100006088\" Type=\"SG\" Ver=\"1.2.0.0\">\n" +
-//                "<DVRHeart State=\"0\" TotalSpace=\"1000\" FreeSpace=\"500\">\n" +
-//                "System,smss.exe,csrss.exe\n" +
-//                "</DVRHeart>\n" +
-//                "<GetTicks/>\n" +
-//                "<OperationCmd Type=\"18\" Channel=\"2\" TriggerTime=\""+now+"\" Note=\"5rWL6K+V\" " +
-//                "GUID=\"7b726e15-4d45-53e7-f0e0-0abb91156fd7\">\n" +
-//                "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABsSFBcUERsXFhceHBsgKEIrKCUlKFE6PTBCYFVlZF9V\n" +
-//                "</OperationCmd>\n" +
-//                "</Agent>";
-//        sendMessage(URL, port, xmlData);
+        LocalDateTime now = LocalDateTime.now();
+//        String host = "127.0.0.1";
+        int port = 5901;
+        String xmlData = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>  \n" +
+                "<Agent ID=\"SGT100006088\" Type=\"SG\" Ver=\"1.2.0.0\">\n" +
+                "<DVRHeart State=\"0\" TotalSpace=\"1000\" FreeSpace=\"500\">\n" +
+                "System,smss.exe,csrss.exe\n" +
+                "</DVRHeart>\n" +
+                "<GetTicks/>\n" +
+                "<OperationCmd Type=\"18\" Channel=\"2\" TriggerTime=\""+now+"\" Note=\"5rWL6K+V\" " +
+                "GUID=\"7b726e15-4d45-53e7-f0e0-0abb91156fd7\">\n" +
+                "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDABsSFBcUERsXFhceHBsgKEIrKCUlKFE6PTBCYFVlZF9V\n" +
+                "</OperationCmd>\n" +
+                "</Agent>";
+        sendMessage(URL, port, xmlData);
         return resultVO;
     }
 

+ 1 - 6
service-agbox/service-agbox-biz/src/main/java/com/usky/agbox/service/mqtt/event/event.java

@@ -36,13 +36,8 @@ public class event implements MqttStrategy {
                 eventVO2.put("deviceId",eventVO1.get("deviceId"));
                 PatrolAgbox.updateHeart(eventVO2.toJSONString());
             }else {
-                if (eventVO1.get("eventType").equals(33)||eventVO1.get("eventType").equals(34)||eventVO1.get(
-                        "eventType").equals(9)){
+                if (eventVO1.get("eventType").equals(33)||eventVO1.get("eventType").equals(34)){
                     eventVO.put("eventCode",5);
-                }else if (eventVO1.get("eventType").equals(8)){
-                    eventVO.put("eventCode",3);
-                }else if (eventVO1.get("eventType").equals(10)){
-                    eventVO.put("eventCode",4);
                 }else {
                     eventVO.put("eventCode",16);
                 }

+ 1 - 1
service-agbox/service-agbox-biz/src/main/java/com/usky/agbox/service/util/HttpClientUtils.java

@@ -77,7 +77,7 @@ public class HttpClientUtils {
         try {
             // 创建Http Post请求
             HttpPost httpPost = new HttpPost(url);
-            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
+            httpPost.setHeader("Content-Type", "charset=utf-8");
             // 创建参数列表
             if (param != null) {
                 List<NameValuePair> paramList = new ArrayList<>();

+ 1 - 1
service-agbox/service-agbox-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/service-alarm" />
+    <property name="log.path" value="/var/log/uskycloud/service-agbox" />
     <!-- 日志输出格式 -->
     <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" />-->

+ 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>-->

+ 5 - 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>
@@ -70,6 +74,7 @@
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.2.6.RELEASE</version>
                 <executions>
                     <execution>
                         <goals>

+ 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;
                 }

+ 7 - 2
service-alarm/service-alarm-biz/src/main/java/com/usky/alarm/service/mqtt/alarm/Alarm.java

@@ -56,13 +56,18 @@ public class Alarm implements MqttStrategy {
         List<DmpDevice> list = dmpDeviceService.list(queryWrapper1);
         baseAlarm.setDeviceId(alarams.get(0).get("devId").toString());
         baseAlarm.setAlarmTime(time2);
-        baseAlarm.setAlarmType(dp.get(0).get("serial").toString());
+        String alarmType = dp.get(0).get("serial").toString();
+        baseAlarm.setAlarmType(alarmType);
         baseAlarm.setAlarmObject(alarams.get(0).get("deviceName").toString());
         baseAlarm.setAlarmData(dp.get(0).get("status").toString());
         baseAlarm.setAlarmAttribute(dp.get(0).get("property").toString());
         if (alarams.get(0).get("deviceType").equals("1")){
             baseAlarm.setAlarmContent(dp.get(0).get("property").toString()+","+dp.get(0).get("value").toString());
-            baseAlarm.setAlarmGrade(1);
+            if(alarmType.equals("812") || alarmType.equals("815") || alarmType.equals("819")){
+                baseAlarm.setAlarmGrade(1);
+            }else{
+                baseAlarm.setAlarmGrade(2);
+            }
             baseAlarm.setAlarmAddress(dp.get(0).get("value").toString());
         }else if (alarams.get(0).get("deviceType").equals("2")){
             baseAlarm.setAlarmContent(dp.get(0).get("property").toString()+","+dp.get(0).get("value").toString());

+ 9 - 0
service-cdi/service-cdi-api/src/main/java/com/usky/cdi/RemotecdiTaskService.java

@@ -1,4 +1,13 @@
 package com.usky.cdi;
 
+import com.usky.cdi.factory.RemotecdiTaskFactory;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(contextId = "RemotecdiTaskService", value = "service-cdi", fallbackFactory = RemotecdiTaskFactory.class)
 public interface RemotecdiTaskService {
+    @GetMapping("/synchronizeDeviceData")
+    void synchronizeDeviceData(@RequestParam("tenantId") Integer tenantId,
+                               @RequestParam("engineeringId") Long engineeringId);
 }

+ 22 - 1
service-cdi/service-cdi-api/src/main/java/com/usky/cdi/factory/RemotecdiTaskFactory.java

@@ -1,4 +1,25 @@
 package com.usky.cdi.factory;
 
-public class RemotecdiTaskFactory {
+import com.usky.cdi.RemotecdiTaskService;
+import com.usky.common.core.exception.FeignBadRequestException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RemotecdiTaskFactory implements FallbackFactory<RemotecdiTaskService> {
+    private static final Logger log = LoggerFactory.getLogger(RemotecdiTaskFactory.class);
+
+    @Override
+    public RemotecdiTaskService create(Throwable throwable) {
+        log.error("用户服务调用失败:{}", throwable.getMessage());
+        return new RemotecdiTaskService() {
+            @Override
+            public void synchronizeDeviceData(Integer tenantId, Long engineeringId) {
+                throw new FeignBadRequestException(500, "人防设备数据定时推送异常" + throwable.getMessage());
+            }
+
+        };
+    }
 }

+ 7 - 0
service-cdi/service-cdi-biz/pom.xml

@@ -74,6 +74,13 @@
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
         </dependency>
+
+        <dependency>
+            <groupId>com.mchange</groupId>
+            <artifactId>mchange-commons-java</artifactId>
+            <version>0.2.15</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

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

@@ -11,6 +11,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -22,6 +23,7 @@ import java.net.UnknownHostException;
  */
 
 //@EnableSwagger2
+@EnableScheduling
 @EnableFeignClients(basePackages = "com.usky")
 @MapperScan(value = "com.usky.cdi.mapper")
 @ComponentScan("com.usky")

+ 15 - 12
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/IotDataController.java

@@ -1,7 +1,10 @@
 package com.usky.cdi.controller;
 
+import com.alibaba.fastjson.JSONObject;
 import com.usky.cdi.service.impl.IotDataTransferService;
+import com.usky.cdi.service.vo.IotDataTransferVO;
 import com.usky.cdi.service.vo.base.*;
+import com.usky.common.core.bean.ApiResult;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -29,36 +32,36 @@ public class IotDataController {
      * 上报水浸状态
      */
     @PostMapping("/flooded")
-    public String sendWaterLeak() {
-        boolean success = iotDataTransferService.sendWaterLeak();
-        return success ? "上报成功" : "上报失败";
+    public ApiResult<Void> sendWaterLeak(@RequestBody IotDataTransferVO jsonObject) {
+        iotDataTransferService.sendWaterLeak(jsonObject);
+        return ApiResult.success();
     }
 
     /**
      * 上报温度、湿度、氧气、一氧化碳、二氧化碳
      */
     @PostMapping("/envData")
-    public String sendEnvData() {
-        boolean success = iotDataTransferService.sendEnvData();
-        return success ? "上报成功" : "上报失败";
+    public ApiResult<Void> sendEnvData(@RequestBody IotDataTransferVO jsonObject) {
+        iotDataTransferService.sendEnvData(jsonObject);
+        return ApiResult.success();
     }
 
     /**
      * 上报人员闯入
      */
     @PostMapping("/personPresence")
-    public String sendPerson(@RequestBody PersonPresenceVO vo) {
-        boolean success = iotDataTransferService.sendPersonPresence(vo);
-        return success ? "上报成功" : "上报失败";
+    public ApiResult<Void> sendPerson(@RequestBody IotDataTransferVO jsonObject) {
+        iotDataTransferService.sendPersonPresence(jsonObject);
+        return ApiResult.success();
     }
 
     /**
      * 上报用电负荷
      */
     @PostMapping("/electricityLoad")
-    public String sendElectricityLoad() {
-        boolean success = iotDataTransferService.sendElectricityLoad();
-        return success ? "上报成功" : "上报失败";
+    public ApiResult<Void> sendElectricityLoad(@RequestBody IotDataTransferVO jsonObject) {
+        iotDataTransferService.sendElectricityLoad(jsonObject);
+        return ApiResult.success();
     }
 
 }

+ 4 - 4
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/MybatisGeneratorUtils.java

@@ -43,10 +43,10 @@ public class MybatisGeneratorUtils {
         //2、数据源配置
         //修改数据源
         DataSourceConfig dsc = new DataSourceConfig();
-        dsc.setUrl("jdbc:mysql://47.98.201.187:3306/jdxf?useUnicode=true&serverTimezone=GMT&useSSL=false&characterEncoding=utf8");
+        dsc.setUrl("jdbc:mysql://47.111.81.118:13307/usky-cloud?useUnicode=true&serverTimezone=GMT&useSSL=false&characterEncoding=utf8");
         dsc.setDriverName("com.mysql.jdbc.Driver");
-        dsc.setUsername("fuYuChuan");
-        dsc.setPassword("fuYuChuan@123");
+        dsc.setUsername("usky");
+        dsc.setPassword("Yt#75Usky");
         mpg.setDataSource(dsc);
 
         // 3、包配置
@@ -71,7 +71,7 @@ public class MybatisGeneratorUtils {
         // strategy.setTablePrefix("t_"); // 表名前缀
         strategy.setEntityLombokModel(true); //使用lombok
         //修改自己想要生成的表
-        strategy.setInclude(new String[]{"sp_rtu2017", "sp_sj2017"});  // 逆向工程使用的表   如果要生成多个,这里可以传入String[]
+        strategy.setInclude("dmp_product");  // 逆向工程使用的表   如果要生成多个,这里可以传入String[]
         mpg.setStrategy(strategy);
 
         // 关闭默认 xml 生成,调整生成 至 根目录

+ 25 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/api/RemotecdiTaskApi.java

@@ -0,0 +1,25 @@
+package com.usky.cdi.controller.api;
+
+import com.usky.cdi.RemotecdiTaskService;
+import com.usky.cdi.service.impl.IotDataTransferService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  数据统一查询 前端控制器
+ * </p>
+ *
+ * @author f
+ */
+@RestController
+public class RemotecdiTaskApi implements RemotecdiTaskService {
+
+    @Autowired
+    private IotDataTransferService iotDataTransferService;
+
+    @Override
+    public void synchronizeDeviceData(Integer tenantId, Long engineeringId) {
+        iotDataTransferService.synchronizeDeviceData(tenantId, engineeringId);
+    }
+}

+ 22 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/controller/web/DmpProductController.java

@@ -0,0 +1,22 @@
+package com.usky.cdi.controller.web;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 产品信息表 前端控制器
+ * </p>
+ *
+ * @author fu
+ * @since 2025-12-05
+ */
+@RestController
+@RequestMapping("/dmpProduct")
+public class DmpProductController {
+
+}
+

+ 141 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/domain/DmpProduct.java

@@ -0,0 +1,141 @@
+package com.usky.cdi.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 fu
+ * @since 2025-12-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DmpProduct implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 产品名称
+     */
+    private String productName;
+
+    /**
+     * 接入方式
+     */
+    private Integer accessMode;
+
+    /**
+     * 网络类型
+     */
+    private Integer networkType;
+
+    /**
+     * 设备类型
+     */
+    private Integer deviceType;
+
+    /**
+     * 通信协议
+     */
+    private Integer comProtocol;
+
+    /**
+     * 认证方式
+     */
+    private String authMode;
+
+    /**
+     * 设备型号
+     */
+    private String deviceModel;
+
+    /**
+     * 产品描述
+     */
+    private String productDescribe;
+
+    /**
+     * 厂家名称
+     */
+    private String factoryName;
+
+    /**
+     * 厂家联系人
+     */
+    private String factoryPerson;
+
+    /**
+     * 厂家联系电话
+     */
+    private String factoryPhone;
+
+    /**
+     * 资质证书1
+     */
+    private String certificateUrl1;
+
+    /**
+     * 资质证书2
+     */
+    private String certificateUrl2;
+
+    /**
+     * 资质证书3
+     */
+    private String certificateUrl3;
+
+    /**
+     * 协议文档
+     */
+    private String agreementUrl;
+
+    /**
+     * 删除标识
+     */
+    private Integer deleteFlag;
+
+    /**
+     * 创建人
+     */
+    private String createdBy;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createdTime;
+
+    /**
+     * 更新人
+     */
+    private String updatedBy;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updatedTime;
+
+    /**
+     * 租户号
+     */
+    private Integer tenantId;
+
+    /**
+     * 产品编码
+     */
+    private String productCode;
+
+
+}

+ 16 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/mapper/DmpProductMapper.java

@@ -0,0 +1,16 @@
+package com.usky.cdi.mapper;
+
+import com.usky.cdi.domain.DmpProduct;
+import com.usky.common.mybatis.core.CrudMapper;
+
+/**
+ * <p>
+ * 产品信息表 Mapper 接口
+ * </p>
+ *
+ * @author fu
+ * @since 2025-12-05
+ */
+public interface DmpProductMapper extends CrudMapper<DmpProduct> {
+
+}

+ 16 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/DmpProductService.java

@@ -0,0 +1,16 @@
+package com.usky.cdi.service;
+
+import com.usky.cdi.domain.DmpProduct;
+import com.usky.common.mybatis.core.CrudService;
+
+/**
+ * <p>
+ * 产品信息表 服务类
+ * </p>
+ *
+ * @author fu
+ * @since 2025-12-05
+ */
+public interface DmpProductService extends CrudService<DmpProduct> {
+
+}

+ 20 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/impl/DmpProductServiceImpl.java

@@ -0,0 +1,20 @@
+package com.usky.cdi.service.impl;
+
+import com.usky.cdi.domain.DmpProduct;
+import com.usky.cdi.mapper.DmpProductMapper;
+import com.usky.cdi.service.DmpProductService;
+import com.usky.common.mybatis.core.AbstractCrudService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 产品信息表 服务实现类
+ * </p>
+ *
+ * @author fu
+ * @since 2025-12-05
+ */
+@Service
+public class DmpProductServiceImpl extends AbstractCrudService<DmpProductMapper, DmpProduct> implements DmpProductService {
+
+}

+ 514 - 159
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/impl/IotDataTransferService.java

@@ -2,24 +2,35 @@ package com.usky.cdi.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.usky.cdi.domain.DmpDevice;
+import com.usky.cdi.domain.DmpProduct;
+import com.usky.cdi.mapper.DmpDeviceMapper;
+import com.usky.cdi.mapper.DmpProductMapper;
 import com.usky.cdi.service.config.mqtt.MqttGateway;
 import com.usky.cdi.service.enums.EnvMonitorMqttTopic;
 import com.usky.cdi.service.util.DeviceDataQuery;
 import com.usky.cdi.service.util.SnowflakeIdGenerator;
+import com.usky.cdi.service.vo.IotDataTransferVO;
 import com.usky.cdi.service.vo.base.*;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.PostConstruct;
+
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Random;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
- *
  * @author fyc
  * @email yuchuan.fu@chinausky.com
  * @date 2025/11/20
@@ -32,15 +43,30 @@ public class IotDataTransferService {
     @Autowired(required = false)
     private MqttGateway mqttGateway;
 
-    private final SnowflakeIdGenerator idGenerator;
+    private SnowflakeIdGenerator idGenerator;
 
     @Autowired
     private DeviceDataQuery deviceDataQuery;
 
+    @Autowired
+    private DmpDeviceMapper dmpDeviceMapper;
+
+    @Value("${device.data.simulation}")
+    private boolean simulation;
+
+    @Autowired
+    private DmpProductMapper dmpProductMapper;
+
+    // 从配置文件读取Snowflake参数,默认值为2
+    @Value("${snowflake.worker-id:2}")
+    private long workerId;
+
+    @Value("${snowflake.data-center-id:2}")
+    private long dataCenterId;
 
-    public IotDataTransferService() {
-        // 使用默认的workerId和datacenterId,实际项目中可以从配置读取
-        this.idGenerator = new SnowflakeIdGenerator(1L, 1L);
+    @PostConstruct
+    public void init() {
+        this.idGenerator = new SnowflakeIdGenerator(workerId, dataCenterId);
     }
 
     /**
@@ -61,225 +87,554 @@ public class IotDataTransferService {
      * 发送水浸状态(deviceType:702)
      * Topic: iotInfo/flooded
      *
-     * @return 是否发送成功
+     * @return 推送结果,包含成功数和失败数
      */
-    public boolean sendWaterLeak() {
-        if (mqttGateway == null) {
-            log.warn("MQTT Gateway未初始化,无法发送消息");
-            return false;
+    public Map<String, Integer> sendWaterLeak(IotDataTransferVO transferVO) {
+        Map<String, Integer> result = new HashMap<>();
+        result.put("successCount", 0);
+        result.put("failureCount", 0);
+
+        if (!validateMqttGateway()) {
+            return result;
         }
+
         try {
-            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(702);
+            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
+            Integer deviceType = transferVO.getDeviceType();
+            Integer totalDevices = transferVO.getDevices().size();
+
+            log.info("开始推送水浸状态数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
+                    deviceType, totalDevices, deviceData.size());
 
             if (deviceData.isEmpty()) {
-                log.warn("没有获取到水浸数据!");
-                return false;
+                log.warn("没有获取到水浸数据!设备类型:{}", deviceType);
+                result.put("failureCount", totalDevices);
+                return result;
             }
 
+            Long engineeringId = transferVO.getEngineeringId();
             for (JSONObject deviceDataItem : deviceData) {
-                Integer leachStatus = Integer.valueOf(deviceDataItem.getString("leach_status"));
-                Long dataTime = deviceDataItem.getLong("time");
-                LocalDateTime dataEndTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dataTime), ZoneId.systemDefault());
+                LocalDateTime dataEndTime = parseDataTime(deviceDataItem);
+                if (dataEndTime == null) {
+                    result.put("failureCount", result.get("failureCount") + 1);
+                    continue;
+                }
+
+                Integer deviceId = deviceDataItem.getIntValue("device_id");
+                Integer value = deviceDataItem.getInteger("leach_status");
+                if (value == null) {
+                    log.warn("设备{}的水浸状态数据为空", deviceId);
+                    result.put("failureCount", result.get("failureCount") + 1);
+                    continue;
+                }
 
                 WaterLeakVO vo = new WaterLeakVO();
                 vo.setDataPacketID(generateDataPacketID());
-                vo.setSensorID(4399L);
-                vo.setEngineeringID(9527L);
+                vo.setSensorID(deviceId);
+                vo.setEngineeringID(engineeringId);
                 vo.setPublishTime(getCurrentTime());
-                vo.setSensorValue(leachStatus);
+                vo.setSensorValue(value);
                 vo.setDataEndTime(dataEndTime);
 
-                String json = JSON.toJSONString(vo);
-                String topic = EnvMonitorMqttTopic.WATER_LEAK.getTopic();
-
-                log.info("发送水浸状态信息,Topic: {}, Data: {}", topic, json);
-                mqttGateway.sendToMqtt(topic, json);
+                try {
+                    sendMqttMessage(EnvMonitorMqttTopic.WATER_LEAK, vo, "水浸状态信息");
+                    result.put("successCount", result.get("successCount") + 1);
+                } catch (Exception e) {
+                    log.warn("设备{}的水浸状态数据推送失败:{}", deviceId, e.getMessage());
+                    result.put("failureCount", result.get("failureCount") + 1);
+                }
             }
 
-            return true;
+            log.info("水浸状态数据推送完成,设备类型:{},成功:{},失败:{}",
+                    deviceType, result.get("successCount"), result.get("failureCount"));
+
+            return result;
         } catch (Exception e) {
-            log.error("发送水浸状态信息失败", e);
-            return false;
+            log.error("水浸状态数据推送发生异常", e);
+            result.put("failureCount", transferVO.getDevices().size());
+            return result;
         }
     }
 
     /**
-     * 发送温湿度及气体浓度数据(设备类型:701)
+     * 发送温湿度及气体浓度数据(设备类型:701,707-711)
      * 包含: wd(温度), sd(湿度), o2(氧气), co(一氧化碳), co2(二氧化碳)
      *
-     * @return 是否发送成功
+     * @return 推送结果,包含成功数和失败数
      */
-    public boolean sendEnvData() {
-        if (mqttGateway == null) {
-            log.warn("MQTT Gateway未初始化,无法发送消息");
-            return false;
+    public Map<String, Integer> sendEnvData(IotDataTransferVO transferVO) {
+        Map<String, Integer> result = new HashMap<>();
+        result.put("successCount", 0);
+        result.put("failureCount", 0);
+
+        if (!validateMqttGateway()) {
+            return result;
         }
+
         try {
-            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(701);
+            Integer deviceType = transferVO.getDeviceType();
+            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
+            Integer totalDevices = transferVO.getDevices().size();
+
+            log.info("开始推送温湿度及气体浓度数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
+                    deviceType, totalDevices, deviceData.size());
 
             if (deviceData.isEmpty()) {
-                log.warn("没有获取到空气质量数据!");
-                return false;
+                log.warn("没有获取到空气质量数据!设备类型:{}", deviceType);
+                result.put("failureCount", totalDevices);
+                return result;
             }
 
+            Long engineeringId = transferVO.getEngineeringId();
             for (JSONObject deviceDataItem : deviceData) {
-                Long dataTime = deviceDataItem.getLong("time");
-                LocalDateTime dataEndTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dataTime), ZoneId.systemDefault());
-
-                // 发送温度
-                TempVO tempVO = new TempVO();
-                tempVO.setDataPacketID(generateDataPacketID());
-                tempVO.setSensorID(4399L);
-                tempVO.setEngineeringID(9527L);
-                tempVO.setPublishTime(getCurrentTime());
-                tempVO.setSensorValue(deviceDataItem.getFloat("wd"));
-                tempVO.setDataEndTime(dataEndTime);
-                String tempJson = JSON.toJSONString(tempVO);
-                mqttGateway.sendToMqtt(EnvMonitorMqttTopic.TEMP.getTopic(), tempJson);
-                log.info("发送温度信息,Topic: {}, Data: {}", EnvMonitorMqttTopic.TEMP.getTopic(), tempJson);
-
-                // 发送湿度
-                HumidityVO humidityVO = new HumidityVO();
-                humidityVO.setDataPacketID(generateDataPacketID());
-                humidityVO.setSensorID(4399L);
-                humidityVO.setEngineeringID(9527L);
-                humidityVO.setPublishTime(getCurrentTime());
-                humidityVO.setSensorValue(deviceDataItem.getFloat("sd"));
-                humidityVO.setDataEndTime(dataEndTime);
-                String humidityJson = JSON.toJSONString(humidityVO);
-                mqttGateway.sendToMqtt(EnvMonitorMqttTopic.HUMIDITY.getTopic(), humidityJson);
-                log.info("发送湿度信息,Topic: {}, Data: {}", EnvMonitorMqttTopic.HUMIDITY.getTopic(), humidityJson);
-
-                // 发送氧气浓度
-                OxygenVO oxygenVO = new OxygenVO();
-                oxygenVO.setDataPacketID(generateDataPacketID());
-                oxygenVO.setSensorID(4399L);
-                oxygenVO.setEngineeringID(9527L);
-                oxygenVO.setPublishTime(getCurrentTime());
-                oxygenVO.setSensorValue(deviceDataItem.getFloat("o2"));
-                oxygenVO.setDataEndTime(dataEndTime);
-                String oxygenJson = JSON.toJSONString(oxygenVO);
-                mqttGateway.sendToMqtt(EnvMonitorMqttTopic.OXYGEN.getTopic(), oxygenJson);
-                log.info("发送氧气浓度信息,Topic: {}, Data: {}", EnvMonitorMqttTopic.OXYGEN.getTopic(), oxygenJson);
-
-                // 发送一氧化碳浓度
-                CoVO coVO = new CoVO();
-                coVO.setDataPacketID(generateDataPacketID());
-                coVO.setSensorID(4399L);
-                coVO.setEngineeringID(9527L);
-                coVO.setPublishTime(getCurrentTime());
-                coVO.setSensorValue(deviceDataItem.getFloat("co"));
-                coVO.setDataEndTime(dataEndTime);
-                String coJson = JSON.toJSONString(coVO);
-                mqttGateway.sendToMqtt(EnvMonitorMqttTopic.CO.getTopic(), coJson);
-                log.info("发送一氧化碳浓度信息,Topic: {}, Data: {}", EnvMonitorMqttTopic.CO.getTopic(), coJson);
-
-                // 发送二氧化碳浓度
-                Co2VO co2VO = new Co2VO();
-                co2VO.setDataPacketID(generateDataPacketID());
-                co2VO.setSensorID(4399L);
-                co2VO.setEngineeringID(9527L);
-                co2VO.setPublishTime(getCurrentTime());
-                co2VO.setSensorValue(deviceDataItem.getFloat("co2"));
-                co2VO.setDataEndTime(dataEndTime);
-                String co2Json = JSON.toJSONString(co2VO);
-                mqttGateway.sendToMqtt(EnvMonitorMqttTopic.CO2.getTopic(), co2Json);
-                log.info("发送二氧化碳浓度信息,Topic: {}, Data: {}", EnvMonitorMqttTopic.CO2.getTopic(), co2Json);
+                LocalDateTime dataEndTime = parseDataTime(deviceDataItem);
+                if (dataEndTime == null) {
+                    result.put("failureCount", result.get("failureCount") + 1);
+                    continue;
+                }
+
+                Integer deviceId = deviceDataItem.getIntValue("device_id");
+                boolean deviceSuccess = true;
+
+                // 根据设备类型发送对应的数据
+                try {
+                    switch (deviceType) {
+                        case 707:
+                            sendTempData(deviceId, dataEndTime, deviceDataItem, engineeringId);
+                            break;
+                        case 708:
+                            sendHumidityData(deviceId, dataEndTime, deviceDataItem, engineeringId);
+                            break;
+                        case 709:
+                            sendOxygenData(deviceId, dataEndTime, deviceDataItem, engineeringId);
+                            break;
+                        case 710:
+                            sendCo2Data(deviceId, dataEndTime, deviceDataItem, engineeringId);
+                            break;
+                        case 711:
+                            sendCoData(deviceId, dataEndTime, deviceDataItem, engineeringId);
+                            break;
+                    }
+                } catch (Exception e) {
+                    log.warn("设备{}的环境数据推送失败:{}", deviceId, e.getMessage());
+                    deviceSuccess = false;
+                }
+
+                // 统计设备推送结果
+                if (deviceSuccess) {
+                    result.put("successCount", result.get("successCount") + 1);
+                } else {
+                    result.put("failureCount", result.get("failureCount") + 1);
+                }
             }
 
-            return true;
+            log.info("温湿度及气体浓度数据推送完成,设备类型:{},成功:{},失败:{}",
+                    deviceType, result.get("successCount"), result.get("failureCount"));
+
+            return result;
         } catch (Exception e) {
-            log.error("发送环境数据失败", e);
-            return false;
+            log.error("温湿度及气体浓度数据推送发生异常", e);
+            result.put("failureCount", transferVO.getDevices().size());
+            return result;
         }
     }
 
     /**
-     * 发送人员闯入情况
+     * 发送人员闯入情况(703)
      *
-     * @param vo 人员闯入
-     * @return 是否发送成功
+     * @return 推送结果,包含成功数和失败数
      **/
-    public boolean sendPersonPresence(PersonPresenceVO vo) {
-        if (mqttGateway == null) {
-            log.warn("MQTT Gateway未初始化,无法发送消息");
-            return false;
+    public Map<String, Integer> sendPersonPresence(IotDataTransferVO transferVO) {
+        Map<String, Integer> result = new HashMap<>();
+        result.put("successCount", 0);
+        result.put("failureCount", 0);
+
+        if (!validateMqttGateway()) {
+            return result;
         }
+
         try {
-            if (vo.getDataPacketID() == null) {
-                vo.setDataPacketID(generateDataPacketID());
+            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
+            Integer deviceType = transferVO.getDeviceType();
+            Integer totalDevices = transferVO.getDevices().size();
+
+            log.info("开始推送人员闯入情况数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
+                    deviceType, totalDevices, deviceData.size());
+
+            if (deviceData.isEmpty()) {
+                log.warn("没有获取到人员闯入情况数据!设备类型:{}", deviceType);
+                result.put("failureCount", totalDevices);
+                return result;
             }
-            if (vo.getPublishTime() == null) {
+
+            Long engineeringId = transferVO.getEngineeringId();
+            for (JSONObject deviceDataItem : deviceData) {
+                LocalDateTime dataEndTime = parseDataTime(deviceDataItem);
+                if (dataEndTime == null) {
+                    result.put("failureCount", result.get("failureCount") + 1);
+                    continue;
+                }
+
+                Integer deviceId = deviceDataItem.getIntValue("device_id");
+
+                PersonPresenceVO vo = new PersonPresenceVO();
+                vo.setDataPacketID(generateDataPacketID());
+                vo.setSensorID(deviceId);
+                vo.setDataEndTime(dataEndTime);
                 vo.setPublishTime(getCurrentTime());
+                vo.setEngineeringID(engineeringId);
+                // 传感器值固定为0(可能是默认值或占位符)
+                vo.setSensorValue(0);
+
+                try {
+                    sendMqttMessage(EnvMonitorMqttTopic.PERSON_PRESENCE, vo, "人员闯入情况");
+                    result.put("successCount", result.get("successCount") + 1);
+                } catch (Exception e) {
+                    log.warn("设备{}的人员闯入情况数据推送失败:{}", deviceId, e.getMessage());
+                    result.put("failureCount", result.get("failureCount") + 1);
+                }
             }
 
-            String json = JSON.toJSONString(vo);
-            String topic = EnvMonitorMqttTopic.PERSON_PRESENCE.getTopic();
-            log.info("发送人员闯入情况,Topic: {}, Data: {}", topic, json);
-            mqttGateway.sendToMqtt(topic, json);
-            return true;
+            log.info("人员闯入情况数据推送完成,设备类型:{},成功:{},失败:{}",
+                    deviceType, result.get("successCount"), result.get("failureCount"));
+
+            return result;
         } catch (Exception e) {
-            log.error("发送人员闯入情况失败", e);
-            return false;
+            log.error("人员闯入情况数据推送发生异常", e);
+            result.put("failureCount", transferVO.getDevices().size());
+            return result;
         }
     }
 
     /**
-     * 发送人防用电负荷情况
+     * 发送人防用电负荷情况(704)
      *
-     * @return 是否发送成功
+     * @return 推送结果,包含成功数和失败数
      **/
-    public boolean sendElectricityLoad() {
-        if (mqttGateway == null) {
-            log.warn("MQTT Gateway未初始化,无法发送消息");
-            return false;
+    public Map<String, Integer> sendElectricityLoad(IotDataTransferVO transferVO) {
+        Map<String, Integer> result = new HashMap<>();
+        result.put("successCount", 0);
+        result.put("failureCount", 0);
+
+        if (!validateMqttGateway()) {
+            return result;
         }
+
         try {
-            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(704);
+            List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
+            Integer deviceType = transferVO.getDeviceType();
+            Integer totalDevices = transferVO.getDevices().size();
 
+            log.info("开始推送人防用电负荷情况数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
+                    deviceType, totalDevices, deviceData.size());
+
+            if (deviceData.isEmpty()) {
+                log.warn("没有获取到人防用电负荷情况数据!设备类型:{}", deviceType);
+                result.put("failureCount", totalDevices);
+                return result;
+            }
+
+            Long engineeringId = transferVO.getEngineeringId();
             for (JSONObject deviceDataItem : deviceData) {
-                Long dataTime = deviceDataItem.getLong("time");
-                LocalDateTime dataEndTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dataTime), ZoneId.systemDefault());
-                Integer voltageA = deviceDataItem.getInteger("voltage_a");
-                Integer voltageB = deviceDataItem.getInteger("voltage_b");
-                Integer voltageC = deviceDataItem.getInteger("voltage_c");
-                Integer currentA = deviceDataItem.getInteger("current_a");
-                Integer currentB = deviceDataItem.getInteger("current_b");
-                Integer currentC = deviceDataItem.getInteger("current_c");
-                Integer temperatureA = deviceDataItem.getInteger("temperature_a");
-                Integer temperatureB = deviceDataItem.getInteger("temperature_b");
-                Integer temperatureC = deviceDataItem.getInteger("temperature_c");
-                Integer currentResidual = deviceDataItem.getInteger("current_residual");
+                LocalDateTime dataEndTime = parseDataTime(deviceDataItem);
+                if (dataEndTime == null) {
+                    result.put("failureCount", result.get("failureCount") + 1);
+                    continue;
+                }
 
+                Integer deviceId = deviceDataItem.getIntValue("device_id");
                 ElectricityLoadVO vo = new ElectricityLoadVO();
                 vo.setDataPacketID(generateDataPacketID());
-                vo.setSensorID(new Random().nextLong());
-                vo.setEngineeringID(new Random().nextLong());
+                vo.setSensorID(deviceId);
+                vo.setEngineeringID(engineeringId);
                 vo.setPublishTime(getCurrentTime());
                 vo.setDataEndTime(dataEndTime);
-                vo.setAVoltage(Float.valueOf(voltageA));
-                vo.setBVoltage(Float.valueOf(voltageB));
-                vo.setCVoltage(Float.valueOf(voltageC));
-                vo.setAElectricity(Float.valueOf(currentA));
-                vo.setBElectricity(Float.valueOf(currentB));
-                vo.setCElectricity(Float.valueOf(currentC));
-                vo.setLine1TEMP(Float.valueOf(temperatureA));
-                vo.setLine2TEMP(Float.valueOf(temperatureB));
-                vo.setLine3TEMP(Float.valueOf(temperatureC));
-                vo.setLeakageCurrent(Float.valueOf(currentResidual));
-                vo.setTotalPower(new Random().nextFloat() * 1000F);
-
-                String json = JSON.toJSONString(vo);
-                String topic = EnvMonitorMqttTopic.ELECTRICITY_LOAD.getTopic();
-                log.info("发送人防用电负荷情况,Topic: {}, Data: {}", topic, json);
-                mqttGateway.sendToMqtt(topic, json);
+                vo.setAVoltage(deviceDataItem.getFloat("aVoltage"));
+                vo.setBVoltage(deviceDataItem.getFloat("bVoltage"));
+                vo.setCVoltage(deviceDataItem.getFloat("cVoltage"));
+                vo.setAElectricity(deviceDataItem.getFloat("aElectricity"));
+                vo.setBElectricity(deviceDataItem.getFloat("bElectricity"));
+                vo.setCElectricity(deviceDataItem.getFloat("cElectricity"));
+                vo.setLine1TEMP(deviceDataItem.getFloat("line1TEMP"));
+                vo.setLine2TEMP(deviceDataItem.getFloat("Line2TEMP"));
+                vo.setLine3TEMP(deviceDataItem.getFloat("Line3TEMP"));
+                vo.setLeakageCurrent(deviceDataItem.getFloat("leakageCurrent"));
+
+                // 根据模拟模式选择不同的功率字段
+                vo.setTotalPower(simulation ?
+                        deviceDataItem.getFloat("totalPower") :
+                        deviceDataItem.getFloat("active_power"));
+
+                try {
+                    sendMqttMessage(EnvMonitorMqttTopic.ELECTRICITY_LOAD, vo, "人防用电负荷情况");
+                    result.put("successCount", result.get("successCount") + 1);
+                } catch (Exception e) {
+                    log.warn("设备{}的人防用电负荷情况数据推送失败:{}", deviceId, e.getMessage());
+                    result.put("failureCount", result.get("failureCount") + 1);
+                }
             }
-            return true;
+
+            log.info("人防用电负荷情况数据推送完成,设备类型:{},成功:{},失败:{}",
+                    deviceType, result.get("successCount"), result.get("failureCount"));
+
+            return result;
         } catch (Exception e) {
-            log.error("发送人防用电负荷情况失败", e);
+            log.error("人防用电负荷情况数据推送发生异常", e);
+            result.put("failureCount", transferVO.getDevices().size());
+            return result;
+        }
+    }
+
+    // 提取公共发送方法,减少代码冗余
+    private void sendTempData(Integer deviceId, LocalDateTime dataEndTime, JSONObject deviceDataItem, Long engineeringID) {
+        Float value = deviceDataItem.getFloat("wd");
+        if (value == null) {
+            log.warn("设备{}的温度数据为空", deviceId);
+            return;
+        }
+        TempVO tempVO = new TempVO();
+        tempVO.setDataPacketID(generateDataPacketID());
+        tempVO.setSensorID(deviceId);
+        tempVO.setEngineeringID(engineeringID);
+        tempVO.setPublishTime(getCurrentTime());
+        tempVO.setSensorValue(value);
+        tempVO.setDataEndTime(dataEndTime);
+        sendMqttMessage(EnvMonitorMqttTopic.TEMP, tempVO, "温度信息");
+    }
+
+    private void sendHumidityData(Integer deviceId, LocalDateTime dataEndTime, JSONObject deviceDataItem, Long engineeringID) {
+        Float value = deviceDataItem.getFloat("sd");
+        if (value == null) {
+            log.warn("设备{}的湿度数据为空", deviceId);
+            return;
+        }
+        HumidityVO humidityVO = new HumidityVO();
+        humidityVO.setDataPacketID(generateDataPacketID());
+        humidityVO.setSensorID(deviceId);
+        humidityVO.setEngineeringID(engineeringID);
+        humidityVO.setPublishTime(getCurrentTime());
+        humidityVO.setSensorValue(value);
+        humidityVO.setDataEndTime(dataEndTime);
+        sendMqttMessage(EnvMonitorMqttTopic.HUMIDITY, humidityVO, "湿度信息");
+    }
+
+    private void sendOxygenData(Integer deviceId, LocalDateTime dataEndTime, JSONObject deviceDataItem, Long engineeringID) {
+        Float value = deviceDataItem.getFloat("o2");
+        if (value == null) {
+            log.warn("设备{}的氧气浓度数据为空", deviceId);
+            return;
+        }
+        OxygenVO oxygenVO = new OxygenVO();
+        oxygenVO.setDataPacketID(generateDataPacketID());
+        oxygenVO.setSensorID(deviceId);
+        oxygenVO.setEngineeringID(engineeringID);
+        oxygenVO.setPublishTime(getCurrentTime());
+        oxygenVO.setSensorValue(value);
+        oxygenVO.setDataEndTime(dataEndTime);
+        sendMqttMessage(EnvMonitorMqttTopic.OXYGEN, oxygenVO, "氧气浓度信息");
+    }
+
+    private void sendCoData(Integer deviceId, LocalDateTime dataEndTime, JSONObject deviceDataItem, Long engineeringID) {
+        Float value = deviceDataItem.getFloat("co");
+        if (value == null) {
+            log.warn("设备{}的一氧化碳浓度数据为空", deviceId);
+            return;
+        }
+        CoVO coVO = new CoVO();
+        coVO.setDataPacketID(generateDataPacketID());
+        coVO.setSensorID(deviceId);
+        coVO.setEngineeringID(engineeringID);
+        coVO.setPublishTime(getCurrentTime());
+        coVO.setSensorValue(value);
+        coVO.setDataEndTime(dataEndTime);
+        sendMqttMessage(EnvMonitorMqttTopic.CO, coVO, "一氧化碳浓度信息");
+    }
+
+    private void sendCo2Data(Integer deviceId, LocalDateTime dataEndTime, JSONObject deviceDataItem, Long engineeringID) {
+        Float value = deviceDataItem.getFloat("co2");
+        if (value == null) {
+            log.warn("设备{}的二氧化碳浓度数据为空", deviceId);
+            return;
+        }
+        Co2VO co2VO = new Co2VO();
+        co2VO.setDataPacketID(generateDataPacketID());
+        co2VO.setSensorID(deviceId);
+        co2VO.setEngineeringID(engineeringID);
+        co2VO.setPublishTime(getCurrentTime());
+        co2VO.setSensorValue(value);
+        co2VO.setDataEndTime(dataEndTime);
+        sendMqttMessage(EnvMonitorMqttTopic.CO2, co2VO, "二氧化碳浓度信息");
+    }
+
+    /**
+     * 同步设备数据
+     * @param tenantId 租户ID
+     * @param engineeringId 工程ID
+     */
+    public void synchronizeDeviceData(Integer tenantId, Long engineeringId) {
+        // 参数校验
+        if (tenantId == null || engineeringId == null) {
+            log.error("租户ID或工程ID不能为空");
+            return;
+        }
+
+        // 查询租户下的所有产品类型
+        List<String> deviceTypeList = getDeviceTypeListByTenant(tenantId);
+        if (deviceTypeList.isEmpty()) {
+            log.warn("租户{}不存在任何产品", tenantId);
+            return;
+        }
+
+        // 查询设备列表
+        List<DmpDevice> deviceList = getDeviceListByType(deviceTypeList, tenantId);
+        if (deviceList.isEmpty()) {
+            log.warn("租户{}不存在任何设备", tenantId);
+            return;
+        }
+
+        // 按设备类型分组
+        Map<Integer, List<DmpDevice>> deviceTypeMap = deviceList.stream()
+                .collect(Collectors.groupingBy(DmpDevice::getDeviceType));
+
+        // 构建数据传输对象列表
+        List<IotDataTransferVO> transferList = new ArrayList<>();
+        deviceTypeMap.forEach((deviceType, devices) -> {
+            IotDataTransferVO transferVO = new IotDataTransferVO();
+            transferVO.setDeviceType(deviceType);
+            transferVO.setDevices(devices);
+            transferVO.setEngineeringId(engineeringId);
+            transferList.add(transferVO);
+        });
+
+        // 按产品代码分组,构建ProductCode到uuid列表的映射,过滤掉产品代码为null的设备
+        Map<String, List<String>> codeDeviceUuidsMap = deviceList.stream()
+                .filter(device -> device.getProductCode() != null)
+                .collect(Collectors.groupingBy(DmpDevice::getProductCode,
+                        Collectors.mapping(DmpDevice::getDeviceUuid, Collectors.toList())));
+
+        // 任务开始日志
+        Integer totalDevices = deviceList.size();
+        Integer totalProductTypes = codeDeviceUuidsMap.size();
+        log.info("设备数据同步任务开始,租户ID:{},工程ID:{}", tenantId, engineeringId);
+        log.info("总共涉及产品类型数:{}个,产品代码为:{}", totalProductTypes, codeDeviceUuidsMap.keySet());
+        log.info("总共需要推送设备数量:{}个,涉及设备类型数:{}个,设备类型为:{}",
+                totalDevices, deviceTypeMap.size(), deviceTypeMap.keySet());
+
+        // 记录每种设备类型的设备数量
+        deviceTypeMap.forEach((deviceType, devices) -> {
+            log.info("设备类型:{},设备数量:{}", deviceType, devices.size());
+        });
+
+        // 按设备类型处理数据同步
+        int totalSuccessCount = 0;
+        int totalFailureCount = 0;
+
+        for (IotDataTransferVO transferVO : transferList) {
+            Integer deviceType = transferVO.getDeviceType();
+            Map<String, Integer> result = new HashMap<>();
+
+            switch (deviceType) {
+                case 707:
+                case 708:
+                case 709:
+                case 710:
+                case 711:
+                    result = sendEnvData(transferVO);
+                    break;
+                case 702:
+                    result = sendWaterLeak(transferVO);
+                    break;
+                case 703:
+                    result = sendPersonPresence(transferVO);
+                    break;
+                case 704:
+                    result = sendElectricityLoad(transferVO);
+                    break;
+                default:
+                    log.debug("不支持的设备类型:{}", deviceType);
+                    continue;
+            }
+
+            // 累加成功数和失败数
+            totalSuccessCount += result.get("successCount");
+            totalFailureCount += result.get("failureCount");
+        }
+
+        // 任务完成总结
+        log.info("设备数据同步任务完成,租户ID:{},工程ID:{}", tenantId, engineeringId);
+        log.info("总共涉及产品类型数:{}个,产品代码为:{}", totalProductTypes, codeDeviceUuidsMap.keySet());
+        log.info("总共推送设备数量:{}个,成功:{}个,失败:{}个",
+                totalDevices, totalSuccessCount, totalFailureCount);
+    }
+
+    /**
+     * 查询租户下的设备类型列表
+     * @param tenantId 租户ID
+     * @return 设备类型列表
+     */
+    private List<String> getDeviceTypeListByTenant(Integer tenantId) {
+        LambdaQueryWrapper<DmpProduct> productQueryWrapper = new LambdaQueryWrapper<>();
+        productQueryWrapper.select(DmpProduct::getProductCode)
+                .eq(DmpProduct::getTenantId, tenantId)
+                .eq(DmpProduct::getDeleteFlag, 0);
+        List<DmpProduct> productList = dmpProductMapper.selectList(productQueryWrapper);
+        return productList.stream()
+                .map(DmpProduct::getProductCode)
+                .distinct() // 去重
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 根据设备类型列表查询设备
+     * @param productCodeList 设备类型列表
+     * @return 设备列表
+     */
+    private List<DmpDevice> getDeviceListByType(List<String> productCodeList, Integer tenantId) {
+        LambdaQueryWrapper<DmpDevice> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.select(DmpDevice::getDeviceUuid, DmpDevice::getDeviceType, DmpDevice::getDeviceId, DmpDevice::getProductCode)
+                .in(DmpDevice::getProductCode, productCodeList)
+                .eq(DmpDevice::getDeleteFlag, 0)
+                .notIn(DmpDevice::getServiceStatus, 3)
+                .orderByAsc(DmpDevice::getProductCode);
+        return dmpDeviceMapper.selectList(queryWrapper);
+    }
+
+    /**
+     * 验证MQTT网关是否初始化
+     * @return 是否初始化
+     */
+    private boolean validateMqttGateway() {
+        if (mqttGateway == null) {
+            log.warn("MQTT Gateway未初始化,无法发送消息");
             return false;
         }
+        return true;
     }
 
+    /**
+     * 解析数据时间
+     * @param deviceDataItem 设备数据
+     * @return 解析后的时间,如果解析失败返回null
+     */
+    private LocalDateTime parseDataTime(JSONObject deviceDataItem) {
+        Long dataTime = deviceDataItem.getLong("time");
+        if (dataTime == null) {
+            log.warn("设备{}的time为空", deviceDataItem.getString("device_id"));
+            return null;
+        }
+        return LocalDateTime.ofInstant(Instant.ofEpochMilli(dataTime), ZoneId.systemDefault());
+    }
 
-}
+    /**
+     * 发送MQTT消息
+     * @param topicEnum 主题枚举
+     * @param vo 消息对象
+     * @param messageType 消息类型描述
+     */
+    private void sendMqttMessage(EnvMonitorMqttTopic topicEnum, Object vo, String messageType) {
+        String json = JSON.toJSONString(vo);
+        String topic = topicEnum.getTopic();
+        // 不再记录每条数据的详情,只记录发送操作
+        mqttGateway.sendToMqtt(topic, json);
+    }
+}

+ 225 - 94
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/util/DeviceDataQuery.java

@@ -3,9 +3,9 @@ package com.usky.cdi.service.util;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.usky.cdi.domain.DmpDevice;
 import com.usky.cdi.mapper.DmpDeviceMapper;
+import com.usky.cdi.service.vo.IotDataTransferVO;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,7 +13,9 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
+import java.text.DecimalFormat;
 import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.stream.Collectors;
 
 /**
@@ -35,168 +37,297 @@ public class DeviceDataQuery {
     private boolean simulation;
     private Map<String, String> deviceFieldMapping;
 
+    // 定义各参数的格式化器(整数位,小数位)
+    private static final DecimalFormat FORMAT_2_2 = new DecimalFormat("00.00"); // 2位整数+2位小数
+    private static final DecimalFormat FORMAT_0_3 = new DecimalFormat("0.000"); // 0位整数+3位小数
+    private static final DecimalFormat FORMAT_3_2 = new DecimalFormat("000.00"); // 3位整数+2位小数
+    private static final DecimalFormat FORMAT_4_2 = new DecimalFormat("0000.00"); // 4位整数+2位小数
+
     /**
      * 获取指定设备类型的设备数据
+     * @param transferVO 设备数据传输请求参数
+     * @return 设备数据列表
      */
-    public List<JSONObject> getDeviceData(Integer deviceType) {
-        List<String> deviceUuids = getDeviceUuids(deviceType);
-        if (deviceUuids.isEmpty()) {
-            log.warn("该租户下没有注册设备!");
+    public List<JSONObject> getDeviceData(IotDataTransferVO transferVO) {
+        // 参数验证
+        if (transferVO == null || transferVO.getDevices() == null || transferVO.getDevices().isEmpty()) {
+            log.warn("获取设备数据失败:参数无效");
             return Collections.emptyList();
         }
 
-        JSONObject requestBody = new JSONObject();
-        requestBody.put("deviceUuids", deviceUuids);
-
-        String response = HttpClientUtils.doPostJson(baseUrl, String.valueOf(requestBody));
+        try {
+            // 构建请求参数
+            JSONObject requestBody = new JSONObject();
+            List<String> deviceUuids = transferVO.getDevices().stream()
+                    .map(DmpDevice::getDeviceUuid)
+                    .collect(Collectors.toList());
+            requestBody.put("deviceUuids", deviceUuids);
 
-        List<JSONObject> resultList = parseResponseData(response, deviceType);
+            log.debug("请求设备数据接口,设备数量:{}", deviceUuids.size());
+            String response = HttpClientUtils.doPostJson(baseUrl, requestBody.toJSONString());
 
-        if (resultList.isEmpty() && simulation) {
-            resultList = generateSimulationData(deviceType, deviceUuids);
-        }
+            List<JSONObject> resultList = parseResponseData(response, transferVO.getDeviceType(), transferVO.getDevices());
 
-        return resultList;
-
-    }
+            // 若返回数据为空且开启模拟模式,则生成模拟数据
+            if (resultList.isEmpty() && simulation) {
+                log.info("接口返回数据为空,生成模拟数据,设备类型:{}", transferVO.getDeviceType());
+                resultList = generateSimulationData(transferVO.getDeviceType(), transferVO.getDevices());
+            }
 
-    /**
-     * 获取指定设备类型的设备UUID列表
-     */
-    private List<String> getDeviceUuids(Integer deviceType) {
-        LambdaQueryWrapper<DmpDevice> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(DmpDevice::getTenantId, 1208)
-                .eq(deviceType != null, DmpDevice::getDeviceType, deviceType);
-        List<DmpDevice> dmpDevices = dmpDeviceMapper.selectList(queryWrapper);
-        return dmpDevices.stream().map(DmpDevice::getDeviceUuid).collect(Collectors.toList());
+            return resultList;
+        } catch (Exception e) {
+            log.error("获取设备数据失败:{}", e.getMessage(), e);
+            // 异常情况下若开启模拟模式,则生成模拟数据
+            if (simulation) {
+                log.info("接口调用异常,生成模拟数据,设备类型:{}", transferVO.getDeviceType());
+                return generateSimulationData(transferVO.getDeviceType(), transferVO.getDevices());
+            }
+            return Collections.emptyList();
+        }
     }
 
     /**
      * 解析接口响应数据,提取指定字段
+     * @param responseJson 接口响应JSON字符串
+     * @param deviceType 设备类型
+     * @param devices 设备列表
+     * @return 解析后的设备数据列表
      */
-    private List<JSONObject> parseResponseData(String responseJson, Integer deviceType) {
+    private List<JSONObject> parseResponseData(String responseJson, Integer deviceType, List<DmpDevice> devices) {
         List<JSONObject> resultList = new ArrayList<>();
-        if (responseJson == null) {
+        if (responseJson == null || responseJson.trim().isEmpty()) {
+            log.warn("接口响应数据为空");
             return resultList;
         }
 
-        JSONObject responseObj = JSON.parseObject(responseJson);
-        if (!"SUCCESS".equals(responseObj.getString("status")) || !"0".equals(responseObj.getString("code"))) {
-            System.err.println("接口返回失败:" + responseObj.getString("msg"));
-            return resultList;
-        }
+        try {
+            // 构建设备UUID到ID的映射,过滤掉deviceUuid为null的设备
+            Map<String, String> deviceUuidToIdMap = devices.stream()
+                    .filter(device -> device.getDeviceUuid() != null)
+                    .collect(Collectors.toMap(DmpDevice::getDeviceUuid, DmpDevice::getDeviceId));
 
-        JSONArray dataArray = responseObj.getJSONArray("data");
-        if (dataArray == null || dataArray.isEmpty()) {
-            return resultList;
-        }
+            JSONObject responseObj = JSON.parseObject(responseJson);
 
-        List<String> targetFields = getTargetFieldsByDeviceType(deviceType);
+            // 检查响应状态
+            String status = responseObj.getString("status");
+            String code = responseObj.getString("code");
 
-        for (int i = 0; i < dataArray.size(); i++) {
-            JSONObject deviceData = dataArray.getJSONObject(i);
-            JSONObject metrics = deviceData.getJSONObject("metrics");
-            String deviceUuid = deviceData.getString("deviceuuid");
+            if (!"SUCCESS".equals(status) || !"0".equals(code)) {
+                log.warn("接口返回失败:状态={}, 错误码={}, 错误信息={}", status, code, responseObj.getString("msg"));
+                return resultList;
+            }
 
-            if (metrics == null) {
-                continue;
+            JSONArray dataArray = responseObj.getJSONArray("data");
+            if (dataArray == null || dataArray.isEmpty()) {
+                log.debug("接口响应数据为空数组");
+                return resultList;
             }
 
-            JSONObject targetData = new JSONObject();
-            boolean hasValidData = false;
-            for (String field : targetFields) {
-                Object value = metrics.get(field);
-                if (value != null) {
-                    targetData.put(field, value);
-                    hasValidData = true;
+            List<String> targetFields = getTargetFieldsByDeviceType(deviceType);
+
+            for (int i = 0; i < dataArray.size(); i++) {
+                JSONObject deviceData = dataArray.getJSONObject(i);
+                if (deviceData == null) {
+                    continue;
+                }
+
+                JSONObject metrics = deviceData.getJSONObject("metrics");
+                String deviceUuid = deviceData.getString("deviceuuid");
+
+                if (metrics == null || deviceUuid == null) {
+                    continue;
+                }
+
+                JSONObject targetData = new JSONObject();
+                boolean hasValidData = false;
+
+                // 提取目标字段数据
+                for (String field : targetFields) {
+                    Object value = metrics.get(field);
+                    if (value != null) {
+                        targetData.put(field, value);
+                        hasValidData = true;
+                    }
+                }
+
+                // 添加设备标识信息
+                targetData.put("deviceuuid", deviceUuid);
+                String deviceId = deviceUuidToIdMap.get(deviceUuid);
+                if (deviceId != null) {
+                    targetData.put("device_id", deviceId);
                 }
-            }
 
-            targetData.put("deviceuuid", deviceUuid);
-            if (hasValidData) {
-                resultList.add(targetData);
+                if (hasValidData) {
+                    resultList.add(targetData);
+                }
             }
-        }
 
-        return resultList;
+            log.debug("解析接口响应数据完成,有效设备数据数量:{}", resultList.size());
+            return resultList;
+        } catch (Exception e) {
+            log.error("解析接口响应数据失败:{}", e.getMessage(), e);
+            return Collections.emptyList();
+        }
     }
 
     /**
      * 根据设备类型获取目标字段(自动包含time)
+     * @param deviceType 设备类型
+     * @return 目标字段列表
      */
     private List<String> getTargetFieldsByDeviceType(Integer deviceType) {
+        if (deviceType == null) {
+            log.warn("获取目标字段失败:设备类型为空");
+            return Collections.singletonList("time");
+        }
+
         String fieldsStr = deviceFieldMapping.get(deviceType.toString());
+        if (fieldsStr == null || fieldsStr.trim().isEmpty()) {
+            log.warn("获取目标字段失败:设备类型{}对应的字段映射不存在", deviceType);
+            return Collections.singletonList("time");
+        }
+
         List<String> fields = Arrays.stream(fieldsStr.split(","))
                 .map(String::trim)
+                .filter(field -> !field.isEmpty())
                 .collect(Collectors.toList());
+
+        // 确保包含时间字段
         if (!fields.contains("time")) {
             fields.add("time");
         }
+
         return fields;
     }
 
     /**
-     * 生成模拟数据
+     * 生成模拟数据(按指定精度格式化)
+     * @param deviceType 设备类型
+     * @param devices 设备列表
+     * @return 模拟数据列表
      */
-    private List<JSONObject> generateSimulationData(Integer deviceType, List<String> deviceUuids) {
+    private List<JSONObject> generateSimulationData(Integer deviceType, List<DmpDevice> devices) {
         List<JSONObject> simulationList = new ArrayList<>();
         long currentTime = System.currentTimeMillis();
 
-        for (String deviceUuid : deviceUuids) {
+        // 定义模拟数据范围常量
+        final double TEMP_RANGE_MIN = 10.0;
+        final double TEMP_RANGE_MAX = 20.0;
+        final double HUMIDITY_RANGE_MIN = 40.0;
+        final double HUMIDITY_RANGE_MAX = 85.0;
+        final double OXYGEN_RANGE_MIN = 20.0;
+        final double OXYGEN_RANGE_MAX = 21.0;
+        final double CO2_RANGE_MIN = 750.0;
+        final double CO2_RANGE_MAX = 760.0;
+        final double VOLTAGE_RANGE_MIN = 220.0;
+        final double VOLTAGE_RANGE_MAX = 230.0;
+        final double CURRENT_RANGE_MIN = 0.0;
+        final double CURRENT_RANGE_MAX = 50.0;
+        final double POWER_RANGE_MIN = 1.0;
+        final double POWER_RANGE_MAX = 20.0;
+        final double TEMP_LINE_RANGE_MIN = 20.0;
+        final double TEMP_LINE_RANGE_MAX = 50.0;
+        final double LEAKAGE_CURRENT_RANGE_MIN = 0.0;
+        final double LEAKAGE_CURRENT_RANGE_MAX = 100.0;
+
+        for (DmpDevice device : devices) {
             JSONObject simulationData = new JSONObject();
-            // simulationData.put("deviceuuid", deviceUuid);
             simulationData.put("time", currentTime);
+            simulationData.put("device_id", device.getDeviceId());
+
+            if (deviceType == null) {
+                log.warn("生成模拟数据失败:设备类型为空,设备ID:{}", device.getId());
+                continue;
+            }
 
             switch (deviceType) {
-                // 空气质量
-                case 701:
-                    simulationData.put("wd", new Random().nextInt(50) - 10); // 温度:-10~40℃
-                    simulationData.put("sd", new Random().nextInt(101)); // 湿度:0~100%
-                    simulationData.put("o2", new Random().nextDouble() * 21); // 氧气:0~21%
-                    simulationData.put("co", new Random().nextDouble() * 100); // 一氧化碳:0~100ppm
-                    simulationData.put("co2", new Random().nextDouble() * 2000); // 二氧化碳:0~2000ppm
+                // 单一温度传感器(707)
+                case 707:
+                    double temp707 = ThreadLocalRandom.current().nextDouble(TEMP_RANGE_MIN, TEMP_RANGE_MAX);
+                    simulationData.put("wd", formatNumber(temp707, FORMAT_2_2));
+                    break;
+
+                // 单一湿度传感器(708)
+                case 708:
+                    double hum708 = ThreadLocalRandom.current().nextDouble(HUMIDITY_RANGE_MIN, HUMIDITY_RANGE_MAX);
+                    simulationData.put("sd", formatNumber(hum708, FORMAT_2_2));
+                    break;
+
+                // 单一氧气传感器(709)
+                case 709:
+                    double o2709 = ThreadLocalRandom.current().nextDouble(OXYGEN_RANGE_MIN, OXYGEN_RANGE_MAX);
+                    simulationData.put("o2", formatNumber(o2709, FORMAT_2_2));
+                    break;
+
+                // 单一二氧化碳传感器(710)
+                case 710:
+                    double co2710 = ThreadLocalRandom.current().nextDouble(CO2_RANGE_MIN, CO2_RANGE_MAX);
+                    simulationData.put("co2", formatNumber(co2710, FORMAT_0_3));
                     break;
-                // 水浸
+
+                // 单一一氧化碳传感器(711)
+                case 711:
+                    simulationData.put("co", 0);
+                    break;
+
+                // 水浸(702)
                 case 702:
-                    // 渗漏状态:0-正常,1-渗漏
-                    simulationData.put("leach_status", new Random().nextInt(2));
+                    simulationData.put("leach_status", 0);
                     break;
-                // 人员统计
+
+                // 人员统计(703)
                 case 703:
-                    // 流量数据:模拟正数
-                    simulationData.put("amount_into", new Random().nextDouble() * 100);
-                    simulationData.put("amount_out", new Random().nextDouble() * 100);
-                    simulationData.put("day_into", new Random().nextDouble() * 1000);
-                    simulationData.put("day_out", new Random().nextDouble() * 1000);
+                    simulationData.put("sensorValue", 0);
                     break;
-                // 电气火灾
+
+                // 电气火灾(704)
                 case 704:
-                    // 电气参数:模拟合理范围
-                    simulationData.put("voltage_a", 220 + new Random().nextDouble() * 10); // 电压A:220~230V
-                    simulationData.put("voltage_b", 220 + new Random().nextDouble() * 10);
-                    simulationData.put("voltage_c", 220 + new Random().nextDouble() * 10);
-                    simulationData.put("current_a", new Random().nextDouble() * 50); // 电流A:0~50A
-                    simulationData.put("current_b", new Random().nextDouble() * 50);
-                    simulationData.put("current_c", new Random().nextDouble() * 50);
-                    simulationData.put("temperature_a", 20 + new Random().nextDouble() * 30); // 线温A:20~50℃
-                    simulationData.put("temperature_b", 20 + new Random().nextDouble() * 30);
-                    simulationData.put("temperature_c", 20 + new Random().nextDouble() * 30);
-                    simulationData.put("current_residual", new Random().nextDouble() * 100); // 剩余电流:0~1A
-                    break;
-                // 电能采集
-                case 705:
-                    // 电能:模拟正数
-                    simulationData.put("electrical_energy", new Random().nextDouble() * 10000);
+                    // A/B/C相电压:3位整数+2位小数(220.00~230.00V)
+                    simulationData.put("aVoltage", formatNumber(ThreadLocalRandom.current().nextDouble(VOLTAGE_RANGE_MIN, VOLTAGE_RANGE_MAX), FORMAT_3_2));
+                    simulationData.put("bVoltage", formatNumber(ThreadLocalRandom.current().nextDouble(VOLTAGE_RANGE_MIN, VOLTAGE_RANGE_MAX), FORMAT_3_2));
+                    simulationData.put("cVoltage", formatNumber(ThreadLocalRandom.current().nextDouble(VOLTAGE_RANGE_MIN, VOLTAGE_RANGE_MAX), FORMAT_3_2));
+
+                    // A/B/C相电流:3位整数+2位小数(0.00~50.00A)
+                    simulationData.put("aElectricity", formatNumber(ThreadLocalRandom.current().nextDouble(CURRENT_RANGE_MIN, CURRENT_RANGE_MAX), FORMAT_3_2));
+                    simulationData.put("bElectricity", formatNumber(ThreadLocalRandom.current().nextDouble(CURRENT_RANGE_MIN, CURRENT_RANGE_MAX), FORMAT_3_2));
+                    simulationData.put("cElectricity", formatNumber(ThreadLocalRandom.current().nextDouble(CURRENT_RANGE_MIN, CURRENT_RANGE_MAX), FORMAT_3_2));
+
+                    // 总功率:4位整数+2位小数(1.00~20.00)
+                    simulationData.put("totalPower", formatNumber(ThreadLocalRandom.current().nextDouble(POWER_RANGE_MIN, POWER_RANGE_MAX), FORMAT_4_2));
+
+                    // 线温1-4:2位整数+2位小数(20.00~50.00℃)
+                    simulationData.put("line1TEMP", formatNumber(ThreadLocalRandom.current().nextDouble(TEMP_LINE_RANGE_MIN, TEMP_LINE_RANGE_MAX), FORMAT_2_2));
+                    simulationData.put("Line2TEMP", formatNumber(ThreadLocalRandom.current().nextDouble(TEMP_LINE_RANGE_MIN, TEMP_LINE_RANGE_MAX), FORMAT_2_2));
+                    simulationData.put("Line3TEMP", formatNumber(ThreadLocalRandom.current().nextDouble(TEMP_LINE_RANGE_MIN, TEMP_LINE_RANGE_MAX), FORMAT_2_2));
+                    simulationData.put("Line4TEMP", formatNumber(ThreadLocalRandom.current().nextDouble(TEMP_LINE_RANGE_MIN, TEMP_LINE_RANGE_MAX), FORMAT_2_2));
+
+                    // 剩余电流:4位整数+2位小数(0.00~100.00mA)
+                    simulationData.put("leakageCurrent", formatNumber(ThreadLocalRandom.current().nextDouble(LEAKAGE_CURRENT_RANGE_MIN, LEAKAGE_CURRENT_RANGE_MAX), FORMAT_4_2));
                     break;
+
                 default:
+                    log.warn("未知设备类型:{},无法生成模拟数据", deviceType);
                     break;
             }
 
             simulationList.add(simulationData);
         }
 
-        System.out.println("生成模拟数据,设备类型:" + deviceType + ",数量:" + simulationList.size());
+        log.info("生成模拟数据完成,设备类型:{},数量:{}", deviceType, simulationList.size());
         return simulationList;
     }
 
+    /**
+     * 通用数值格式化方法
+     * @param value 原始数值
+     * @param format 格式化器
+     * @return 格式化后的字符串
+     */
+    private String formatNumber(double value, DecimalFormat format) {
+        if (format == null) {
+            return String.valueOf(value);
+        }
+        return format.format(value);
+    }
+
 }

+ 41 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/util/DeviceDataSyncService.java

@@ -0,0 +1,41 @@
+package com.usky.cdi.service.util;
+
+import com.usky.cdi.service.impl.IotDataTransferService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * 设备数据同步组件(包含定时任务)
+ */
+@Slf4j
+@Component
+public class DeviceDataSyncService {
+
+    private final IotDataTransferService iotDataTransferService;
+
+    @Autowired
+    public DeviceDataSyncService(IotDataTransferService iotDataTransferService) {
+        this.iotDataTransferService = iotDataTransferService;
+    }
+
+    /**
+     * 定时任务:定期执行设备数据同步上报
+     * fixedDelay:任务执行完成后固定延迟29分钟执行下一次
+     * initialDelay:初始化后立即执行第一次任务
+     */
+    @Scheduled(fixedDelay = 29 * 60 * 1000, initialDelay = 0)
+    public void scheduledDeviceDataSync() {
+        Integer tenantId = 1205;
+        Long engineeringId = 3101070011L;
+        log.info("开始执行设备数据同步定时任务,租户ID:{},工程ID:{}", tenantId, engineeringId);
+
+        try {
+            iotDataTransferService.synchronizeDeviceData(tenantId, engineeringId);
+        } catch (Exception e) {
+            log.error("定时任务执行设备数据同步失败:{}", e.getMessage(), e);
+        }
+    }
+}

+ 28 - 0
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/vo/IotDataTransferVO.java

@@ -0,0 +1,28 @@
+package com.usky.cdi.service.vo;
+
+import com.usky.cdi.domain.DmpDevice;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author fu
+ * @date 2025/12/08 10:02
+ */
+@Data
+public class IotDataTransferVO {
+    /**
+     * 设备UUID列表
+     */
+    private List<DmpDevice> devices;
+
+    /**
+     * 人防工程ID
+     */
+    private Long engineeringId;
+
+    /**
+     * 产品ID
+     */
+    private Integer deviceType;
+}

+ 1 - 1
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/vo/base/BaseEnvMonitorPushVO.java

@@ -35,7 +35,7 @@ public abstract class BaseEnvMonitorPushVO implements Serializable {
      * 物联设施ID(必填)
      * 类型:Int,长度8(0 ~ 99999999)
      */
-    private Long sensorID;
+    private Integer sensorID;
 
     /**
      * 监测时间(必填)

+ 0 - 11
service-cdi/service-cdi-biz/src/main/java/com/usky/cdi/service/vo/base/ElectricityLoadVO.java

@@ -20,11 +20,6 @@ public class ElectricityLoadVO extends BaseEnvMonitorPushVO {
     private static final long serialVersionUID = 1L;
 
     // ====================== 专属字段(严格映射数据包定义)======================
-    /**
-     * 物联设施ID(必填)
-     * 类型:Int,长度8(0 ~ 99999999)
-     */
-    private Long sensorID;
 
     /**
      * A相电压(必填)
@@ -114,7 +109,6 @@ public class ElectricityLoadVO extends BaseEnvMonitorPushVO {
     @Override
     protected void validateSensorValue() {
         // 1. 必填字段非空校验(父类已校验公共字段,此处校验专属必填字段)
-        if (sensorID == null) throw new IllegalArgumentException("物联设施ID(sensorID)为必填项");
         if (aVoltage == null) throw new IllegalArgumentException("A相电压(aVoltage)为必填项");
         if (bVoltage == null) throw new IllegalArgumentException("B相电压(bVoltage)为必填项");
         if (cVoltage == null) throw new IllegalArgumentException("C相电压(cVoltage)为必填项");
@@ -138,11 +132,6 @@ public class ElectricityLoadVO extends BaseEnvMonitorPushVO {
         if (line3TEMP != null) validateFloatRange(line3TEMP, -99.99f, 99.99f, "线温3", 2);
         if (line4TEMP != null) validateFloatRange(line4TEMP, -99.99f, 99.99f, "线温4", 2);
         if (leakageCurrent != null) validateFloatRange(leakageCurrent, 0.00f, 9999.99f, "剩余电流", 2);
-
-        // 4. 物联设施ID长度校验
-        if (String.valueOf(sensorID).length() > 8) {
-            throw new IllegalArgumentException("物联设施ID(sensorID)长度不能超过8位");
-        }
     }
 
     /**

+ 1 - 1
service-cdi/service-cdi-biz/src/main/resources/bootstrap.yml

@@ -1,6 +1,6 @@
 # Tomcat
 server:
-  port: 9893
+  port: 9901
 
 # Spring
 spring: 

+ 2 - 2
service-cdi/service-cdi-biz/src/main/resources/logback.xml

@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration scan="true" scanPeriod="60 seconds" debug="false">
     <!-- 日志存放路径 -->
-    <property name="log.path" value="/var/log/uskycloud/service-offline" />
+    <property name="log.path" value="/var/log/uskycloud/service-cdi" />
     <!-- 日志输出格式 -->
     <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.iot.mapper"/>
+    <property name="SQL_PACKAGE" value="com.usky.cdi.mapper"/>
 
     <!-- 控制台输出 -->
     <appender name="console" class="ch.qos.logback.core.ConsoleAppender">

+ 0 - 30
service-cdi/service-cdi-biz/src/main/resources/mapper.cdi/DmpDeviceMapper.xml

@@ -1,30 +0,0 @@
-<?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.alarm.mapper.DmpDeviceMapper">
-
-    <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.usky.cdi.domain.DmpDevice">
-        <id column="id" property="id" />
-        <result column="device_id" property="deviceId" />
-        <result column="device_name" property="deviceName" />
-        <result column="device_type" property="deviceType" />
-        <result column="product_id" property="productId" />
-        <result column="sim_code" property="simCode" />
-        <result column="imsi_code" property="imsiCode" />
-        <result column="subscribe_flag" property="subscribeFlag" />
-        <result column="node_type" property="nodeType" />
-        <result column="group_id" property="groupId" />
-        <result column="delete_flag" property="deleteFlag" />
-        <result column="created_by" property="createdBy" />
-        <result column="created_time" property="createdTime" />
-        <result column="updated_by" property="updatedBy" />
-        <result column="updated_time" property="updatedTime" />
-        <result column="tenant_id" property="tenantId" />
-        <result column="company_code" property="companyCode" />
-        <result column="install_address" property="installAddress" />
-        <result column="service_status" property="serviceStatus" />
-        <result column="product_code" property="productCode" />
-        <result column="device_uuid" property="deviceUuid" />
-    </resultMap>
-
-</mapper>

+ 32 - 0
service-cdi/service-cdi-biz/src/main/resources/mapper/cdi/DmpProductMapper.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.cdi.mapper.DmpProductMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.cdi.domain.DmpProduct">
+        <id column="id" property="id" />
+        <result column="product_name" property="productName" />
+        <result column="access_mode" property="accessMode" />
+        <result column="network_type" property="networkType" />
+        <result column="device_type" property="deviceType" />
+        <result column="com_protocol" property="comProtocol" />
+        <result column="auth_mode" property="authMode" />
+        <result column="device_model" property="deviceModel" />
+        <result column="product_describe" property="productDescribe" />
+        <result column="factory_name" property="factoryName" />
+        <result column="factory_person" property="factoryPerson" />
+        <result column="factory_phone" property="factoryPhone" />
+        <result column="certificate_url1" property="certificateUrl1" />
+        <result column="certificate_url2" property="certificateUrl2" />
+        <result column="certificate_url3" property="certificateUrl3" />
+        <result column="agreement_url" property="agreementUrl" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="created_by" property="createdBy" />
+        <result column="created_time" property="createdTime" />
+        <result column="updated_by" property="updatedBy" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="product_code" property="productCode" />
+    </resultMap>
+
+</mapper>

+ 3 - 3
service-cdi/service-cdi-biz/src/main/resources/smart-doc.json

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

+ 0 - 13
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/ServletInitializer.java

@@ -1,13 +0,0 @@
-package com.usky.cockpit;
-
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
-
-public class ServletInitializer extends SpringBootServletInitializer {
-
-	@Override
-	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
-		return application.sources(RuoYiSystemApplication.class);
-	}
-
-}

+ 0 - 116
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/base/BaseController.java

@@ -1,116 +0,0 @@
-package com.usky.cockpit.common.base;
-
-import com.usky.cockpit.common.domain.AjaxResult;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.InitBinder;
-import java.beans.PropertyEditorSupport;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * web层通用数据处理
- * 
- * @ClassName: BaseController
- * @author fuce
- * @date 2018年8月18日
- *
- */
-
-public class BaseController {
-
-	/**
-	 * 将前台传递过来的日期格式的字符串,自动转化为Date类型
-	 */
-	@InitBinder
-	public void initBinder(WebDataBinder binder) {
-		// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-		// dateFormat.setLenient(false);
-		binder.registerCustomEditor(Date.class, new MyDateEditor());
-	}
-
-	private class MyDateEditor extends PropertyEditorSupport {
-		@Override
-		public void setAsText(String text) throws IllegalArgumentException {
-			// 通过两次异常的处理可以,绑定两次日期的格式
-			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-			Date date = null;
-			try {
-				date = format.parse(text);
-			} catch (ParseException e) {
-				format = new SimpleDateFormat("yyyy-MM-dd");
-				try {
-					date = format.parse(text);
-				} catch (ParseException e1) {
-					format = new SimpleDateFormat("yyyy/MM/dd H:mm");
-					try {
-						date = format.parse(text);
-					} catch (ParseException e2) {
-						e2.printStackTrace();
-					}
-				}
-			}
-			setValue(date);
-		}
-	}
-
-	/**
-	 * 响应返回结果
-	 * 
-	 * @param rows 影响行数
-	 * @return 操作结果
-	 */
-	protected AjaxResult toAjax(int rows) {
-		return rows > 0 ? success() : error();
-	}
-
-	/**
-	 * 返回成功
-	 */
-	public AjaxResult success() {
-		return AjaxResult.success();
-	}
-
-	/**
-	 * 返回失败消息
-	 */
-	public AjaxResult error() {
-		return AjaxResult.error();
-	}
-
-	public AjaxResult successData(int code, Object value) {
-		AjaxResult json = new AjaxResult();
-		json.put("code", code);
-		json.put("data", value);
-		return json;
-	}
-
-	/**
-	 * 返回成功消息
-	 */
-	public AjaxResult success(String message) {
-		return AjaxResult.success(message);
-	}
-
-	/**
-	 * 返回失败消息
-	 */
-	public AjaxResult error(String message) {
-		return AjaxResult.error(message);
-	}
-
-	/**
-	 * 返回错误码消息
-	 */
-	public AjaxResult error(int code, String message) {
-		return AjaxResult.error(code, message);
-	}
-
-	/**
-	 * 返回object数据
-	 */
-	public AjaxResult retobject(int code, Object data) {
-		return AjaxResult.successData(code, data);
-	}
-
-}

+ 0 - 24
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/CorsConfig.java

@@ -1,24 +0,0 @@
-//package com.usky.cockpit.common.config;
-//
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.web.servlet.config.annotation.CorsRegistry;
-//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-//
-////重写WebMvcConfigurer实现全局跨域配置
-//@Configuration
-//public class CorsConfig implements WebMvcConfigurer{
-//	@Override
-//    public void addCorsMappings(CorsRegistry registry) {
-//        	registry.addMapping("/**")
-//            // 是否发送Cookie
-//            .allowCredentials(true)
-//            // 放行哪些原始域
-//            .allowedOrigins("*")
-//            // 放行哪些请求方式
-//            .allowedMethods("GET", "POST", "PUT", "DELETE")
-//            // 放行哪些原始请求头部信息
-//            .allowedHeaders("*")
-//            // 暴露哪些头部信息
-//            .exposedHeaders("*");
-//    }
-//}

+ 0 - 16
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/DateStringConvert.java

@@ -1,16 +0,0 @@
-package com.usky.cockpit.common.config;
-
-import com.usky.common.core.util.DateUtils;
-import org.springframework.core.convert.converter.Converter;
-
-import java.util.Date;
-
-/**
- * @author han
- */
-public class DateStringConvert implements Converter<Date, String> {
-    @Override
-    public String convert(Date source) {
-        return DateUtils.format(source);
-    }
-}

+ 0 - 20
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/MybatisPlusConfig.java

@@ -1,20 +0,0 @@
-package com.usky.cockpit.common.config;
-
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class MybatisPlusConfig {
-	 /**
-     * 新的分页插件,一缓和二缓遵循mybatis的规则,
-     */
-    @Bean
-    public MybatisPlusInterceptor mybatisPlusInterceptor() {
-        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
-        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.SQLITE));
-        return interceptor;
-    }
-}

+ 0 - 16
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/StringDateConverter.java

@@ -1,16 +0,0 @@
-package com.usky.cockpit.common.config;
-
-import com.usky.common.core.util.DateUtils;
-import org.springframework.core.convert.converter.Converter;
-
-import java.util.Date;
-
-/**
- * @author yq
- */
-public class StringDateConverter implements Converter<String, Date> {
-    @Override
-    public Date convert(String source) {
-        return DateUtils.parseDate(source);
-    }
-}

+ 0 - 72
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/config/V2Config.java

@@ -1,72 +0,0 @@
-package com.usky.cockpit.common.config;
-
-import java.util.Map;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.stereotype.Component;
-
-/**
- * 读取项目相关配置
- * 
- * @author fuce
- */
-@Component
-@Configuration
-public class V2Config {
-
-	/**
-	 * 存储路径
-	 */
-	private String fileurl;
-	/**
-	 * 请求url
-	 */
-	private String httpurl;
-	/**
-	 * 虚拟路径map
-	 */
-	private Map<String, String> xnljmap;
-	
-	/**
-	 * 默认文件格式
-	 */
-	private String defaultFormat;
-	
-
-	public String getFileurl() {
-		return fileurl;
-	}
-
-	public void setFileurl(String fileurl) {
-		this.fileurl = fileurl;
-	}
-
-	
-
-	
-
-	public String getHttpurl() {
-		return httpurl;
-	}
-
-	public void setHttpurl(String httpurl) {
-		this.httpurl = httpurl;
-	}
-
-	public Map<String, String> getXnljmap() {
-		return xnljmap;
-	}
-
-	public void setXnljmap(Map<String, String> xnljmap) {
-		this.xnljmap = xnljmap;
-	}
-
-	public String getDefaultFormat() {
-		return defaultFormat;
-	}
-
-	public void setDefaultFormat(String defaultFormat) {
-		this.defaultFormat = defaultFormat;
-	}
-	
-	
-}

+ 0 - 104
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/domain/AjaxResult.java

@@ -1,104 +0,0 @@
-package com.usky.cockpit.common.domain;
-
-import java.util.HashMap;
-
-/**
-* @ClassName: AjaxResult
-* @Description: ajax操作消息提醒
-* @author fuce
-* @date 2018年8月18日
-*
- */
-public class AjaxResult extends HashMap<String, Object>
-{
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 初始化一个新创建的 Message 对象
-     */
-    public AjaxResult()
-    {
-    }
-
-    /**
-     * 返回错误消息
-     * 
-     * @return 错误消息
-     */
-    public static AjaxResult error()
-    {
-        return error(500, "操作失败");
-    }
-
-    /**
-     * 返回错误消息
-     * 
-     * @param msg 内容
-     * @return 错误消息
-     */
-    public static AjaxResult error(String msg)
-    {
-        return error(500, msg);
-    }
-
-    /**
-     * 返回错误消息
-     * 
-     * @param code 错误码
-     * @param msg 内容
-     * @return 错误消息
-     */
-    public static AjaxResult error(int code, String msg)
-    {
-        AjaxResult json = new AjaxResult();
-        json.put("code", code);
-        json.put("msg", msg);
-        return json;
-    }
-
-    /**
-     * 返回成功消息
-     * 
-     * @param msg 内容
-     * @return 成功消息
-     */
-    public static AjaxResult success(String msg)
-    {
-        AjaxResult json = new AjaxResult();
-        json.put("msg", msg);
-        json.put("code", 200);
-        return json;
-    }
-    
-    /**
-     * 返回成功消息
-     * 
-     * @return 成功消息
-     */
-    public static AjaxResult success()
-    {
-        return AjaxResult.success("操作成功");
-    }
-    
-    public static AjaxResult successData(int code, Object value){
-    	 AjaxResult json = new AjaxResult();
-    	 json.put("code", code);
-         json.put("data", value);
-         return json;
-    }
-   
-    
-    /**
-     * 返回成功消息
-     * 
-     * @param key 键值
-     * @param value 内容
-     * @return 成功消息
-     */
-    @Override
-    public AjaxResult put(String key, Object value)
-    {
-        super.put(key, value);
-        return this;
-    }
-}

+ 0 - 84
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/domain/ResultTable.java

@@ -1,84 +0,0 @@
-package com.usky.cockpit.common.domain;
-
-public class ResultTable {
-     /**
-     * 状态码
-     * */
-    private Integer code;
-
-    /**
-     * 提示消息
-     * */
-    private String msg;
-
-    /**
-     * 消息总量
-     * */
-    private Long count;
-
-    /**
-     * 数据对象
-     * */
-    private Object data;
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public void setCode(Integer code) {
-        this.code = code;
-    }
-
-    public String getMsg() {
-        return msg;
-    }
-
-    public void setMsg(String msg) {
-        this.msg = msg;
-    }
-
-    public Long getCount() {
-        return count;
-    }
-
-    public void setCount(Long count) {
-        this.count = count;
-    }
-
-    public Object getData() {
-        return data;
-    }
-
-    public void setData(Object data) {
-        this.data = data;
-    }
-
-    /**
-     * 构 建
-     * */
-    public static ResultTable pageTable(long count,Object data){
-        ResultTable resultTable = new ResultTable();
-        resultTable.setData(data);
-        resultTable.setCode(0);
-        resultTable.setCount(count);
-        if(data!=null) {
-       	 resultTable.setMsg("获取成功");
-       }else {
-       	 resultTable.setMsg("获取失败");
-       }
-        return resultTable;
-    }
-
-    public static ResultTable dataTable(Object data){
-        ResultTable resultTable = new ResultTable();
-        resultTable.setData(data);
-        resultTable.setCode(0);
-        if(data!=null) {
-        	 resultTable.setMsg("获取成功");
-        }else {
-        	 resultTable.setMsg("获取失败");
-        }
-       
-        return resultTable;
-    }
-}

+ 0 - 50
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/domain/Tablepar.java

@@ -1,50 +0,0 @@
-package com.usky.cockpit.common.domain;
-
-/**
- * boostrap table post 参数
- * @author fc
- *
- */
-public class Tablepar {
-	private int page;//页码
-	private int limit;//数量
-	private String orderByColumn;//排序字段
-	private String isAsc;//排序字符 asc desc 
-	private String searchText;//列表table里面的搜索
-
-	public int getPage() {
-		return page;
-	}
-
-	public void setPage(int page) {
-		this.page = page;
-	}
-
-	public int getLimit() {
-		return limit;
-	}
-
-	public void setLimit(int limit) {
-		this.limit = limit;
-	}
-
-	public String getOrderByColumn() {
-		return orderByColumn;
-	}
-	public void setOrderByColumn(String orderByColumn) {
-		this.orderByColumn = orderByColumn;
-	}
-	public String getIsAsc() {
-		return isAsc;
-	}
-	public void setIsAsc(String isAsc) {
-		this.isAsc = isAsc;
-	}
-	public String getSearchText() {
-		return searchText;
-	}
-	public void setSearchText(String searchText) {
-		this.searchText = searchText;
-	}
-
-}

+ 0 - 21
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/interceptor/Interceptor.java

@@ -1,21 +0,0 @@
-package com.usky.cockpit.common.interceptor;
-
-import org.springframework.web.servlet.HandlerInterceptor;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * 拦截器
- */
-public class Interceptor implements HandlerInterceptor {
-    /**
-     * 在请求处理之前进行调用(Controller方法调用之前)
-     */
-	@Override
-    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
-       
-        return true;//如果设置为false时,被请求时,拦截器执行到此处将不会继续操作
-        //如果设置为true时,请求将会继续执行后面的操作
-    }
-
-}

+ 0 - 31
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/common/interceptor/WebMvcConfig.java

@@ -1,31 +0,0 @@
-package com.usky.cockpit.common.interceptor;
-
-import com.usky.cockpit.common.config.DateStringConvert;
-import com.usky.cockpit.common.config.StringDateConverter;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.format.FormatterRegistry;
-import org.springframework.format.support.FormattingConversionService;
-import org.springframework.http.converter.ObjectToStringHttpMessageConverter;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-/**
- * @author han
- */
-@Configuration
-public class WebMvcConfig implements WebMvcConfigurer {
-
-    @Override
-    public void addFormatters(FormatterRegistry registry) {
-        registry.addConverter(new StringDateConverter());
-    }
-
-    @Bean
-    public ObjectToStringHttpMessageConverter objectToStringHttpMessageConverter() {
-        FormattingConversionService conversionService = new FormattingConversionService();
-        conversionService.addConverter(new StringDateConverter());
-        conversionService.addConverter(new DateStringConvert());
-        ObjectToStringHttpMessageConverter httpMessageconverter = new ObjectToStringHttpMessageConverter(conversionService);
-        return httpMessageconverter;
-    }
-}

+ 0 - 371
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/FileController.java

@@ -1,371 +0,0 @@
-package com.usky.cockpit.controller.web;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.Map;
-import java.util.Map.Entry;
-import javax.servlet.http.HttpServletResponse;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.usky.cockpit.model.SysFile;
-import com.usky.cockpit.model.vo.SysFileVo;
-import com.usky.cockpit.service.ISysFileService;
-import com.usky.cockpit.util.SnowflakeIdWorker;
-import com.usky.common.core.web.domain.AjaxResult;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import lombok.extern.slf4j.Slf4j;
-import com.usky.cockpit.common.config.V2Config;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.codec.Base64;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.util.StrUtil;
-
-/**
- * 文件上传controller
- * @author fuce 
- * @date: 2018年9月16日 下午4:23:50
- */
-@Api(value = "文件上传")
-@RestController
-@RequestMapping("/api/file")
-@Slf4j
-public class FileController{
-
-
-	@Autowired
-	private V2Config v2Config;
-	@Autowired
-	private ISysFileService iSysFileService;
-
-	/**
-	 * 删除文件
-	 * @param ids
-	 * @return
-	 */
-	@ApiOperation(value = "删除", notes = "删除")
-	@DeleteMapping("/remove")
-	public AjaxResult remove(String ids){
-		Boolean b=iSysFileService.removeByIds(StrUtil.split(ids, ',',-1));
-		if(b){
-			return AjaxResult.success();
-		}else{
-			return AjaxResult.error();
-		}
-	}
-	
-	
-	@ApiOperation(value = "修改", notes = "修改")
-	@PutMapping("/update")
-	public AjaxResult update(String id,@RequestBody MultipartFile object) throws IllegalStateException, IOException{
-		SysFile sysFile=iSysFileService.getById(id);
-		if(sysFile!=null){
-			String fileurl=sysFile.getAbsolutePath()+sysFile.getRelativePath()+File.separator+sysFile.getFileName();
-			object.transferTo(new File(fileurl));
-			return AjaxResult.success("修改成功");
-		}else{
-			return AjaxResult.error();
-		}
-	}
-
-	/**
-	 * 上传文件
-	 * @param object 文件流对象
-	 * @return
-	 * @throws Exception
-	 */
-	@PostMapping("/upload")
-	public AjaxResult upload(@RequestBody MultipartFile object) throws IOException{
-		String fileName = object.getOriginalFilename();
-		//默认文件格式
-		String suffixName=v2Config.getDefaultFormat();
-		String mediaKey="";
-		Long filesize= object.getSize();
-		//文件名字
-		String fileSuffixName="";
-		if(fileName.lastIndexOf(".")!=-1) {//有后缀
-			 suffixName = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
-			 //mediaKey=MD5.create().digestHex(fileName);
-			 mediaKey= SnowflakeIdWorker.getUUID();
-			 fileSuffixName=mediaKey+suffixName;
-		}else {//无后缀
-			//取得唯一id
-			 //mediaKey = MD5.create().digestHex(fileName+suffixName);
-			mediaKey=SnowflakeIdWorker.getUUID();
-			//fileSuffixName=mediaKey+suffixName;
-		}
-		String virtualKey=getFirstNotNull(v2Config.getXnljmap());
-		String absolutePath=v2Config.getXnljmap().get(getFirstNotNull(v2Config.getXnljmap()));
-		SysFile sysFile=new SysFile();
-		sysFile.setId(SnowflakeIdWorker.getUUID());
-		sysFile.setFileName(fileSuffixName);
-		sysFile.setFileSize(Integer.parseInt(filesize+""));
-		sysFile.setFileSuffix(suffixName);
-		sysFile.setCreateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
-		String filepath=DateUtil.formatDate(new Date());
-		sysFile.setRelativePath(filepath);
-		sysFile.setVirtualKey(virtualKey);
-		sysFile.setAbsolutePath(absolutePath.replace("file:",""));
-		iSysFileService.saveOrUpdate(sysFile);
-		File desc = getAbsoluteFile(v2Config.getFileurl()+File.separator+filepath,fileSuffixName);
-		object.transferTo(desc);
-		SysFileVo sysFileVo=BeanUtil.copyProperties(sysFile, SysFileVo.class);
-		sysFileVo.setFileurl(v2Config.getHttpurl()+sysFile.getVirtualKey()+"/"+sysFile.getRelativePath()+"/"+sysFile.getFileName());
-		return AjaxResult.success(sysFileVo);
-	}
-	
-	
-	/**
-	 * Base64字符串转成图片
-	 * @throws IOException 
-	 */
-	@PostMapping("/uploadbase64")
-	public synchronized AjaxResult uploadbase64(String base64str) throws IOException{
-		if(StrUtil.isNotBlank(base64str)){
-			String suffixName=v2Config.getDefaultFormat();
-			String mediaKey=SnowflakeIdWorker.getUUID();
-			String fileSuffixName=mediaKey+suffixName;
-			String virtualKey=getFirstNotNull(v2Config.getXnljmap());
-			String absolutePath=v2Config.getXnljmap().get(getFirstNotNull(v2Config.getXnljmap()));
-			SysFile sysFile=new SysFile();
-			sysFile.setId(SnowflakeIdWorker.getUUID());
-			sysFile.setFileName(fileSuffixName);
-			sysFile.setFileSuffix(suffixName);
-			sysFile.setCreateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
-			String filepath=DateUtil.formatDate(new Date());
-			sysFile.setRelativePath(filepath);
-			sysFile.setVirtualKey(virtualKey);
-			sysFile.setAbsolutePath(absolutePath.replace("file:",""));
-			File desc = getAbsoluteFile(v2Config.getFileurl()+File.separator+filepath,fileSuffixName);
-			File file=null;
-			try {
-				 file=Base64.decodeToFile(base64str, desc);
-			} catch (Exception e) {
-				System.out.println("错误base64:"+base64str);
-				e.printStackTrace();
-			}
-			sysFile.setFileSize(Integer.parseInt(file.length()+""));
-			iSysFileService.saveOrUpdate(sysFile);
-			SysFileVo sysFileVo=BeanUtil.copyProperties(sysFile, SysFileVo.class);
-			sysFileVo.setFileurl(v2Config.getHttpurl()+sysFile.getVirtualKey()+"/"+sysFile.getRelativePath()+"/"+sysFile.getFileName());
-			return AjaxResult.success(sysFileVo);
-		}
-		return AjaxResult.error();
-		
-	}
-	
-	
-	/**
-	 * 定制方法
-	 * 根据关键字与相对路径获取文件内容 
-	 * @param key 访问关键字
-	 * @return
-	 */
-	@PostMapping("/getFileText")
-	public AjaxResult getFileText(String key,String relativePath){
-		String absolutePath= v2Config.getXnljmap().get(key).replace("file:", "");
-		String fileurl=absolutePath+relativePath;
-		try {
-			String text=FileUtil.readUtf8String(fileurl);
-			return AjaxResult.success(text);
-		}catch (IORuntimeException e) {
-			return AjaxResult.error("没有该文件");
-		}
-		catch (Exception e) {
-			return AjaxResult.error("报错:"+e.getMessage());
-		}
-	}
-	
-	
-	/**
-	 * 定制方法
-	 * 根据关键字与相对路径获取文件内容 
-	 * @param key 访问关键字
-	 * @return
-	 * @throws IOException 
-	 */
-	@PostMapping("/getFileText302")
-	public void getFileText302(String key,String relativePath,HttpServletResponse response) throws IOException{
-		String str=v2Config.getHttpurl()+key+"/"+relativePath;
-		response.sendRedirect(str);
-		
-	}
-	
-	
-	
-	
-	/**
-	 * 覆盖上传文件 key与指定路径
-	 * @param object 文件流对象
-	 * @return
-	 * @throws Exception
-	 */
-	@PostMapping("/coverupload")
-	public AjaxResult coverupload(@RequestBody MultipartFile object,String key,String relativePath) throws IOException{
-		
-		String fileName = object.getOriginalFilename();
-		String suffixName=v2Config.getDefaultFormat();
-		Long filesize= object.getSize();
-		//文件名字
-		String fileSuffixName="";
-		if(fileName.lastIndexOf(".")!=-1) {//有后缀
-			 suffixName = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
-			 //mediaKey=MD5.create().digestHex(fileName);
-			 //mediaKey=SnowflakeIdWorker.getUUID();
-			 fileSuffixName=relativePath.substring(relativePath.lastIndexOf("/")+1,relativePath.length());
-		}else {//无后缀
-			//取得唯一id
-			 //mediaKey = MD5.create().digestHex(fileName+suffixName);
-			//mediaKey=SnowflakeIdWorker.getUUID();
-			//fileSuffixName=mediaKey+suffixName;
-		}
-		String virtualKey=key;
-		String absolutePath=v2Config.getXnljmap().get(key).replace("file:", "");
-		SysFile sysFile=new SysFile();
-		sysFile.setId(SnowflakeIdWorker.getUUID());
-		sysFile.setFileName(fileSuffixName);
-		sysFile.setFileSize(Integer.parseInt(filesize+""));
-		sysFile.setFileSuffix(suffixName);
-		sysFile.setCreateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
-		String filepath=relativePath.substring(0,relativePath.lastIndexOf("/"));
-		sysFile.setRelativePath(filepath);
-		sysFile.setVirtualKey(virtualKey);
-		sysFile.setAbsolutePath(absolutePath);
-		iSysFileService.saveOrUpdate(sysFile);
-		File desc = getAbsoluteFile(absolutePath+filepath,fileSuffixName);
-		object.transferTo(desc);
-		SysFileVo sysFileVo=BeanUtil.copyProperties(sysFile, SysFileVo.class);
-		sysFileVo.setFileurl(v2Config.getHttpurl()+sysFile.getVirtualKey()+"/"+sysFile.getRelativePath()+"/"+sysFile.getFileName());
-		return AjaxResult.success(sysFileVo);
-	}
-	
-	
-	
-
-	
-	/**
-	 * 根据文件id查询文件信息json
-	 * @param id
-	 * @return
-	 */
-	@GetMapping("/getFileid/{id}")
-	public AjaxResult getFileid(@PathVariable("id") String id){
-		SysFile sysFile=iSysFileService.getById(id);
-		if(sysFile!=null){
-			SysFileVo sysFileVo=BeanUtil.copyProperties(sysFile, SysFileVo.class);
-			sysFileVo.setFileurl(v2Config.getHttpurl()+sysFile.getVirtualKey()+"/"+sysFile.getRelativePath()+"/"+sysFile.getFileName());
-			return AjaxResult.success(sysFileVo);
-		}
-		return AjaxResult.error("没有该文件");
-		
-	}
-	
-	/**
-	 * 根据文件id 302跳转到绝对地址
-	 * @param id
-	 * @param response
-	 * @throws IOException
-	 */
-	@GetMapping("/getFileid/302/{id}")
-	public void getFileid302(@PathVariable("id") String id,HttpServletResponse response) throws IOException{
-		SysFile sysFile=iSysFileService.getById(id);
-		if(sysFile!=null){
-			String str=v2Config.getHttpurl()+sysFile.getVirtualKey()+"/"+sysFile.getRelativePath()+"/"+sysFile.getFileName();
-			response.sendRedirect(str);
-		}
-	}
-	
-	
-	
-	
-	
-	
-	/**
-	 * 分页查询
-	 * @param current
-	 * @param size
-	 * @return
-	 */
-	@GetMapping("/list")
-	public Object list(long current, long size){
-		Page<SysFile> page= new Page<SysFile>(current, size);
-		IPage<SysFile> sysFile=iSysFileService.page(page, new LambdaQueryWrapper<SysFile>());
-		return sysFile;
-	}
-	
-	
-	
-	
-
-    /**
-     * 获取map中第一个非空数据key
-     *
-     * @param <K> Key的类型
-     * @param <V> Value的类型
-     * @param map 数据源
-     * @return 返回的值
-     */
-    public static <K, V> K getFirstNotNull(Map<K, V> map) {
-        K obj = null;
-        for (Entry<K, V> entry : map.entrySet()) {
-            obj =  entry.getKey();
-            if (obj != null) {
-                break;
-            }
-        }
-        return obj;
-    }
-	
-	
-    public  final static File getAbsoluteFile(String uploadDir, String filename) throws IOException
-    {
-        File desc = new File(uploadDir+File.separator + filename);
-
-        if (!desc.getParentFile().exists())
-        {
-            desc.getParentFile().mkdirs();
-        }
-        if (!desc.exists())
-        {
-            desc.createNewFile();
-        }
-        return desc;
-    }
-	
-	
-	/**
-	 * 获取上传文件的md5
-	 * @param file
-	 * @return
-	 * @throws IOException
-	 */
-	public String getMd5(MultipartFile file) {
-	    try {
-	        //获取文件的byte信息
-	        byte[] uploadBytes = file.getBytes();
-	        // 拿到一个MD5转换器
-	        MessageDigest md5 = MessageDigest.getInstance("MD5");
-	        byte[] digest = md5.digest(uploadBytes);
-	        //转换为16进制
-	        return new BigInteger(1, digest).toString(16);
-	    } catch (Exception e) {
-	        log.error(e.getMessage());
-	    }
-	    return null;
-	}
-
-
-    
-    
-}

+ 0 - 254
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/GoviewProjectController.java

@@ -1,254 +0,0 @@
-package com.usky.cockpit.controller.web;
-
-import com.usky.cockpit.common.config.V2Config;
-import com.usky.cockpit.common.domain.ResultTable;
-import com.usky.cockpit.common.domain.Tablepar;
-import com.usky.cockpit.controller.web.FileController;
-import com.usky.cockpit.model.GoviewProject;
-import com.usky.cockpit.model.GoviewProjectData;
-import com.usky.cockpit.model.SysFile;
-import com.usky.cockpit.model.vo.GoviewProjectVo;
-import com.usky.cockpit.model.vo.SysFileVo;
-import com.usky.cockpit.service.IGoviewProjectDataService;
-import com.usky.cockpit.service.IGoviewProjectService;
-import com.usky.cockpit.service.ISysFileService;
-import com.usky.cockpit.util.ConvertUtil;
-import com.usky.cockpit.util.SnowflakeIdWorker;
-import com.usky.common.core.web.domain.AjaxResult;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-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.extension.plugins.pagination.Page;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.date.DateUtil;
-import io.swagger.annotations.ApiOperation;
-import java.io.File;
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.List;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.ui.ModelMap;
-
-/**
- * <p>
- *  前端控制器
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@RestController
-@RequestMapping("/api/goview/project")
-public class GoviewProjectController{
-	@Autowired
-	private ISysFileService iSysFileService;
-	@Autowired
-	private V2Config v2Config;
-	@Autowired
-	private IGoviewProjectService iGoviewProjectService;
-	@Autowired
-	private IGoviewProjectDataService iGoviewProjectDataService;
-	
-
-	@GetMapping("/list")
-	@ResponseBody
-	public ResultTable list(Tablepar tablepar){
-		Page<GoviewProject> page= new Page<GoviewProject>(tablepar.getPage(), tablepar.getLimit());
-		IPage<GoviewProject> iPages=iGoviewProjectService.page(page, new LambdaQueryWrapper<GoviewProject>());
-		ResultTable resultTable=new ResultTable();
-		resultTable.setData(iPages.getRecords());
-		resultTable.setCode(200);
-		resultTable.setCount(iPages.getTotal());
-		resultTable.setMsg("获取成功");
-		return resultTable;
-	}
-	
-	
-	/**
-     * 新增保存
-     * @param 
-     * @return
-     */
-	//@Log(title = "项目表新增", action = "111")
-	@ApiOperation(value = "新增", notes = "新增")
-	@PostMapping("/create")
-	@ResponseBody
-	public AjaxResult add(@RequestBody GoviewProject goviewProject){
-		goviewProject.setCreateTime(DateUtil.now());
-		goviewProject.setState(-1);
-		boolean b=iGoviewProjectService.save(goviewProject);
-		if(b){
-			return AjaxResult.success("创建成功");
-		}else{
-			return AjaxResult.error();
-		}
-	}
-	
-	
-	/**
-	 * 项目表删除
-	 * @param ids
-	 * @return
-	 */
-	//@Log(title = "项目表删除", action = "111")
-	@ApiOperation(value = "删除", notes = "删除")
-	@DeleteMapping("/delete")
-	@ResponseBody
-	public AjaxResult remove(String ids){
-		List<String> lista= ConvertUtil.toListStrArray(ids);
-		Boolean b=iGoviewProjectService.removeByIds(lista);
-		if(b){
-			return AjaxResult.success();
-		}else{
-			return AjaxResult.error();
-		}
-	}
-	
-	@ApiOperation(value = "修改保存", notes = "修改保存")
-    @PostMapping("/edit")
-    @ResponseBody
-    public AjaxResult editSave(@RequestBody GoviewProject goviewProject)
-    {
-		Boolean b= iGoviewProjectService.updateById(goviewProject);
-        if(b){
-        	return AjaxResult.success();
-        }
-        return AjaxResult.error();
-    }
-	
-	
-	@ApiOperation(value = "项目重命名", notes = "项目重命名")
-    @PostMapping("/rename")
-    @ResponseBody
-    public AjaxResult rename(@RequestBody GoviewProject goviewProject)
-    {
-		
-		LambdaUpdateWrapper<GoviewProject> updateWrapper=new LambdaUpdateWrapper<GoviewProject>();
-		updateWrapper.eq(GoviewProject::getId, goviewProject.getId());
-		updateWrapper.set(GoviewProject::getProjectName, goviewProject.getProjectName());
-		Boolean b=iGoviewProjectService.update(updateWrapper);
-		if(b){
-        	return AjaxResult.success();
-        }
-		return AjaxResult.error();
-    }
-	
-	
-	//发布/取消项目状态
-    @PutMapping("/publish")
-	@ResponseBody
-    public AjaxResult updateVisible(@RequestBody GoviewProject goviewProject){
-    	if(goviewProject.getState()==-1||goviewProject.getState()==1) {
-    	
-    		LambdaUpdateWrapper<GoviewProject> updateWrapper=new LambdaUpdateWrapper<GoviewProject>();
-    		updateWrapper.eq(GoviewProject::getId, goviewProject.getId());
-    		updateWrapper.set(GoviewProject::getState, goviewProject.getState());
-    		Boolean b=iGoviewProjectService.update(updateWrapper);
-    		if(b){
-            	return AjaxResult.success();
-            }
-    		return AjaxResult.error();
-    	}
-    	return AjaxResult.error("警告非法字段");
-	}
-	
-    
-    @ApiOperation(value = "获取项目存储数据", notes = "获取项目存储数据")
-	@GetMapping("/getData")
-	@ResponseBody
-    public AjaxResult getData(String projectId, ModelMap map)
-    {
-		GoviewProject goviewProject= iGoviewProjectService.getById(projectId);
-		
-		GoviewProjectData blogText=iGoviewProjectDataService.getProjectid(projectId);
-		if(blogText!=null) {
-			GoviewProjectVo goviewProjectVo=new GoviewProjectVo();
-			BeanUtils.copyProperties(goviewProject,goviewProjectVo);
-			goviewProjectVo.setContent(blogText.getContent());
-			return AjaxResult.success("获取成功");
-		}
-		return AjaxResult.success("无数据");
-        
-    }
-	
-	
-	
-	@ApiOperation(value = "保存项目数据", notes = "保存项目数据")
-	@PostMapping("/save/data")
-	@ResponseBody
-	public AjaxResult saveData(GoviewProjectData data) {
-		
-		GoviewProject goviewProject= iGoviewProjectService.getById(data.getProjectId());
-		if(goviewProject==null) {
-			return AjaxResult.error("没有该项目ID");
-		}
-		GoviewProjectData goviewProjectData= iGoviewProjectDataService.getOne(new LambdaQueryWrapper<GoviewProjectData>().eq(GoviewProjectData::getProjectId, goviewProject.getId()));
-		if(goviewProjectData!=null) {
-			 data.setId(goviewProjectData.getId());
-			 iGoviewProjectDataService.updateById(data);
-			 return AjaxResult.success("数据保存成功");
-		}else {
-			iGoviewProjectDataService.save(data);
-			return AjaxResult.success("数据保存成功");
-		}
-	}
-	
-	/**
-	 * 上传文件
-	 * @param object 文件流对象
-	 * @return
-	 * @throws Exception
-	 */
-	@PostMapping("/upload")
-	public AjaxResult upload(@RequestBody MultipartFile object) throws IOException{
-		String fileName = object.getOriginalFilename();
-		//默认文件格式
-		String suffixName=v2Config.getDefaultFormat();
-		String mediaKey="";
-		Long filesize= object.getSize();
-		//文件名字
-		String fileSuffixName="";
-		if(fileName.lastIndexOf(".")!=-1) {//有后缀
-			 suffixName = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
-			 //mediaKey=MD5.create().digestHex(fileName);
-			 mediaKey= SnowflakeIdWorker.getUUID();
-			 fileSuffixName=mediaKey+suffixName;
-		}else {//无后缀
-			//取得唯一id
-			 //mediaKey = MD5.create().digestHex(fileName+suffixName);
-			mediaKey=SnowflakeIdWorker.getUUID();
-			//fileSuffixName=mediaKey+suffixName;
-		}
-		String virtualKey= FileController.getFirstNotNull(v2Config.getXnljmap());
-		String absolutePath=v2Config.getXnljmap().get(FileController.getFirstNotNull(v2Config.getXnljmap()));
-		SysFile sysFile=new SysFile();
-		sysFile.setId(SnowflakeIdWorker.getUUID());
-		sysFile.setFileName(fileSuffixName);
-		sysFile.setFileSize(Integer.parseInt(filesize+""));
-		sysFile.setFileSuffix(suffixName);
-		sysFile.setCreateTime(DateUtil.formatLocalDateTime(LocalDateTime.now()));
-		String filepath=DateUtil.formatDate(new Date());
-		sysFile.setRelativePath(filepath);
-		sysFile.setVirtualKey(virtualKey);
-		sysFile.setAbsolutePath(absolutePath.replace("file:",""));
-		iSysFileService.saveOrUpdate(sysFile);
-		File desc = FileController.getAbsoluteFile(v2Config.getFileurl()+File.separator+filepath,fileSuffixName);
-		object.transferTo(desc);
-		SysFileVo sysFileVo=BeanUtil.copyProperties(sysFile, SysFileVo.class);
-		sysFileVo.setFileurl(v2Config.getHttpurl()+sysFile.getVirtualKey()+"/"+sysFile.getRelativePath()+"/"+sysFile.getFileName());
-		return AjaxResult.success(sysFileVo);
-	}
-	
-
-}

+ 0 - 21
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/Indexcontroller.java

@@ -1,21 +0,0 @@
-package com.usky.cockpit.controller.web;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-public class Indexcontroller {
-
-	@GetMapping("/")
-	public void index(HttpServletResponse response) throws IOException {
-		response.setContentType("text/html; charset=utf-8");
-		PrintWriter out = response.getWriter();
-		out.println("<p style='color:orange'>goview后台首页</p>");
-		out.flush();
-		out.close();
-
-	}
-}

+ 0 - 19
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/controller/web/SysUserController.java

@@ -1,19 +0,0 @@
-package com.usky.cockpit.controller.web;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- *  前端控制器
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@RestController
-@RequestMapping("/v2/sys-user")
-public class SysUserController {
-
-}

+ 0 - 18
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/GoviewProjectDataMapper.java

@@ -1,18 +0,0 @@
-package com.usky.cockpit.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.usky.cockpit.model.GoviewProjectData;
-import org.springframework.stereotype.Repository;
-
-/**
- * <p>
- *  Mapper 接口
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@Repository
-public interface GoviewProjectDataMapper extends BaseMapper<GoviewProjectData> {
-
-}

+ 0 - 16
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/GoviewProjectMapper.java

@@ -1,16 +0,0 @@
-package com.usky.cockpit.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.usky.cockpit.model.GoviewProject;
-
-/**
- * <p>
- *  Mapper 接口
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-public interface GoviewProjectMapper extends BaseMapper<GoviewProject> {
-
-}

+ 0 - 19
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/SysFileMapper.java

@@ -1,19 +0,0 @@
-package com.usky.cockpit.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.usky.cockpit.model.SysFile;
-import org.springframework.stereotype.Repository;
-
-
-/**
- * <p>
- *  Mapper 接口
- * </p>
- *
- * @author fc
- * @since 2022-12-22
- */
-@Repository
-public interface SysFileMapper extends BaseMapper<SysFile> {
-
-}

+ 0 - 16
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/mapper/SysUserMapper.java

@@ -1,16 +0,0 @@
-package com.usky.cockpit.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.usky.cockpit.model.SysUser;
-
-/**
- * <p>
- *  Mapper 接口
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-public interface SysUserMapper extends BaseMapper<SysUser> {
-
-}

+ 0 - 48
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/GoviewProject.java

@@ -1,48 +0,0 @@
-package com.usky.cockpit.model;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * <p>
- * 
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@TableName("ckpt_project")
-@Data
-public class GoviewProject implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    private String projectName;
-
-    private Integer state;
-
-    @TableField(fill = FieldFill.INSERT)
-    private String createTime;
-
-    private String createUserId;
-
-    private Integer isDelete;
-
-    private String indexImage;
-
-    private String remarks;
-
-}
-
-
-

+ 0 - 39
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/GoviewProjectData.java

@@ -1,39 +0,0 @@
-package com.usky.cockpit.model;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import java.io.Serializable;
-import java.sql.Blob;
-import java.sql.SQLException;
-
-/**
- * <p>
- * 
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@TableName("ckpt_project_data")
-@Data
-public class GoviewProjectData implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-    @TableId(type = IdType.ASSIGN_ID)
-    private String id;
-
-    private String projectId;
-
-    @TableField(fill = FieldFill.INSERT)
-    private String createTime;
-
-    private String createUserId;
-
-    private String content;
-
-   
-}

+ 0 - 119
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/SysFile.java

@@ -1,119 +0,0 @@
-package com.usky.cockpit.model;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-
-/**
- * <p>
- * 
- * </p>
- *
- * @author fc
- * @since 2022-12-22
- */
-@TableName("sys_file")
-public class SysFile implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.INPUT)
-    private String id;
-
-    private String fileName;
-
-    private Integer fileSize;
-
-    private String fileSuffix;
-    
-    /**
-     * 虚拟路径
-     */
-    private String virtualKey;
-    
-    /**
-     * 相对路径
-     */
-    private String relativePath;
-    
-    /**
-     * 绝对路径
-     */
-    private String absolutePath;
-    
-    
-    
-    
-    @TableField(fill = FieldFill.INSERT)
-    private String createTime;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-    public String getFileName() {
-        return fileName;
-    }
-
-    public void setFileName(String fileName) {
-        this.fileName = fileName;
-    }
-   
-    public Integer getFileSize() {
-        return fileSize;
-    }
-
-    public void setFileSize(Integer fileSize) {
-        this.fileSize = fileSize;
-    }
-    public String getFileSuffix() {
-        return fileSuffix;
-    }
-
-    public void setFileSuffix(String fileSuffix) {
-        this.fileSuffix = fileSuffix;
-    }
-    public String getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(String createTime) {
-        this.createTime = createTime;
-    }
-    
-
-	public String getVirtualKey() {
-		return virtualKey;
-	}
-
-	public void setVirtualKey(String virtualKey) {
-		this.virtualKey = virtualKey;
-	}
-
-	public String getAbsolutePath() {
-		return absolutePath;
-	}
-
-	public void setAbsolutePath(String absolutePath) {
-		this.absolutePath = absolutePath;
-	}
-
-	public String getRelativePath() {
-		return relativePath;
-	}
-
-	public void setRelativePath(String relativePath) {
-		this.relativePath = relativePath;
-	}
-
-
-
-	
-	
-}

+ 0 - 39
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/SysUser.java

@@ -1,39 +0,0 @@
-package com.usky.cockpit.model;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * <p>
- * 
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@TableName("sys_user")
-@Data
-public class SysUser implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(type = IdType.ASSIGN_ID)
-    private String id;
-
-    private String username;
-
-    private String password;
-
-    private String nickname;
-
-    private Integer depId;
-
-    private String posId;
-
- 
-}

+ 0 - 119
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/vo/GoviewProjectVo.java

@@ -1,119 +0,0 @@
-package com.usky.cockpit.model.vo;
-
-import java.io.Serializable;
-import java.util.Date;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import cn.hutool.core.date.DateUtil;
-import io.swagger.annotations.ApiModelProperty;
-
-public class GoviewProjectVo implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-	
-	@ApiModelProperty(value = "主键")
-	private String id;
-	
-	@ApiModelProperty(value = "项目名称")
-	private String projectName;
-	
-	@ApiModelProperty(value = "项目状态[-1未发布,1发布]")
-	private Integer state;
-	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
-	@ApiModelProperty(value = "创建时间")
-	private Date createTime;
-	
-	@ApiModelProperty(value = "创建人id")
-	private String createUserId;
-	
-	@ApiModelProperty(value = "删除状态[1删除,-1未删除]")
-	private Integer isDelete;
-	
-	@ApiModelProperty(value = "首页图片")
-	private String indexImage;
-	
-	@ApiModelProperty(value = "项目介绍")
-	private String remarks;
-	
-	private String content;
-	
-	
-	@JsonProperty("id")
-	public String getId() {
-		return id;
-	}
-
-	public void setId(String id) {
-		this.id =  id;
-	}
-	@JsonProperty("projectName")
-	public String getProjectName() {
-		return projectName;
-	}
-
-	public void setProjectName(String projectName) {
-		this.projectName =  projectName;
-	}
-	@JsonProperty("state")
-	public Integer getState() {
-		return state;
-	}
-
-	public void setState(Integer state) {
-		this.state =  state;
-	}
-	@JsonProperty("createTime")
-	public Date getCreateTime() {
-		return createTime;
-	}
-
-	public void setCreateTime(Date createTime) {
-		this.createTime =  createTime;
-	}
-	@JsonProperty("createUserId")
-	public String getCreateUserId() {
-		return createUserId;
-	}
-
-	public void setCreateUserId(String createUserId) {
-		this.createUserId =  createUserId;
-	}
-	@JsonProperty("isDelete")
-	public Integer getIsDelete() {
-		return isDelete;
-	}
-
-	public void setIsDelete(Integer isDelete) {
-		this.isDelete =  isDelete;
-	}
-	@JsonProperty("indexImage")
-	public String getIndexImage() {
-		return indexImage;
-	}
-
-	public void setIndexImage(String indexImage) {
-		this.indexImage =  indexImage;
-	}
-	@JsonProperty("remarks")
-	public String getRemarks() {
-		return remarks;
-	}
-
-	public void setRemarks(String remarks) {
-		this.remarks =  remarks;
-	}
-	public String getContent() {
-		return content;
-	}
-
-	public void setContent(String content) {
-		this.content = content;
-	}
-
-	public String dateToStringConvert(Date date) {
-		if(date!=null) {
-			return DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
-		}
-		return "";
-	}
-}

+ 0 - 70
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/model/vo/SysFileVo.java

@@ -1,70 +0,0 @@
-package com.usky.cockpit.model.vo;
-
-
-public class SysFileVo {
-	
-    private String id;
-    private String fileName;
-    private Integer fileSize;
-    private String createTime;
-    
-    /**
-     * 相对路径
-     */
-    private String relativePath;
-    
-    /**
-     * 虚拟路径key
-     */
-    private String virtualKey;
-    
-    /**
-     * 请求url
-     */
-    private String fileurl;
-    
-    
-	public String getId() {
-		return id;
-	}
-	public void setId(String id) {
-		this.id = id;
-	}
-	public String getFileName() {
-		return fileName;
-	}
-	public void setFileName(String fileName) {
-		this.fileName = fileName;
-	}
-	public Integer getFileSize() {
-		return fileSize;
-	}
-	public void setFileSize(Integer fileSize) {
-		this.fileSize = fileSize;
-	}
-	public String getCreateTime() {
-		return createTime;
-	}
-	public void setCreateTime(String createTime) {
-		this.createTime = createTime;
-	}
-	public String getRelativePath() {
-		return relativePath;
-	}
-	public void setRelativePath(String relativePath) {
-		this.relativePath = relativePath;
-	}
-	public String getVirtualKey() {
-		return virtualKey;
-	}
-	public void setVirtualKey(String virtualKey) {
-		this.virtualKey = virtualKey;
-	}
-	public String getFileurl() {
-		return fileurl;
-	}
-	public void setFileurl(String fileurl) {
-		this.fileurl = fileurl;
-	}
-	
-}

+ 0 - 19
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/IGoviewProjectDataService.java

@@ -1,19 +0,0 @@
-package com.usky.cockpit.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.usky.cockpit.model.GoviewProjectData;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务类
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-public interface IGoviewProjectDataService extends IService<GoviewProjectData> {
-	
-	public GoviewProjectData getProjectid(String projectId);
-
-}

+ 0 - 17
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/IGoviewProjectService.java

@@ -1,17 +0,0 @@
-package com.usky.cockpit.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.usky.cockpit.model.GoviewProject;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务类
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-public interface IGoviewProjectService extends IService<GoviewProject> {
-
-}

+ 0 - 20
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/ISysFileService.java

@@ -1,20 +0,0 @@
-package com.usky.cockpit.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.usky.cockpit.model.SysFile;
-import org.springframework.stereotype.Service;
-
-
-/**
- * <p>
- *  服务类
- * </p>
- *
- * @author fc
- * @since 2022-12-22
- */
-public interface ISysFileService extends IService<SysFile> {
-
-	
-	public SysFile selectByExamplefileName(String filename);
-}

+ 0 - 17
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/ISysUserService.java

@@ -1,17 +0,0 @@
-package com.usky.cockpit.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.usky.cockpit.model.SysUser;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务类
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-public interface ISysUserService extends IService<SysUser> {
-
-}

+ 0 - 31
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/GoviewProjectDataServiceImpl.java

@@ -1,31 +0,0 @@
-package com.usky.cockpit.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.usky.cockpit.mapper.GoviewProjectDataMapper;
-import com.usky.cockpit.model.GoviewProjectData;
-import com.usky.cockpit.service.IGoviewProjectDataService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@Service
-public class GoviewProjectDataServiceImpl extends ServiceImpl<GoviewProjectDataMapper, GoviewProjectData> implements IGoviewProjectDataService {
-	@Autowired
-	GoviewProjectDataMapper dataMapper;
-	@Override
-	public GoviewProjectData getProjectid(String projectId) {
-		LambdaQueryWrapper<GoviewProjectData> lambdaQueryWrapper=new LambdaQueryWrapper<GoviewProjectData>();
-		lambdaQueryWrapper.eq(GoviewProjectData::getProjectId, projectId);
-		return dataMapper.selectOne(lambdaQueryWrapper);
-		
-	}
-
-}

+ 0 - 20
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/GoviewProjectServiceImpl.java

@@ -1,20 +0,0 @@
-package com.usky.cockpit.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.usky.cockpit.mapper.GoviewProjectMapper;
-import com.usky.cockpit.model.GoviewProject;
-import com.usky.cockpit.service.IGoviewProjectService;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@Service
-public class GoviewProjectServiceImpl extends ServiceImpl<GoviewProjectMapper, GoviewProject> implements IGoviewProjectService {
-
-}

+ 0 - 30
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/SysFileServiceImpl.java

@@ -1,30 +0,0 @@
-package com.usky.cockpit.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.usky.cockpit.mapper.SysFileMapper;
-import com.usky.cockpit.model.SysFile;
-import com.usky.cockpit.service.ISysFileService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author fc
- * @since 2022-12-22
- */
-@Service
-public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService {
-	@Autowired
-	private SysFileMapper sysFileMapper;
-	
-	@Override
-	public SysFile selectByExamplefileName(String filename) {
-		SysFile sysFile=sysFileMapper.selectOne(new LambdaQueryWrapper<SysFile>().eq(SysFile::getFileName, filename));
-        return sysFile;
-	}
-
-}

+ 0 - 20
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/service/impl/SysUserServiceImpl.java

@@ -1,20 +0,0 @@
-package com.usky.cockpit.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.usky.cockpit.mapper.SysUserMapper;
-import com.usky.cockpit.model.SysUser;
-import com.usky.cockpit.service.ISysUserService;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  服务实现类
- * </p>
- *
- * @author fc
- * @since 2023-04-30
- */
-@Service
-public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
-
-}

+ 0 - 252
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/util/ConvertUtil.java

@@ -1,252 +0,0 @@
-package com.usky.cockpit.util;
-
-import cn.hutool.core.util.StrUtil;
-import java.math.BigDecimal;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 类型转换器
- * 
- * @author fc
- * 
- */
-public class ConvertUtil {
-
-	/**
-	 * 转换为字符串<br>
-	 * 如果给定的值为null,或者转换失败,返回默认值<br>
-	 * 转换失败不会报错
-	 * 
-	 * @param value 被转换的值
-	 * @param defaultValue 转换错误时的默认值
-	 * @return 结果
-	 */
-	public static String toStr(Object value, String defaultValue) {
-		if (null == value) {
-			return defaultValue;
-		}
-		if (value instanceof String) {
-			return (String) value;
-		}
-		return value.toString();
-	}
-
-	/**
-	 * 转换为Integer数组<br>
-	 * @param split 被转换的值
-	 * @return 结果
-	 */
-	public static Integer[] toIntArray(String str) {
-		return toIntArray(",", str);
-	}
-
-	/**
-	 * 转换为Integer数组<br>
-	 * @param split 分隔符
-	 * @param split 被转换的值
-	 * @return 结果
-	 */
-	public static Integer[] toIntArray(String split, String str) {
-		if (StrUtil.isEmpty(str)) {
-			return new Integer[] {};
-		}
-		String[] strings = str.split(split);
-		final Integer[] ints = new Integer[strings.length];
-		for (int i = 0; i < strings.length; i++) {
-			final Integer v = toInt(strings[i], 0);
-			ints[i] = v;
-		}
-		return ints;
-	}
-
-	/**
-	 * 转换为int<br>
-	 * 如果给定的值为空,或者转换失败,返回默认值<br>
-	 * 转换失败不会报错
-	 * @param value 被转换的值
-	 * @param defaultValue 转换错误时的默认值
-	 * @return 结果
-	 */
-	public static Integer toInt(Object value, Integer defaultValue) {
-		if (value == null) {
-			return defaultValue;
-		}
-		if (value instanceof Integer) {
-			return (Integer) value;
-		}
-		if (value instanceof Number) {
-			return ((Number) value).intValue();
-		}
-		final String valueStr = toStr(value, null);
-		if (StrUtil.isEmpty(valueStr)) {
-			return defaultValue;
-		}
-		try {
-			return Integer.parseInt(valueStr.trim());
-		} catch (Exception e) {
-			return defaultValue;
-		}
-	}
-
-	/**
-	 * 转换为List<String>数组<br>
-	 * @param split 被转换的值
-	 * @return 结果
-	 */
-	public static List<String> toListStrArray(String str) {
-		String[] stringArray = toStrArray(str);
-		List<String> stringB = Arrays.asList(stringArray);
-		return stringB;
-	}
-
-
-
-	/**
-	 * 转换为List<Long>数组<br>
-	 * @param split 被转换的值
-	 * @return 结果
-	 */
-	public static List<Long> toListLongArray(String str) {
-		Long[] stringArray = toLongArray(str);
-		List<Long> stringB = Arrays.asList(stringArray);
-		return stringB;
-	}
-
-
-	/**
-	 * 转换为String数组<br> 
-	 * @param split 被转换的值
-	 * @return 结果
-	 */
-	public static String[] toStrArray(String str) {
-		return toStrArray(",", str);
-	}
-
-	/**
-	 * 转换为String数组<br>
-	 * 
-	 * @param split 分隔符
-	 * @param split 被转换的值
-	 * @return 结果
-	 */
-	public static String[] toStrArray(String split, String str) {
-		return str.split(split);
-	}
-	/**
-     * 转换为Long数组<br>
-     * 
-     * @param split 被转换的值
-     * @return 结果
-     */
-    public static Long[] toLongArray(String str)
-    {
-        return toLongArray(",", str);
-    }
-    /**
-     * 转换为Long数组<br>
-     * 
-     * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
-     * @param values 被转换的值
-     * @return 结果
-     */
-    public static Long[] toLongArray(String split, String str)
-    {
-        if (StrUtil.isEmpty(str))
-        {
-            return new Long[] {};
-        }
-        String[] arr = str.split(split);
-        final Long[] longs = new Long[arr.length];
-        for (int i = 0; i < arr.length; i++)
-        {
-            final Long v = toLong(arr[i], null);
-            longs[i] = v;
-        }
-        return longs;
-    }
-    /**
-     * 转换为long<br>
-     * 如果给定的值为空,或者转换失败,返回默认值<br>
-     * 转换失败不会报错
-     * 
-     * @param value 被转换的值
-     * @param defaultValue 转换错误时的默认值
-     * @return 结果
-     */
-    public static Long toLong(Object value, Long defaultValue)
-    {
-        if (value == null)
-        {
-            return defaultValue;
-        }
-        if (value instanceof Long)
-        {
-            return (Long) value;
-        }
-        if (value instanceof Number)
-        {
-            return ((Number) value).longValue();
-        }
-        final String valueStr = toStr(value, null);
-        if (StrUtil.isEmpty(valueStr))
-        {
-            return defaultValue;
-        }
-        try
-        {
-            // 支持科学计数法
-            return new BigDecimal(valueStr.trim()).longValue();
-        }
-        catch (Exception e)
-        {
-            return defaultValue;
-        }
-    }
-    
-    /**
-     * 转换为BigDecimal<br>
-     * 如果给定的值为空,或者转换失败,返回默认值<br>
-     * 转换失败不会报错
-     * 
-     * @param value 被转换的值
-     * @param defaultValue 转换错误时的默认值
-     * @return 结果
-     */
-    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
-    {
-        if (value == null)
-        {
-            return defaultValue;
-        }
-        if (value instanceof BigDecimal)
-        {
-            return (BigDecimal) value;
-        }
-        if (value instanceof Long)
-        {
-            return new BigDecimal((Long) value);
-        }
-        if (value instanceof Double)
-        {
-            return new BigDecimal((Double) value);
-        }
-        if (value instanceof Integer)
-        {
-            return new BigDecimal((Integer) value);
-        }
-        final String valueStr = toStr(value, null);
-        if (StrUtil.isEmpty(valueStr))
-        {
-            return defaultValue;
-        }
-        try
-        {
-            return new BigDecimal(valueStr);
-        }
-        catch (Exception e)
-        {
-            return defaultValue;
-        }
-    }
-}

+ 0 - 73
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/util/SaTokenUtil.java

@@ -1,73 +0,0 @@
-//package com.usky.cockpit.util;
-//
-//
-//import com.usky.cockpit.model.SysUser;
-//import org.springframework.beans.BeanUtils;
-//import cn.dev33.satoken.stp.StpUtil;
-//
-///**
-// * 封装 Sa-Token 常用操作
-// * @author kong
-// *
-// */
-//public class SaTokenUtil {
-//
-//	/**
-//     * 获取登录用户model
-//     */
-//    public static SysUser getUser() {
-//    	Object object=StpUtil.getSession().get("user");
-//    	if(object!=null){
-//    		SysUser tsysUser=new SysUser();
-//    		BeanUtils.copyProperties(tsysUser, object);
-//    		return tsysUser;
-//    	}
-//    	return null;
-//    }
-//
-//    /**
-//     * set用户
-//     */
-//    public static void setUser(SysUser user) {
-//    	StpUtil.getSession().set("user", user);
-//    }
-//
-//  /**
-//   * 获取登录用户id
-//   */
-//	public static String getUserId() {
-//		return StpUtil.getLoginIdAsString();
-//	}
-//
-//    /**
-//     * 获取登录用户name
-//     */
-//    public static String getLoginName() {
-//    	SysUser tsysUser = getUser();
-//        if (tsysUser == null){
-//            throw new RuntimeException("用户不存在!");
-//        }
-//        return tsysUser.getUsername();
-//    }
-//
-//    /**
-//     * 获取登录用户ip
-//     * @return
-//     * @author fuce
-//     * @Date 2019年11月21日 上午9:58:26
-//     */
-//    public static String getIp() {
-//
-//        return StpUtil.getTokenSession().getString("login_ip");
-//    }
-//    /**
-//     * 判断是否登录
-//     * @return
-//     * @author fuce
-//     * @Date 2019年11月21日 上午9:58:26
-//     */
-//    public static boolean isLogin() {
-//        return StpUtil.isLogin();
-//    }
-//
-//}

+ 0 - 155
service-cockpit/service-cockpit-biz/src/main/java/com/usky/cockpit/util/SnowflakeIdWorker.java

@@ -1,155 +0,0 @@
-package com.usky.cockpit.util;
-
-/**
- * Twitter_Snowflake<br>
- * SnowFlake的结构如下(每部分用-分开):<br>
- * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
- * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
- * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
- * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
- * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
- * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
- * 加起来刚好64位,为一个Long型。<br>
- * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
- */
-public class SnowflakeIdWorker {
- 
-    // ==============================Fields===========================================
-    /** 开始时间截 (2015-01-01) */
-    private final long twepoch = 1489111610226L;
- 
-    /** 机器id所占的位数 */
-    private final long workerIdBits = 5L;
- 
-    /** 数据标识id所占的位数 */
-    private final long dataCenterIdBits = 5L;
- 
-    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
-    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
- 
-    /** 支持的最大数据标识id,结果是31 */
-    private final long maxDataCenterId = -1L ^ (-1L << dataCenterIdBits);
- 
-    /** 序列在id中占的位数 */
-    private final long sequenceBits = 12L;
- 
-    /** 机器ID向左移12位 */
-    private final long workerIdShift = sequenceBits;
- 
-    /** 数据标识id向左移17位(12+5) */
-    private final long dataCenterIdShift = sequenceBits + workerIdBits;
- 
-    /** 时间截向左移22位(5+5+12) */
-    private final long timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits;
- 
-    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
-    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
- 
-    /** 工作机器ID(0~31) */
-    private long workerId;
- 
-    /** 数据中心ID(0~31) */
-    private long dataCenterId;
- 
-    /** 毫秒内序列(0~4095) */
-    private long sequence = 0L;
- 
-    /** 上次生成ID的时间截 */
-    private long lastTimestamp = -1L;
- 
-    
-    static SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);
-    //==============================Constructors=====================================
-    /**
-     * 构造函数
-     * @param workerId 工作ID (0~31)
-     * @param dataCenterId 数据中心ID (0~31)
-     */
-    public SnowflakeIdWorker(long workerId, long dataCenterId) {
-        if (workerId > maxWorkerId || workerId < 0) {
-            throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));
-        }
-        if (dataCenterId > maxDataCenterId || dataCenterId < 0) {
-            throw new IllegalArgumentException(String.format("dataCenterId can't be greater than %d or less than 0", maxDataCenterId));
-        }
-        this.workerId = workerId;
-        this.dataCenterId = dataCenterId;
-    }
- 
-    // ==============================Methods==========================================
-    /**
-     * 获得下一个ID (该方法是线程安全的)
-     * @return SnowflakeId
-     */
-    public synchronized long nextId() {
-        long timestamp = timeGen();
- 
-        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
-        if (timestamp < lastTimestamp) {
-            throw new RuntimeException(
-                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
-        }
- 
-        //如果是同一时间生成的,则进行毫秒内序列
-        if (lastTimestamp == timestamp) {
-            sequence = (sequence + 1) & sequenceMask;
-            //毫秒内序列溢出
-            if (sequence == 0) {
-                //阻塞到下一个毫秒,获得新的时间戳
-                timestamp = tilNextMillis(lastTimestamp);
-            }
-        }
-        //时间戳改变,毫秒内序列重置
-        else {
-            sequence = 0L;
-        }
- 
-        //上次生成ID的时间截
-        lastTimestamp = timestamp;
- 
-        //移位并通过或运算拼到一起组成64位的ID
-        return ((timestamp - twepoch) << timestampLeftShift) //
-                | (dataCenterId << dataCenterIdShift) //
-                | (workerId << workerIdShift) //
-                | sequence;
-    }
- 
-    /**
-     * 阻塞到下一个毫秒,直到获得新的时间戳
-     * @param lastTimestamp 上次生成ID的时间截
-     * @return 当前时间戳
-     */
-    protected long tilNextMillis(long lastTimestamp) {
-        long timestamp = timeGen();
-        while (timestamp <= lastTimestamp) {
-            timestamp = timeGen();
-        }
-        return timestamp;
-    }
- 
-    /**
-     * 返回以毫秒为单位的当前时间
-     * @return 当前时间(毫秒)
-     */
-    protected long timeGen() {
-        return System.currentTimeMillis();
-    }
- 
-    //==============================Test=============================================
-    /** 测试 */
-    public static void main(String[] args) {
-        System.out.println(System.currentTimeMillis());
-        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);
-        long startTime = System.nanoTime();
-        for (int i = 0; i < 500; i++) {
-            long id = idWorker.nextId();
-            System.out.println(id);
-        }
-        System.out.println((System.nanoTime()-startTime)/1000000+"ms");
-    }
-    
-    public static String getUUID() {
-    	long id = idWorker.nextId();
-    	return String.valueOf(id);
-    }
-}

+ 0 - 5
service-cockpit/service-cockpit-biz/src/main/resources/mapper/GoviewProjectDataMapper.xml

@@ -1,5 +0,0 @@
-<?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="cn.com.v2.mapper.GoviewProjectDataMapper">
-
-</mapper>

+ 0 - 5
service-cockpit/service-cockpit-biz/src/main/resources/mapper/GoviewProjectMapper.xml

@@ -1,5 +0,0 @@
-<?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="cn.com.v2.mapper.GoviewProjectMapper">
-
-</mapper>

+ 0 - 5
service-cockpit/service-cockpit-biz/src/main/resources/mapper/SysFileMapper.xml

@@ -1,5 +0,0 @@
-<?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="cn.com.v2oss.mapper.SysFileMapper">
-
-</mapper>

+ 0 - 5
service-cockpit/service-cockpit-biz/src/main/resources/mapper/SysUserMapper.xml

@@ -1,5 +0,0 @@
-<?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="cn.com.v2.mapper.SysUserMapper">
-
-</mapper>

+ 4 - 2
service-eg/service-eg-biz/src/main/java/com/usky/eg/controller/web/EgDeviceController.java

@@ -92,8 +92,10 @@ public class EgDeviceController {
                                                  @RequestParam("commandValue") String commandValue,
                                                  @RequestParam(value = "domain",required = false) String domain,
                                                  @RequestParam(value = "userId",required = false) Long userId,
-                                                 @RequestParam(value = "userName",required = false) String userName){
-        return ApiResult.success(egDeviceService.control(productCode,deviceUuid,commandCode,commandValue,domain,userId,userName));
+                                                 @RequestParam(value = "userName",required = false) String userName,
+                                                 @RequestParam(value = "categoryType",required = false , defaultValue = "1") Integer categoryType,
+                                                 @RequestParam(value = "gatewayUuid",required = false) String gatewayUuid){
+        return ApiResult.success(egDeviceService.control(productCode,deviceUuid,commandCode,commandValue,domain,userId,userName,categoryType,gatewayUuid));
     }
 
 }

+ 12 - 0
service-eg/service-eg-biz/src/main/java/com/usky/eg/domain/EgDevice.java

@@ -123,6 +123,18 @@ public class EgDevice implements Serializable {
      */
     private String openMode;
 
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 工作状态
+     */
+    private String workStatus;
+
+    /**
+
     /**
      * 用户人脸信息记录
      */

+ 3 - 1
service-eg/service-eg-biz/src/main/java/com/usky/eg/service/EgDeviceService.java

@@ -31,5 +31,7 @@ public interface EgDeviceService extends CrudService<EgDevice> {
 
     boolean checkNameUnique(EgDevice egDevice);
 
-    Map<String,Object> control(String productCode, String deviceUuid, String commandCode, String commandValue, String domain, Long userId, String userName);
+    boolean checkDeviceNameUnique(EgDevice egDevice);
+
+    Map<String,Object> control(String productCode, String deviceUuid, String commandCode, String commandValue, String domain, Long userId, String userName, Integer categoryType, String gatewayUuid);
 }

+ 68 - 29
service-eg/service-eg-biz/src/main/java/com/usky/eg/service/impl/EgDeviceServiceImpl.java

@@ -68,13 +68,15 @@ 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.eq(MeetingFace::getTenantId,tenantId);
+            meetingFaceQuery.select(MeetingFace::getFid,MeetingFace::getCreateTime,MeetingFace::getVefNum,MeetingFace::getFaceName,MeetingFace::getRemark,MeetingFace::getFaceStatus,MeetingFace::getCardNum,MeetingFace::getBindDevice,MeetingFace::getDeptId,MeetingFace::getTenantId,MeetingFace::getUserId)
+                    .eq(MeetingFace::getTenantId,tenantId);
             List<MeetingFace> meetingAllFaceList = meetingFaceMapper.selectList(meetingFaceQuery);
 
             for (int i = 0; i < page.getRecords().size(); i++) {
@@ -105,24 +107,27 @@ public class EgDeviceServiceImpl extends AbstractCrudService<EgDeviceMapper, EgD
         long userId = SecurityUtils.getUserId();
         //人员设备权限校验,校验通过,可以下发命令控制设备
         Integer fid = baseMapper.getMeetingFaceData(userId);
-        if(fid == null){
-            throw new BusinessException("人脸卡号信息未注册");
-        }
+//        if(fid == null){
+//            throw new BusinessException("人脸卡号信息未注册");
+//        }
         Integer[] deviceFid = baseMapper.getMeetingFaceDeviceList(fid);
-        if(deviceFid.length == 0){
-            throw new BusinessException("人员未绑定设备,请检查");
-        }
+//        if(deviceFid.length == 0){
+//            throw new BusinessException("人员未绑定设备,请检查");
+//        }
 
         IPage<EgDevice> page = new Page<>(requestVO.getCurrent(),requestVO.getSize());
-        LambdaQueryWrapper<EgDevice> queryWrapper = Wrappers.lambdaQuery();
-        queryWrapper.like(StringUtils.isNotBlank(requestVO.getDeviceName()),EgDevice::getDeviceName,requestVO.getDeviceName())
-                .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())
-                .in(EgDevice::getId,deviceFid)
-                .eq(EgDevice::getTenantId,SecurityUtils.getTenantId())
-                .orderByDesc(EgDevice::getId);
-        page = this.page(page,queryWrapper);
+        if(deviceFid.length > 0){
+            LambdaQueryWrapper<EgDevice> queryWrapper = Wrappers.lambdaQuery();
+            queryWrapper.like(StringUtils.isNotBlank(requestVO.getDeviceName()),EgDevice::getDeviceName,requestVO.getDeviceName())
+                    .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())
+                    .in(EgDevice::getId,deviceFid)
+                    .eq(EgDevice::getTenantId,SecurityUtils.getTenantId())
+                    .orderByDesc(EgDevice::getId);
+            page = this.page(page,queryWrapper);
+        }
+
 
         return new CommonPage<>(page.getRecords(),page.getTotal(),requestVO.getSize(),requestVO.getCurrent());
     }
@@ -132,6 +137,9 @@ public class EgDeviceServiceImpl extends AbstractCrudService<EgDeviceMapper, EgD
         if(checkNameUnique(egDevice)){
             throw new BusinessException("新增门禁门号设备'"+egDevice.getDeviceId()+","+egDevice.getEgNumber()+"'失败,设备已存在");
         }
+        if(checkDeviceNameUnique(egDevice)){
+            throw new BusinessException("新增门禁设备'"+egDevice.getDeviceName()+"'失败,设备已存在");
+        }
 
         egDevice.setDeviceUuid(UUIDUtils.uuid());
         egDevice.setCreateBy(SecurityUtils.getUsername());
@@ -154,33 +162,49 @@ public class EgDeviceServiceImpl extends AbstractCrudService<EgDeviceMapper, EgD
     }
 
     @Override
-    public void update(EgDevice egDevice){
-        if(checkNameUnique(egDevice)){
-            throw new BusinessException("修改门禁门号设备'"+egDevice.getDeviceId()+","+egDevice.getEgNumber()+"'失败,设备已存在");
-        }
-
-        egDevice.setUpdateBy(SecurityUtils.getUsername());
-        egDevice.setUpdateTime(LocalDateTime.now());
-
-        this.updateById(egDevice);
+    public void update(EgDevice egDevice) {
 
         String[] fids = new String[0];
-        egDeviceMapper.deleteMeetingFaceDevice(egDevice.getId());
         if(Objects.nonNull(egDevice.getBindFace()) || StringUtils.isNotBlank(egDevice.getBindFace())){
             fids = egDevice.getBindFace().split(",");
+
+            egDeviceMapper.deleteMeetingFaceDevice(egDevice.getId());
+        }else{
+            EgDevice one = this.getById(egDevice.getId());
+            egDevice.setBindFace(one.getBindFace());
         }
         if(fids.length > 0){
             for (int i = 0; i < fids.length; i++) {
                 egDeviceMapper.insertMeetingFaceDevice(Integer.parseInt(fids[i]),egDevice.getId());
             }
         }
+
+
+        if(checkNameUnique(egDevice)){
+            throw new BusinessException("修改门禁门号设备'"+egDevice.getDeviceId()+","+egDevice.getEgNumber()+"'失败,设备已存在");
+        }
+        if(checkDeviceNameUnique(egDevice)){
+            throw new BusinessException("新增门禁设备'"+egDevice.getDeviceName()+"'失败,设备已存在");
+        }
+
+        egDevice.setUpdateBy(SecurityUtils.getUsername());
+        egDevice.setUpdateTime(LocalDateTime.now());
+
+        this.updateById(egDevice);
     }
 
     @Override
     public void attachUpdate(EgDevice egDevice){
+
+        EgDevice one = this.getById(egDevice.getId());
+        egDevice.setBindFace(one.getBindFace());
+
         if(checkNameUnique(egDevice)){
             throw new BusinessException("更新门禁设备附加功能'"+egDevice.getDeviceId()+"'失败,设备已存在");
         }
+        if(checkDeviceNameUnique(egDevice)){
+            throw new BusinessException("新增门禁设备'"+egDevice.getDeviceName()+"'失败,设备已存在");
+        }
 
         egDevice.setUpdateBy(SecurityUtils.getUsername());
         egDevice.setUpdateTime(LocalDateTime.now());
@@ -217,7 +241,17 @@ public class EgDeviceServiceImpl extends AbstractCrudService<EgDeviceMapper, EgD
     }
 
     @Override
-    public Map<String,Object> control(String productCode, String deviceUuid, String commandCode, String commandValue, String domain, Long userId, String userName){
+    public boolean checkDeviceNameUnique(EgDevice egDevice){
+        Integer id = null == egDevice.getId() ? -1 : egDevice.getId();
+        LambdaQueryWrapper<EgDevice> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(EgDevice::getDeviceName,egDevice.getDeviceName())
+                .eq(EgDevice::getTenantId, SecurityUtils.getTenantId());
+        EgDevice one = this.getOne(queryWrapper);
+        return null != one && !Objects.equals(one.getId(),id);
+    }
+
+    @Override
+    public Map<String,Object> control(String productCode, String deviceUuid, String commandCode, String commandValue, String domain, Long userId, String userName, Integer categoryType, String gatewayUuid){
         Integer tenantId;
         long commandUserId;
         String commandUserName;
@@ -257,11 +291,16 @@ public class EgDeviceServiceImpl extends AbstractCrudService<EgDeviceMapper, EgD
 
         Map<String,Object> map = new HashMap<>();
         map.put("method","control");
+        map.put("deviceUuid", deviceUuid);
         Map<String,Object> map1 = new HashMap<>();
         map1.put("commandCode",commandCode);
         map1.put("commandValue",commandValue);
         map.put("params",map1);
 
-        return remoteTransferService.deviceControl(productCode,deviceUuid, JSON.toJSONString(map),tenantId,commandUserId,commandUserName);
+        if(categoryType == 3){
+            return remoteTransferService.deviceControl(productCode, gatewayUuid, JSON.toJSONString(map), tenantId, commandUserId, commandUserName);
+        }else{
+            return remoteTransferService.deviceControl(productCode, deviceUuid, JSON.toJSONString(map), tenantId, commandUserId, commandUserName);
+        }
     }
 }

+ 7 - 0
service-eg/service-eg-biz/src/main/java/com/usky/eg/service/impl/EgRecordServiceImpl.java

@@ -6,6 +6,8 @@ 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.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.security.utils.SecurityUtils;
@@ -61,11 +63,13 @@ public class EgRecordServiceImpl extends AbstractCrudService<EgRecordMapper, EgR
 
         egRecord.setCreateTime(LocalDateTime.now());
         egRecord.setTenantId(tenantId);
+        egRecord.setDeptId(SecurityUtils.getLoginUser().getSysUser().getDeptId().intValue());
 
         this.save(egRecord);
     }
 
     @Override
+    @DataScope
     public CommonPage<EgRecord> page(EgRecordRequestVO requestVO){
         IPage<EgRecord> page = new Page<>(requestVO.getCurrent(),requestVO.getSize());
         String deviceName = requestVO.getDeviceName();
@@ -86,11 +90,14 @@ public class EgRecordServiceImpl extends AbstractCrudService<EgRecordMapper, EgR
             egDeviceList = egDeviceMapper.selectList(egDeviceQuery);
         }
 
+        String dataScopeSql = DataScopeContextHolder.getDataScopeSql();
+
         LambdaQueryWrapper<EgRecord> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.like(StringUtils.isNotBlank(requestVO.getUserName()),EgRecord::getUserName,requestVO.getUserName())
                 .eq(null != requestVO.getPassType(),EgRecord::getPassType,requestVO.getPassType())
                 .in(CollectionUtils.isNotEmpty(egDeviceIdList),EgRecord::getEgDeviceId,egDeviceIdList)
                 .between(StringUtils.isNotBlank(requestVO.getStartTime())&&StringUtils.isNotBlank(requestVO.getEndTime()),EgRecord::getPassTime,requestVO.getStartTime(),requestVO.getEndTime())
+                .apply(Objects.nonNull(dataScopeSql), dataScopeSql)
                 .orderByDesc(EgRecord::getId);
         page = this.page(page,queryWrapper);
         if((page.getRecords().size() > 0) && (egDeviceList.size() > 0)){

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