shiyue 1 hónapja
commit
d4ebf86359
100 módosított fájl, 7443 hozzáadás és 0 törlés
  1. 381 0
      pom.xml
  2. 31 0
      src/main/java/com/energy/manage/analyse/ManageAppApplication.java
  3. 25 0
      src/main/java/com/energy/manage/analyse/common/base/BaseConstant.java
  4. 16 0
      src/main/java/com/energy/manage/analyse/common/base/BaseController.java
  5. 44 0
      src/main/java/com/energy/manage/analyse/common/base/BaseDomainWithUser.java
  6. 26 0
      src/main/java/com/energy/manage/analyse/common/base/BaseException.java
  7. 12 0
      src/main/java/com/energy/manage/analyse/common/base/BaseRepository.java
  8. 23 0
      src/main/java/com/energy/manage/analyse/common/base/BaseService.java
  9. 60 0
      src/main/java/com/energy/manage/analyse/common/base/BaseServiceImpl.java
  10. 41 0
      src/main/java/com/energy/manage/analyse/common/base/NewBaseDomain.java
  11. 112 0
      src/main/java/com/energy/manage/analyse/common/base/Page.java
  12. 56 0
      src/main/java/com/energy/manage/analyse/common/exception/BusinessException.java
  13. 17 0
      src/main/java/com/energy/manage/analyse/common/exception/ErrorSignException.java
  14. 7 0
      src/main/java/com/energy/manage/analyse/common/exception/NoRequestException.java
  15. 9 0
      src/main/java/com/energy/manage/analyse/common/exception/ServiceErrorException.java
  16. 27 0
      src/main/java/com/energy/manage/analyse/common/exception/ServiceException.java
  17. 4 0
      src/main/java/com/energy/manage/analyse/common/exception/TokenInvalidException.java
  18. 29 0
      src/main/java/com/energy/manage/analyse/common/exception/UserNotLoginException.java
  19. 15 0
      src/main/java/com/energy/manage/analyse/common/mapper/MyMapper.java
  20. 131 0
      src/main/java/com/energy/manage/analyse/common/reponse/ConstVar.java
  21. 50 0
      src/main/java/com/energy/manage/analyse/common/reponse/HttpResult.java
  22. 406 0
      src/main/java/com/energy/manage/analyse/common/reponse/RespMsg.java
  23. 177 0
      src/main/java/com/energy/manage/analyse/common/reponse/ResultResp.java
  24. 21 0
      src/main/java/com/energy/manage/analyse/config/HttpConfig.java
  25. 46 0
      src/main/java/com/energy/manage/analyse/config/Knife4jConfiguration.java
  26. 35 0
      src/main/java/com/energy/manage/analyse/config/LoginVerifyInterceptorConf.java
  27. 116 0
      src/main/java/com/energy/manage/analyse/config/SystemExceptionHandler.java
  28. 57 0
      src/main/java/com/energy/manage/analyse/config/WebMVCConfig.java
  29. 60 0
      src/main/java/com/energy/manage/analyse/constant/AnomalySensorType.java
  30. 128 0
      src/main/java/com/energy/manage/analyse/constant/DetectorTableEnum.java
  31. 89 0
      src/main/java/com/energy/manage/analyse/constant/DetectorType.java
  32. 120 0
      src/main/java/com/energy/manage/analyse/controller/anomaly/AnomalyController.java
  33. 44 0
      src/main/java/com/energy/manage/analyse/controller/base/BaseServiceController.java
  34. 78 0
      src/main/java/com/energy/manage/analyse/controller/healthscores/HealthscoresController.java
  35. 48 0
      src/main/java/com/energy/manage/analyse/controller/wakediagnosis/WakeWindFarmController.java
  36. 23 0
      src/main/java/com/energy/manage/analyse/domain/dto/AnomalyDTO.java
  37. 26 0
      src/main/java/com/energy/manage/analyse/domain/dto/AnomalyModelDTO.java
  38. 27 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyAerodynamicsVO.java
  39. 23 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyChartVO.java
  40. 24 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyCount.java
  41. 27 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyCtrlParamVO.java
  42. 51 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyDailyVO.java
  43. 20 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyModelVO.java
  44. 39 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyOverviewVO.java
  45. 32 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyPitchVO.java
  46. 32 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalySensorCountVO.java
  47. 28 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyThermodynamicDiagramVO.java
  48. 28 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyWindpwrVO.java
  49. 24 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyYawVO.java
  50. 26 0
      src/main/java/com/energy/manage/analyse/domain/vo/anomaly/BarChartVO.java
  51. 107 0
      src/main/java/com/energy/manage/analyse/domain/vo/enginegroup/WindEngineGroupVO.java
  52. 166 0
      src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthOverviewListVO.java
  53. 36 0
      src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthOverviewVO.java
  54. 118 0
      src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthscoresTendencyVO.java
  55. 14 0
      src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthscoresWindVO.java
  56. 18 0
      src/main/java/com/energy/manage/analyse/domain/vo/wakewindfarm/WakeTurbineVO.java
  57. 20 0
      src/main/java/com/energy/manage/analyse/domain/vo/wakewindfarm/WakeWindFarmVO.java
  58. 139 0
      src/main/java/com/energy/manage/analyse/mappers/anomaly/AnomalyWindfarmMapper.java
  59. 62 0
      src/main/java/com/energy/manage/analyse/mappers/healthscores/HealthscoresMapper.java
  60. 41 0
      src/main/java/com/energy/manage/analyse/mappers/wakediagnosis/WakeWindFarmMapper.java
  61. 16 0
      src/main/java/com/energy/manage/analyse/mappers/windenginegroup/WindEngineGroupMapper.java
  62. 19 0
      src/main/java/com/energy/manage/analyse/mappers/windfield/WindFieldMapper.java
  63. 21 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyCabletwistPO.java
  64. 14 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyCpPO.java
  65. 14 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyCpTsrPO.java
  66. 13 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyDeloadPO.java
  67. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyMinpitchPO.java
  68. 337 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyModelPO.java
  69. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyOperationPO.java
  70. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPitchcoordPO.java
  71. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPitchregulationPO.java
  72. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPowercurvePO.java
  73. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPowerqualityPO.java
  74. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyScatterPO.java
  75. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalySimulinkPO.java
  76. 16 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyStaticyawPO.java
  77. 12 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyTsrPO.java
  78. 49 0
      src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyWindfarmPO.java
  79. 92 0
      src/main/java/com/energy/manage/analyse/po/anomaly/BaseAnomalyDetectorPO.java
  80. 142 0
      src/main/java/com/energy/manage/analyse/po/healthscores/HealthscoresPO.java
  81. 111 0
      src/main/java/com/energy/manage/analyse/po/healthscores/HealthscoresWindPO.java
  82. 53 0
      src/main/java/com/energy/manage/analyse/po/wakediagnosis/WakeTurbinePO.java
  83. 60 0
      src/main/java/com/energy/manage/analyse/po/wakediagnosis/WakeWindFarmPO.java
  84. 87 0
      src/main/java/com/energy/manage/analyse/po/windenginegroup/WindEngineGroupPO.java
  85. 100 0
      src/main/java/com/energy/manage/analyse/po/windfield/WindFieldPO.java
  86. 102 0
      src/main/java/com/energy/manage/analyse/service/anomaly/AnomalyService.java
  87. 940 0
      src/main/java/com/energy/manage/analyse/service/anomaly/impl/AnomalyServiceImpl.java
  88. 42 0
      src/main/java/com/energy/manage/analyse/service/healthscores/HealthscoresService.java
  89. 333 0
      src/main/java/com/energy/manage/analyse/service/healthscores/impl/HealthscoresServiceImpl.java
  90. 21 0
      src/main/java/com/energy/manage/analyse/service/wakediagnosis/WakeWindFarmService.java
  91. 174 0
      src/main/java/com/energy/manage/analyse/service/wakediagnosis/impl/WakeWindFarmServiceImpl.java
  92. 35 0
      src/main/resources/application.properties
  93. 22 0
      src/main/resources/banner/banner.txt
  94. 38 0
      src/main/resources/bootstrap.properties
  95. 239 0
      src/main/resources/confback/README.MD
  96. 134 0
      src/main/resources/confback/application-prod.properties
  97. 50 0
      src/main/resources/confback/bootstrap.properties
  98. 13 0
      src/main/resources/logback.xml
  99. 162 0
      src/main/resources/logback/logback-analyse.xml
  100. 162 0
      src/main/resources/logback/logback-dev.xml

+ 381 - 0
pom.xml

@@ -0,0 +1,381 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.zhzn.energy</groupId>
+    <artifactId>energy-manage-analyse</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+
+    <properties>
+        <java.version>1.8</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
+        <swagger.version>2.6.1</swagger.version>
+        <fastjson.version>1.2.9</fastjson.version>
+        <aliyun-openservices.version>1.2.3</aliyun-openservices.version>
+        <aliyun-sdk-oss.version>2.4.0</aliyun-sdk-oss.version>
+        <docker.image.prefix>test</docker.image.prefix>
+        <spring.boot.version>2.3.2.RELEASE</spring.boot.version>
+        <spring.cloud.alibaba.version>1.5.0.RELEASE</spring.cloud.alibaba.version>
+    </properties>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-dependencies</artifactId>
+        <version>2.3.2.RELEASE</version>
+    </parent>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
+            <version>${spring.cloud.alibaba.version}</version>
+            <type>pom</type>
+            <scope>import</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-dependencies</artifactId>
+            <version>Finchley.RELEASE</version>
+            <type>pom</type>
+            <scope>import</scope>
+        </dependency>
+
+        <!-- spring boot -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.lettuce</groupId>
+                    <artifactId>lettuce-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+
+
+        <!-- 多数据源 -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+            <version>3.4.0</version>
+        </dependency>
+
+        <!-- spring boot -->
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+
+        <!--分页-->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.2.10</version>
+        </dependency>
+        <!--分页-->
+
+        <!-- 通用mapper -->
+        <dependency>
+            <groupId>tk.mybatis</groupId>
+            <artifactId>mapper-spring-boot-starter</artifactId>
+            <version>4.2.1</version>
+        </dependency>
+        <!-- 通用mapper -->
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>1.1.10</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>8.0.21</version>
+        </dependency>
+
+        <!-- json -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+        <!-- json -->
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.14.4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.caucho</groupId>
+            <artifactId>hessian</artifactId>
+            <version>4.0.51</version>
+        </dependency>
+
+
+        <!--nacos 配置中心 -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+            <version>2.2.3.RELEASE</version>
+        </dependency>
+        <!-- 引入swagger依赖 -->
+
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-boot-starter</artifactId>
+            <version>3.0.0</version>
+
+        </dependency>
+
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.5.21</version>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.5.21</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-spring-boot-starter</artifactId>
+            <version>3.0.1</version>
+        </dependency>
+
+        <!-- jwt -->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.9.9</version>
+        </dependency>
+        <dependency>
+            <groupId>org.checkerframework</groupId>
+            <artifactId>checker-qual</artifactId>
+            <version>3.12.0</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.7.15</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vdurmont</groupId>
+            <artifactId>emoji-java</artifactId>
+            <version>5.1.1</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.1.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.junit.vintage</groupId>
+                    <artifactId>junit-vintage-engine</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- json转换 -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-joda</artifactId>
+            <version>2.9.10</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate.validator</groupId>
+            <artifactId>hibernate-validator</artifactId>
+        </dependency>
+
+        <!-- zip压缩包 -->
+        <dependency>
+            <groupId>net.lingala.zip4j</groupId>
+            <artifactId>zip4j</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>2.2.3</version>
+        </dependency>
+
+        <!-- 浏览器解析工具 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>1.21</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.10</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}-service</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources/</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.properties</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources/</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+
+        <!-- 插件 -->
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.0.5.RELEASE</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <mainClass>com.energy.manage.analyse.ManageAppApplication</mainClass>
+                </configuration>
+            </plugin>
+            <!-- Compiler 插件, 设定JDK版本 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin.version}</version>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>utf-8</encoding>
+                    <showWarnings>true</showWarnings>
+                    <compilerArguments>
+                        <endorseddirs>${endorsed.dir}</endorseddirs>
+                    </compilerArguments>
+                </configuration>
+            </plugin>
+        </plugins>
+        
+    </build>
+
+    <!-- 配置环境 -->
+    <profiles>
+        <profile>
+            <id>analyse</id>
+            <properties>
+                <profiles.active>analyse</profiles.active>
+            </properties>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+        </profile>
+        <profile>
+            <id>dev</id>
+            <properties>
+                <profiles.active>dev</profiles.active>
+            </properties>
+        </profile>
+        <profile>
+            <id>show</id>
+            <properties>
+                <profiles.active>show</profiles.active>
+            </properties>
+        </profile>
+        <profile>
+            <id>prod</id>
+            <properties>
+                <profiles.active>prod</profiles.active>
+            </properties>
+        </profile>
+    </profiles>
+
+
+</project>

+ 31 - 0
src/main/java/com/energy/manage/analyse/ManageAppApplication.java

@@ -0,0 +1,31 @@
+package com.energy.manage.analyse;
+
+
+import com.energy.manage.analyse.common.mapper.MyMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import tk.mybatis.spring.annotation.MapperScan;
+
+
+@EnableDiscoveryClient
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+@EnableAspectJAutoProxy(exposeProxy = true)
+@EnableTransactionManagement
+@EnableAsync
+@MapperScan(value = "com.energy.manage.analyse.mappers", markerInterface = MyMapper.class)
+@Slf4j
+public class ManageAppApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(ManageAppApplication.class, args);
+        log.info("============= AnalyseService Application Service Start Success =====>");
+    }
+
+
+}

+ 25 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseConstant.java

@@ -0,0 +1,25 @@
+package com.energy.manage.analyse.common.base;
+
+/**
+ * 系统常量
+ * Created by apple on 2017/5/9.
+ */
+public class BaseConstant {
+
+  /**
+   * 成功
+   */
+  public static final String SUCCESSFUL_CODE = "1";
+
+  public static final String FAILURE_CODE = "0"; //失败
+
+  public static final String AUTH_CODE = "401";//未授权客户机访问数据
+
+  public static final String PARAMETER_CODE = "400";// 错误请求 — 请求中有语法问题
+
+  public static final String CONDITIONS_CODE = "412";// 参数条件错误
+
+  public static final String PERFORM_CODE = "5011"; //服务器执行错误
+
+
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseController.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.common.base;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Controller基础类
+ */
+public class BaseController {
+  /**
+   * 日志对象
+   */
+  protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+
+}

+ 44 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseDomainWithUser.java

@@ -0,0 +1,44 @@
+package com.energy.manage.analyse.common.base;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author shiyue
+ */
+@Data
+public class BaseDomainWithUser extends NewBaseDomain {
+
+    /*
+     * 创建人
+     */
+    private Integer createBy;
+
+    /*
+     * 创建人名称
+     */
+    private String createUser;
+
+    /*
+     * 更新人
+     */
+    private Integer updateBy;
+
+    /*
+     * 更新人名称
+     */
+    private String updateUser;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+
+    /**
+     * 用户角色
+     */
+    private Integer roleId;
+}

+ 26 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseException.java

@@ -0,0 +1,26 @@
+package com.energy.manage.analyse.common.base;
+
+
+/**
+ * Created by  on 1/17/17.
+ */
+public class BaseException extends RuntimeException {
+  private static final long serialVersionUID = -6336125614015879324L;
+
+  public BaseException() {
+    super();
+  }
+
+  public BaseException(String message) {
+    super(message);
+  }
+
+
+  public BaseException(Throwable cause) {
+    super(cause);
+  }
+
+  public BaseException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}

+ 12 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseRepository.java

@@ -0,0 +1,12 @@
+package com.energy.manage.analyse.common.base;
+
+/**
+ * @author
+ */
+public class BaseRepository<T> extends BaseServiceImpl<T> {
+
+    public int insertSelective(T data) {
+        return mapper.insertSelective(data);
+    }
+
+}

+ 23 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseService.java

@@ -0,0 +1,23 @@
+package com.energy.manage.analyse.common.base;
+
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public interface BaseService<T> {
+
+  T selectByKey(Object key);
+
+  int save(T entity);
+
+  int delete(Object key);
+
+  int updateAll(T entity);
+
+  int updateNotNull(T entity);
+
+  List<T> selectByExample(Object example);
+
+
+}

+ 60 - 0
src/main/java/com/energy/manage/analyse/common/base/BaseServiceImpl.java

@@ -0,0 +1,60 @@
+package com.energy.manage.analyse.common.base;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.common.Mapper;
+
+import java.util.List;
+
+@Transactional(rollbackFor = Exception.class)
+public abstract class BaseServiceImpl<T> implements BaseService<T> {
+
+  private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+  @Autowired
+  protected Mapper<T> mapper;
+
+  public Mapper<T> getMapper() {
+    return mapper;
+  }
+
+  @Override
+  public T selectByKey(Object key) {
+    //说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号
+    return mapper.selectByPrimaryKey(key);
+  }
+
+  @Override
+  public int save(T entity) {
+    //说明:保存一个实体,null的属性也会保存,不会使用数据库默认值
+    return mapper.insert(entity);
+  }
+
+  @Override
+  public int delete(Object key) {
+    //说明:根据主键字段进行删除,方法参数必须包含完整的主键属性
+    return mapper.deleteByPrimaryKey(key);
+  }
+
+  @Override
+  public int updateAll(T entity) {
+    //说明:根据主键更新实体全部字段,null值会被更新
+    return mapper.updateByPrimaryKey(entity);
+  }
+
+  @Override
+  public int updateNotNull(T entity) {
+    //根据主键更新属性不为null的值
+    return mapper.updateByPrimaryKeySelective(entity);
+  }
+
+  @Override
+  public List<T> selectByExample(Object example) {
+    //说明:根据Example条件进行查询
+    //重点:这个查询支持通过Example类指定查询列,通过 selectProperties方法指定查询列
+    return mapper.selectByExample(example);
+  }
+
+}

+ 41 - 0
src/main/java/com/energy/manage/analyse/common/base/NewBaseDomain.java

@@ -0,0 +1,41 @@
+package com.energy.manage.analyse.common.base;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.util.Date;
+
+
+@Data
+@EqualsAndHashCode
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC)
+public class NewBaseDomain {
+
+
+    @Id
+    @GeneratedValue(generator = "JDBC")
+    @Column(name = "id")
+    @ApiModelProperty(value = "主键id")
+    private Integer id;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "修改时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "创建人")
+    private Integer createBy;
+
+    @ApiModelProperty(value = "修改人")
+    private Integer updateBy;
+
+}

+ 112 - 0
src/main/java/com/energy/manage/analyse/common/base/Page.java

@@ -0,0 +1,112 @@
+package com.energy.manage.analyse.common.base;
+
+import org.springframework.util.CollectionUtils;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+public class Page<T> implements Serializable {
+  private Integer pageNum = 1;
+  private Integer pageSize = 10;
+  private Long totalSize;
+  private Integer pages;
+  private List<T> list;
+
+  public Integer getPageNum() {
+    return pageNum;
+  }
+
+  public void setPageNum(Integer pageNum) {
+    this.pageNum = pageNum;
+  }
+
+  public Integer getPageSize() {
+    return pageSize;
+  }
+
+  public void setPageSize(Integer pageSize) {
+    this.pageSize = pageSize;
+  }
+
+  public Long getTotalSize() {
+    return totalSize;
+  }
+
+  public void setTotalSize(Long totalSize) {
+    this.totalSize = totalSize;
+  }
+
+  public Integer getPages() {
+    pages = (int) (totalSize / pageSize);
+    int mod = (int) (totalSize % pageSize);
+    if (mod > 0) {
+      pages += 1;
+    }
+    return pages;
+  }
+
+  public void setPages(Integer pages) {
+    this.pages = pages;
+  }
+
+  public List<T> getList() {
+    return list;
+  }
+
+  public void setList(List<T> list) {
+    if (CollectionUtils.isEmpty(list)) {
+      this.list = Collections.emptyList();
+    } else {
+      this.list = list;
+    }
+  }
+
+  public Page() {
+  }
+
+  /**
+   * 构建分页数据
+   *
+   * @param pageNum
+   * @param pageSize
+   * @param totalSize
+   * @param list
+   * @param <T>
+   * @return
+   */
+  public static <T> Page<T> build(int pageNum, int pageSize, long totalSize, List<T> list) {
+    Page<T> page = new Page<>();
+    page.setPageNum(pageNum);
+    page.setPageSize(pageSize);
+    page.setTotalSize(totalSize);
+    page.setList(list);
+    return page;
+  }
+
+  /**
+   * Page Redis List 分页工具,获取分页起始数据
+   *
+   * @param pageNum
+   * @param pageSize
+   * @return
+   */
+  public static int getPageDataStart(int pageNum, int pageSize) {
+    pageNum = pageNum <= 0 ? 1 : pageNum;
+    pageSize = pageSize <= 0 ? 10 : pageSize;
+    return (pageNum - 1) * pageSize;
+  }
+
+  /**
+   * Page Redis List 分页工具,获取分页结束数据
+   *
+   * @param pageNum
+   * @param pageSize
+   * @return
+   */
+  public static int getPageDataEnd(int pageNum, int pageSize) {
+    pageNum = pageNum <= 0 ? 1 : pageNum;
+    pageSize = pageSize <= 0 ? 10 : pageSize;
+    return pageNum * pageSize - 1;
+  }
+}

+ 56 - 0
src/main/java/com/energy/manage/analyse/common/exception/BusinessException.java

@@ -0,0 +1,56 @@
+package com.energy.manage.analyse.common.exception;
+
+
+/**
+ * 业务异常超类
+ *
+ * @version 1.0
+ * @Project common
+ * @Author wy
+ * @Date 2019年4月11日
+ */
+public class BusinessException extends RuntimeException {
+
+  private static final long serialVersionUID = -6093528337682404785L;
+  /**
+   * 异常编码.
+   */
+  private int code = 0;
+
+  private Object data;
+
+  public BusinessException(Throwable cause) {
+    super(cause);
+  }
+
+  public BusinessException(String message) {
+    super(message);
+  }
+
+  public BusinessException(int code, String message) {
+    super(message);
+    this.code = code;
+  }
+
+  public BusinessException(int code, String message, Throwable cause) {
+    super(message, cause);
+    this.code = code;
+  }
+
+  public int getCode() {
+    return this.code;
+  }
+
+  public void setCode(int code) {
+    this.code = code;
+  }
+
+  public Object getData() {
+    return data;
+  }
+
+  public void setData(Object data) {
+    this.data = data;
+  }
+
+}

+ 17 - 0
src/main/java/com/energy/manage/analyse/common/exception/ErrorSignException.java

@@ -0,0 +1,17 @@
+package com.energy.manage.analyse.common.exception;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ErrorSignException extends RuntimeException {
+
+  private Logger logger = LoggerFactory.getLogger(ErrorSignException.class);
+
+  public ErrorSignException(String phone) {
+    logger.info(String.format("用户:%s,签名验证失败访问系统被拦截", phone));
+  }
+
+  public ErrorSignException() {
+    logger.info(String.format("未获取jwt信息,签名验证失败访问系统被拦截"));
+  }
+}

+ 7 - 0
src/main/java/com/energy/manage/analyse/common/exception/NoRequestException.java

@@ -0,0 +1,7 @@
+package com.energy.manage.analyse.common.exception;
+
+/**
+ * 重复提交异常
+ */
+public class NoRequestException extends RuntimeException {
+}

+ 9 - 0
src/main/java/com/energy/manage/analyse/common/exception/ServiceErrorException.java

@@ -0,0 +1,9 @@
+package com.energy.manage.analyse.common.exception;
+
+/**
+ * @author lwz
+ * @createTime 2020-07-29 17:36
+ * @desc
+ */
+public class ServiceErrorException extends RuntimeException {
+}

+ 27 - 0
src/main/java/com/energy/manage/analyse/common/exception/ServiceException.java

@@ -0,0 +1,27 @@
+package com.energy.manage.analyse.common.exception;
+
+
+import com.energy.manage.analyse.common.base.BaseException;
+
+/**
+ * Created by lixzh on 1/17/17.
+ */
+public class ServiceException extends BaseException {
+  private static final long serialVersionUID = -6336125614015879323L;
+
+  public ServiceException() {
+    super();
+  }
+
+  public ServiceException(String message) {
+    super(message);
+  }
+
+  public ServiceException(Throwable cause) {
+    super(cause);
+  }
+
+  public ServiceException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}

+ 4 - 0
src/main/java/com/energy/manage/analyse/common/exception/TokenInvalidException.java

@@ -0,0 +1,4 @@
+package com.energy.manage.analyse.common.exception;
+
+public class TokenInvalidException extends RuntimeException {
+}

+ 29 - 0
src/main/java/com/energy/manage/analyse/common/exception/UserNotLoginException.java

@@ -0,0 +1,29 @@
+package com.energy.manage.analyse.common.exception;
+
+public class UserNotLoginException extends RuntimeException {
+  private Long userId;
+  private String userKey;
+
+  public Long getUserId() {
+    return userId;
+  }
+
+  public void setUserId(Long userId) {
+    this.userId = userId;
+  }
+
+  public String getUserKey() {
+    return userKey;
+  }
+
+  public void setUserKey(String userKey) {
+    this.userKey = userKey;
+  }
+
+  public UserNotLoginException(){}
+
+  public UserNotLoginException(Long userId, String userKey){
+    this.userId = userId;
+    this.userKey = userKey;
+  }
+}

+ 15 - 0
src/main/java/com/energy/manage/analyse/common/mapper/MyMapper.java

@@ -0,0 +1,15 @@
+package com.energy.manage.analyse.common.mapper;
+
+import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.MySqlMapper;
+
+/**
+ * 继承自己的MyMapper
+ * 使用通用mapper
+ * @author shiyue
+ * @since 2017-09-06 21:53
+ */
+public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
+    //TODO
+    //FIXME 特别注意,必须继承该接口,否则mapper无法被扫描到
+}

+ 131 - 0
src/main/java/com/energy/manage/analyse/common/reponse/ConstVar.java

@@ -0,0 +1,131 @@
+package com.energy.manage.analyse.common.reponse;
+
+import java.nio.charset.Charset;
+
+/**
+ * 一些状态变量而已
+ *
+ * @author LIKE
+ * @date 2017年1月17日 下午7:45:46
+ */
+public enum ConstVar {
+
+  FAIL(-1, "失败"),
+  TIMEOUT(109, "操作超时,请重新选择成绩单上传"),
+  SUCCESS(200, "成功"),
+  EXISTSUSER(101, "用户已存在"),
+  SMSFAIL(102, "验证码错误"),
+  SMSCODEFREQUENT(103, "验证码发送太频繁,请稍后重试"),
+  EQUIOMENGTINUSE(118, "设备已经使用"),
+  NOTNULLPARAM(105, "参数不能为空"),
+  PLEASELOGIN(108, "请登录账户"),
+  EXISTSUSERNOTUSE(111, "账号被停用"),
+  NOTEXISTSUSER(112, "用户不存在"),
+  TOKENINVALID(113, "请重新登陆用户"),
+
+  ERRORSIGN(114, "验签失败"),
+  INVALIDPARAM(115, "无效参数"),
+  ISDONE(122, "测验结束,已做题"),
+  SMSOVERDUE(116, "验证码已过期"),
+  // 重复提交
+  NOREQUEST_CODE(117, "不可重复提交"),
+  ERRORPWD(-2, "密码错误"),
+  ERRORVALIDATECODE(-3, "验证码错误"),
+  NOTLOGIN(142, "未登录"),
+  INVALIDATE_TOKEN(141, "Token失效,请重新登录"),
+  PHONE_REPETITION(150, "该手机号已绑定账号请重新输入"),
+  //权限资源模块响应码
+  PERMISSION_ALREADY_SORT(601, "当前父id下该序号已有"),
+  PERMISSION_ALREADY_ROLE(605, "当前资源已有角色关联"),
+  ROLE_ALREADY_USER(606, "当前角色已有关联用户"),
+  ROLE_ALREADY_PERMISSION(607, "当前角色已有关联资源"),
+  ROLE_DESCRIPTION_ALREADY(620, "该角色名已有"),
+
+  NOT_EXIST_COURSE_SERIES(10001, "系列课不存在"),
+  NOT_EXIST_COURSE(10002, "课程不存在"),
+
+  // 微信响应码
+  WEIXIN_EXCEPTION_SMSOVERDUE(110020, "微信授权失败"),
+  WEIXIN_EXCEPTION_CODE(110021, "微信授权code失败"),
+
+  CONSISTENCY_NOT_PWD(110022, "两次密码输入不一致,请重新确认"),
+
+  PUT_IN_NAME_DUBBO(210001, "名称或渠道码不能重复"),
+  PUT_IN_PLAN_PROPORTION(210002, "配置权重之和应为100"),
+  PUT_IN_LINK_DUBBO(210003, "落地页不能重复"),
+  PUT_IN_CHILD_NUMBER(210004, "拟投放子渠道码数量需大于零"),
+  PUT_IN_IMPORT(210005, "上传文件格式不正确"),
+  PUT_IN_MODULE(210006, "模板表头不正确"),
+  PUT_IN_DATA_DUBBO(210007, "数据重复"),
+  PUT_IN_FEELING_UPDATE(210008, "上架产品不可编辑"),
+  PUT_IN_FEELING_DEL(210009, "上架产品不可删除"),
+
+  CRM_TEACHER_NAME(310001, "班主任名称重复"),
+  PARAM_ID_NULL(310002, "id不能为空"),
+
+  PERIOD_TIME_ERROR(410001, "招生时间需早于上课时间,上课时间需早于课程有效期时间,且不能重叠。"),
+  PERIOD_TYPE_ERROR(410002, "直播期类型有误。"),
+  PERIOD_CLASSTIME_ERROR(410003, "直播期上课时间不能重叠。"),
+  PERIOD_COURCE_ERROR(410004, "直播结束回调,course_id无数据。"),
+  PERIOD_UPDATE_ID(410005, "暂无数据可更改,请检查id。"),
+  PERIOD_ADD_TIME(410006, "上课时间不能早于当前时间。"),
+  MESSAGE_TOO_LONG(410007, "发送消息内容不能为空且需要在200字以内"),
+  PERIOD_DETETE_BIND(410008, "有关联课程的营期不能删除"),
+  PERIOD_DETETE_APPLY(410008, "有学员报名的营期不能删除"),
+
+  TOOLS_PHONE(510001, "无学员信息"),
+  TOOLS_PHONE_REGEXP(510002, "手机号码格式不正确"),
+  TOOLS_HAS_WHITE(510003, "该用户已在白名单"),
+
+  DATA_TRANSFER_TYPE_EMPTY(610001, "数据转换类型初始化数据不能为空"),
+  DATA_TRANSFERING(610002, "系统中存在正在转换的数据,请稍后操作数据转换"),
+
+  SAME_WIND_ENGINE_ERR_INFO(710001, "同一批次该机组存在相同分析类型的异常描述信息,不能重复添加"),
+
+  NO_DIFINED_TYPE(810001, "非自定义评论类型,不能删除"),
+
+  DUPLICATE_TYPE_NAME(810002, "该评论类型已存在,不能添加"),
+
+  ANALYSISING(910001, "当前有批次正在进行分析,请稍后重试"),
+
+  EXSIT_BATCH_NAME(1010001, "当前批次名称已存在,请重新编辑"),
+
+
+  EXSIT_ON_CONFIG(1020001, "当前风场已存在启动中的自动分析配置"),
+
+  //测评小程序
+  PAPER_USER_UNBELONG_TO(3000,"哎呀,该测评已经被其他用户绑定过了,您无法进行查看~"),
+  PAPER_ANSWER_SIZE_ERROR(3001,"试题未答完,请检查试题");
+
+
+
+  /*常量~*/
+  public static final String ENCODING = Charset.forName("UTF-8").name();
+
+  public static final String ZERO = ",0";
+
+  private ConstVar(int code, String msg) {
+    this.code = code;
+    this.msg = msg;
+  }
+
+  private String msg;
+  private int code;
+
+  public int getCode() {
+    return code;
+  }
+
+  public void setCode(int code) {
+    this.code = code;
+  }
+
+  public String getMsg() {
+    return msg;
+  }
+
+  public void setMsg(String msg) {
+    this.msg = msg;
+  }
+}
+

+ 50 - 0
src/main/java/com/energy/manage/analyse/common/reponse/HttpResult.java

@@ -0,0 +1,50 @@
+package com.energy.manage.analyse.common.reponse;
+
+import java.util.Optional;
+
+/**
+ * 请求响应实体
+ */
+public class HttpResult {
+
+    private boolean success;
+    private int statusCode;
+    private String message;
+    private String data;
+
+    private HttpResult(boolean success, int statusCode, String message, String data) {
+        this.success = success;
+        this.statusCode = statusCode;
+        this.message = message;
+        this.data = data;
+    }
+
+    public static HttpResult success(int statusCode, String data) {
+        return new HttpResult(true, statusCode, "请求成功", data);
+    }
+
+    public static HttpResult fail(String message) {
+        return new HttpResult(false, -1, message, null);
+    }
+
+    public static HttpResult fail(int statusCode, String message) {
+        return new HttpResult(false, statusCode, message, null);
+    }
+
+    // Getter方法
+    public boolean isSuccess() {
+        return success;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public Optional<String> getData() {
+        return Optional.ofNullable(data);
+    }
+}

+ 406 - 0
src/main/java/com/energy/manage/analyse/common/reponse/RespMsg.java

@@ -0,0 +1,406 @@
+package com.energy.manage.analyse.common.reponse;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.util.StringUtils;
+
+public class RespMsg {
+
+  /**
+   * 操作成功
+   */
+  public static JSONObject SUCCESS() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.SUCCESS.getCode());
+    RS.put("msg", ConstVar.SUCCESS.getMsg());
+    RS.put("status", true);
+    return RS;
+  }
+
+  /**
+   * 操作成功
+   */
+  public static JSONObject SUCCESS(int code, String msg, Object data) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", code);
+    RS.put("msg", msg);
+    RS.put("data", data);
+    RS.put("status", true);
+    return RS;
+  }
+
+  public static JSONObject SUCCESS(Object data) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.SUCCESS.getCode());
+    RS.put("msg", ConstVar.SUCCESS.getMsg());
+    RS.put("data", data);
+    RS.put("status", true);
+    return RS;
+  }
+
+  /**
+   * 操作失败
+   */
+  public static JSONObject FAIL() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.FAIL.getCode());
+    RS.put("msg", ConstVar.FAIL.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 上传操作超时
+   */
+  public static JSONObject TIMEOUT() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.TIMEOUT.getCode());
+    RS.put("msg", ConstVar.TIMEOUT.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  public static JSONObject FAIL(Integer code, String msg) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", code);
+    RS.put("msg", msg);
+    RS.put("status", false);
+    return RS;
+  }
+
+  public static JSONObject FAIL(String msg) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.FAIL.getCode());
+    RS.put("msg", msg);
+    RS.put("status", false);
+    return RS;
+  }
+
+
+  /**
+   * 参数不能为空
+   *
+   * @return
+   */
+  public static JSONObject NOTNULLPARAM() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.NOTNULLPARAM.getCode());
+    RS.put("msg", ConstVar.NOTNULLPARAM.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 用户已存在
+   *
+   * @return
+   */
+  public static JSONObject EXISTSUSER() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.EXISTSUSER.getCode());
+    RS.put("msg", ConstVar.EXISTSUSER.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 账号被停用
+   *
+   * @return
+   */
+  public static JSONObject EXISTSUSERNOTUSE() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.EXISTSUSERNOTUSE.getCode());
+    RS.put("msg", ConstVar.EXISTSUSERNOTUSE.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 用户不存在
+   *
+   * @return
+   */
+  public static JSONObject NOTEXISTSUSER() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.NOTEXISTSUSER.getCode());
+    RS.put("msg", ConstVar.NOTEXISTSUSER.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 密码错误
+   *
+   * @return
+   */
+  public static JSONObject ERRORPWD() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.ERRORPWD.getCode());
+    RS.put("msg", ConstVar.ERRORPWD.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 无效参数
+   *
+   * @return
+   */
+  public static JSONObject INVALIDPARAM(String param) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.INVALIDPARAM.getCode());
+    RS.put("msg", ConstVar.INVALIDPARAM.getMsg() + "-" + param);
+    RS.put("status", false);
+    return RS;
+  }
+
+
+  /**
+   * 请登录用户
+   *
+   * @return
+   */
+  public static JSONObject PLEASELOGIN() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.PLEASELOGIN.getCode());
+    RS.put("msg", ConstVar.PLEASELOGIN.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * token失效
+   *
+   * @return
+   */
+  public static JSONObject TOKENVALID() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.TOKENINVALID.getCode());
+    RS.put("msg", ConstVar.TOKENINVALID.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 验签失败
+   *
+   * @return
+   */
+  public static JSONObject ERRORSIGN() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.ERRORSIGN.getCode());
+    RS.put("msg", ConstVar.ERRORSIGN.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  public static JSONObject SMSOVERDUE() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.SMSOVERDUE.getCode());
+    RS.put("msg", ConstVar.SMSOVERDUE.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 验证码错误
+   *
+   * @return
+   */
+  public static JSONObject SMSFAIL() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.SMSFAIL.getCode());
+    RS.put("msg", ConstVar.SMSFAIL.getMsg());
+    RS.put("status", false);
+    RS.put("data", null);
+    return RS;
+  }
+
+  /**
+   * 验证码错误
+   *
+   * @return
+   */
+  public static JSONObject EQUIOMENGTINUSE() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.EQUIOMENGTINUSE.getCode());
+    RS.put("msg", ConstVar.EQUIOMENGTINUSE.getMsg());
+    RS.put("status", false);
+    RS.put("data", null);
+    return RS;
+  }
+
+  /**
+   * 微信授权失败
+   *
+   * @return
+   */
+  public static JSONObject WEIXINEXCEPTIONSMSOVERDUE() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.WEIXIN_EXCEPTION_SMSOVERDUE.getCode());
+    RS.put("msg", ConstVar.WEIXIN_EXCEPTION_SMSOVERDUE.getMsg());
+    RS.put("status", false);
+    RS.put("data", null);
+    return RS;
+  }
+
+  public static JSONObject FAILException() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.FAIL.getCode());
+    RS.put("status", false);
+    RS.put("msg", "系统错误,请联系管理员");
+    return RS;
+  }
+
+  /**
+   * 验证码发送太频繁
+   *
+   * @return
+   */
+  public static JSONObject SMSCODEFREQUENT() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.SMSCODEFREQUENT.getCode());
+    RS.put("msg", ConstVar.SMSCODEFREQUENT.getMsg());
+    RS.put("data", null);
+    return RS;
+  }
+
+  public static JSONObject ISDONE(String msg) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.ISDONE.getCode());
+    RS.put("msg", msg);
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 微信验证码发送太频繁
+   *
+   * @return
+   */
+  public static JSONObject WXUSERCODE(String appid) {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.WEIXIN_EXCEPTION_CODE.getCode());
+    RS.put("msg", ConstVar.WEIXIN_EXCEPTION_CODE.getMsg());
+    RS.put("data", appid);
+    return RS;
+  }
+
+  /**
+   * 两次密码输入不一致,请重新确认
+   *
+   * @return
+   */
+  public static JSONObject CONSISTENCYNOTPWD() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.CONSISTENCY_NOT_PWD.getCode());
+    RS.put("msg", ConstVar.CONSISTENCY_NOT_PWD.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 用户未登录
+   *
+   * @param msg
+   * @return
+   */
+  public static JSONObject NOTLOGIN(String msg) {
+    if (StringUtils.isEmpty(msg)) {
+      return buildRespMsg(ConstVar.NOTLOGIN.getCode(), ConstVar.NOTLOGIN.getMsg(), null);
+    }
+    return buildRespMsg(ConstVar.NOTLOGIN.getCode(), msg, null);
+  }
+
+  /**
+   * 用户已掉线
+   *
+   * @param msg
+   * @return
+   */
+  public static JSONObject INVALIDATETOKEN(String msg) {
+    if (StringUtils.isEmpty(msg)) {
+      return buildRespMsg(ConstVar.INVALIDATE_TOKEN.getCode(), ConstVar.INVALIDATE_TOKEN.getMsg(), null);
+    }
+    return buildRespMsg(ConstVar.INVALIDATE_TOKEN.getCode(), msg, null);
+  }
+
+
+  /**
+   * 重复提交
+   *
+   * @return
+   */
+  public static JSONObject NOREQUEST() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.NOREQUEST_CODE.getCode());
+    RS.put("msg", ConstVar.NOREQUEST_CODE.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * 系列课不存在
+   *
+   * @return
+   */
+  public static JSONObject NOTEXISTCOURSESERIES() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.NOT_EXIST_COURSE_SERIES.getCode());
+    RS.put("msg", ConstVar.NOT_EXIST_COURSE_SERIES.getMsg());
+    RS.put("status", false);
+
+    return RS;
+  }
+
+  /**
+   * 课程不存在
+   *
+   * @return
+   */
+  public static JSONObject NOTEXISTCOURSE() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.NOT_EXIST_COURSE.getCode());
+    RS.put("msg", ConstVar.NOT_EXIST_COURSE.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+  /**
+   * id为空
+   *
+   * @return
+   */
+  public static JSONObject PARAM_ID_NULL() {
+    JSONObject RS = new JSONObject();
+    RS.put("code", ConstVar.PARAM_ID_NULL.getCode());
+    RS.put("msg", ConstVar.PARAM_ID_NULL.getMsg());
+    RS.put("status", false);
+    return RS;
+  }
+
+
+  /**
+   * 内部方法,构建返回值实体对象
+   *
+   * @param code
+   * @param msg
+   * @param data
+   * @return
+   */
+  private static JSONObject buildRespMsg(Integer code, String msg, Object data) {
+    JSONObject RS = new JSONObject();
+    if (null != code) {
+      RS.put("code", code);
+    }
+    if (!StringUtils.isEmpty(msg)) {
+      RS.put("msg", msg);
+    }
+    if (null != data) {
+      RS.put("data", data);
+    }
+    return RS;
+  }
+
+
+}

+ 177 - 0
src/main/java/com/energy/manage/analyse/common/reponse/ResultResp.java

@@ -0,0 +1,177 @@
+package com.energy.manage.analyse.common.reponse;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.util.StringUtils;
+
+import java.util.Optional;
+
+/**
+ * 前端统一结构返回数据
+ */
+@Getter
+@Setter
+public class ResultResp<T> {
+  private Integer code;
+  private String msg;
+  private Boolean status;
+  private T data;
+
+  /**
+   * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   */
+  /**
+   * 构造器
+   *
+   * @param <T>
+   * @return
+   */
+  private static <T> ResultResp<T> buildResponse(Integer code, String msg, T data, boolean status) {
+    ResultResp<T> resp = new ResultResp<>();
+    if (Optional.ofNullable(code).isPresent()) {
+      resp.setCode(code);
+    }
+    if (!StringUtils.isEmpty(msg)) {
+      resp.setMsg(msg);
+    }
+    if (Optional.ofNullable(data).isPresent()) {
+      resp.setData(data);
+    }
+    resp.setStatus(status);
+    return resp;
+  }
+
+
+  /**
+   * 操作成功
+   */
+  public static ResultResp SUCCESS() {
+    return ResultResp.buildResponse(ConstVar.SUCCESS.getCode(),
+            ConstVar.SUCCESS.getMsg(), null, true);
+  }
+
+  /**
+   * 操作成功
+   */
+  public static <T> ResultResp<T> SUCCESS(T data) {
+    return ResultResp.buildResponse(ConstVar.SUCCESS.getCode(),
+            ConstVar.SUCCESS.getMsg(), data, true);
+  }
+
+  /**
+   * 操作成功
+   */
+  public static <T> ResultResp<T> SUCCESS(Integer code, String msg) {
+    return ResultResp.buildResponse(code, msg, null, true);
+  }
+
+  /**
+   * 操作成功
+   */
+  public static <T> ResultResp<T> SUCCESS(Integer code, String msg, T data) {
+    return ResultResp.buildResponse(code, msg, data, true);
+  }
+
+  /**
+   * 操作失败
+   */
+  public static ResultResp FAIL() {
+    return ResultResp.buildResponse(ConstVar.FAIL.getCode(), ConstVar.FAIL.getMsg(), null, false);
+  }
+
+  public static ResultResp FAIL(String msg) {
+    return ResultResp.buildResponse(ConstVar.FAIL.getCode(), msg, null, false);
+  }
+
+  public static ResultResp FAIL(Integer code, String msg) {
+    return ResultResp.buildResponse(code, msg, null, false);
+  }
+
+  public static ResultResp FAIL(ConstVar constVar) {
+    return ResultResp.buildResponse(constVar.getCode(), constVar.getMsg(), null, false);
+  }
+
+
+  /**
+   * 密码错误
+   *
+   * @return
+   */
+  public static ResultResp ERRORPWD() {
+    return ResultResp.buildResponse(ConstVar.ERRORPWD.getCode(), ConstVar.ERRORPWD.getMsg(), null, false);
+  }
+
+  /**
+   * 参数不能为空
+   *
+   * @return
+   */
+  public static ResultResp NOTNULLPARAM() {
+    return ResultResp.buildResponse(ConstVar.NOTNULLPARAM.getCode(), ConstVar.NOTNULLPARAM.getMsg(), null, false);
+  }
+
+  /**
+   * 用户不存在
+   *
+   * @return
+   */
+  public static ResultResp NOTEXISTSUSER() {
+    return ResultResp.buildResponse(ConstVar.NOTEXISTSUSER.getCode(),ConstVar.NOTEXISTSUSER.getMsg(), null, false);
+  }
+
+
+  /**
+   * 用户已经存在
+   *
+   * @return
+   */
+  public static ResultResp EXISTSUSER() {
+    return ResultResp.buildResponse(ConstVar.EXISTSUSER.getCode(),ConstVar.EXISTSUSER.getMsg(), null, false);
+  }
+
+  /**
+   * 无效参数
+   *
+   * @return
+   */
+  public static ResultResp INVALIDPARAM(String param) {
+    return ResultResp.buildResponse(ConstVar.INVALIDPARAM.getCode(), ConstVar.INVALIDPARAM.getMsg(), null, false);
+  }
+
+  /**
+   * token失效
+   *
+   * @return
+   */
+  public static ResultResp TOKENVALID() {
+    return ResultResp.buildResponse(ConstVar.TOKENINVALID.getCode(), ConstVar.TOKENINVALID.getMsg(), null, false);
+  }
+
+  /**
+   * 验签失败
+   *
+   * @return
+   */
+  public static ResultResp ERRORSIGN() {
+    return ResultResp.buildResponse(ConstVar.ERRORSIGN.getCode(), ConstVar.ERRORSIGN.getMsg(), null, false);
+  }
+
+  /**
+   * 系统异常
+   *
+   * @return
+   */
+  public static ResultResp USERNOTLOGIN() {
+    return ResultResp.buildResponse(ConstVar.PLEASELOGIN.getCode(), ConstVar.PLEASELOGIN.getMsg(), null, false);
+  }
+
+  /**
+   * 系统异常
+   *
+   * @return
+   */
+  public static ResultResp FAILException() {
+    return ResultResp.buildResponse(ConstVar.FAIL.getCode(), "系统错误,请联系管理员", null, false);
+  }
+
+}

+ 21 - 0
src/main/java/com/energy/manage/analyse/config/HttpConfig.java

@@ -0,0 +1,21 @@
+package com.energy.manage.analyse.config;
+
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+import java.time.Duration;
+
+@Configuration
+public class HttpConfig {
+
+    @Bean
+    public RestTemplate restTemplate() {
+        RestTemplate restTemplate = new RestTemplateBuilder()
+                .setConnectTimeout(Duration.ofSeconds(3))
+                .setReadTimeout(Duration.ofSeconds(10))
+                .build();
+        return restTemplate;
+    }
+}

+ 46 - 0
src/main/java/com/energy/manage/analyse/config/Knife4jConfiguration.java

@@ -0,0 +1,46 @@
+package com.energy.manage.analyse.config;
+
+import io.swagger.models.auth.In;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Configuration
+@EnableSwagger2
+public class Knife4jConfiguration {
+
+    @Bean(value = "defaultApi2")
+    public Docket defaultApi2() {
+        Docket docket = new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                //分组名称
+                .groupName("2.X版本")
+                .select()
+                //这里指定Controller扫描包路径
+                .apis(RequestHandlerSelectors.basePackage("com.energy.manage.analyse.controller"))
+                .paths(PathSelectors.any())
+                .build();
+        return docket;
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("中能智能分析业务后台相关接口文档")
+                .description("包含模块:异常检测和健康诊断接口")
+                .termsOfServiceUrl("https://lanhuapp.com/url/4qLCF")
+                .contact(new Contact("研发中心", "", ""))
+                .version("1.0")
+                .build();
+    }
+
+}

+ 35 - 0
src/main/java/com/energy/manage/analyse/config/LoginVerifyInterceptorConf.java

@@ -0,0 +1,35 @@
+package com.energy.manage.analyse.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+@Configuration
+@ConditionalOnProperty(value = "energy.login.enabled", havingValue = "true")
+public class LoginVerifyInterceptorConf extends WebMvcConfigurationSupport {
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+    }
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        // 设置允许跨域的路径
+        registry.addMapping("/**")
+                // 设置允许跨域请求的域名
+                .allowedOrigins("*")
+                // 是否允许证书
+                .allowCredentials(true)
+                // 设置允许的方法
+                .allowedMethods("GET", "POST", "DELETE", "PUT")
+                // 设置允许的header属性
+                .allowedHeaders("*")
+                // 跨域允许时间
+                .maxAge(3600);
+    }
+
+}

+ 116 - 0
src/main/java/com/energy/manage/analyse/config/SystemExceptionHandler.java

@@ -0,0 +1,116 @@
+package com.energy.manage.analyse.config;
+
+import com.alibaba.fastjson.JSONObject;
+import com.energy.manage.analyse.common.exception.*;
+import com.energy.manage.analyse.common.reponse.RespMsg;
+import com.energy.manage.analyse.common.reponse.ResultResp;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.lang.Nullable;
+import org.springframework.util.StringUtils;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+
+@RestControllerAdvice
+@Slf4j
+public class SystemExceptionHandler {
+
+    @ExceptionHandler(value = ServiceErrorException.class)
+    @ResponseBody
+    @CrossOrigin
+    public JSONObject doServiceErrorException() {
+        return RespMsg.FAILException();
+    }
+
+    @ExceptionHandler(value = UserNotLoginException.class)
+    @ResponseBody
+    @CrossOrigin
+    public JSONObject doUserNotLoginHandler() {
+        return RespMsg.PLEASELOGIN();
+    }
+
+    @ExceptionHandler(value = TokenInvalidException.class)
+    @ResponseBody
+    @CrossOrigin
+    public JSONObject doMorePersonLoginHandler() {
+        return RespMsg.TOKENVALID();
+    }
+
+    @ExceptionHandler(value = ErrorSignException.class)
+    @CrossOrigin
+    @ResponseBody
+    public JSONObject doErrorSign() {
+        return RespMsg.ERRORSIGN();
+    }
+
+    @ExceptionHandler(value = NoRequestException.class)
+    @CrossOrigin
+    @ResponseBody
+    public JSONObject doNoRequestHandler() {
+        return RespMsg.NOREQUEST();
+    }
+
+    @ExceptionHandler(value = BusinessException.class)
+    @CrossOrigin
+    @ResponseBody
+    public JSONObject serviceExceptionHandler(BusinessException businessException) {
+        return RespMsg.FAIL(businessException.getCode(), businessException.getMessage());
+    }
+
+    @ExceptionHandler(value = MethodArgumentNotValidException.class)
+    @CrossOrigin
+    @ResponseBody
+    public ResultResp methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException methodArgumentNotValidException) {
+        return ResultResp.FAIL(methodArgumentNotValidException.getBindingResult().getFieldErrors().get(0).getDefaultMessage());
+    }
+
+    /**
+     * 违反约束异常处理
+     *
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(ConstraintViolationException.class)
+    @ResponseBody
+    public ResultResp handConstraintViolationException(ConstraintViolationException e) {
+        String msg = e.getConstraintViolations()
+                .stream()
+                .map(ConstraintViolation::getMessage)
+                .collect(Collectors.joining("; "));
+        return ResultResp.FAIL(msg);
+    }
+
+
+    @ExceptionHandler(ValidationException.class)
+    @ResponseBody
+    public ResultResp validException(ValidationException exception) {
+        return ResultResp.FAIL(exception.getMessage());
+    }
+
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    protected ModelAndView handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
+                                                               HttpServletRequest request, HttpServletResponse response,
+                                                               @Nullable Object handler) throws IOException {
+        String[] supportedMethods = ex.getSupportedMethods();
+        if (supportedMethods != null) {
+            response.setHeader("Allow", StringUtils.arrayToDelimitedString(supportedMethods, ", "));
+        }
+        log.error("访问[{}]类型[{}]不支持", request.getRequestURI(),request.getMethod().toUpperCase(Locale.ROOT));
+        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ex.getMessage());
+        return new ModelAndView();
+    }
+}

+ 57 - 0
src/main/java/com/energy/manage/analyse/config/WebMVCConfig.java

@@ -0,0 +1,57 @@
+package com.energy.manage.analyse.config;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.List;
+
+
+@Configuration
+public class WebMVCConfig  implements WebMvcConfigurer {
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        //swagger2 静态资源映射
+        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+    }
+
+    /**
+     * 跨域问题
+     * @param registry
+     */
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                //.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "X-Token", "content-type")
+                .allowedHeaders("*")  //服务器允许的请求头
+                .allowedMethods("POST", "PUT", "GET", "OPTIONS", "DELETE")  //服务器允许的请求方法
+                .allowCredentials(true)  //允许带 cookie 的跨域请求
+                .allowedOrigins("*")  //服务端允许哪些域请求资源
+                .maxAge(3600);   //预检请求的缓存时间
+    }
+
+
+    @Override
+    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
+        converters.add(mappingJackson2HttpMessageConverter());
+    }
+
+    @Bean
+    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
+        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+        ObjectMapper objectMapper = new ObjectMapper();
+        //未知属性忽略
+        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        converter.setObjectMapper(objectMapper);
+        return converter;
+    }
+
+}

+ 60 - 0
src/main/java/com/energy/manage/analyse/constant/AnomalySensorType.java

@@ -0,0 +1,60 @@
+package com.energy.manage.analyse.constant;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public enum AnomalySensorType {
+
+
+    POWER_SENSOR("sensor_anomaly_power", "功率传感器异常"),
+
+    WIND_SENSOR("sensor_anomaly_wind", "风速传感器异常"),
+
+    PITCH_SENSOR("sensor_anomaly_pitch", "变桨传感器异常"),
+
+    SPEED_SENSOR("sensor_anomaly_speed", "转速传感器异常"),
+
+    TORQUE_SENSOR("sensor_anomaly_torque", "转矩传感器异常"),
+
+    WIND_POWER_LOGIC("sensor_anomaly_wind_pwr", "风速-功率逻辑异常"),
+
+    SPEED_TORQUE_LOGIC("sensor_anomaly_spd_trq", "转速-扭矩逻辑异常");
+
+
+    private final String fieldName;
+    private final String displayName;
+
+    AnomalySensorType(String fieldName, String displayName) {
+        this.fieldName = fieldName;
+        this.displayName = displayName;
+    }
+
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public int getStatus(Map<String, Integer> sensorStatusMap) {
+        return sensorStatusMap.getOrDefault(this.fieldName, 0);
+    }
+
+    public boolean isAbnormal(Map<String, Integer> sensorStatusMap) {
+        return getStatus(sensorStatusMap) == 1;
+    }
+
+    public static List<AnomalySensorType> getAbnormalSensors(Map<String, Integer> sensorStatusMap) {
+        List<AnomalySensorType> abnormalSensors = new ArrayList<>();
+        for (AnomalySensorType type : values()) {
+            if (type.isAbnormal(sensorStatusMap)) {
+                abnormalSensors.add(type);
+            }
+        }
+        return abnormalSensors;
+    }
+
+
+}

+ 128 - 0
src/main/java/com/energy/manage/analyse/constant/DetectorTableEnum.java

@@ -0,0 +1,128 @@
+package com.energy.manage.analyse.constant;
+
+public enum DetectorTableEnum {
+
+
+    /**
+     * 风速功率功率曲线检测器
+     */
+    POWER_CURVE("anomaly_powercurve", "(风速功率)功率曲线检测器"),
+
+    /**
+     * 风速功率功率散点检测器
+     */
+    SCATTER("anomaly_scatter", "(风速功率)功率散点检测器"),
+
+    /**
+     * 风速功率simulink检测器
+     */
+    SIMULINK("anomaly_simulink", "(风速功率)simulink检测器"),
+    /**
+     * 偏航扭缆角度检测器
+     */
+    CABLE_TWIST("anomaly_cabletwist", "(偏航)扭缆角度检测器"),
+    /**
+     * 偏航偏航角度检测器
+     */
+    STATIC_YAW("anomaly_staticyaw", "(偏航)偏航角度检测器"),
+
+    /**
+     * 变桨最小桨距角检测器
+     */
+    MIN_PITCH("anomaly_minpitch", "(变桨)最小桨距角检测器"),
+    /**
+     * 变桨-转速-功率检测器
+     */
+    PITCH_COORD("anomaly_pitchcoord", "(变桨)变桨-转速-功率检测器"),
+
+    /**
+     * 变桨检测器
+     */
+    PITCH_REGULATION("anomaly_pitchregulation", "(变桨)变桨检测器"),
+
+    /**
+     * 运行状态机械运行状态检测器
+     */
+    OPERATION("anomaly_operation", "(运行状态)机械运行状态检测器"),
+
+    /**
+     * 运行状态电气功率质量检测器
+     */
+    POWER_QUALITY("anomaly_powerquality", "(运行状态)电气功率质量检测器"),
+
+
+    /**
+     * Cp 检测器
+     * 对应字段:model5_aerodynamics_cp
+     */
+    CP_DETECTOR("anomaly_cp", "Cp检测器"),
+
+    /**
+     * TSR 风速分箱检测器
+     * 对应字段:model5_aerodynamics_tsr
+     */
+    TSR_DETECTOR("anomaly_tsr", "TSR风速分箱检测器"),
+
+    /**
+     * Cp-TSR 联合分布检测器
+     * 对应字段:model5_aerodynamics_cp_tsr
+     */
+    CP_TSR_DETECTOR("anomaly_cp_tsr", "Cp-TSR联合分布检测器");
+
+
+
+    private final String tableName;
+    private final String description;
+
+    DetectorTableEnum(String tableName, String description) {
+        this.tableName = tableName;
+        this.description = description;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * 根据表名获取枚举
+     */
+    public static DetectorTableEnum fromTableName(String tableName) {
+        for (DetectorTableEnum value : values()) {
+            if (value.getTableName().equals(tableName)) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 获取完整的表名(带年份后缀)
+     * 注意:这里年份2026是硬编码的,如果有动态需求可以调整
+     */
+    public String getFullTableName(String year) {
+        return tableName +"_"+ year;
+    }
+
+    /**
+     * 获取模块名称
+     * 根据描述判断所属模块
+     */
+    public String getModuleName() {
+        if (description.contains("偏航")) {
+            return "yaw";
+        } else if (description.contains("变桨")) {
+            return "pitch";
+        } else if (description.contains("风速功率")) {
+            return "wind_power";
+        } else if (description.contains("运行状态")) {
+            return "control_params";
+        }
+        return "unknown";
+    }
+
+
+}

+ 89 - 0
src/main/java/com/energy/manage/analyse/constant/DetectorType.java

@@ -0,0 +1,89 @@
+package com.energy.manage.analyse.constant;
+
+/**
+ * 检测器枚举
+ */
+public enum DetectorType {
+
+    // 模块1:风速功率检测器
+    MODEL1_POWERCURVE("model1_powercurve", "功率曲线检测器"),
+    MODEL1_SCATTER("model1_scatter", "功率散点检测器"),
+    MODEL1_SIMULINK("model1_simulink", "simulink检测器"),
+
+    // 模块2:偏航检测器
+    MODEL2_STATICYAW("model2_staticyaw", "偏航角度检测器"),
+    MODEL2_CABLETWIST("model2_cabletwist", "扭缆角度检测器"),
+
+    // 模块3:变桨检测器
+    MODEL3_PITCHREGULATION("model3_pitchregulation", "变桨检测器"),
+    MODEL3_PITCHCOORD("model3_pitchcoord", "变桨-转速-功率检测器"),
+    MODEL3_MINPITCH("model3_minpitch", "最小桨距角检测器"),
+
+    // 模块4:运行状态检测器
+    MODEL4_POWERQUALITY("model4_powerquality", "电气功率质量检测器"),
+    MODEL4_OPERATIONSTATE("model4_operationstate", "机械运行状态检测器"),
+    MODEL4_DELOAD("model4_ctrlparam_deload", "降载检测器"),
+
+    // 模块5:气动性能
+    MODEL5_CP("model5_aerodynamics_cp", "Cp检测器"),
+    MODEL5_TSR("model5_aerodynamics_tsr", "TSR风速分箱检测器"),
+    MODEL5_CP_TSR("model5_aerodynamics_cp_tsr", "Cp-TSR联合分布检测器");
+
+    private final String code;
+    private final String description;
+
+    DetectorType(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * 根据code获取枚举
+     */
+    public static DetectorType fromCode(String code) {
+        for (DetectorType type : values()) {
+            if (type.code.equals(code)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 检查是否是模块1检测器
+     */
+    public boolean isModule1Detector() {
+        return this.name().startsWith("MODEL1_");
+    }
+
+    /**
+     * 检查是否是模块2检测器
+     */
+    public boolean isModule2Detector() {
+        return this.name().startsWith("MODEL2_");
+    }
+
+    /**
+     * 检查是否是模块3检测器
+     */
+    public boolean isModule3Detector() {
+        return this.name().startsWith("MODEL3_");
+    }
+
+    /**
+     * 检查是否是模块4检测器
+     */
+    public boolean isModule4Detector() {
+        return this.name().startsWith("MODEL4_");
+    }
+
+
+}

+ 120 - 0
src/main/java/com/energy/manage/analyse/controller/anomaly/AnomalyController.java

@@ -0,0 +1,120 @@
+package com.energy.manage.analyse.controller.anomaly;
+
+import com.energy.manage.analyse.common.reponse.ResultResp;
+import com.energy.manage.analyse.controller.base.BaseServiceController;
+import com.energy.manage.analyse.domain.dto.AnomalyDTO;
+import com.energy.manage.analyse.domain.dto.AnomalyModelDTO;
+import com.energy.manage.analyse.domain.vo.anomaly.*;
+import com.energy.manage.analyse.service.anomaly.AnomalyService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+/**
+ * @author sy
+ * @desc
+ */
+@Slf4j
+@Api(value = "AnomalyController",tags = "风机异常检测查询接口")
+@RestController
+@RequestMapping("/anomaly")
+public class AnomalyController extends BaseServiceController {
+
+    @Autowired
+    private AnomalyService anomalyService;
+
+    @ApiOperation("查询异常风机概览")
+    @PostMapping("/getAnomalyOverview")
+    public ResultResp<AnomalyOverviewVO> getAnomalyOverview(@RequestBody AnomalyDTO anomalyDTO){
+        AnomalyOverviewVO anomalyOverview= anomalyService.getAnomalyOverview(anomalyDTO);
+        return success(anomalyOverview);
+    }
+
+    @ApiOperation("查询柱状图")
+    @PostMapping("/getBarChartStats")
+    public ResultResp<BarChartVO> getBarChartStats(@RequestBody AnomalyDTO anomalyDTO){
+        BarChartVO barChartStats = anomalyService.getBarChartStats(anomalyDTO);
+        return success(barChartStats);
+    }
+
+    @ApiOperation("查询热力图")
+    @PostMapping("/getAnomalyModelMap")
+    public ResultResp<AnomalyChartVO> getAnomalyModelMap(@RequestBody AnomalyDTO anomalyDTO){
+        AnomalyChartVO anomalyChartVO = anomalyService.getAnomalyModelMap(anomalyDTO);
+        return success(anomalyChartVO);
+    }
+
+    @ApiOperation("风机卡片")
+    @PostMapping("/getAnomalyModel")
+    public ResultResp<List<AnomalyModelVO>> getAnomalyModel(@RequestBody AnomalyDTO anomalyDTO){
+        List<AnomalyModelVO> anomalyModelVOS = anomalyService.getAnomalyModel(anomalyDTO);
+        return success(anomalyModelVOS);
+    }
+
+
+    @ApiOperation("风速功率模块模块")
+    @PostMapping("/getAnomalyWindpwr")
+    public ResultResp<AnomalyWindpwrVO> getAnomalyWindpwr(@RequestBody AnomalyModelDTO anomalyModelDTO){
+        AnomalyWindpwrVO anomalyWindpwrVO = anomalyService.getAnomalyWindpwr(anomalyModelDTO);
+        return success(anomalyWindpwrVO);
+    }
+
+
+    @ApiOperation("偏航模块模块")
+    @PostMapping("/geAnomalyYaw")
+    public ResultResp<AnomalyYawVO> geAnomalyYaw(@RequestBody AnomalyModelDTO anomalyModelDTO){
+        AnomalyYawVO anomalyYawVO = anomalyService.geAnomalyYaw(anomalyModelDTO);
+        return success(anomalyYawVO);
+    }
+
+    @ApiOperation("变桨模块模块")
+    @PostMapping("/getAnomalyPitch")
+    public ResultResp<AnomalyPitchVO> getAnomalyPitch(@RequestBody AnomalyModelDTO anomalyModelDTO){
+        AnomalyPitchVO anomalyPitchVO = anomalyService.getAnomalyPitch(anomalyModelDTO);
+        return success(anomalyPitchVO);
+    }
+
+    @ApiOperation("气动性能")
+    @PostMapping("/getAerodynamics")
+    public ResultResp<AnomalyAerodynamicsVO> getAerodynamics(@RequestBody AnomalyModelDTO anomalyModelDTO){
+        AnomalyAerodynamicsVO anomalyAerodynamicsVO = anomalyService.getAerodynamics(anomalyModelDTO);
+        return success(anomalyAerodynamicsVO);
+    }
+
+    @ApiOperation("运行状态模块模块")
+    @PostMapping("/getAnomalyCtrlParam")
+    public ResultResp<AnomalyCtrlParamVO> getAnomalyCtrlParam(@RequestBody AnomalyModelDTO anomalyModelDTO){
+        AnomalyCtrlParamVO anomalyCtrlParamVO = anomalyService.getAnomalyCtrlParam(anomalyModelDTO);
+        return success(anomalyCtrlParamVO);
+    }
+
+    @ApiOperation("获取模块异常趋势曲线图(支持年度分表+跨年跨表)")
+    @PostMapping("/getPitchAnomalyTrend")
+    public ResultResp<List<AnomalyDailyVO>> getPitchAnomalyTrend(@RequestBody AnomalyModelDTO anomalyModelDTO){
+        List<AnomalyDailyVO> anomalyDailyDTOS = anomalyService.getPitchAnomalyTrend(anomalyModelDTO);
+        return success(anomalyDailyDTOS);
+    }
+
+
+
+    @ApiOperation("查询传感器异常台数 -- 雷达图")
+    @PostMapping("/getAnomalySensorCount")
+    public ResultResp<AnomalySensorCountVO> getAnomalySensorCount(@RequestBody AnomalyDTO anomalyDTO){
+        AnomalySensorCountVO anomalySensorCountVO = anomalyService.getAnomalySensorCount(anomalyDTO);
+        return success(anomalySensorCountVO);
+    }
+
+
+    @ApiOperation("查询模块异常台数 -- 雷达图")
+    @PostMapping("/getAnomalyModelCount")
+    public ResultResp<AnomalyCount> getAnomalyModelCount(@RequestBody AnomalyDTO anomalyDTO){
+        AnomalyCount anomalyModelCount = anomalyService.getAnomalyModelCount(anomalyDTO);
+        return success(anomalyModelCount);
+    }
+
+}

+ 44 - 0
src/main/java/com/energy/manage/analyse/controller/base/BaseServiceController.java

@@ -0,0 +1,44 @@
+package com.energy.manage.analyse.controller.base;
+
+import com.energy.manage.analyse.common.base.BaseController;
+import com.energy.manage.analyse.common.base.Page;
+import com.energy.manage.analyse.common.reponse.ResultResp;
+import com.github.pagehelper.PageInfo;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.util.List;
+
+/**
+ * @author chy
+ * @date 2024/5/21 10:37
+ * @desc
+ */
+public class BaseServiceController extends BaseController {
+
+    /**
+     * token 在请求头中的key
+     */
+    private final static String TOKE_KEY = "token";
+    /**
+     * 无返回数据成功函数
+     * @param
+     * @return
+     */
+    public ResultResp success() {
+        return ResultResp.SUCCESS(null);
+    }
+
+    /**
+     * 有返回数据成功函数
+     * @param data
+     * @return
+     */
+    public ResultResp success(Object data) {
+        return ResultResp.SUCCESS(data);
+    }
+
+
+
+}

+ 78 - 0
src/main/java/com/energy/manage/analyse/controller/healthscores/HealthscoresController.java

@@ -0,0 +1,78 @@
+package com.energy.manage.analyse.controller.healthscores;
+
+import com.energy.manage.analyse.common.reponse.ResultResp;
+import com.energy.manage.analyse.controller.base.BaseServiceController;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthOverviewVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresTendencyVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresWindVO;
+import com.energy.manage.analyse.service.healthscores.HealthscoresService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @author sy
+ * @desc
+ */
+@Api(value = "HealthscoresController",tags = "风机健康查询接口")
+@RestController
+@RequestMapping("/healthscores")
+public class HealthscoresController extends BaseServiceController {
+
+    @Autowired
+    private HealthscoresService healthscoresService;
+
+    @ApiOperation("首页风场健康台数统计数据")
+    @PostMapping("/getHealthscoresWindList")
+    public ResultResp<List<HealthscoresWindVO>> getHealthscoresWindList(
+                                                                @ApiParam(value = "fieldCode参数为平台内部风场编号,当参数为空时,默认查全部风场", required = false)
+                                                                @RequestParam(value = "fieldCode",required = false) String fieldCode,
+                                                                @ApiParam(value = "datatime参数为查询日期,当参数为空时,默认查昨天日期的数据", required = false)
+                                                                @RequestParam(value = "datatime",required = false) String datatime){
+        List<HealthscoresWindVO> list = healthscoresService.getHealthscoresWind(fieldCode,datatime);
+        return success(list);
+    }
+
+
+
+    @ApiOperation("风场下所有风机健康查询概览页面")
+    @PostMapping("/getHealthOverview")
+    public ResultResp<HealthOverviewVO> getHealthOverview(
+                                                        @ApiParam(value = "fieldCode参数为平台内部风场编号", required = true)
+                                                        @RequestParam(value = "fieldCode") String fieldCode,
+                                                        @ApiParam(value = "datatime参数为查询日期,当参数为空时,默认查昨天日期的数据", required = false)
+                                                        @RequestParam(value = "datatime",required = false) String datatime){
+        HealthOverviewVO healthOverviewVO = healthscoresService.getHealthOverview(fieldCode,datatime);
+        return success(healthOverviewVO);
+    }
+
+
+    @ApiOperation("风机按天数查询趋势图")
+    @PostMapping("/getLastDaysTrend")
+    public ResultResp<HealthscoresTendencyVO> getLastDaysTrend(
+                                                               @ApiParam(value = "fieldId参数为客户内部风场ID,可通过风机概览页面获取", required = true)
+                                                               @RequestParam(value = "fieldId") String fieldId,
+                                                               @ApiParam(value = "engineId参数为客户内部风机ID,可通过风机概览页面获取", required = true)
+                                                               @RequestParam(value = "engineId") String engineId,
+                                                               @ApiParam(value = "day参数为查询多少天的趋势图数据,如7天,30天,365天", required = true)
+                                                               @RequestParam(value = "day") int day){
+        List<HealthscoresTendencyVO> list = healthscoresService.getLastDaysTrend(day,fieldId,engineId);
+        return success(list);
+    }
+
+
+
+
+
+
+
+
+
+}

+ 48 - 0
src/main/java/com/energy/manage/analyse/controller/wakediagnosis/WakeWindFarmController.java

@@ -0,0 +1,48 @@
+package com.energy.manage.analyse.controller.wakediagnosis;
+
+import com.energy.manage.analyse.common.reponse.ResultResp;
+import com.energy.manage.analyse.controller.base.BaseServiceController;
+import com.energy.manage.analyse.domain.vo.wakewindfarm.WakeWindFarmVO;
+import com.energy.manage.analyse.service.wakediagnosis.WakeWindFarmService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @author sy
+ * @desc
+ */
+@Api(value = "WakeWindFarmController",tags = "湍流尾流接口")
+@RestController
+@RequestMapping("/wakewindfarm")
+public class WakeWindFarmController extends BaseServiceController {
+
+    @Autowired
+    private WakeWindFarmService wakeWindFarmService;
+
+
+
+    @ApiOperation("风场湍流尾流的数据")
+    @PostMapping("/getWakeWindFarm")
+    public ResultResp<WakeWindFarmVO> getWakeWindFarm(
+            @ApiParam(value = "fieldCode参数为平台内部风场编号", required = true)
+            @RequestParam(value = "fieldCode") String fieldCode,
+            @ApiParam(value = "datatime参数为查询日期,当参数为空时,默认查昨天日期的数据", required = false)
+            @RequestParam(value = "datatime",required = false) String datatime){
+
+        WakeWindFarmVO wakeWindFarmVO = wakeWindFarmService.getWakeWindFarm(fieldCode,datatime);
+        return success(wakeWindFarmVO);
+
+    }
+
+
+
+
+}

+ 23 - 0
src/main/java/com/energy/manage/analyse/domain/dto/AnomalyDTO.java

@@ -0,0 +1,23 @@
+package com.energy.manage.analyse.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("异常检测风场参数")
+public class AnomalyDTO {
+
+    @ApiModelProperty("风场code")
+    private String fieldCode;
+
+
+    @ApiModelProperty("查询日期")
+    private String datatime;
+
+
+
+
+}

+ 26 - 0
src/main/java/com/energy/manage/analyse/domain/dto/AnomalyModelDTO.java

@@ -0,0 +1,26 @@
+package com.energy.manage.analyse.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("异常检测风场下风机基础参数")
+public class AnomalyModelDTO {
+
+    @ApiModelProperty("风场code")
+    private String fieldId;
+
+    @ApiModelProperty("风机")
+    private String engineId;
+
+
+    @ApiModelProperty("查询日期")
+    private String datatime;
+
+    @ApiModelProperty("曲线图按天数查询7/30")
+    private Integer timeRange;
+
+}

+ 27 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyAerodynamicsVO.java

@@ -0,0 +1,27 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+
+import com.energy.manage.analyse.po.anomaly.AnomalyCpPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyCpTsrPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyTsrPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("气动性能模块")
+public class AnomalyAerodynamicsVO {
+
+   @ApiModelProperty("Cp检测器")
+   private AnomalyCpPO anomalyCpPO;
+
+    @ApiModelProperty("Cp-TSR联合分布检测器")
+   private AnomalyCpTsrPO anomalyCpTsrPO;
+
+    @ApiModelProperty("TSR风速分箱检测器")
+   private AnomalyTsrPO anomalyTsrPO;
+
+
+}

+ 23 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyChartVO.java

@@ -0,0 +1,23 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.Map;
+
+@Getter
+@Setter
+@ApiModel("热力图")
+public class AnomalyChartVO {
+
+    @ApiModelProperty("异常检测器map热力图")
+   private Map<String, List<AnomalyThermodynamicDiagramVO>> anomalyChartMap;
+
+    @ApiModelProperty("传感器热力图")
+   private Map<String, List<AnomalyThermodynamicDiagramVO>> anomalySensorMap;
+
+}

+ 24 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyCount.java

@@ -0,0 +1,24 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("模块统计雷达图")
+public class AnomalyCount {
+
+    @ApiModelProperty("风速功率 任意检测器异常")
+    private  Integer model1Count;
+    @ApiModelProperty("偏航 任意检测器异常 ")
+    private  Integer model2Count;
+    @ApiModelProperty("变桨 任意检测器异常")
+    private  Integer model3Count;
+    @ApiModelProperty("模块4:运行状态 任意检测器异常")
+    private  Integer model4Count;
+    @ApiModelProperty("模块5: 气动")
+    private  Integer model5Count;
+
+}

+ 27 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyCtrlParamVO.java

@@ -0,0 +1,27 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import com.energy.manage.analyse.po.anomaly.AnomalyOperationPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyPowerqualityPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 运行模块
+ */
+@Getter
+@Setter
+@ApiModel("运行模块")
+public class AnomalyCtrlParamVO {
+
+    @ApiModelProperty("电气功率质量检测器")
+    private AnomalyPowerqualityPO anomalyPowerqualityPO;
+
+
+    @ApiModelProperty("机械运行状态检测器")
+    private AnomalyOperationPO anomalyOperationPO;
+
+
+
+}

+ 51 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyDailyVO.java

@@ -0,0 +1,51 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.time.Instant;
+import java.util.Date;
+
+@Getter
+@Setter
+@ApiModel("异常检测曲线图异常占比")
+public class AnomalyDailyVO {
+
+
+    @ApiModelProperty("时间")
+    private Date createTime;
+
+    @ApiModelProperty("模块1(风速功率)异常占比")
+    private BigDecimal  model1WindpwrAnomalyRate;
+
+    @ApiModelProperty("模块2(偏航)异常占比")
+    private BigDecimal model2YawAnomalyRate;
+
+    @ApiModelProperty("模块3(变桨)异常占比")
+    private BigDecimal model3PitchAnomalyRate;
+
+    @ApiModelProperty("模块4(运行状态)异常占比")
+    private BigDecimal model4CtrlparamAnomalyRate;
+
+    @ApiModelProperty("模块5(气动性能)异常占比")
+    private BigDecimal model5AerodynamicsAnomalyRatio;
+
+
+    public AnomalyDailyVO(Date createTime, BigDecimal model1WindpwrAnomalyRate, BigDecimal model2YawAnomalyRate,
+                          BigDecimal model3PitchAnomalyRate, BigDecimal model4CtrlparamAnomalyRate,
+                            BigDecimal model5AerodynamicsAnomalyRatio ){
+
+        this.createTime = createTime;
+        this.model1WindpwrAnomalyRate = model1WindpwrAnomalyRate;
+        this.model2YawAnomalyRate = model2YawAnomalyRate;
+        this.model3PitchAnomalyRate = model3PitchAnomalyRate;
+        this.model4CtrlparamAnomalyRate = model4CtrlparamAnomalyRate;
+        this.model5AerodynamicsAnomalyRatio = model5AerodynamicsAnomalyRatio;
+
+    }
+
+
+}

+ 20 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyModelVO.java

@@ -0,0 +1,20 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import com.energy.manage.analyse.po.anomaly.AnomalyModelPO;
+import io.swagger.annotations.ApiModel;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("风机卡片返回数据")
+public class AnomalyModelVO extends AnomalyModelPO {
+
+
+
+
+
+
+
+
+}

+ 39 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyOverviewVO.java

@@ -0,0 +1,39 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 风机异常概览
+ */
+@Getter
+@Setter
+@ApiModel("风机异常概览")
+public class AnomalyOverviewVO {
+
+    /**
+     * 风场总异常
+     */
+    @ApiModelProperty("风场总异常")
+    private Integer totalAnomalyCount;
+
+    /**
+     * 传感器异常数
+     */
+    @ApiModelProperty("传感器异常数")
+    private Integer sensorAnomalyCount;
+
+    /**
+     * 检测器异常数
+     */
+    @ApiModelProperty("检测器异常数")
+    private Integer detectorAnomalyCount;
+
+
+
+
+
+
+}

+ 32 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyPitchVO.java

@@ -0,0 +1,32 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import com.energy.manage.analyse.po.anomaly.AnomalyMinpitchPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyPitchcoordPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyPitchregulationPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 变桨模块
+ */
+@Getter
+@Setter
+@ApiModel("变桨模块")
+public class AnomalyPitchVO {
+
+
+    @ApiModelProperty("变桨检测器")
+    private AnomalyPitchregulationPO anomalyPitchregulationPO;
+
+    @ApiModelProperty("变桨-转速-功率检测器")
+    private AnomalyPitchcoordPO anomalyPitchcoordPO;
+
+    @ApiModelProperty("最小桨距角检测器")
+    private AnomalyMinpitchPO anomalyMinpitchPO;
+
+
+
+
+}

+ 32 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalySensorCountVO.java

@@ -0,0 +1,32 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("传感器统计雷达图")
+public class AnomalySensorCountVO {
+
+    @ApiModelProperty("功率传感器异常风机数")
+    private Integer sensorAnomalyPowerCount;
+    @ApiModelProperty("风速传感器异常风机数")
+    private Integer sensorAnomalyWindCount;
+    @ApiModelProperty("变桨传感器异常风机数")
+    private Integer sensorAnomalyPitchCount;
+    @ApiModelProperty("转速传感器异常风机数")
+    private Integer sensorAnomalyApeedCount;
+    @ApiModelProperty("转矩传感器异常风机数")
+    private Integer sensorAnomalyTorqueCount;
+    @ApiModelProperty("风速-功率逻辑异常风机数")
+    private Integer sensorAnomalyWindPwrCount;
+    @ApiModelProperty(" 转速-扭矩逻辑异常风机数")
+    private Integer sensorAnomalySpdTrqCount;
+
+
+
+
+}

+ 28 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyThermodynamicDiagramVO.java

@@ -0,0 +1,28 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import com.energy.manage.analyse.po.anomaly.AnomalyModelPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 检测器热力图
+ */
+@Getter
+@Setter
+@ApiModel("检测器热力图")
+public class AnomalyThermodynamicDiagramVO  {
+
+        @ApiModelProperty("风机名称")
+        private String engineName;
+
+        @ApiModelProperty("是否异常")
+        private Integer ifAbnorma;
+
+        @ApiModelProperty("异常比例")
+        private BigDecimal ratio;
+
+}

+ 28 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyWindpwrVO.java

@@ -0,0 +1,28 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import com.energy.manage.analyse.po.anomaly.AnomalyPowercurvePO;
+import com.energy.manage.analyse.po.anomaly.AnomalyScatterPO;
+import com.energy.manage.analyse.po.anomaly.AnomalySimulinkPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 风速功率模块
+ */
+@Getter
+@Setter
+@ApiModel("风速功率模块")
+public class AnomalyWindpwrVO {
+
+    @ApiModelProperty("功率曲线检测器")
+   private  AnomalyPowercurvePO  anomalyPowercurvePO;
+
+    @ApiModelProperty("功率散点检测器")
+   private AnomalyScatterPO anomalyScatterPO;
+
+    @ApiModelProperty("simulink检测器")
+   private AnomalySimulinkPO anomalySimulinkPO;
+
+}

+ 24 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/AnomalyYawVO.java

@@ -0,0 +1,24 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import com.energy.manage.analyse.po.anomaly.AnomalyCabletwistPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyStaticyawPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("偏航模块")
+public class AnomalyYawVO {
+
+
+    @ApiModelProperty("偏航角度检测器")
+    private AnomalyStaticyawPO anomalyStaticyawPO;
+
+    @ApiModelProperty("扭缆角度检测器")
+    private AnomalyCabletwistPO anomalyCabletwistPO;
+
+
+
+}

+ 26 - 0
src/main/java/com/energy/manage/analyse/domain/vo/anomaly/BarChartVO.java

@@ -0,0 +1,26 @@
+package com.energy.manage.analyse.domain.vo.anomaly;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel("异常检测概览页面柱状图")
+public class BarChartVO {
+
+    @ApiModelProperty("风速功率模块")
+    private Integer windpwrCount;
+
+    @ApiModelProperty("偏航模块")
+    private Integer yawCount;
+
+    @ApiModelProperty("变桨模块")
+    private Integer pitchCount;
+
+    @ApiModelProperty("运行模块")
+    private Integer ctrlparamCount;
+
+
+}

+ 107 - 0
src/main/java/com/energy/manage/analyse/domain/vo/enginegroup/WindEngineGroupVO.java

@@ -0,0 +1,107 @@
+package com.energy.manage.analyse.domain.vo.enginegroup;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.util.Date;
+
+@Getter
+@Setter
+@ApiModel
+public class WindEngineGroupVO {
+
+    @ApiModelProperty(value = "主键id")
+    private Integer id;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "修改时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "创建人")
+    private Integer createBy;
+
+    @ApiModelProperty(value = "修改人")
+    private Integer updateBy;
+
+    /**
+     * 客户内部(远景系统)风机id
+     */
+    private String engineId;
+    /**
+     * 风场编号
+     */
+    private String fieldCode;
+    /**
+     * 风机名称
+     */
+    private String engineName;
+    /**
+     * 风机编号
+     */
+    private String engineCode;
+    /**
+     * 机型编号uuid
+     */
+    private String millTypeCode;
+    /**
+     * 额定容量
+     */
+    private Double ratedCapacity;
+    /**
+     * 海拔高度
+     */
+    private Double elevationHeight;
+    /**
+     * 轮毂高度
+     */
+    private Double hubHeight;
+    /**
+     * 经度
+     */
+    private Double longitude;
+    /**
+     * 维度
+     */
+    private Double latitude;
+    /**
+     * 状态
+     */
+    private Integer state;
+    /**
+     * 是否标杆风机 1是2否
+     */
+    private Integer sightcing;
+    /**
+     * 额定风速 (m/s)
+     */
+    private Double rated_wind_speed;
+    /**
+     * 切入风速 (m/s)
+     */
+    private Double ratedCutInWindspeed;
+    /**
+     * 切出风速 (m/s)
+     */
+    private Double ratedCutOutWindspeed;
+    /**
+     * 删除状态
+     */
+    private Integer delState;
+
+
+    /**
+     * 数据来源1,平台输入,2导入
+     */
+    private Integer dataSource;
+
+}

+ 166 - 0
src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthOverviewListVO.java

@@ -0,0 +1,166 @@
+package com.energy.manage.analyse.domain.vo.healthscores;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Getter
+@Setter
+@ApiModel
+public class HealthOverviewListVO {
+
+    /**
+     * 编号
+     */
+    @ApiModelProperty("编号")
+    private Integer id;
+    /**
+     * 风场ID(内部命名)
+     * 对应数据库字段:field_code (VARCHAR(32), 非空,默认空字符串)
+     */
+    @ApiModelProperty("风场ID(客户内部命名)")
+    private String fieldId;
+
+
+    /**
+     * 风机ID(内部命名)
+     * 对应数据库字段:engine_code (VARCHAR(32), 非空,默认空字符串)
+     */
+    @ApiModelProperty("风机ID(客户内部命名)")
+    private String engineId;
+
+    /**
+     * 风机名称
+     */
+    @ApiModelProperty("风机名称")
+    private String engineName;
+
+    /**
+     * 机型型号
+     */
+    @ApiModelProperty("机型型号")
+    private String machineTypeCode;
+
+    /**
+     * 综合健康评分 (0-100)
+     * 对应数据库字段:overall_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("综合健康评分 (0-100)")
+    private BigDecimal overallScore;
+
+    /**
+     * 综合健康等级 (优/良/中/差)
+     * 对应数据库字段:overall_level (VARCHAR(10), 可为空)
+     */
+    @ApiModelProperty("综合健康等级 (优/良/中/差)")
+    private String overallLevel;
+
+    /**
+     * 叶轮健康评分 (0-100)
+     * 对应数据库字段:rotor_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("叶轮健康评分 (0-100)")
+    private BigDecimal rotorScore;
+
+    /**
+     * 塔筒健康评分 (0-100)
+     * 对应数据库字段:tower_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("塔筒健康评分 (0-100)")
+    private BigDecimal towerScore;
+
+    /**
+     * 发电机健康评分 (0-100)
+     * 对应数据库字段:generator_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("发电机健康评分 (0-100)")
+    private BigDecimal generatorScore;
+
+    /**
+     * 齿轮箱健康评分 (0-100)
+     * 对应数据库字段:gearbox_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("齿轮箱健康评分 (0-100)")
+    private BigDecimal gearboxScore;
+
+    /**
+     * 主轴健康评分 (0-100)
+     * 对应数据库字段:main_shaft_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("主轴健康评分 (0-100)")
+    private BigDecimal mainShaftScore;
+
+    /**
+     * 变流器健康评分 (0-100)
+     * 对应数据库字段:converter_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("变流器健康评分 (0-100)")
+    private BigDecimal converterScore;
+
+    /**
+     * 偏航系统健康评分 (0-100)
+     * 对应数据库字段:yaw_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("偏航系统健康评分 (0-100)")
+    private BigDecimal yawSystemScore;
+
+    /**
+     * 变桨系统健康评分 (0-100)
+     * 对应数据库字段:pitch_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("变桨系统健康评分 (0-100)")
+    private BigDecimal pitchSystemScore;
+
+    /**
+     * 液压系统健康评分 (0-100)
+     * 对应数据库字段:hydraulic_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("液压系统健康评分 (0-100)")
+    private BigDecimal hydraulicSystemScore;
+
+    /**
+     * 主控系统健康评分 (0-100)
+     * 对应数据库字段:control_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("主控系统健康评分 (0-100)")
+    private BigDecimal controlSystemScore;
+
+    /**
+     * 数据来源时间 (yyyy-mm-dd)
+     * 对应数据库字段:source_datetime (DATE, 非空)
+     */
+    @ApiModelProperty("数据来源时间 (yyyy-mm-dd)")
+    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
+    private Date sourceDatetime;
+
+    /**
+     * 评估入库时间戳 (yyyy-mm-dd hh:mm:ss)
+     * 对应数据库字段:create_time (DATETIME, 非空,默认当前时间)
+     */
+    @ApiModelProperty("评估入库时间戳 (yyyy-mm-dd hh:mm:ss)")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 结构健康评分
+     */
+    @ApiModelProperty("结构健康评分")
+    private BigDecimal structureScore;
+
+    /**
+     * 部件健康评分
+     */
+    @ApiModelProperty("部件健康评分")
+    private BigDecimal componentScore;
+
+    /**
+     * 系统健康评分
+     */
+    @ApiModelProperty("系统健康评分")
+    private BigDecimal systemScore;
+}

+ 36 - 0
src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthOverviewVO.java

@@ -0,0 +1,36 @@
+package com.energy.manage.analyse.domain.vo.healthscores;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+@ApiModel
+public class HealthOverviewVO {
+
+    /**
+     * 风场健康信息
+     */
+    @ApiModelProperty("风场健康信息")
+    private HealthscoresWindVO healthscoresWindVO;
+
+
+    /**
+     * 健康概览风机集合
+     */
+    @ApiModelProperty("健康概览风机集合")
+    private List<HealthOverviewListVO>  healthOverviewListVOList;
+
+
+
+
+
+
+
+
+
+}

+ 118 - 0
src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthscoresTendencyVO.java

@@ -0,0 +1,118 @@
+package com.energy.manage.analyse.domain.vo.healthscores;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Getter
+@Setter
+@ApiModel
+public class HealthscoresTendencyVO {
+
+    // 空构造(MyBatis反射用)
+    public HealthscoresTendencyVO() {}
+
+    // 仅日期构造(补0时用)
+    public HealthscoresTendencyVO(LocalDate sourceDatetime) {
+        this.sourceDatetime = sourceDatetime;
+    }
+
+    /**
+     * 风场id
+     */
+    @ApiModelProperty("风场id,客户内部编号")
+    private String  fieldId;
+
+    /**
+     * 风机id
+     */
+    @ApiModelProperty("风机id,客户内部编号")
+    private String  engineId;
+
+    /**
+     * 坐标x
+     */
+    @ApiModelProperty("坐标x")
+    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
+    private LocalDate sourceDatetime;
+
+    /**
+     * 叶轮健康评分 (0-100)
+     * 对应数据库字段:rotor_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("叶轮健康评分")
+    private BigDecimal rotorScore;
+
+    /**
+     * 塔筒健康评分 (0-100)
+     * 对应数据库字段:tower_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("塔筒健康评分")
+    private BigDecimal towerScore;
+
+    /**
+     * 发电机健康评分 (0-100)
+     * 对应数据库字段:generator_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("发电机健康评分")
+    private BigDecimal generatorScore;
+
+    /**
+     * 齿轮箱健康评分 (0-100)
+     * 对应数据库字段:gearbox_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("齿轮箱健康评分")
+    private BigDecimal gearboxScore;
+
+    /**
+     * 主轴健康评分 (0-100)
+     * 对应数据库字段:main_shaft_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("主轴健康评分")
+    private BigDecimal mainShaftScore;
+
+    /**
+     * 变流器健康评分 (0-100)
+     * 对应数据库字段:converter_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("变流器健康评分")
+    private BigDecimal converterScore;
+
+    /**
+     * 偏航系统健康评分 (0-100)
+     * 对应数据库字段:yaw_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("偏航系统健康评分")
+    private BigDecimal yawSystemScore;
+
+    /**
+     * 变桨系统健康评分 (0-100)
+     * 对应数据库字段:pitch_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("变桨系统健康评分")
+    private BigDecimal pitchSystemScore;
+
+    /**
+     * 液压系统健康评分 (0-100)
+     * 对应数据库字段:hydraulic_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("液压系统健康评分")
+    private BigDecimal hydraulicSystemScore;
+
+    /**
+     * 主控系统健康评分 (0-100)
+     * 对应数据库字段:control_system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("主控系统健康评分")
+    private BigDecimal controlSystemScore;
+
+    @ApiModelProperty("综合健康评分 (0-100) ")
+    private BigDecimal overallScore;
+
+
+}

+ 14 - 0
src/main/java/com/energy/manage/analyse/domain/vo/healthscores/HealthscoresWindVO.java

@@ -0,0 +1,14 @@
+package com.energy.manage.analyse.domain.vo.healthscores;
+
+import com.energy.manage.analyse.po.healthscores.HealthscoresWindPO;
+import io.swagger.annotations.ApiModel;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel
+public class HealthscoresWindVO extends HealthscoresWindPO {
+
+
+}

+ 18 - 0
src/main/java/com/energy/manage/analyse/domain/vo/wakewindfarm/WakeTurbineVO.java

@@ -0,0 +1,18 @@
+package com.energy.manage.analyse.domain.vo.wakewindfarm;
+
+import com.energy.manage.analyse.po.wakediagnosis.WakeTurbinePO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@ApiModel
+public class WakeTurbineVO extends WakeTurbinePO {
+
+    @ApiModelProperty(value = "风机名称", hidden = true)
+    private String engineName;
+
+
+}

+ 20 - 0
src/main/java/com/energy/manage/analyse/domain/vo/wakewindfarm/WakeWindFarmVO.java

@@ -0,0 +1,20 @@
+package com.energy.manage.analyse.domain.vo.wakewindfarm;
+
+import com.energy.manage.analyse.po.wakediagnosis.WakeWindFarmPO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+@ApiModel
+public class WakeWindFarmVO extends WakeWindFarmPO {
+
+    @ApiModelProperty(value = "湍流尾流风场风机集合")
+    List<WakeTurbineVO> getWakeTurbineList;
+
+
+}

+ 139 - 0
src/main/java/com/energy/manage/analyse/mappers/anomaly/AnomalyWindfarmMapper.java

@@ -0,0 +1,139 @@
+package com.energy.manage.analyse.mappers.anomaly;
+
+import com.energy.manage.analyse.common.mapper.MyMapper;
+import com.energy.manage.analyse.domain.vo.anomaly.*;
+import com.energy.manage.analyse.po.anomaly.AnomalyModelPO;
+import com.energy.manage.analyse.po.anomaly.AnomalyWindfarmPO;
+import com.energy.manage.analyse.po.anomaly.BaseAnomalyDetectorPO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+
+/**
+ * 异常检测mappser接口
+ */
+@Repository
+public interface AnomalyWindfarmMapper extends MyMapper<AnomalyWindfarmPO> {
+
+
+    /**
+     * 异常检测统计
+     * @param fieldId
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    AnomalyOverviewVO selectAnomalyWindfarmAndFieldId(@Param("fieldId") String fieldId,
+                                                      @Param("beginTime") String beginTime,
+                                                      @Param("endTime") String endTime);
+
+
+    /**
+     * 柱状图
+     * @param fieldId
+     * @param year
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    BarChartVO selectAnomalyModelCount(@Param("fieldId") String fieldId,
+                                       @Param("year") String year,
+                                       @Param("beginTime") String beginTime,
+                                       @Param("endTime") String endTime);
+
+
+    /**
+     * 检测器he传感器通用
+     * @param fieldId
+     * @param year
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    List<AnomalyModelPO> selectAllAnomalyModel(@Param("fieldId") String fieldId,
+                                               @Param("year") String year,
+                                               @Param("beginTime") String beginTime,
+                                               @Param("endTime") String endTime);
+
+
+    /**
+     * 异常检测器
+     * @param fieldId
+     * @param engineId
+     * @param tableName
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    BaseAnomalyDetectorPO selectAnomalyDetectorAll(@Param("fieldId") String fieldId,
+                                                   @Param("engineId") String engineId,
+                                                   @Param("tableName") String tableName,
+                                                   @Param("beginTime") String beginTime,
+                                                   @Param("endTime") String endTime);
+
+
+    /**
+     *  单表统计:指定年度表
+     * @param fieldId
+     * @param engineId
+     * @param tableName
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    List<AnomalyDailyVO> selectBySingleTable(@Param("fieldId") String fieldId,
+                                             @Param("engineId") String engineId,
+                                             @Param("tableName") String tableName,
+                                             @Param("startDate") String beginTime,
+                                             @Param("endDate") String endTime);
+
+
+
+
+    /**
+     *  跨表统计:指定年度表
+     * @param fieldId
+     * @param engineId
+     * @param table1,table2
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    List<AnomalyDailyVO> selectByUnionTables(@Param("fieldId") String fieldId,
+                                             @Param("engineId") String engineId,
+                                             @Param("table1") String table1,
+                                             @Param("table2") String table2,
+                                             @Param("startDate") String beginTime,
+                                             @Param("endDate") String endTime);
+
+
+    /**
+     * 根据风场查询异常个数传感器
+     * @param fieldId
+     * @param year
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    AnomalySensorCountVO selectAnomalySensorCountVO(@Param("fieldId") String fieldId,
+                                                    @Param("year") String year,
+                                                    @Param("startDate") String beginTime,
+                                                    @Param("endDate") String endTime);
+
+
+    /**
+     * 异常检测模块统计异常风机台数
+     * @param fieldId
+     * @param year
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    AnomalyCount selectModeCount(@Param("fieldId") String fieldId,
+                                 @Param("year") String year,
+                                 @Param("startDate") String beginTime,
+                                 @Param("endDate") String endTime);
+
+}

+ 62 - 0
src/main/java/com/energy/manage/analyse/mappers/healthscores/HealthscoresMapper.java

@@ -0,0 +1,62 @@
+package com.energy.manage.analyse.mappers.healthscores;
+
+import com.energy.manage.analyse.common.mapper.MyMapper;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthOverviewListVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresTendencyVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresWindVO;
+import com.energy.manage.analyse.po.healthscores.HealthscoresPO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Repository
+public interface HealthscoresMapper extends MyMapper<HealthscoresPO> {
+
+    /**
+     * 查询整个风场健康情况统计信息集合
+     * @param fieldId
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    List<HealthscoresWindVO> selectWindScoreList(@Param("fieldId") String fieldId,
+                                                 @Param("beginTime") String beginTime,
+                                                 @Param("endTime") String endTime);
+
+    /**
+     * 查询单个风场健康情况统计信息
+     * @param fieldId
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    HealthscoresWindVO selectWindHealthscoresScore(@Param("fieldId") String fieldId,
+                                                   @Param("beginTime") String beginTime,
+                                                   @Param("endTime") String endTime);
+
+    /**
+     * 查询风场下所有风机健康情况信息
+     * @param fieldId
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    List<HealthOverviewListVO> selectHealthOverviewList(@Param("year") String year,
+                                                        @Param("fieldId") String fieldId,
+                                                        @Param("beginTime") String beginTime,
+                                                        @Param("endTime") String endTime);
+
+
+    /**
+     * 跨年分表查询近365天数据
+     */
+    List<HealthscoresTendencyVO> listHscoresLastays(@Param("fieldId") String fieldId,
+                                                    @Param("engineId") String engineId,
+                                                    @Param("startDate") LocalDate startDate,
+                                                    @Param("endDate") LocalDate endDate,
+                                                    @Param("tableNames") List<String> tableNames);
+
+
+}

+ 41 - 0
src/main/java/com/energy/manage/analyse/mappers/wakediagnosis/WakeWindFarmMapper.java

@@ -0,0 +1,41 @@
+package com.energy.manage.analyse.mappers.wakediagnosis;
+
+import com.energy.manage.analyse.common.mapper.MyMapper;
+import com.energy.manage.analyse.domain.vo.wakewindfarm.WakeTurbineVO;
+import com.energy.manage.analyse.domain.vo.wakewindfarm.WakeWindFarmVO;
+import com.energy.manage.analyse.po.wakediagnosis.WakeWindFarmPO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface WakeWindFarmMapper  extends MyMapper<WakeWindFarmPO> {
+
+    /**
+     * 查询风场尾流数据信息
+     * @param fieldId
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    WakeWindFarmVO selectWakeWindfarmAndFieldId(@Param("fieldId") String fieldId,
+                                                @Param("beginTime") String beginTime,
+                                                @Param("endTime") String endTime);
+
+
+    /**
+     * 查询风机集合
+     * @param year
+     * @param fieldId
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    List<WakeTurbineVO> selectWakeTurbineAndFieldId(@Param("year") String year,
+                                                    @Param("fieldId") String fieldId,
+                                                    @Param("beginTime") String beginTime,
+                                                    @Param("endTime") String endTime);
+
+
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/mappers/windenginegroup/WindEngineGroupMapper.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.mappers.windenginegroup;
+
+
+
+import com.energy.manage.analyse.common.mapper.MyMapper;
+import com.energy.manage.analyse.po.windenginegroup.WindEngineGroupPO;
+import org.springframework.stereotype.Repository;
+
+
+
+@Repository
+public interface WindEngineGroupMapper extends MyMapper<WindEngineGroupPO> {
+
+
+
+}

+ 19 - 0
src/main/java/com/energy/manage/analyse/mappers/windfield/WindFieldMapper.java

@@ -0,0 +1,19 @@
+package com.energy.manage.analyse.mappers.windfield;
+
+
+import com.energy.manage.analyse.common.mapper.MyMapper;
+import com.energy.manage.analyse.po.windfield.WindFieldPO;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * 风场信息mapper
+ */
+@Repository
+public interface WindFieldMapper extends MyMapper<WindFieldPO> {
+
+
+
+}

+ 21 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyCabletwistPO.java

@@ -0,0 +1,21 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (偏航)扭缆角度检测器
+ * 对应数据库表: anomaly_cabletwist
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyCabletwistPO extends BaseAnomalyDetectorPO {
+
+
+
+
+
+}

+ 14 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyCpPO.java

@@ -0,0 +1,14 @@
+package com.energy.manage.analyse.po.anomaly;
+
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+ * (气动性能)Cp检测器 - 新增
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyCpPO extends BaseAnomalyDetectorPO {
+}

+ 14 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyCpTsrPO.java

@@ -0,0 +1,14 @@
+package com.energy.manage.analyse.po.anomaly;
+
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+ * (气动性能)Cp-TSR联合分布检测器 - 新增
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyCpTsrPO extends BaseAnomalyDetectorPO{
+}

+ 13 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyDeloadPO.java

@@ -0,0 +1,13 @@
+package com.energy.manage.analyse.po.anomaly;
+
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ *(运行状态)降载检测器 -新增
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyDeloadPO extends BaseAnomalyDetectorPO{
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyMinpitchPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (变桨)最小桨距角检测器 - 作废
+ * 对应数据库表: anomaly_minpitch
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyMinpitchPO extends BaseAnomalyDetectorPO {
+}

+ 337 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyModelPO.java

@@ -0,0 +1,337 @@
+package com.energy.manage.analyse.po.anomaly;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Date;
+
+/**
+ * 异常分析模块表实体类
+ * 对应数据库表: anomaly_model
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class AnomalyModelPO {
+
+
+    @ApiModelProperty("主键编号")
+    private Integer id;
+
+    /**
+     * 风场id
+     */
+    @ApiModelProperty("风场id内部编号")
+    private String fieldId;
+
+    /**
+     * 机组id
+     */
+    @ApiModelProperty("机组id")
+    private String engineId;
+
+    /**
+     * 功率传感器是否异常
+     */
+    @ApiModelProperty("功率传感器是否异常")
+    private Integer sensorAnomalyPower;
+
+    @ApiModelProperty("功率传感器是否异常比例--新增")
+    private BigDecimal sensorAnomalyPowerRatio;
+
+    /**
+     * 风速传感器是否异常
+     */
+    @ApiModelProperty("风速传感器是否异常")
+    private Integer sensorAnomalyWind;
+
+    @ApiModelProperty("风速传感器是否异常比例--新增")
+    private BigDecimal sensorAnomalyWindRatio;
+
+    /**
+     * 变桨传感器是否异常
+     */
+    @ApiModelProperty("变桨传感器是否异常")
+    private Integer sensorAnomalyPitch;
+
+
+    @ApiModelProperty("变桨传感器是否异常比例--新增")
+    private BigDecimal sensorAnomalyPitchRatio;
+
+    /**
+     * 转速传感器是否异常
+     */
+    @ApiModelProperty("转速传感器是否异常")
+    private Integer sensorAnomalySpeed;
+
+    @ApiModelProperty("转速传感器是否异常比例--新增")
+    private BigDecimal sensorAnomalySpeedRatio;
+
+    /**
+     * 转矩传感器是否异常
+     */
+    @ApiModelProperty("转矩传感器是否异常")
+    private Integer sensorAnomalyTorque;
+
+    @ApiModelProperty("转矩传感器是否异常比例--新增")
+    private BigDecimal sensorAnomalyTorqueRatio;
+
+    /**
+     * 风速-功率逻辑是否异常
+     */
+    @ApiModelProperty("风速-功率逻辑是否异常")
+    private Integer sensorAnomalyWindPwr;
+
+
+    @ApiModelProperty("风速-功率逻辑是否异常比例--新增")
+    private BigDecimal sensorAnomalyWindPwrRatio;
+
+    /**
+     * 转速-扭矩逻辑是否异常
+     */
+    @ApiModelProperty("转速-扭矩逻辑是否异常")
+    private Integer sensorAnomalySpdTrq;
+
+    @ApiModelProperty("转速-扭矩逻辑是否异常比例--新增")
+    private BigDecimal sensorAnomalySpdTrqRatio;
+
+    /**
+     * 模块1(风速功率)是否异常(0或1)
+     */
+    @ApiModelProperty("模块1(风速功率)是否异常(0或1)")
+    private Integer model1WindpwrIsAnomaly;
+
+
+    /**
+     * 模块1(风速功率)正常总数
+     */
+    @ApiModelProperty("模块1(风速功率)正常总数")
+    private Integer model1WindpwrNormalCount;
+
+    /**
+     * 模块1(风速功率)异常总数
+     */
+    @ApiModelProperty("模块1(风速功率)异常总数")
+    private Integer model1WindpwrAnomalyCount;
+
+    /**
+     * 模块1(风速功率)异常占比
+     */
+    @ApiModelProperty("模块1(风速功率)异常占比")
+    private BigDecimal model1WindpwrAnomalyRate;
+
+    /**
+     * 模块1(风速功率)功率曲线检测器是否异常(0或1)
+     */
+    @ApiModelProperty(" 模块1(风速功率)功率曲线检测器是否异常(0或1)")
+    private Integer model1WindpwrPowercurve;
+
+    @ApiModelProperty("模块1(风速功率)功率曲线检测器--新增")
+    private BigDecimal model1WindpwrPowercurveRatio;
+
+    /**
+     * 模块1(风速功率)功率散点检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块1(风速功率)功率散点检测器是否异常(0或1)")
+    private Integer model1WindpwrScatter;
+
+
+    @ApiModelProperty("模块1(风速功率)功率散点检测器比例 -- 新增")
+    private BigDecimal model1WindpwrScatterRatio;
+
+    /**
+     * 模块1(风速功率)simulink检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块1(风速功率)simulink检测器是否异常(0或1)-- 作废")
+    private Integer model1WindpwrSimulink;
+
+    /**
+     * 模块2(偏航)是否异常(0或1)
+     */
+    @ApiModelProperty("模块2(偏航)是否异常(0或1)")
+    private Integer model2YawIsAnomaly;
+
+    /**
+     * 模块2(偏航)正常总数
+     */
+    @ApiModelProperty("模块2(偏航)正常总数")
+    private Integer model2YawNormalCount;
+
+    /**
+     * 模块2(偏航)异常总数
+     */
+    @ApiModelProperty("模块2(偏航)异常总数")
+    private Integer model2YawAnomalyCount;
+
+    /**
+     * 模块2(偏航)异常占比
+     */
+    @ApiModelProperty("模块2(偏航)异常占比")
+    private BigDecimal model2YawAnomalyRate;
+
+    /**
+     * 模块2(偏航)偏航角度检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块2(偏航)偏航角度检测器是否异常(0或1)")
+    private Integer model2YawStaticyaw;
+
+    @ApiModelProperty("模块2(偏航)偏航角度检测器比例--新增")
+    private BigDecimal model2YawStaticyawRatio;
+
+    /**
+     * 模块2(偏航)扭缆角度检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块2(偏航)扭缆角度检测器是否异常(0或1)")
+    private Integer model2YawCabletwist;
+
+    @ApiModelProperty("模块2(偏航)扭缆角度检测器--新增")
+    private BigDecimal model2YawCabletwistRatio;
+
+    /**
+     * 模块3(变桨)是否异常(0或1)
+     */
+    @ApiModelProperty("模块3(变桨)是否异常(0或1)")
+    private Integer model3PitchIsAnomaly;
+
+    /**
+     * 模块3(变桨)正常总数
+     */
+    @ApiModelProperty("模块3(变桨)正常总数")
+    private Integer model3PitchNormalCount;
+
+    /**
+     * 模块3(变桨)异常总数
+     */
+    @ApiModelProperty("模块3(变桨)异常总数")
+    private Integer model3PitchAnomalyCount;
+
+    /**
+     * 模块3(变桨)异常占比
+     */
+    @ApiModelProperty("模块3(变桨)异常占比")
+    private BigDecimal model3PitchAnomalyRate;
+
+    /**
+     * 模块3(变桨)变桨检测器是否异常(0或1)
+     */
+    @ApiModelProperty(" 模块3(变桨)变桨检测器是否异常(0或1)")
+    private Integer model3PitchPitchregulation;
+
+    @ApiModelProperty("模块3(变桨)变桨检测器比例--新增")
+    private BigDecimal model3PitchPitchregulationRatio;
+
+    /**
+     * 模块3(变桨)变桨-转速-功率检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块3(变桨)变桨-转速-功率检测器是否异常(0或1)")
+    private Integer model3PitchPitchcoord;
+
+    @ApiModelProperty("模块3(变桨)变桨-转速-功率检测器--新增")
+    private BigDecimal model3PitchPitchcoordRatio;
+
+    /**
+     * 模块3(变桨)最小桨距角检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块3(变桨)最小桨距角检测器是否异常(0或1) -- 作废")
+    private Integer model3PitchMinpitch;
+
+    /**
+     * 模块4(运行状态)是否异常(0或1)
+     */
+    @ApiModelProperty("模块4(运行状态)是否异常(0或1)")
+    private Integer model4IsAnomaly;
+
+    /**
+     * 模块4(运行状态)正常总数
+     */
+    @ApiModelProperty(" 模块4(运行状态)正常总数")
+    private Integer model4CtrlparamNormalCount;
+
+    /**
+     * 模块4(运行状态)异常总数
+     */
+    @ApiModelProperty("模块4(运行状态)异常总数")
+    private Integer model4CtrlparamAnomalyCount;
+
+    /**
+     * 模块4(运行状态)异常占比
+     */
+    @ApiModelProperty("模块4(运行状态)异常占比")
+    private BigDecimal model4CtrlparamAnomalyRate;
+
+    /**
+     * 模块4(运行状态)电气功率质量检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块4(运行状态)电气功率质量检测器是否异常(0或1)")
+    private Integer model4CtrlparamPowerquality;
+
+    @ApiModelProperty("模块4(运行状态)电气功率质量检测器比例新增")
+    private BigDecimal model4CtrlparamPowerqualityRatio;
+
+    /**
+     * 模块4(运行状态)机械运行状态检测器是否异常(0或1)
+     */
+    @ApiModelProperty("模块4(运行状态)机械运行状态检测器是否异常(0或1)")
+    private Integer model4CtrlparamOperationstate;
+
+    @ApiModelProperty("模块4(运行状态)机械运行状态检测器比例 -- 新增")
+    private BigDecimal model4CtrlparamOperationstateRatio;
+
+
+    @ApiModelProperty("模块4(运行状态)降载检测器是否异常(0或1)新增")
+    private Integer model4CtrlparamDeload;
+
+    @ApiModelProperty("模块4(运行状态)降载检测器比例--新增")
+    private BigDecimal model4CtrlparamDeloadRatio;
+
+    @ApiModelProperty("模块5(气动性能)是否异常(0或1)")
+    private Integer model5IsAnomaly;
+
+    @ApiModelProperty("模块5(气动性能)正常总数")
+    private Integer model5AerodynamicsNormalCount;
+
+    @ApiModelProperty("模块5(气动性能)异常总数")
+    private Integer model5AerodynamicsAnomalyCount;
+
+    @ApiModelProperty("模块5(气动性能)异常占比")
+    private BigDecimal model5AerodynamicsAnomalyRatio;
+
+    @ApiModelProperty("模块5(气动性能)Cp检测器是否异常(0或1)")
+    private Integer model5AerodynamicsCp;
+
+    @ApiModelProperty("模块5(气动性能)Cp检测器异常比例--新增")
+    private BigDecimal model5AerodynamicsCpRatio;
+
+    @ApiModelProperty("模块5(气动性能)TSR风速分箱检测器是否异常(0或1)")
+    private Integer model5AerodynamicsTsr;
+
+    @ApiModelProperty("模块5(气动性能)TSR风速分箱检测器异常比例--新增")
+    private BigDecimal model5AerodynamicsTsrRatio;
+
+    @ApiModelProperty("模块5(气动性能)Cp-TSR联合分布检测器是否异常(0或1)")
+    private Integer model5AerodynamicsCpTsr;
+
+    @ApiModelProperty("模块5(气动性能)Cp-TSR联合分布检测器异常比例--新增")
+    private BigDecimal model5AerodynamicsCpTsrRatio;
+
+    /**
+     * 数据来源时间,以天为单位
+     */
+    @ApiModelProperty("数据来源时间,以天为单位")
+    private Date sourceDatetime;
+
+    /**
+     * 入库时间戳 (yyyy-mm-dd hh:mm:ss)
+     */
+    @ApiModelProperty("入库时间戳 (yyyy-mm-dd hh:mm:ss)")
+    private Date createTime;
+
+
+
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyOperationPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (运行状态)机械运行状态检测器
+ * 对应数据库表: anomaly_operation
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyOperationPO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPitchcoordPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (变桨)变桨-转速-功率检测器
+ * 对应数据库表: anomaly_pitchcoord
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyPitchcoordPO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPitchregulationPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (变桨)变桨检测器
+ * 对应数据库表: anomaly_pitchregulation
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyPitchregulationPO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPowercurvePO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (风速功率)功率曲线检测器
+ * 对应数据库表: anomaly_powercurve
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyPowercurvePO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyPowerqualityPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (运行状态)电气功率质量检测器
+ * 对应数据库表: anomaly_powerquality
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyPowerqualityPO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyScatterPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (风速功率)功率散点检测器
+ * 对应数据库表: anomaly_scatter
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyScatterPO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalySimulinkPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (风速功率)simulink检测器
+ * 对应数据库表: anomaly_simulink
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalySimulinkPO extends BaseAnomalyDetectorPO {
+}

+ 16 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyStaticyawPO.java

@@ -0,0 +1,16 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+/**
+ * (偏航)偏航角度检测器
+ * 对应数据库表: anomaly_staticyaw
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyStaticyawPO extends BaseAnomalyDetectorPO {
+}

+ 12 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyTsrPO.java

@@ -0,0 +1,12 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * (气动性能)TSR风速分箱检测器 - 新增
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class AnomalyTsrPO extends BaseAnomalyDetectorPO{
+}

+ 49 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/AnomalyWindfarmPO.java

@@ -0,0 +1,49 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Builder;
+
+import java.util.Date;
+
+/**
+ * 异常检测风场表结构实体类
+ * 对应数据库表: anomaly_windfarm
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class AnomalyWindfarmPO {
+    private Integer id;
+
+    /**
+     * 风场id
+     */
+    private String fieldId;
+
+    /**
+     * 异常风机总数
+     */
+    private Integer resultAnomalyCount;
+
+    /**
+     * 仅传感器异常风机总数
+     */
+    private Integer sensorAnomalyCount;
+
+    /**
+     * 仅检测异常风机总数
+     */
+    private Integer anomalyDetectionCount;
+
+    /**
+     * 数据来源时间,以天为单位
+     */
+    private Date sourceDatetime;
+
+    /**
+     * 入库时间戳 (yyyy-mm-dd hh:mm:ss)
+     */
+    private Date createTime;
+}

+ 92 - 0
src/main/java/com/energy/manage/analyse/po/anomaly/BaseAnomalyDetectorPO.java

@@ -0,0 +1,92 @@
+package com.energy.manage.analyse.po.anomaly;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 异常检测实体基类
+ * 为所有检测器表提供公共字段
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BaseAnomalyDetectorPO {
+
+    private Integer id;
+
+    /**
+     * 风场id
+     */
+    private String fieldId;
+
+    /**
+     * 机组id
+     */
+    private String engineId;
+
+    /**
+     * 模块名称: wind_power,yaw,pitch,control_params
+     */
+    private String anomalyModelName;
+
+    /**
+     * 传感器是否异常
+     */
+    private Integer sensorIsAnomaly;
+
+    /**
+     * 检测器是否异常
+     */
+    private Integer detectorIsAnomaly;
+
+    /**
+     * 传感器异常类型
+     */
+    private Integer sensorAnomalyType;
+
+    /**
+     * 传感器异常计数
+     */
+    private Integer sensorAnomalyCount;
+
+    /**
+     * 传感器正常计数
+     */
+    private Integer sensorNormallyCount;
+
+    /**
+     * 检测器异常计数
+     */
+    private Integer detectorAnomalyCount;
+
+    /**
+     * 检测器正常计数
+     */
+    private Integer detectorNormallyCount;
+
+    /**
+     * minio路径,json文件
+     */
+    private String filePath;
+
+    /**
+     * 图表minio地址
+     */
+    private String graphPath;
+
+    /**
+     * 数据来源时间,以天为单位
+     */
+    private LocalDate sourceDatetime;
+
+    /**
+     * 入库时间戳 (yyyy-mm-dd hh:mm:ss)
+     */
+    private LocalDateTime createTime;
+
+
+
+}

+ 142 - 0
src/main/java/com/energy/manage/analyse/po/healthscores/HealthscoresPO.java

@@ -0,0 +1,142 @@
+package com.energy.manage.analyse.po.healthscores;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class HealthscoresPO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     * 对应数据库字段:id (INT, 自增主键)
+     */
+    private Integer id;
+
+    /**
+     * 风场ID(内部命名)
+     * 对应数据库字段:field_code (VARCHAR(32), 非空,默认空字符串)
+     */
+    private String fieldId;
+
+    /**
+     * 风机ID(内部命名)
+     * 对应数据库字段:engine_code (VARCHAR(32), 非空,默认空字符串)
+     */
+    private String engineId;
+
+    /**
+     * 机型型号
+     */
+    private String machineTypeCode;
+
+    /**
+     * 综合健康评分 (0-100)
+     * 对应数据库字段:overall_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal overallScore;
+
+    /**
+     * 综合健康等级 (优/良/中/差)
+     * 对应数据库字段:overall_level (VARCHAR(10), 可为空)
+     */
+    private String overallLevel;
+
+    /**
+     * 叶轮健康评分 (0-100)
+     * 对应数据库字段:rotor_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal rotorScore;
+
+    /**
+     * 塔筒健康评分 (0-100)
+     * 对应数据库字段:tower_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal towerScore;
+
+    /**
+     * 发电机健康评分 (0-100)
+     * 对应数据库字段:generator_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal generatorScore;
+
+    /**
+     * 齿轮箱健康评分 (0-100)
+     * 对应数据库字段:gearbox_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal gearboxScore;
+
+    /**
+     * 主轴健康评分 (0-100)
+     * 对应数据库字段:main_shaft_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal mainShaftScore;
+
+    /**
+     * 变流器健康评分 (0-100)
+     * 对应数据库字段:converter_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal converterScore;
+
+    /**
+     * 偏航系统健康评分 (0-100)
+     * 对应数据库字段:yaw_system_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal yawSystemScore;
+
+    /**
+     * 变桨系统健康评分 (0-100)
+     * 对应数据库字段:pitch_system_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal pitchSystemScore;
+
+    /**
+     * 液压系统健康评分 (0-100)
+     * 对应数据库字段:hydraulic_system_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal hydraulicSystemScore;
+
+    /**
+     * 主控系统健康评分 (0-100)
+     * 对应数据库字段:control_system_score (DECIMAL(5,2), 可为空)
+     */
+    private BigDecimal controlSystemScore;
+
+    /**
+     * 数据来源时间 (yyyy-mm-dd)
+     * 对应数据库字段:source_datetime (DATE, 非空)
+     */
+    private Date sourceDatetime;
+
+    /**
+     * 评估入库时间戳 (yyyy-mm-dd hh:mm:ss)
+     * 对应数据库字段:create_time (DATETIME, 非空,默认当前时间)
+     */
+    private Date createTime;
+
+    /**
+     * 结构健康评分
+     */
+    private BigDecimal structureScore;
+
+    /**
+     * 部件健康评分
+     */
+    private BigDecimal componentScore;
+
+    /**
+     * 系统健康评分
+     */
+    private BigDecimal systemScore;
+
+
+
+}

+ 111 - 0
src/main/java/com/energy/manage/analyse/po/healthscores/HealthscoresWindPO.java

@@ -0,0 +1,111 @@
+package com.energy.manage.analyse.po.healthscores;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel
+public class HealthscoresWindPO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     * 对应数据库字段:id (INT, 自增主键)
+     */
+    @ApiModelProperty("主键ID")
+    private Integer id;
+
+    /**
+     * 风场ID(客户内部编号)
+     * 对应数据库字段:fieldId (VARCHAR(32), 非空,默认空字符串)
+     */
+    @ApiModelProperty("风场ID(客户内部编号)")
+    private String fieldId;
+
+    /**
+     * 风场内健康等级为优的风机个数
+     * 对应数据库字段:excellent_count (INT, 可为空)
+     */
+    @ApiModelProperty("风场内健康等级为优的风机占比")
+    private BigDecimal excellentCount;
+
+    /**
+     * 风场内健康等级为良的风机个数
+     * 对应数据库字段:good_count (INT, 可为空)
+     */
+    @ApiModelProperty("风场内健康等级为良的风机占比")
+    private BigDecimal goodCount;
+
+    /**
+     * 风场内健康等级为中的风机个数
+     * 对应数据库字段:fair_count (INT, 可为空)
+     */
+    @ApiModelProperty("风场内健康等级为中的风机占比")
+    private BigDecimal fairCount;
+
+    /**
+     * 风场内健康等级为差的风机个数
+     * 对应数据库字段:poor_count (INT, 可为空)
+     */
+    @ApiModelProperty("风场内健康等级为差的风机占比")
+    private BigDecimal poorCount;
+
+    /**
+     * 风场综合健康评分 (0-100)
+     * 对应数据库字段:overall_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("风场综合健康评分")
+    private BigDecimal overallScore;
+
+    /**
+     * 风场结构健康评分 (0-100)
+     * 对应数据库字段:structure_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("风场结构健康评分")
+    private BigDecimal structureScore;
+
+    /**
+     * 风场系统健康评分 (0-100)
+     * 对应数据库字段:system_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("风场系统健康评分")
+    private BigDecimal systemScore;
+
+    /**
+     * 风场部件健康评分 (0-100)
+     * 对应数据库字段:component_score (DECIMAL(5,2), 可为空)
+     */
+    @ApiModelProperty("风场部件健康评分")
+    private BigDecimal componentScore;
+
+    /**
+     * 数据来源时间 (yyyy-mm-dd)
+     * 对应数据库字段:source_datetime (DATE, 非空)
+     */
+    @ApiModelProperty("数据来源时间")
+    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
+    private Date sourceDatetime;
+
+    /**
+     * 评估入库时间戳 (yyyy-mm-dd hh:mm:ss)
+     * 对应数据库字段:create_time (DATETIME, 非空,默认当前时间)
+     */
+    @ApiModelProperty("评估入库时间戳")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "GMT+8")
+    private Date createTime;
+
+
+
+}

+ 53 - 0
src/main/java/com/energy/manage/analyse/po/wakediagnosis/WakeTurbinePO.java

@@ -0,0 +1,53 @@
+package com.energy.manage.analyse.po.wakediagnosis;
+
+
+/**
+ * 湍流尾流风机表
+ * 对应数据库表:analyse.wake_turbine_2026
+ */
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WakeTurbinePO  implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键ID", hidden = true)
+    private Long id;
+
+    @ApiModelProperty(value = "风场ID", required = true, example = "WF001")
+    private String fieldId;
+
+    @ApiModelProperty(value = "风机ID", required = true, example = "TUR001")
+    private String engineId;
+
+    @ApiModelProperty(value = "是否受尾流影响(0或1)")
+    private BigDecimal isWake;
+
+    @ApiModelProperty(value = "湍流强度")
+    private BigDecimal turbulenceIntensity;
+
+    @ApiModelProperty(value = "尾流速度损失", example = "0.25")
+    private BigDecimal velocityDeficit;
+
+    @ApiModelProperty(value = "检测置信度", example = "0.95")
+    private BigDecimal confidentLevel;
+
+    @ApiModelProperty(value = "每个风机的尾流影响图", example = "0.00")
+    private BigDecimal wakeTurbinePath;
+
+    @ApiModelProperty(value = "数据采集时间", required = true, example = "2023-12-13")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date dateResource;
+
+}

+ 60 - 0
src/main/java/com/energy/manage/analyse/po/wakediagnosis/WakeWindFarmPO.java

@@ -0,0 +1,60 @@
+package com.energy.manage.analyse.po.wakediagnosis;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.Builder;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 湍流尾流风场表
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+@ApiModel(value = "WakeWindfarm对象", description = "湍流尾流风场表")
+public class WakeWindFarmPO implements Serializable {
+
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键ID")
+    private Integer id;
+
+    @ApiModelProperty("风场id")
+    private String fieldId;
+
+    @ApiModelProperty("风场尾流影响分布图路径")
+    private String wakeDistributePath;
+
+    @ApiModelProperty("风场尾流亏损置信度散点图路径")
+    private String wakeLossConfidentPath;
+
+    @ApiModelProperty("风场各风机速度亏损与附加湍流柱状图")
+    private String velocityDeficitPath;
+
+    @ApiModelProperty("风机尾流检测结果文本描述路径")
+    private String wakeDiscriptionPath;
+
+    @ApiModelProperty("时间,以天为单位")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date dataDate;
+
+    @ApiModelProperty("玫瑰图 - 新增")
+    private String wakeRoseDiagramPath;
+
+    @ApiModelProperty("风速分布图地址  - 新增 ")
+    private String windSpeedDistributionChart;
+
+
+
+
+
+}

+ 87 - 0
src/main/java/com/energy/manage/analyse/po/windenginegroup/WindEngineGroupPO.java

@@ -0,0 +1,87 @@
+package com.energy.manage.analyse.po.windenginegroup;
+
+import com.energy.manage.analyse.common.base.NewBaseDomain;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.persistence.Table;
+
+@Data
+@Table(name = "wind_engine_group")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class WindEngineGroupPO extends NewBaseDomain {
+
+    /**
+     * 客户内部(远景系统)风机id
+     */
+    private String engineId;
+    /**
+     * 风场编号
+     */
+    private String fieldCode;
+    /**
+     * 风机名称
+     */
+    private String engineName;
+    /**
+     * 风机编号
+     */
+    private String engineCode;
+    /**
+     * 机型编号uuid
+     */
+    private String millTypeCode;
+    /**
+     * 额定容量
+     */
+    private Double ratedCapacity;
+    /**
+     * 海拔高度
+     */
+    private Double elevationHeight;
+    /**
+     * 轮毂高度
+     */
+    private Double hubHeight;
+    /**
+     * 经度
+     */
+    private Double longitude;
+    /**
+     * 维度
+     */
+    private Double latitude;
+    /**
+     * 状态
+     */
+    private Integer state;
+    /**
+     * 是否标杆风机 1是2否
+     */
+    private Integer sightcing;
+    /**
+     * 额定风速 (m/s)
+     */
+    private Double rated_wind_speed;
+    /**
+     * 切入风速 (m/s)
+     */
+    private Double ratedCutInWindspeed;
+    /**
+     * 切出风速 (m/s)
+     */
+    private Double ratedCutOutWindspeed;
+    /**
+     * 删除状态
+     */
+    private Integer delState;
+
+
+    /**
+     * 数据来源1,平台输入,2导入
+     */
+    private Integer dataSource;
+
+}

+ 100 - 0
src/main/java/com/energy/manage/analyse/po/windfield/WindFieldPO.java

@@ -0,0 +1,100 @@
+package com.energy.manage.analyse.po.windfield;
+
+import com.energy.manage.analyse.common.base.NewBaseDomain;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.persistence.Table;
+
+/**
+ * 风场信息
+ */
+@Data
+@Table(name = "wind_field")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class WindFieldPO extends NewBaseDomain {
+
+    /**
+     *  客户内部(远景系统)风场id
+     */
+    private String fieldId;
+
+    /**
+     * 企业编号
+     */
+    private String companyCode;
+    /**
+     * 风场编号
+     */
+    private String fieldCode;
+    /**
+     * 风场名称
+     */
+    private String fieldName;
+    /**
+     * 空气密度 - 合同功率曲线
+     */
+    private Double density;
+
+    /**
+     * 风机数量
+     */
+    private Integer engineNumber;
+
+    /**
+     * 总额定容量
+     */
+    private Double ratedCapacityNumber;
+
+    /**
+     * 启用状态
+     */
+    private Integer state;
+    /**
+     * 省编号
+     */
+    private Integer provinceId;
+    /**
+     * 省名字
+     */
+    private String provinceName;
+    /**
+     * 市编号
+     */
+    private Integer cityId;
+    /**
+     * 市名字
+     */
+    private String cityName;
+    /**
+     * 经度
+     */
+    private Double longitude;
+    /**
+     * 纬度
+     */
+    private Double latitude;
+    /**
+     * 海拔高度
+     */
+    private Double elevationHeight;
+    /**
+     * 删除状态
+     */
+    private Integer delState;
+
+    /**
+     * 合同功率曲线地址
+     */
+    private String powerContractUrl;
+
+    /**
+     * 数据来源1,平台输入,2导入
+     */
+    private Integer dataSource;
+
+
+}
+

+ 102 - 0
src/main/java/com/energy/manage/analyse/service/anomaly/AnomalyService.java

@@ -0,0 +1,102 @@
+package com.energy.manage.analyse.service.anomaly;
+
+import com.energy.manage.analyse.domain.dto.AnomalyDTO;
+import com.energy.manage.analyse.domain.dto.AnomalyModelDTO;
+import com.energy.manage.analyse.domain.vo.anomaly.*;
+
+import java.util.List;
+
+/**
+ * 异常分析接口
+ */
+public interface AnomalyService {
+
+    /**
+     * 查询异常风机概览
+     * @param anomalyDTO
+     * @return
+     */
+    AnomalyOverviewVO getAnomalyOverview(AnomalyDTO anomalyDTO);
+
+    /**
+     * 柱状图
+     * @param anomalyDTO
+     * @return
+     */
+    BarChartVO getBarChartStats(AnomalyDTO anomalyDTO);
+
+    /**
+     * 检测器热力图
+     * @param anomalyDTO
+     * @return
+     */
+    AnomalyChartVO getAnomalyModelMap(AnomalyDTO anomalyDTO);
+
+
+    /**
+     * 风机卡片
+     * @param anomalyDTO
+     * @return
+     */
+    List<AnomalyModelVO> getAnomalyModel(AnomalyDTO anomalyDTO);
+
+    /**
+     * 风速功率模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    AnomalyWindpwrVO getAnomalyWindpwr(AnomalyModelDTO anomalyModelDTO);
+
+    /**
+     * 偏航模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    AnomalyYawVO geAnomalyYaw(AnomalyModelDTO anomalyModelDTO);
+
+    /**
+     * 变桨模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    AnomalyPitchVO getAnomalyPitch(AnomalyModelDTO anomalyModelDTO);
+
+    /**
+     * 运行状态模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    AnomalyCtrlParamVO getAnomalyCtrlParam(AnomalyModelDTO anomalyModelDTO);
+
+
+    /**
+     * 气动性能
+     * @param anomalyModelDTO
+     * @return
+     */
+    AnomalyAerodynamicsVO getAerodynamics(AnomalyModelDTO anomalyModelDTO);
+
+
+    /**
+     * 获取变桨模块异常趋势(支持年度分表+跨年跨表)
+     * @param anomalyModelDTO
+     * @return
+     */
+    List<AnomalyDailyVO> getPitchAnomalyTrend(AnomalyModelDTO anomalyModelDTO);
+
+
+    /**
+     * 查询传感器异常台数
+     * @param anomalyDTO
+     * @return
+     */
+    AnomalySensorCountVO getAnomalySensorCount(AnomalyDTO anomalyDTO);
+
+    /**
+     * 异常检测模块统计异常风机台数
+     * @param anomalyDTO
+     * @return
+     */
+    AnomalyCount getAnomalyModelCount(AnomalyDTO anomalyDTO);
+
+}

+ 940 - 0
src/main/java/com/energy/manage/analyse/service/anomaly/impl/AnomalyServiceImpl.java

@@ -0,0 +1,940 @@
+package com.energy.manage.analyse.service.anomaly.impl;
+
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.energy.manage.analyse.constant.AnomalySensorType;
+import com.energy.manage.analyse.constant.DetectorTableEnum;
+import com.energy.manage.analyse.constant.DetectorType;
+import com.energy.manage.analyse.domain.dto.AnomalyDTO;
+import com.energy.manage.analyse.domain.dto.AnomalyModelDTO;
+import com.energy.manage.analyse.domain.vo.anomaly.*;
+import com.energy.manage.analyse.mappers.anomaly.AnomalyWindfarmMapper;
+import com.energy.manage.analyse.mappers.windenginegroup.WindEngineGroupMapper;
+import com.energy.manage.analyse.mappers.windfield.WindFieldMapper;
+import com.energy.manage.analyse.po.anomaly.*;
+import com.energy.manage.analyse.po.windenginegroup.WindEngineGroupPO;
+import com.energy.manage.analyse.po.windfield.WindFieldPO;
+import com.energy.manage.analyse.service.anomaly.AnomalyService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class AnomalyServiceImpl implements AnomalyService {
+
+    @Autowired
+    private AnomalyWindfarmMapper anomalyWindfarmMapper;
+
+    @Autowired
+    private WindFieldMapper windFieldMapper;
+
+    @Autowired
+    private WindEngineGroupMapper windEngineGroupMapper;
+
+    // 通用日期格式化器(线程安全,可全局复用)
+    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    // 分表前缀
+    private static final String TABLE_PREFIX = "analyse.anomaly_model_";
+
+
+    @Override
+    public AnomalyOverviewVO getAnomalyOverview(AnomalyDTO anomalyDTO) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(anomalyDTO.getFieldCode());
+        if (windFieldPO != null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+        return anomalyWindfarmMapper.selectAnomalyWindfarmAndFieldId(fieldId, beginTime, endTime);
+    }
+
+    /**
+     * 查询风场信息
+     *
+     * @param fieldCode
+     * @return
+     */
+    private WindFieldPO getWindField(String fieldCode) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("master");
+        WindFieldPO windFieldPO = null;
+        if (!StringUtils.isEmpty(fieldCode)) {
+            WindFieldPO po = new WindFieldPO();
+            po.setFieldCode(fieldCode);
+            windFieldPO = windFieldMapper.selectOne(po);
+        }
+        return windFieldPO;
+    }
+
+    /**
+     * 查询风机对象集合
+     * @param eids
+     * @return
+     */
+    private Map<String, String> getWindEngineGroupMap(Set<String> eids) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("master");
+        // 查询平台风机模块
+        Example example = new Example(WindEngineGroupPO.class);
+        Example.Criteria criteria = example.createCriteria();
+        criteria.andIn("engineId", eids);
+        List<WindEngineGroupPO> list =  windEngineGroupMapper.selectByExample(example);
+        // key为String时
+        Map<String, String> windEngineMap = list.stream()
+                .collect(Collectors.toMap(
+                        WindEngineGroupPO::getEngineId,
+                        WindEngineGroupPO::getEngineName,
+                        (oldValue, newValue) -> oldValue
+                ));
+
+        return windEngineMap;
+    }
+
+
+    @Override
+    public BarChartVO getBarChartStats(AnomalyDTO anomalyDTO) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(anomalyDTO.getFieldCode());
+        if (windFieldPO != null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+        return anomalyWindfarmMapper.selectAnomalyModelCount(fieldId, year, beginTime, endTime);
+    }
+
+
+    @Override
+    public List<AnomalyModelVO> getAnomalyModel(AnomalyDTO anomalyDTO) {
+
+        AnomalyChartVO anomalyChartVO = new AnomalyChartVO();
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(anomalyDTO.getFieldCode());
+        if (windFieldPO != null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+        List<AnomalyModelPO> getAnomalyModelList = anomalyWindfarmMapper.selectAllAnomalyModel(fieldId, year, beginTime, endTime);
+        if (CollectionUtil.isEmpty(getAnomalyModelList)) {
+            return null;
+        }
+
+        // 复制对象集合
+        List<AnomalyModelVO> anomalyModelVOS = getAnomalyModelList.stream()
+                // 逐个复制对象属性:源对象 → 目标类的新对象
+                .map(source -> BeanUtil.copyProperties(source, AnomalyModelVO.class))
+                .collect(Collectors.toList());
+
+        return anomalyModelVOS;
+    }
+
+
+    @Override
+    public AnomalyChartVO getAnomalyModelMap(AnomalyDTO anomalyDTO){
+
+        AnomalyChartVO anomalyChartVO = new AnomalyChartVO();
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(anomalyDTO.getFieldCode());
+        if (windFieldPO != null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+        List<AnomalyModelPO> getAnomalyModelList = anomalyWindfarmMapper.selectAllAnomalyModel(fieldId, year, beginTime, endTime);
+        if (CollectionUtil.isEmpty(getAnomalyModelList)) {
+            return null;
+        }
+
+        // 获取风机id集合
+        Set<String> eids = getAnomalyModelList.parallelStream().map(AnomalyModelPO::getEngineId).collect(Collectors.toSet());
+        Map<String, String> engineMap =  getWindEngineGroupMap(eids);
+
+        Map<String, List<AnomalyThermodynamicDiagramVO>> anomalyChartMap = getAnomalyThermodynamicDiagramMap(getAnomalyModelList,engineMap);
+        Map<String, List<AnomalyThermodynamicDiagramVO>> anomalySensorMap = getAnomalySensorMap(getAnomalyModelList,engineMap);
+
+        anomalyChartVO.setAnomalyChartMap(anomalyChartMap);
+        anomalyChartVO.setAnomalySensorMap(anomalySensorMap);
+
+        return anomalyChartVO;
+    }
+
+
+    /**
+     * 整合数据检测器map
+     * @param getAnomalyModelList
+     * @param engineMap
+     * @return
+     */
+    private  Map<String, List<AnomalyThermodynamicDiagramVO>> getAnomalyThermodynamicDiagramMap(List<AnomalyModelPO> getAnomalyModelList,Map<String, String> engineMap){
+
+        Map<String, List<AnomalyThermodynamicDiagramVO>> map = new HashMap<>();
+        // 模块1:风速功率检测器
+        List<AnomalyThermodynamicDiagramVO> model1PowercurveList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model1ScatterList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model1SimulinkList = new ArrayList<>();
+
+        // 模块2:偏航检测器
+        List<AnomalyThermodynamicDiagramVO> model2StaticyawList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model2CabletwistList = new ArrayList<>();
+
+        // 模块3:变桨检测器
+        List<AnomalyThermodynamicDiagramVO> model3PitchregulationList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model3PitchcoordList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model3MinpitchList = new ArrayList<>();
+
+        // 模块4:运行状态检测器
+        List<AnomalyThermodynamicDiagramVO> model4PowerqualityList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model4OperationstateList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model4CtrlparamDeloadList = new ArrayList<>();
+
+        // 模块5:气动性能
+        List<AnomalyThermodynamicDiagramVO> model5CPList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model5TSRList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> model5CPTSRList = new ArrayList<>();
+
+
+        // 模块1:风速功率检测器
+        AnomalyThermodynamicDiagramVO model1Powercurve = null;
+        AnomalyThermodynamicDiagramVO model1Scatter = null;
+        AnomalyThermodynamicDiagramVO model1Simulink = null;
+        // 模块2:偏航检测器
+        AnomalyThermodynamicDiagramVO model2Staticyaw = null;
+        AnomalyThermodynamicDiagramVO  model2Cabletwist = null;
+        // 模块3:变桨检测器
+        AnomalyThermodynamicDiagramVO model3Pitchregulation = null;
+        AnomalyThermodynamicDiagramVO model3Pitchcoord = null;
+        AnomalyThermodynamicDiagramVO model3Minpitch = null;
+        // 模块4:运行状态检测器
+        AnomalyThermodynamicDiagramVO model4Powerquality = null;
+        AnomalyThermodynamicDiagramVO model4Operationstate = null;
+        AnomalyThermodynamicDiagramVO model4CtrlparamDeload = null;
+        // 模块5:气动性能
+        AnomalyThermodynamicDiagramVO model5CP = null;
+        AnomalyThermodynamicDiagramVO model5TSR = null;
+        AnomalyThermodynamicDiagramVO model5CPTSR = null;
+
+        for (AnomalyModelPO anomalyModelPO : getAnomalyModelList) {
+
+            // 模块1:风速功率检测器
+            model1Powercurve = new AnomalyThermodynamicDiagramVO();
+            model1Powercurve.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model1Powercurve.setIfAbnorma(anomalyModelPO.getModel1WindpwrPowercurve());
+            model1Powercurve.setRatio(anomalyModelPO.getModel1WindpwrPowercurveRatio());
+            model1PowercurveList.add(model1Powercurve);
+
+            model1Scatter = new AnomalyThermodynamicDiagramVO();
+            model1Scatter.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model1Scatter.setIfAbnorma(anomalyModelPO.getModel1WindpwrScatter());
+            model1Scatter.setRatio(anomalyModelPO.getModel1WindpwrScatterRatio());
+            model1ScatterList.add(model1Scatter);
+
+            model1Simulink = new AnomalyThermodynamicDiagramVO();
+            model1Simulink.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model1Simulink.setIfAbnorma(anomalyModelPO.getModel1WindpwrSimulink());
+            model1SimulinkList.add(model1Simulink);
+
+            // 模块2:偏航检测器
+            model2Staticyaw = new AnomalyThermodynamicDiagramVO();
+            model2Staticyaw.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model2Staticyaw.setIfAbnorma(anomalyModelPO.getModel2YawStaticyaw());
+            model2Staticyaw.setRatio(anomalyModelPO.getModel2YawStaticyawRatio());
+            model2StaticyawList.add(model2Staticyaw);
+
+            model2Cabletwist = new AnomalyThermodynamicDiagramVO();
+            model2Cabletwist.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model2Cabletwist.setIfAbnorma(anomalyModelPO.getModel2YawCabletwist());
+            model2Staticyaw.setRatio(anomalyModelPO.getModel2YawStaticyawRatio());
+            model2CabletwistList.add(model2Cabletwist);
+
+            // 模块3:变桨检测器
+            model3Pitchregulation = new AnomalyThermodynamicDiagramVO();
+            model3Pitchregulation.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model3Pitchregulation.setIfAbnorma(anomalyModelPO.getModel3PitchPitchregulation());
+            model3Pitchregulation.setRatio(anomalyModelPO.getModel3PitchPitchregulationRatio());
+            model3PitchregulationList.add(model3Pitchregulation);
+
+            model3Pitchcoord = new AnomalyThermodynamicDiagramVO();
+            model3Pitchcoord.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model3Pitchcoord.setIfAbnorma(anomalyModelPO.getModel3PitchPitchcoord());
+            model3Pitchcoord.setRatio(anomalyModelPO.getModel3PitchPitchcoordRatio());
+            model3PitchcoordList.add(model3Pitchcoord);
+
+            model3Minpitch = new AnomalyThermodynamicDiagramVO();
+            model3Minpitch.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model3Minpitch.setIfAbnorma(anomalyModelPO.getModel3PitchMinpitch());
+            model3MinpitchList.add(model3Minpitch);
+
+            // 模块4:运行状态检测器
+            model4Powerquality = new AnomalyThermodynamicDiagramVO();
+            model4Powerquality.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model4Powerquality.setIfAbnorma(anomalyModelPO.getModel4CtrlparamPowerquality());
+            model4Powerquality.setRatio(anomalyModelPO.getModel4CtrlparamPowerqualityRatio());
+            model4PowerqualityList.add(model4Powerquality);
+
+            model4Operationstate = new AnomalyThermodynamicDiagramVO();
+            model4Operationstate.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model4Operationstate.setIfAbnorma(anomalyModelPO.getModel4CtrlparamOperationstate());
+            model4Operationstate.setRatio(anomalyModelPO.getModel4CtrlparamOperationstateRatio());
+            model4OperationstateList.add(model4Operationstate);
+
+            model4CtrlparamDeload = new AnomalyThermodynamicDiagramVO();
+            model4CtrlparamDeload.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model4CtrlparamDeload.setRatio(anomalyModelPO.getModel4CtrlparamPowerqualityRatio());
+            model4CtrlparamDeloadList.add(model4CtrlparamDeload);
+
+            // 模块5:气动性能
+            model5CP = new AnomalyThermodynamicDiagramVO();
+            model5CP.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model5CP.setRatio(anomalyModelPO.getModel5AerodynamicsCpRatio());
+            model5CPList.add(model5CP);
+
+            model5TSR = new AnomalyThermodynamicDiagramVO();
+            model5TSR.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model5TSR.setRatio(anomalyModelPO.getModel5AerodynamicsTsrRatio());
+            model5TSRList.add(model5TSR);
+
+            model5CPTSR = new AnomalyThermodynamicDiagramVO();
+            model5CPTSR.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            model5CPTSR.setRatio(anomalyModelPO.getModel5AerodynamicsCpTsrRatio());
+            model5CPTSRList.add(model5CPTSR);
+
+        }
+        // 模块1:风速功率检测器
+        map.put(DetectorType.MODEL1_POWERCURVE.getCode(),model1PowercurveList);
+        map.put(DetectorType.MODEL1_SCATTER.getCode(),model1ScatterList);
+        map.put(DetectorType.MODEL1_SIMULINK.getCode(),model1SimulinkList);
+        // 模块2:偏航检测器
+        map.put(DetectorType.MODEL2_STATICYAW.getCode(),model2StaticyawList);
+        map.put(DetectorType.MODEL2_CABLETWIST.getCode(),model2CabletwistList);
+        // 模块3:变桨检测器
+        map.put(DetectorType.MODEL3_PITCHREGULATION.getCode(),model3PitchregulationList);
+        map.put(DetectorType.MODEL3_PITCHCOORD.getCode(),model3PitchcoordList);
+        map.put(DetectorType.MODEL3_MINPITCH.getCode(),model3MinpitchList);
+        // 模块4:运行状态检测器
+        map.put(DetectorType.MODEL4_POWERQUALITY.getCode(),model4PowerqualityList);
+        map.put(DetectorType.MODEL4_OPERATIONSTATE.getCode(),model4OperationstateList);
+        map.put(DetectorType.MODEL4_DELOAD.getCode(),model4CtrlparamDeloadList);
+        // 模块5:气动性能
+        map.put(DetectorType.MODEL5_CP.getCode(),model5CPList);
+        map.put(DetectorType.MODEL5_TSR.getCode(),model5TSRList);
+        map.put(DetectorType.MODEL5_CP_TSR.getCode(),model5CPTSRList);
+
+        return map;
+    }
+
+
+    private  Map<String, List<AnomalyThermodynamicDiagramVO>> getAnomalySensorMap(List<AnomalyModelPO> getAnomalyModelList,Map<String, String> engineMap){
+
+        Map<String, List<AnomalyThermodynamicDiagramVO>> map = new HashMap<>();
+
+        // 物理传感器异常列表
+        List<AnomalyThermodynamicDiagramVO> powerSensorAnomalyList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> windSpeedSensorAnomalyList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> pitchSensorAnomalyList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> rotationSpeedSensorAnomalyList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> torqueSensorAnomalyList = new ArrayList<>();
+
+        // 逻辑关联异常列表
+        List<AnomalyThermodynamicDiagramVO> windPowerLogicAnomalyList = new ArrayList<>();
+        List<AnomalyThermodynamicDiagramVO> speedTorqueLogicAnomalyList = new ArrayList<>();
+
+        // 物理传感器异常列表
+        AnomalyThermodynamicDiagramVO powerSensorAnomaly = null;
+        AnomalyThermodynamicDiagramVO windSpeedSensorAnomaly =  null;
+        AnomalyThermodynamicDiagramVO pitchSensorAnomaly =  null;
+        AnomalyThermodynamicDiagramVO rotationSpeedSensorAnomaly = null;
+        AnomalyThermodynamicDiagramVO torqueSensorAnomaly =  null;
+
+        // 逻辑关联异常列表
+        AnomalyThermodynamicDiagramVO windPowerLogicAnomaly =  null;
+        AnomalyThermodynamicDiagramVO speedTorqueLogicAnomaly =  null;
+
+
+        for (AnomalyModelPO anomalyModelPO : getAnomalyModelList) {
+
+            powerSensorAnomaly = new AnomalyThermodynamicDiagramVO();
+            powerSensorAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            powerSensorAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalyPower());
+            powerSensorAnomaly.setRatio(anomalyModelPO.getSensorAnomalyPowerRatio());
+            powerSensorAnomalyList.add(powerSensorAnomaly);
+
+            windSpeedSensorAnomaly = new AnomalyThermodynamicDiagramVO();
+            windSpeedSensorAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            windSpeedSensorAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalyWind());
+            windSpeedSensorAnomaly.setRatio(anomalyModelPO.getSensorAnomalyWindRatio());
+            windSpeedSensorAnomalyList.add(windSpeedSensorAnomaly);
+
+            pitchSensorAnomaly = new AnomalyThermodynamicDiagramVO();
+            pitchSensorAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            pitchSensorAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalyPitch());
+            pitchSensorAnomaly.setRatio(anomalyModelPO.getSensorAnomalyPitchRatio());
+            pitchSensorAnomalyList.add(pitchSensorAnomaly);
+
+            rotationSpeedSensorAnomaly = new AnomalyThermodynamicDiagramVO();
+            rotationSpeedSensorAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            rotationSpeedSensorAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalySpeed());
+            rotationSpeedSensorAnomaly.setRatio(anomalyModelPO.getSensorAnomalySpeedRatio());
+            rotationSpeedSensorAnomalyList.add(rotationSpeedSensorAnomaly);
+
+            torqueSensorAnomaly = new AnomalyThermodynamicDiagramVO();
+            torqueSensorAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            torqueSensorAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalyTorque());
+            torqueSensorAnomaly.setRatio(anomalyModelPO.getSensorAnomalyTorqueRatio());
+            torqueSensorAnomalyList.add(torqueSensorAnomaly);
+
+            windPowerLogicAnomaly = new AnomalyThermodynamicDiagramVO();
+            windPowerLogicAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            windPowerLogicAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalyWindPwr());
+            windPowerLogicAnomaly.setRatio(anomalyModelPO.getSensorAnomalyWindPwrRatio());
+            windPowerLogicAnomalyList.add(windPowerLogicAnomaly);
+
+            speedTorqueLogicAnomaly = new AnomalyThermodynamicDiagramVO();
+            speedTorqueLogicAnomaly.setEngineName(engineMap.get(anomalyModelPO.getEngineId()));
+            speedTorqueLogicAnomaly.setIfAbnorma(anomalyModelPO.getSensorAnomalySpeed());
+            speedTorqueLogicAnomaly.setRatio(anomalyModelPO.getSensorAnomalySpeedRatio());
+            speedTorqueLogicAnomalyList.add(speedTorqueLogicAnomaly);
+
+        }
+
+        map.put(AnomalySensorType.POWER_SENSOR.getFieldName(),powerSensorAnomalyList);
+        map.put(AnomalySensorType.WIND_SENSOR.getFieldName(),windSpeedSensorAnomalyList);
+        map.put(AnomalySensorType.PITCH_SENSOR.getFieldName(),pitchSensorAnomalyList);
+        map.put(AnomalySensorType.SPEED_SENSOR.getFieldName(),rotationSpeedSensorAnomalyList);
+        map.put(AnomalySensorType.TORQUE_SENSOR.getFieldName(),torqueSensorAnomalyList);
+        map.put(AnomalySensorType.WIND_POWER_LOGIC.getFieldName(),windPowerLogicAnomalyList);
+        map.put(AnomalySensorType.SPEED_TORQUE_LOGIC.getFieldName(),speedTorqueLogicAnomalyList);
+
+        return map;
+    }
+
+
+    /**
+     * 获取变桨模块异常趋势(支持年度分表+跨年跨表)
+     * @param anomalyModelDTO 7/30天
+     */
+    @Override
+    public List<AnomalyDailyVO> getPitchAnomalyTrend(AnomalyModelDTO anomalyModelDTO) {
+
+        // 1. 计算日期范围(自动跨年)
+        LocalDate endDate = LocalDate.parse(anomalyModelDTO.getDatatime());
+        LocalDate startDate = endDate.minusDays(anomalyModelDTO.getTimeRange() - 1);
+
+        // 2. 自动查询:单表 / 跨表
+        List<AnomalyDailyVO> dbData = getUnionAnomalyData(startDate, endDate,anomalyModelDTO);
+
+        // 3. 补全缺失日期(图表无断层)
+        List<AnomalyDailyVO> fullData = fillMissingDate(startDate, endDate, dbData);
+
+        return fullData;
+    }
+
+
+    @Override
+    public AnomalySensorCountVO getAnomalySensorCount(AnomalyDTO anomalyDTO) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(anomalyDTO.getFieldCode());
+        if (windFieldPO != null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        AnomalySensorCountVO anomalySensorCountVO = anomalyWindfarmMapper.selectAnomalySensorCountVO(fieldId,year,beginTime,endTime);
+
+        return anomalySensorCountVO;
+    }
+
+
+    @Override
+    public AnomalyCount getAnomalyModelCount(AnomalyDTO anomalyDTO) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(anomalyDTO.getFieldCode());
+        if (windFieldPO != null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        AnomalyCount anomalyCount = anomalyWindfarmMapper.selectModeCount(fieldId,year,beginTime,endTime);
+
+        return anomalyCount;
+    }
+
+
+
+
+
+
+
+    /**
+     * 核心:自动判断 单表/跨表 查询
+     */
+    private List<AnomalyDailyVO> getUnionAnomalyData(LocalDate start, LocalDate end, AnomalyModelDTO anomalyModelDTO) {
+        int startYear = start.getYear();
+        int endYear = end.getYear();
+
+        // 场景1:同一年 → 查询单张分表
+        if (startYear == endYear) {
+            String tableName = TABLE_PREFIX + startYear;
+            return anomalyWindfarmMapper.selectBySingleTable(anomalyModelDTO.getFieldId(),anomalyModelDTO.getEngineId(),
+                    tableName, start.toString(), end.toString());
+        }
+        // 场景2:跨年份 → 查询两张分表(UNION ALL)
+        else {
+            String table1 = TABLE_PREFIX + startYear;
+            String table2 = TABLE_PREFIX + endYear;
+            return anomalyWindfarmMapper.selectByUnionTables(anomalyModelDTO.getFieldId(),anomalyModelDTO.getEngineId(),
+                    table1,table2, start.toString(), end.toString());
+        }
+    }
+
+
+    /**
+     * 补全无数据日期(赋值0)
+     */
+    private List<AnomalyDailyVO> fillMissingDate(LocalDate start, LocalDate end, List<AnomalyDailyVO> data) {
+        Map<Date, AnomalyDailyVO> dataMap = data.stream().collect(Collectors.toMap(AnomalyDailyVO::getCreateTime, dto -> dto));
+
+        List<AnomalyDailyVO> result = new ArrayList<>();
+
+        for (LocalDate date = start; !date.isAfter(end); date = date.plusDays(1)) {
+
+            result.add(dataMap.getOrDefault(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()),
+                    new AnomalyDailyVO(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()),
+                            new BigDecimal(0), new BigDecimal(0), new BigDecimal(0),new BigDecimal(0),new BigDecimal(0))));
+        }
+        return result;
+    }
+
+
+    /**
+     * 风速功率模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    @Override
+    public AnomalyWindpwrVO getAnomalyWindpwr(AnomalyModelDTO anomalyModelDTO){
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyModelDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyModelDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyModelDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+        BaseAnomalyDetectorPO powerPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.POWER_CURVE.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyPowercurvePO anomalyPowercurvePO = new AnomalyPowercurvePO();
+        BeanUtil.copyProperties(powerPO,anomalyPowercurvePO);
+
+        BaseAnomalyDetectorPO scatterPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.SCATTER.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyScatterPO anomalyScatterPO = new AnomalyScatterPO();
+        BeanUtil.copyProperties(scatterPO,anomalyScatterPO);
+
+        BaseAnomalyDetectorPO simulinkPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.SIMULINK.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalySimulinkPO  anomalySimulinkPO = new AnomalySimulinkPO();
+        BeanUtil.copyProperties(simulinkPO,anomalySimulinkPO);
+
+        AnomalyWindpwrVO anomalyWindpwrVO = new AnomalyWindpwrVO();
+        anomalyWindpwrVO.setAnomalyPowercurvePO(anomalyPowercurvePO);
+        anomalyWindpwrVO.setAnomalyScatterPO(anomalyScatterPO);
+        anomalyWindpwrVO.setAnomalySimulinkPO(anomalySimulinkPO);
+
+        return anomalyWindpwrVO;
+    }
+
+    /**
+     * 偏航模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    @Override
+    public AnomalyYawVO geAnomalyYaw(AnomalyModelDTO anomalyModelDTO){
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyModelDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyModelDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyModelDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+        BaseAnomalyDetectorPO  staticyaw=  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.CABLE_TWIST.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyStaticyawPO anomalyStaticyawPO = new AnomalyStaticyawPO();
+        BeanUtil.copyProperties(staticyaw,anomalyStaticyawPO);
+
+        BaseAnomalyDetectorPO cabletwistPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.STATIC_YAW.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyCabletwistPO anomalyCabletwistPO = new AnomalyCabletwistPO();
+        BeanUtil.copyProperties(cabletwistPO,anomalyCabletwistPO);
+
+        AnomalyYawVO anomalyYawVO = new AnomalyYawVO();
+        anomalyYawVO.setAnomalyStaticyawPO(anomalyStaticyawPO);
+        anomalyYawVO.setAnomalyCabletwistPO(anomalyCabletwistPO);
+
+        return anomalyYawVO;
+    }
+
+
+    /**
+     * 变桨模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    @Override
+    public AnomalyPitchVO getAnomalyPitch(AnomalyModelDTO anomalyModelDTO){
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyModelDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyModelDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyModelDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+        BaseAnomalyDetectorPO pitchregulationPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.PITCH_REGULATION.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyPitchregulationPO anomalyPitchregulationPO = new AnomalyPitchregulationPO();
+        BeanUtil.copyProperties(pitchregulationPO,anomalyPitchregulationPO);
+
+        BaseAnomalyDetectorPO pitchcoordPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.PITCH_COORD.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyPitchcoordPO anomalyPitchcoordPO = new AnomalyPitchcoordPO();
+        BeanUtil.copyProperties(pitchcoordPO,anomalyPitchcoordPO);
+
+        BaseAnomalyDetectorPO minpitchPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.MIN_PITCH.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyMinpitchPO  anomalyMinpitchPO = new AnomalyMinpitchPO();
+        BeanUtil.copyProperties(minpitchPO,anomalyMinpitchPO);
+
+        AnomalyPitchVO anomalyPitchVO = new AnomalyPitchVO();
+        anomalyPitchVO.setAnomalyPitchregulationPO (anomalyPitchregulationPO);
+        anomalyPitchVO.setAnomalyPitchcoordPO(anomalyPitchcoordPO);
+        anomalyPitchVO.setAnomalyMinpitchPO(anomalyMinpitchPO);
+
+        return anomalyPitchVO;
+    }
+
+    /**
+     * 运行状态模块模块
+     * @param anomalyModelDTO
+     * @return
+     */
+    @Override
+    public AnomalyCtrlParamVO getAnomalyCtrlParam(AnomalyModelDTO anomalyModelDTO){
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyModelDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyModelDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyModelDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+        BaseAnomalyDetectorPO powerqualityPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.POWER_QUALITY.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyPowerqualityPO anomalyPowerqualityPO = new AnomalyPowerqualityPO();
+        BeanUtil.copyProperties(powerqualityPO,anomalyPowerqualityPO);
+
+        BaseAnomalyDetectorPO operationPO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.OPERATION.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyOperationPO anomalyOperationPO = new AnomalyOperationPO();
+        BeanUtil.copyProperties(operationPO,anomalyOperationPO);
+
+        AnomalyCtrlParamVO anomalyCtrlParamVO = new AnomalyCtrlParamVO();
+        anomalyCtrlParamVO.setAnomalyPowerqualityPO (anomalyPowerqualityPO);
+        anomalyCtrlParamVO.setAnomalyOperationPO(anomalyOperationPO);
+
+        return anomalyCtrlParamVO;
+    }
+
+
+    /**
+     * 气动性能
+     * @param anomalyModelDTO
+     * @return
+     */
+    @Override
+    public AnomalyAerodynamicsVO getAerodynamics(AnomalyModelDTO anomalyModelDTO){
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(anomalyModelDTO.getDatatime())) {
+            beginTime = appendTimeToString(anomalyModelDTO.getDatatime(), 00, 00, 00);
+            endTime = appendTimeToString(anomalyModelDTO.getDatatime(), 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+
+        BaseAnomalyDetectorPO anomalyCpBasePO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.CP_DETECTOR.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyCpPO anomalyCpPO = new AnomalyCpPO();
+        BeanUtil.copyProperties(anomalyCpBasePO,anomalyCpPO);
+
+        BaseAnomalyDetectorPO anomalyTsrBasePO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.TSR_DETECTOR.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyTsrPO anomalyTsrPO = new AnomalyTsrPO();
+        BeanUtil.copyProperties(anomalyTsrBasePO,anomalyTsrPO);
+
+        BaseAnomalyDetectorPO anomalyCpTsrBasePO =  anomalyWindfarmMapper.selectAnomalyDetectorAll(anomalyModelDTO.getFieldId(),
+                DetectorTableEnum.CP_TSR_DETECTOR.getFullTableName(year),
+                anomalyModelDTO.getEngineId(),beginTime,endTime);
+        AnomalyCpTsrPO anomalyCpTsrPO = new AnomalyCpTsrPO();
+        BeanUtil.copyProperties(anomalyCpTsrBasePO,anomalyCpTsrPO);
+
+
+        AnomalyAerodynamicsVO anomalyAerodynamicsVO = new AnomalyAerodynamicsVO();
+        anomalyAerodynamicsVO.setAnomalyCpPO(anomalyCpPO);
+        anomalyAerodynamicsVO.setAnomalyCpTsrPO(anomalyCpTsrPO);
+        anomalyAerodynamicsVO.setAnomalyTsrPO(anomalyTsrPO);
+
+        return anomalyAerodynamicsVO;
+    }
+
+
+
+
+    /**
+     * 分隔符
+     * ==============================================================================================================================
+     */
+
+    /**
+     * 给String类型的年月日拼接时分秒
+     *
+     * @param dateStr 年月日字符串(如 "2026-03-02")
+     * @param hour    小时
+     * @param minute  分钟
+     * @param second  秒
+     * @return 带时分秒的字符串(如 "2026-03-02 15:30:00")
+     */
+    private String appendTimeToString(String dateStr, int hour, int minute, int second) {
+        // 1. 解析为LocalDate(校验日期合法性)
+        LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER);
+        // 2. 拼接时分秒为LocalDateTime
+        LocalDateTime localDateTime = localDate.atTime(hour, minute, second);
+        // 3. 格式化为字符串
+        return localDateTime.format(DATETIME_FORMATTER);
+    }
+
+    /**
+     * 重载:获取昨天开始/结束时间的字符串格式
+     */
+    private String getYesterdayStartStr() {
+        return getYesterdayStart().format(DATETIME_FORMATTER);
+    }
+
+    private String getYesterdayEndStr() {
+        // 严格格式化为 23:59:59(去掉纳秒)
+        return getYesterdayEnd().format(DATETIME_FORMATTER).substring(0, 19);
+    }
+
+    /**
+     * 获取昨天的开始时间(yyyy-MM-dd 00:00:00)
+     *
+     * @return LocalDateTime
+     */
+    private LocalDateTime getYesterdayStart() {
+        // 1. 获取昨天的日期
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        // 2. 拼接 00:00:00 等价于 yesterday.atTime(0, 0, 0)
+        return yesterday.atStartOfDay();
+    }
+
+    /**
+     * 获取昨天的结束时间(yyyy-MM-dd 23:59:59)
+     *
+     * @return LocalDateTime
+     */
+    private LocalDateTime getYesterdayEnd() {
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        // 拼接 23:59:59
+        return yesterday.atTime(23, 59, 59);
+        // 若需严格的23:59:59,用:yesterday.atTime(23, 59, 59)
+    }
+}

+ 42 - 0
src/main/java/com/energy/manage/analyse/service/healthscores/HealthscoresService.java

@@ -0,0 +1,42 @@
+package com.energy.manage.analyse.service.healthscores;
+
+
+import com.energy.manage.analyse.domain.vo.healthscores.HealthOverviewVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresTendencyVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresWindVO;
+
+import java.util.List;
+
+/**
+ * 健康查询接口
+ */
+public interface HealthscoresService {
+
+
+    /**
+     * 风场健康查询综合页面(包含首页)
+     * @param datatime
+     * @return
+     */
+    List<HealthscoresWindVO> getHealthscoresWind(String fieldCode, String datatime);
+
+
+    /**
+     * 风场下风机健康查询概览页面
+     * @param fieldCode
+     * @param datatime
+     * @return
+     */
+    HealthOverviewVO getHealthOverview(String fieldCode, String datatime);
+
+
+    /**
+     * 风机健康趋势图
+     * @param day
+     * @param fieldId
+     * @param engineId
+     * @return
+     */
+    List<HealthscoresTendencyVO> getLastDaysTrend(int day, String fieldId, String engineId);
+
+}

+ 333 - 0
src/main/java/com/energy/manage/analyse/service/healthscores/impl/HealthscoresServiceImpl.java

@@ -0,0 +1,333 @@
+package com.energy.manage.analyse.service.healthscores.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.energy.manage.analyse.domain.vo.enginegroup.WindEngineGroupVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthOverviewListVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthOverviewVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresTendencyVO;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthscoresWindVO;
+import com.energy.manage.analyse.mappers.healthscores.HealthscoresMapper;
+import com.energy.manage.analyse.mappers.windenginegroup.WindEngineGroupMapper;
+import com.energy.manage.analyse.mappers.windfield.WindFieldMapper;
+import com.energy.manage.analyse.po.windenginegroup.WindEngineGroupPO;
+import com.energy.manage.analyse.po.windfield.WindFieldPO;
+import com.energy.manage.analyse.service.healthscores.HealthscoresService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+@Slf4j
+public class HealthscoresServiceImpl implements HealthscoresService {
+
+    @Autowired
+    private HealthscoresMapper healthscoresMapper;
+
+    @Autowired
+    private WindFieldMapper windFieldMapper;
+
+    @Autowired
+    private WindEngineGroupMapper windEngineGroupMapper;
+
+    // 通用日期格式化器(线程安全,可全局复用)
+    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+
+    @Override
+    public List<HealthscoresWindVO> getHealthscoresWind(String fieldCode, String datatime) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(fieldCode);
+        if (windFieldPO!=null) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(datatime)) {
+            beginTime = appendTimeToString(datatime, 00, 00, 00);
+            endTime = appendTimeToString(datatime, 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+
+        List<HealthscoresWindVO> list = getHealthscoresWind(fieldId, beginTime, endTime);
+        return list;
+    }
+
+    private WindFieldPO getWindField(String fieldCode) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("master");
+        WindFieldPO windFieldPO = null;
+        if (!StringUtils.isEmpty(fieldCode)) {
+            WindFieldPO po = new WindFieldPO();
+            po.setFieldCode(fieldCode);
+            windFieldPO = windFieldMapper.selectOne(po);
+        }
+        return windFieldPO;
+    }
+
+
+    private List<HealthscoresWindVO> getHealthscoresWind(String fieldId, String beginTime, String endTime) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+        return healthscoresMapper.selectWindScoreList(fieldId, beginTime, endTime);
+    }
+
+
+    @Override
+    public HealthOverviewVO getHealthOverview(String fieldCode, String datatime) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(fieldCode);
+        if (!StringUtils.isEmpty(fieldCode)) {
+            fieldId = windFieldPO.getFieldId();
+        }
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(datatime)) {
+            beginTime = appendTimeToString(datatime, 00, 00, 00);
+            endTime = appendTimeToString(datatime, 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+        // 查询健康评估模块
+        HealthOverviewVO healthOverviewVO = new HealthOverviewVO();
+        HealthscoresWindVO healthscoresWind = healthscoresMapper.selectWindHealthscoresScore(fieldId, beginTime, endTime);
+
+        if (healthscoresWind != null) {
+            healthOverviewVO.setHealthscoresWindVO(healthscoresWind);
+        }
+        String year = String.valueOf(LocalDate.now().getYear());
+        List<HealthOverviewListVO> overviewListVOS = healthscoresMapper.selectHealthOverviewList(year, fieldId, beginTime, endTime);
+
+        if(CollectionUtil.isEmpty(overviewListVOS)){
+            log.warn("overviewListVOS 健康集合为null");
+            return null;
+        }
+
+        Set<String> eids = overviewListVOS.parallelStream().map(HealthOverviewListVO::getEngineId).collect(Collectors.toSet());
+        List<WindEngineGroupPO> list = getWindEngineGroupList(eids);
+        for(HealthOverviewListVO vo : overviewListVOS){
+            for(WindEngineGroupPO po : list){
+                if(vo.getEngineId().equals(po.getEngineId())){
+                    vo.setEngineName(po.getEngineName());
+                }
+            }
+        }
+
+        healthOverviewVO.setHealthOverviewListVOList(overviewListVOS);
+        return healthOverviewVO;
+    }
+
+
+    /**
+     * 查询风机对象集合
+     * @param eids
+     * @return
+     */
+    private List<WindEngineGroupPO> getWindEngineGroupList(Set<String> eids) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("master");
+        // 查询平台风机模块
+        Example example = new Example(WindEngineGroupPO.class);
+        Example.Criteria criteria = example.createCriteria();
+        criteria.andIn("engineId", eids);
+        return  windEngineGroupMapper.selectByExample(example);
+    }
+
+
+    @Override
+    public List<HealthscoresTendencyVO> getLastDaysTrend(int day, String fieldId, String engineId) {
+        // 1. 校验入参(非空)
+        if (Objects.isNull(fieldId) || fieldId.isEmpty() || Objects.isNull(engineId) || engineId.isEmpty()) {
+            throw new IllegalArgumentException("风场ID和风机ID不能为空");
+        }
+
+        // 1. 计算起止日期
+        LocalDate[] range = getLastNDaysRange(day);
+        LocalDate startDate = range[0];
+        LocalDate endDate = range[1];
+
+        // 3. 生成连续的365天日期序列(基础维度,确保每个日期都有记录)
+        List<LocalDate> allDates = generateContinuousDates(startDate, endDate);
+
+        // 4. 确定要查询的表名(按年份拆分,如healthscores_2025、healthscores_2026)
+        List<String> tableNames = getValidTableNames(startDate, endDate);
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+        // 3. 跨表查询数据
+        List<HealthscoresTendencyVO> hscoresLastays = healthscoresMapper.listHscoresLastays(fieldId, engineId, startDate, endDate, tableNames);
+
+        // 6. 封装已有数据到Map(key=日期,value=评分数据,方便快速匹配)
+        Map<LocalDate, HealthscoresTendencyVO> existDataMap = hscoresLastays.stream()
+                .collect(Collectors.toMap(
+                        HealthscoresTendencyVO::getSourceDatetime,
+                        data -> data,
+                        (oldVal, newVal) -> oldVal
+                ));
+
+        // 7. 补0处理:遍历所有日期,缺失则新建(所有评分字段默认0)
+        List<HealthscoresTendencyVO> finalResult = new ArrayList<>();
+        for (LocalDate date : allDates) {
+            HealthscoresTendencyVO score = existDataMap.getOrDefault(date, new HealthscoresTendencyVO(date));
+            // 补全风场/风机ID(前端展示用)
+            score.setFieldId(fieldId);
+            score.setEngineId(engineId);
+            finalResult.add(score);
+        }
+
+        return finalResult;
+    }
+
+
+    /**
+     * ====================== 当前接口使用日期工具 ======================
+     */
+
+    /**
+     * 给String类型的年月日拼接时分秒
+     *
+     * @param dateStr 年月日字符串(如 "2026-03-02")
+     * @param hour    小时
+     * @param minute  分钟
+     * @param second  秒
+     * @return 带时分秒的字符串(如 "2026-03-02 15:30:00")
+     */
+    private String appendTimeToString(String dateStr, int hour, int minute, int second) {
+        // 1. 解析为LocalDate(校验日期合法性)
+        LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER);
+        // 2. 拼接时分秒为LocalDateTime
+        LocalDateTime localDateTime = localDate.atTime(hour, minute, second);
+        // 3. 格式化为字符串
+        return localDateTime.format(DATETIME_FORMATTER);
+    }
+
+    /**
+     * 重载:获取昨天开始/结束时间的字符串格式
+     */
+    private String getYesterdayStartStr() {
+        return getYesterdayStart().format(DATETIME_FORMATTER);
+    }
+
+    private String getYesterdayEndStr() {
+        // 严格格式化为 23:59:59(去掉纳秒)
+        return getYesterdayEnd().format(DATETIME_FORMATTER).substring(0, 19);
+    }
+
+    /**
+     * 获取昨天的开始时间(yyyy-MM-dd 00:00:00)
+     *
+     * @return LocalDateTime
+     */
+    private LocalDateTime getYesterdayStart() {
+        // 1. 获取昨天的日期
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        // 2. 拼接 00:00:00 等价于 yesterday.atTime(0, 0, 0)
+        return yesterday.atStartOfDay();
+    }
+
+    /**
+     * 获取昨天的结束时间(yyyy-MM-dd 23:59:59)
+     *
+     * @return LocalDateTime
+     */
+    private LocalDateTime getYesterdayEnd() {
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        // 拼接 23:59:59
+        return yesterday.atTime(23, 59, 59);
+        // 若需严格的23:59:59,用:yesterday.atTime(23, 59, 59)
+    }
+
+    /**
+     * 获取近 N 天的开始、结束日期
+     * 参数days 为需要查几天的数据
+     */
+    private LocalDate[] getLastNDaysRange(int days) {
+        LocalDate endDate = LocalDate.now().minusDays(1);
+        LocalDate startDate = endDate.minusDays(days - 1);
+        return new LocalDate[]{startDate, endDate};
+    }
+
+    /**
+     * 获取日期范围内涉及的所有年份(最多2个)
+     */
+    private Set<Integer> getYearSet(LocalDate start, LocalDate end) {
+        return Stream.of(start.getYear(), end.getYear())
+                .collect(Collectors.toSet());
+    }
+
+    /**
+     * 生成连续的日期序列(Java8 Stream实现)
+     */
+    private List<LocalDate> generateContinuousDates(LocalDate start, LocalDate end) {
+        long days = java.time.temporal.ChronoUnit.DAYS.between(start, end);
+        return Stream.iterate(start, date -> date.plusDays(1))
+                .limit(days + 1) // +1 包含结束日期
+                .collect(Collectors.toList());
+    }
+
+
+    /**
+     * 获取合法的表名列表(防SQL注入,仅允许healthscores_+4位数字)
+     */
+    private List<String> getValidTableNames(LocalDate start, LocalDate end) {
+        Set<String> tableNames = new HashSet<>();
+        String tablePrefix = "healthscores_";
+
+        // 遍历日期范围的所有年份
+        int startYear = start.getYear();
+        int endYear = end.getYear();
+        for (int year = startYear; year <= endYear; year++) {
+            tableNames.add(tablePrefix + year);
+        }
+
+        // 严格校验表名格式(防SQL注入)
+        tableNames.forEach(name -> {
+            if (!name.matches("^healthscores_\\d{4}$")) {
+                throw new IllegalArgumentException("非法表名:" + name + "(仅允许healthscores_四位数字格式)");
+            }
+        });
+
+        return new ArrayList<>(tableNames);
+    }
+
+}

+ 21 - 0
src/main/java/com/energy/manage/analyse/service/wakediagnosis/WakeWindFarmService.java

@@ -0,0 +1,21 @@
+package com.energy.manage.analyse.service.wakediagnosis;
+
+import com.energy.manage.analyse.domain.vo.wakewindfarm.WakeWindFarmVO;
+
+/**
+ * 湍流尾流接口
+ */
+public interface WakeWindFarmService {
+
+
+    /**
+     * 查询尾流数据信息
+     * @param fieldCode
+     * @param datatime
+     * @return
+     */
+    WakeWindFarmVO getWakeWindFarm(String fieldCode, String datatime);
+
+
+
+}

+ 174 - 0
src/main/java/com/energy/manage/analyse/service/wakediagnosis/impl/WakeWindFarmServiceImpl.java

@@ -0,0 +1,174 @@
+package com.energy.manage.analyse.service.wakediagnosis.impl;
+
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.energy.manage.analyse.domain.vo.healthscores.HealthOverviewListVO;
+import com.energy.manage.analyse.domain.vo.wakewindfarm.WakeTurbineVO;
+import com.energy.manage.analyse.domain.vo.wakewindfarm.WakeWindFarmVO;
+import com.energy.manage.analyse.mappers.wakediagnosis.WakeWindFarmMapper;
+import com.energy.manage.analyse.mappers.windenginegroup.WindEngineGroupMapper;
+import com.energy.manage.analyse.mappers.windfield.WindFieldMapper;
+import com.energy.manage.analyse.po.wakediagnosis.WakeTurbinePO;
+import com.energy.manage.analyse.po.windenginegroup.WindEngineGroupPO;
+import com.energy.manage.analyse.po.windfield.WindFieldPO;
+import com.energy.manage.analyse.service.wakediagnosis.WakeWindFarmService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Example;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class WakeWindFarmServiceImpl implements WakeWindFarmService {
+
+    @Autowired
+    private WindFieldMapper windFieldMapper;
+
+    @Autowired
+    private WakeWindFarmMapper wakeWindFarmMapper;
+
+    @Autowired
+    private WindEngineGroupMapper windEngineGroupMapper;
+
+    // 通用日期格式化器(线程安全,可全局复用)
+    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    @Override
+    public WakeWindFarmVO getWakeWindFarm(String fieldCode, String datatime) {
+
+        String fieldId = null;
+        WindFieldPO windFieldPO = getWindField(fieldCode);
+        if (!StringUtils.isEmpty(fieldCode)) {
+            fieldId = windFieldPO.getFieldId();
+        }
+
+        if (fieldId == null) {
+            log.warn(" 健康检测大唐内部风场编号没有对应台账fieldId  ");
+            return null;
+        }
+
+        String beginTime = null;
+        String endTime = null;
+        if (!StringUtils.isEmpty(datatime)) {
+            beginTime = appendTimeToString(datatime, 00, 00, 00);
+            endTime = appendTimeToString(datatime, 23, 59, 59);
+        } else {
+            beginTime = getYesterdayStartStr();
+            endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
+        }
+
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("slave");
+
+        WakeWindFarmVO wakeWindFarmVO = wakeWindFarmMapper.selectWakeWindfarmAndFieldId(fieldId,beginTime,endTime);
+
+        String year = String.valueOf(LocalDate.now().getYear());
+        List<WakeTurbineVO> wakeTurbinePOList =  wakeWindFarmMapper.selectWakeTurbineAndFieldId(year, fieldId, beginTime, endTime);
+
+        Set<String> eids = wakeTurbinePOList.parallelStream().map(WakeTurbineVO::getEngineId).collect(Collectors.toSet());
+        List<WindEngineGroupPO> list = getWindEngineGroupList(eids);
+        for(WakeTurbineVO vo : wakeTurbinePOList){
+            for(WindEngineGroupPO po : list){
+                if(vo.getEngineId().equals(po.getEngineId())){
+                    vo.setEngineName(po.getEngineName());
+                }
+            }
+        }
+
+        wakeWindFarmVO.setGetWakeTurbineList(wakeTurbinePOList);
+        return wakeWindFarmVO;
+    }
+
+
+    /**
+     * 查询风机对象集合
+     * @param eids
+     * @return
+     */
+    private List<WindEngineGroupPO> getWindEngineGroupList(Set<String> eids) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("master");
+        // 查询平台风机模块
+        Example example = new Example(WindEngineGroupPO.class);
+        Example.Criteria criteria = example.createCriteria();
+        criteria.andIn("engineId", eids);
+        return  windEngineGroupMapper.selectByExample(example);
+    }
+
+    private WindFieldPO getWindField(String fieldCode) {
+        // 清除当前
+        DynamicDataSourceContextHolder.poll();
+        // 切换数据源
+        DynamicDataSourceContextHolder.push("master");
+        WindFieldPO windFieldPO = null;
+        if (!StringUtils.isEmpty(fieldCode)) {
+            WindFieldPO po = new WindFieldPO();
+            po.setFieldCode(fieldCode);
+            windFieldPO = windFieldMapper.selectOne(po);
+        }
+        return windFieldPO;
+    }
+
+    /**
+     * 给String类型的年月日拼接时分秒
+     *
+     * @param dateStr 年月日字符串(如 "2026-03-02")
+     * @param hour    小时
+     * @param minute  分钟
+     * @param second  秒
+     * @return 带时分秒的字符串(如 "2026-03-02 15:30:00")
+     */
+    private String appendTimeToString(String dateStr, int hour, int minute, int second) {
+        // 1. 解析为LocalDate(校验日期合法性)
+        LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER);
+        // 2. 拼接时分秒为LocalDateTime
+        LocalDateTime localDateTime = localDate.atTime(hour, minute, second);
+        // 3. 格式化为字符串
+        return localDateTime.format(DATETIME_FORMATTER);
+    }
+
+    /**
+     * 重载:获取昨天开始/结束时间的字符串格式
+     */
+    private String getYesterdayStartStr() {
+        return getYesterdayStart().format(DATETIME_FORMATTER);
+    }
+
+    /**
+     * 获取昨天的开始时间(yyyy-MM-dd 00:00:00)
+     *
+     * @return LocalDateTime
+     */
+    private LocalDateTime getYesterdayStart() {
+        // 1. 获取昨天的日期
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        // 2. 拼接 00:00:00 等价于 yesterday.atTime(0, 0, 0)
+        return yesterday.atStartOfDay();
+    }
+
+
+    /**
+     * 获取昨天的结束时间(yyyy-MM-dd 23:59:59)
+     *
+     * @return LocalDateTime
+     */
+    private LocalDateTime getYesterdayEnd() {
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        // 拼接 23:59:59
+        return yesterday.atTime(23, 59, 59);
+        // 若需严格的23:59:59,用:yesterday.atTime(23, 59, 59)
+    }
+
+}

+ 35 - 0
src/main/resources/application.properties

@@ -0,0 +1,35 @@
+#============================应用配置=========================================
+# 项目环境
+spring.profiles.active = @profiles.active@
+# 应用名称
+spring.application.name = energy-manage-analyse-service
+#=============================tomcat配置=======================================
+
+# 上下文路径
+server.servlet.context-path = /energy-manage-analyse-service/
+#uri编码格式
+server.tomcat.uri-encoding = UTF-8
+# 最大连接数
+server.tomcat.max-connections=100000
+# 最小空闲线程数
+server.tomcat.threads.min-spare=100
+# 最大线程数
+server.tomcat.threads.max=800
+# 当tomcat启动线程达到最大时,允许的最大排队请求个数
+server.tomcat.accept-count = 1000
+# server.tomcat.basedir = /opt/projecttmp
+server.maxHttpHeaderSize = 8192
+#请求数据量
+server.tomcat.max-http-form-post-size = 200MB
+#超时时间
+server.tomcat.connection-timeout = 180000
+#=============================日志配置=======================================
+# 日志路径(环境)
+path.log = @profiles.active@
+# debug - sql显示
+logging.level.com.energy.manage.service.mappers= debug
+
+#=============================banner配置=======================================
+#banner路径
+spring.banner.location=classpath:banner/banner.txt
+

+ 22 - 0
src/main/resources/banner/banner.txt

@@ -0,0 +1,22 @@
+-- Created by shiyue
+
+                                       _ooOoo_
+                                      o8888888o
+                                      88" . "88
+                                      (| -_- |)
+                                      O\  =  /O
+                                   ____/`---'\____
+                                 .'  \\|     |//  `.
+                                /  \\|||  :  |||//  \
+                               /  _||||| -:- |||||-  \
+                               |   | \\\  -  /// |   |
+                               | \_|  ''\---/''  |   |
+                               \  .-\__  `-`  ___/-. /
+                             ___`. .'  /--.--\  `. . __
+                          ."" '<  `.___\_<|>_/___.'  >'"".
+                         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
+                         \  \ `-.   \_ __\ /__ _/   .-` /  /
+                    ======`-.____`-.___\_____/___.-`____.-'======
+                                       `=---='
+                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+                             佛祖保佑               永无BUG

+ 38 - 0
src/main/resources/bootstrap.properties

@@ -0,0 +1,38 @@
+#============================nacos配置=========================================
+spring.cloud.nacos.config.server-addr = 192.168.50.234:8848
+spring.cloud.nacos.config.namespace = 79c42a7a-2c7d-4dcf-8a2c-b334271e2191
+spring.cloud.nacos.config.name=application.properties
+spring.cloud.nacos.config.group = @profiles.active@
+#============================mybatis配置=========================================
+#扫描mapper.xml
+mybatis.mapper-locations = classpath*:mybatis/**/*.xml
+mybatis.type-aliases-package = com.energy.manage.analyse.po
+mybatis.configuration.mapUnderscoreToCamelCase = true
+#sql打印F
+mybatis.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl
+#mappers 多个接口时逗号隔开
+mapper.mappers = com.energy.manage.analyse.common.mapper.MyMapper
+mapper.not-empty =false
+mapper.identity = MYSQL
+#分页
+pagehelper.helperDialect = mysql
+pagehelper.reasonable = true
+pagehelper.supportMethodsArguments = true
+
+#============================swagger配置=========================================
+#http://localhost:16200/energy-manage-service/doc.html
+knife4j.enable=true
+
+#============================文件上传配置=========================================
+# 自定义配置文件上传
+spring.servlet.multipart.enabled = true
+spring.servlet.multipart.max-file-size = 314572800
+spring.servlet.multipart.max-request-size= 1048576000
+
+#============================json配置=========================================
+# 全局时间格式转化
+#spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+#spring.jackson.time-zone=GMT+8
+spring.jackson.date-format = yyyy-MM-dd HH:mm
+spring.jackson.time-zone= GMT+8
+spring.jackson.serialization.write-dates-as-timestamps=true

+ 239 - 0
src/main/resources/confback/README.MD

@@ -0,0 +1,239 @@
+# 风电机组发电性能分析算法
+    用于与风电机组发电性能分析系统集成,算法版本v1.2
+
+## 名词/术语
+    index: 表示数组索引
+    分析类型: 表示 针对风电机组发电性能的不同分析,例如:静态偏航误差、功率曲线散点分析、变桨功率分析等
+    直驱风电机组: 无齿轮箱
+    半直驱风电机组:有齿轮箱且结构较双馈风电机组简单
+    双馈风电机组: 有齿轮箱且结构较半直驱风电机组复杂
+    非直驱风电机组: 有齿轮箱,包括:半直驱风电机组、双馈风电机组
+
+## 风电机组发电性能分析类型
+### 分析类型列表
+|    分析类型名称|        包名|         类名|    方法名|
+|------------|------------|------------|------------|
+|数据情况||||
+|机组分钟级SCADA数据记录完整度分析|algorithm.dataIntegrityOfMinuteAnalyst|DataIntegrityOfMinuteAnalyst|executeAnalysis|
+|秒级SCADA数据记录完整度分析|algorithm.dataIntegrityOfSecondAnalyst|DataIntegrityOfSecondAnalyst|executeAnalysis|
+|风资源分析||||
+|机组风速频率分析|algorithm.windSpeedFrequencyAnalyst|WindSpeedFrequencyAnalyst|executeAnalysis|
+|机组风向玫瑰分析|algorithm.windDirectionFrequencyAnalyst|WindDirectionFrequencyAnalyst|executeAnalysis|
+|机组风速均值分析|algorithm.windSpeedAnalyst|WindSpeedAnalyst|executeAnalysis|
+|功率曲线分析||||
+|机组有功功率曲线分析|algorithm.powerCurveAnalyst|PowerCurveAnalyst|executeAnalysis|
+|机组逐月有功功率散点2D分析|algorithm.powerScatter2DAnalyst|PowerScatter2DAnalyst|executeAnalysis|
+|机组逐月有功功率散点3D分析|algorithm.powerScatterAnalyst|PowerScatterAnalyst|executeAnalysis|
+|额定功率分析||||
+|机组额定功率和风速分析|algorithm.ratedPowerWindSpeedAnalyst|RatedPowerWindSpeedAnalyst|executeAnalysis|
+|机组额定风速分析|algorithm.ratedWindSpeedAnalyst|RatedWindSpeedAnalyst|executeAnalysis|
+|性能特性分析||||
+|机组风能利用系数和有功功率分析|algorithm.cpAnalyst|CpAnalyst|executeAnalysis|
+|机组风能利用系数和风速分析|algorithm.cpWindSpeedAnalyst|CpWindSpeedAnalyst|executeAnalysis|
+|机组风能利用系数时序分析|algorithm.cpTrendAnalyst|CpTrendAnalyst|executeAnalysis|
+|机组叶尖速比和有功功率分析|algorithm.tsrAnalyst|TSRAnalyst|executeAnalysis|
+|机组叶尖速比和风速分析|algorithm.tsrWindSpeedAnalyst|TSRWindSpeedAnalyst|executeAnalysis|
+|机组叶尖速比时序分析|algorithm.tsrTrendAnalyst|TSRTrendAnalyst|executeAnalysis|
+|机组发电机转速和有功功率分析|algorithm.generatorSpeedPowerAnalyst|GeneratorSpeedPowerAnalyst|executeAnalysis|
+|机组发电机转速和转矩分析|algorithm.generatorSpeedTorqueAnalyst|GeneratorSpeedTorqueAnalyst|executeAnalysis|
+|静态偏航误差分析||||
+|机组静态偏航误差分析|algorithm.yawErrorAnalyst|YawErrorAnalyst|executeAnalysis|
+|变桨特性分析||||
+|机组最小桨距角分析|algorithm.minPitchAnalyst|MinPitchAnalyst|executeAnalysis|
+|变桨-转速-转矩(功率)协调分析||||
+|机组变桨和有功功率协调性分析|algorithm.pitchPowerAnalyst|PitchPowerAnalyst|executeAnalysis|
+|机组变桨和发电机转速协调性分析|algorithm.pitchGeneratorSpeedAnalyst|PitchGeneratorSpeedAnalyst|executeAnalysis|
+|机组变桨和有功功率及风速分析|algorithm.pitchPowerWindSpeedAnalyst|PitchPowerWindSpeedAnalyst|executeAnalysis|
+|温度传感器性能分析||||
+|机组环境温度传感器分析|algorithm.temperatureEnvironmentAnalyst|TemperatureEnvironmentAnalyst|executeAnalysis|
+|机组大部件温度传感器分析|algorithm.temperatureLargeComponentsAnalyst|TemperatureLargeComponentsAnalyst|executeAnalysis|
+|尚未归类的分析类型||||
+|机组功率震荡分析|algorithm.powerOscillationAnalyst|PowerOscillationAnalyst|executeAnalysis|
+|机组变桨和叶尖速比及风能利用系数分析|algorithm.pitchTSRCpAnalyst|PitchTSRCpAnalyst|executeAnalysis|
+|机组机舱振动风向玫瑰振动散点分析|algorithm.cabinVibrateAnalyst|CabinVibrateAnalyst|executeAnalysis|
+
+## 数据契约
+### 输入数据契约
+
+#### 说明
+    键 dataContractType 表示 数据契约类型说明
+    键 dataContractType.type 表示 数据契约类型,其值数据类型为字符串且非空,值 GenerationAnalysisOfTurbine 为风电机组发电分析
+    键 dataContractType.version 表示 数据契约类型版本,其值数据类型为字符串且非空,值 1.2.0 为 用于与风电机组发电性能分析系统集成
+
+
+    键 dataContract 表示 数据契约说明
+    键 dataContract.autoOrManual 表示 区分调用来源是自动触发,还是人工触发,其值数据类型为字符串且非空,枚举值:automatic、manual,值:automatic 表示自动触发;manual 表示人工触发;
+    键 dataContract.dataSource 表示 分析使用数据源,其值数据类型为对象且非空
+    键 dataContract.dataSource.scada 表示 分析使用scada数据的数据源,其值数据类型为字符串且非空,枚举值:minute、second、all,值: minute 用于人工分析场景,指定分析类型使用scada分钟级数据;seconde 用于人工分析场景,指定分析类型使用scada秒级数据;all 用于自动分析场景,分析类型按自身设计使用scada数据进行分析;
+
+    键 dataContract.dataFilter 表示 数据筛选
+    键 dataContract.dataFilter.powerFarmID 表示 电场编号, 其值数据类型为字符串且非空
+    键 dataContract.dataFilter.turbines 表示 发电设备(风电机组等)编号信息, 其值数据类型为数组且非空
+    键 dataContract.dataFilter.beginTime 表示 数据开始时间, 其值数据类型为字符串,格式:yyyy-MM-dd hh:mm:ss 当值为null时不进行当前数据批次数据进行开始时间筛选
+    键 dataContract.dataFilter.beginTime 表示 数据开始时间, 其值数据类型为字符串,格式:yyyy-MM-dd hh:mm:ss 当值为null时不进行当前数据批次数据进行开始时间筛选
+    键 dataContract.dataFilter.endTime 表示 数据截止时间, 其值数据类型为字符串,格式:yyyy-MM-dd hh:mm:ss 当值为null时不进行当前数据批次数据进行截止时间筛选
+    键 dataContract.dataFilter.excludingMonths 表示 排除指定月份数据, 其值数据类型为数组,格式:yyyy-MM 当值为null时不排除指定月份数据
+
+    键 dataContract.dataFilter.customFilter 表示 自定义scada数据测点筛选, 其值数据类型为对象 ,当值为null时不进行自定义筛选
+    键 dataContract.dataFilter.customFilter.valueWindSpeed 表示 自定义scada数据风速测点筛选, 其值数据类型为对象 ,当值为null时不进行风速测点的自定义筛选
+    键 dataContract.dataFilter.customFilter.valueWindSpeed.min 表示 自定义scada数据风速测点最小值筛选, 其值数据类型为数值 ,当值为null时不进行风速测点最小值的自定义筛选
+    键 dataContract.dataFilter.customFilter.valueWindSpeed.max 表示 自定义scada数据风速测点最大值筛选, 其值数据类型为数值 ,当值为null时不进行风速测点最大值的自定义筛选
+
+    键 dataContract.dataFilter.customFilter.valuePitchAngle 表示 自定义scada数据桨距角测点筛选, 其值数据类型为对象 ,当值为null时不进行桨距角测点的自定义筛选
+    键 dataContract.dataFilter.customFilter.valuePitchAngle.min 表示 自定义scada数据桨距角测点最小值筛选, 其值数据类型为数值 ,当值为null时不进行桨距角测点最小值的自定义筛选
+    键 dataContract.dataFilter.customFilter.valuePitchAngle.max 表示 自定义scada数据桨距角测点最大值筛选, 其值数据类型为数值 ,当值为null时不进行桨距角测点最大值的自定义筛选
+
+    键 dataContract.dataFilter.customFilter.valueActivePower 表示 自定义scada数据有功功率测点筛选, 其值数据类型为对象 ,当值为null时不进行有功功率测点的自定义筛选
+    键 dataContract.dataFilter.customFilter.valueActivePower.min 表示 自定义scada数据有功功率测点最小值筛选, 其值数据类型为数值 ,当值为null时不进行有功功率测点最小值的自定义筛选
+    键 dataContract.dataFilter.customFilter.valueActivePower.max 表示 自定义scada数据有功功率测点最大值筛选, 其值数据类型为数值 ,当值为null时不进行有功功率测点最大值的自定义筛选
+
+    键 dataContract.dataFilter.customFilter.valueGeneratorSpeed 表示 自定义scada数据发电机转速测点筛选, 其值数据类型为对象 ,当值为null时不进行发电机转速测点的自定义筛选
+    键 dataContract.dataFilter.customFilter.valueGeneratorSpeed.min 表示 自定义scada数据发电机转速测点最小值筛选, 其值数据类型为数值 ,当值为null时不进行发电机转速测点最小值的自定义筛选
+    键 dataContract.dataFilter.customFilter.valueGeneratorSpeed.max 表示 自定义scada数据发电机转速测点最大值筛选, 其值数据类型为数值 ,当值为null时不进行发电机转速测点最大值的自定义筛选
+    
+
+    键 dataContract.configAnalysis 表示 分析类型配置,其值数据类型为数组,且非空,至少包含一个分析类型
+    键 dataContract.configAnalysis[index].package 表示 分析类型的包名,其值数据类型为字符串且非空
+    键 dataContract.configAnalysis[index].className 表示 分析类型的类名,其值数据类型为字符串且非空
+    键 dataContract.configAnalysis[index].methodName 表示 分析类型的类方法名,其值数据类型为字符串且非空
+    键 dataContract.configAnalysis[index].analysisReustCode 表示 分析结果编码,其值数据类型为数组且非空
+
+    键 dataContract.graphSets 表示 分析输出图形配置,其值数据类型为对象,且非空
+    键 dataContract.graphSets.generatorSpeed 表示 发电机转速轴系设置,其值数据类型为对象且非空
+    键 dataContract.graphSets.generatorSpeed.step 表示 发电机转速轴系的步长设置,其值数据类型为数值且非空,默认值: 非直驱风电机组为200;直驱风电机组为5;
+    键 dataContract.graphSets.generatorSpeed.min 表示 发电机转速轴系的最小值设置,其值数据类型为数值且非空,默认值: 非直驱风电机组为1000;直驱风电机组为0;
+    键 dataContract.graphSets.generatorSpeed.max 表示 发电机转速轴系的最大值设置,其值数据类型为数值且非空,默认值:非直驱风电机组为2000;直驱风电机组为30;
+
+    键 dataContract.graphSets.generatorTorque 表示 发电机转矩轴系设置,其值数据类型为对象且非空
+    键 dataContract.graphSets.generatorTorque.step 表示 发电机转矩轴系的步长设置,其值数据类型为数值且非空,默认值: 2000;
+    键 dataContract.graphSets.generatorTorque.min 表示 发电机转矩轴系的最小值设置,其值数据类型为数值且非空,默认值:0;
+    键 dataContract.graphSets.generatorTorque.max 表示 发电机转矩轴系的最大值设置,其值数据类型为数值且非空,默认值:12000;
+
+    键 dataContract.graphSets.cp 表示 风能利用系数轴系设置,其值数据类型为对象且非空
+    键 dataContract.graphSets.cp.step 表示 风能利用系数轴系的步长设置,其值数据类型为数值且非空,默认值: 0.5;
+    键 dataContract.graphSets.cp.min 表示 风能利用系数轴系的最小值设置,其值数据类型为数值且非空,默认值:0;
+    键 dataContract.graphSets.cp.max 表示 风能利用系数轴系的最大值设置,其值数据类型为数值且非空,默认值:2;
+
+    键 dataContract.graphSets.tsr 表示 叶尖速比轴系设置,其值数据类型为对象且非空
+    键 dataContract.graphSets.tsr.step 表示 叶尖速比轴系的步长设置,其值数据类型为数值且非空,默认值: 5;
+    键 dataContract.graphSets.tsr.min 表示 叶尖速比轴系的最小值设置,其值数据类型为数值且非空,默认值:0;
+    键 dataContract.graphSets.tsr.max 表示 叶尖速比轴系的最大值设置,其值数据类型为数值且非空,默认值:30;
+
+    键 dataContract.graphSets.pitchAngle 表示 桨距角轴系设置,其值数据类型为对象且非空
+    键 dataContract.graphSets.pitchAngle.step 表示 桨距角轴系的步长设置,其值数据类型为数值且非空,默认值: 2
+    键 dataContract.graphSets.pitchAngle.min 表示 桨距角轴系的最小值设置,其值数据类型为数值且非空,默认值:-1;
+    键 dataContract.graphSets.pitchAngle.max 表示 桨距角轴系的最大值设置,其值数据类型为数值且非空,默认值:20;
+
+    键 dataContract.graphSets.activePower 表示 有功功率轴系设置,其值数据类型为对象且非空
+    键 dataContract.graphSets.activePower.step 表示 有功功率轴系的步长设置,其值数据类型为数值且非空,默认值: 250;
+    键 dataContract.graphSets.activePower.min 表示 发有功功率轴系的最小值设置,其值数据类型为数值且非空,默认值:0;
+    键 dataContract.graphSets.activePower.max 表示 有功功率轴系的最大值设置,其值数据类型为数值且非空,默认值:额定功率*1.2;
+
+  #### 示例:
+    ```
+    {
+        "dataContractType": {
+            "type": "analysisExecuteOrder",
+            "version": "1.2.0"
+        },
+        "dataContract": {
+            "autoOrManual":"automatic",
+            "dataSource": {
+                "scada": "second"
+            },
+            "dataFilter": {
+                "powerFarmID": "010-00001",
+                "turbines": [
+                    "010-00001-0001",
+                    "010-00001-0002"
+                ],
+                "dataBatchNum": "B2024042211-0",
+                "beginTime": "2023-01-01 00:00:00",
+                "endTime": "2023-12-31 23:59:59",
+                "excludingMonths": [
+                    "2023-12",
+                    "2023-09"
+                ],
+                "customFilter": {
+                    "valueWindSpeed": {
+                        "min": 3.0,
+                        "max": 25.0
+                    },
+                    "valuePitchAngle": {
+                        "min": 2,
+                        "max": null
+                    },
+                    "valueActivePower": {
+                        "min": 10,
+                        "max": 2500
+                    },
+                    "valueGeneratorSpeed": {
+                        "min": 10,
+                        "max": 2500
+                    }
+                }
+            },
+            "configAnalysis": [
+                {
+                    "package": "algorithm.powerCurveAnalyst",
+                    "className": "PowerCurveAnalyst",
+                    "methodName": "executeAnalysis"
+                },
+                {
+                    "package": "algorithm.powerScatter2DAnalyst",
+                    "className": "PowerScatter2DAnayst",
+                    "methodName": "executeAnalysis"
+                },
+                {
+                    "package": "algorithm.powerScatterAnalyst",
+                    "className": "PowerScatterAnalyst",
+                    "methodName": "executeAnalysis"
+                },
+                {
+                    "package": "algorithm.windSpeedFrequencyAnalyst",
+                    "className": "WindSpeedFrequencyAnalyst",
+                    "methodName": "executeAnalysis"
+                },
+                {
+                    "package": "algorithm.generatorSpeedPowerAnalyst",
+                    "className": "GeneratorSpeedPowerAnalyst",
+                    "methodName": "executeAnalysis"
+                }
+            ],
+            "graphSets": {
+                "generatorSpeed": {
+                    "step": 200,
+                    "min": 1000,
+                    "max": 2000
+                },
+                "generatorTorque": {
+                    "step": 2000,
+                    "min": 0,
+                    "max": 12000
+                },
+                "cp": {
+                    "step": 0.5,
+                    "min": 0,
+                    "max": 2
+                },
+                "tsr": {
+                    "step": 5,
+                    "min": 0,
+                    "max": 30
+                },
+                "pitchAngle": {
+                    "step": 1,
+                    "min": -1,
+                    "max": 20
+                },
+                "activePower": {
+                    "step": 250,
+                    "min": 0,
+                    "max": 2000
+                }
+            }
+        }
+    }
+    ```
+
+### 返回数据锲约

+ 134 - 0
src/main/resources/confback/application-prod.properties

@@ -0,0 +1,134 @@
+#接口访问
+#http://localhost:16200/energy-manage-service/doc.html
+######################自定义配置文件######################
+# 日志路径(环境)
+path.log = @profiles.active@
+spring.banner.location=classpath:banner/banner.txt
+
+server.port = 16200
+server.servlet.context-path = /energy-manage-service/
+server.tomcat.uri-encoding = UTF-8
+# 最大连接数
+server.tomcat.max-connections=100000
+# 最小空闲线程数
+server.tomcat.threads.min-spare=100
+# 最大线程数
+server.tomcat.threads.max=800
+# 当tomcat启动线程达到最大时,允许的最大排队请求个数
+server.tomcat.accept-count = 1000
+# server.tomcat.basedir = /opt/projecttmp
+server.maxHttpHeaderSize = 8192
+#请求数据量
+server.tomcat.max-http-form-post-size = 200MB
+#超时时间
+server.tomcat.connection-timeout = 180000
+# 应用名称
+spring.application.name = energy-manage-service
+# 自定义配置文件上传
+spring.servlet.multipart.max-file-size = 314572800
+spring.servlet.multipart.max-request-size= 1048576000
+# 全局时间格式转化
+#spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+#spring.jackson.time-zone=GMT+8
+spring.jackson.serialization.write-dates-as-timestamps=true
+# 指定开发环境-由maven控制多环境
+spring.profiles.active = @profiles.active@
+
+#数据库设置
+spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
+#spring.datasource.druid.driver-class-name = com.mysql.jdbc.Driver
+spring.datasource.druid.driver-class-name = com.mysql.cj.jdbc.Driver
+spring.datasource.druid.url = jdbc:mysql://127.0.0.1:3306/energy?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
+spring.datasource.druid.username = root
+spring.datasource.druid.password = shiyue
+#初始化大小
+spring.datasource.druid.initial-size = 30
+#最小
+spring.datasource.druid.min-idle = 20
+#最大
+spring.datasource.druid.max-active = 300
+#获取连接等待的超时时间
+spring.datasource.druid.max-wait = 600000
+#间隔多久进行一次检测,检测需要关闭的链接
+spring.datasource.druid.time-between-eviction-runs-millis = 60000
+#一个链接在池中最小生存时间
+spring.datasource.druid.min-evictable-idle-time-millis = 3000000
+##配置连接在池中的最大生存时间
+#spring.datasource.druid.max-evictable-idle-time-millis = 400000
+spring.datasource.druid.validation-query = SELECT 'x'
+spring.datasource.druid.test-on-borrow = false
+spring.datasource.druid.test-on-return = false
+## 启用空闲连接检测,以便回收
+spring.datasource.druid.test-while-idle = true
+## 打开PSCache,并且指定每个连接上PSCache的大小
+spring.datasource.druid.pool-prepared-statements = false
+spring.datasource.druid.max-pool-prepared-statement-per-connection-size = 20
+spring.datasource.druid.remove-abandoned = true
+spring.datasource.druid.remove-abandoned-timeout = 7200
+spring.datasource.druid.log-abandoned = false
+
+#Mybatis
+mybatis.mapper-locations = classpath*:mybatis/**/*.xml
+mybatis.type-aliases-package = com.energy.manage.common.po
+mybatis.configuration.mapUnderscoreToCamelCase = true
+
+#mappers 多个接口时逗号隔开
+mapper.mappers = com.energy.manage.common.mapper.MyMapper
+mapper.not-empty =false
+mapper.identity = MYSQL
+
+#pagehelper
+pagehelper.helperDialect = mysql
+pagehelper.reasonable = true
+pagehelper.supportMethodsArguments = true
+
+#redis-config
+spring.redis.jedis.pool.max-idle = 100
+spring.redis.jedis.pool.min-idle = 10
+spring.redis.jedis.pool.max-active = 1000
+spring.redis.jedis.pool.max-wait = 100000
+spring.redis.database = 1
+spring.redis.host = 127.0.0.1
+spring.redis.port = 6379
+spring.redis.password = 123456
+
+# debug - sql显示
+logging.level.com.energy.manage.service.mappers= debug
+
+# 接口文档
+knife4j.enable=true
+
+#xxl-job
+#xxl.job.admin.addresses = http://192.168.50.241:16800/xxl-job-admin
+#xxl.job.accessToken =
+#xxl.job.executor.appname = xxl-job-executor-sample
+#xxl.job.executor.address =
+#xxl.job.executor.ip =
+#xxl.job.executor.port = 9999
+#xxl.job.executor.logpath = /Users/shiyue/Downloads/logs/xxl
+#xxl.job.executor.logretentiondays = 30
+
+
+#kafka
+spring.kafka.bootstrap-servers=127.0.0.1:9092
+spring.kafka.producer.batch-size=16384
+spring.kafka.producer.acks=all
+spring.kafka.producer.retries=3
+
+#消费者
+spring.kafka.consumer.bootstrapServers=127.0.0.1:9092
+#spring.kafka.consumer.topics=xxxx
+spring.kafka.consumer.groupId=energy-manage
+spring.kafka.consumer.sessionTimeOut=30000
+spring.kafka.consumer.enableAutoCommit=false
+spring.kafka.consumer.autoCommitInterval=1000
+spring.kafka.consumer.maxPollRecords=50
+spring.kafka.consumer.maxPollInterval=300000
+spring.kafka.consumer.keyDeserializer=org.apache.kafka.common.serialization.StringDeserializer
+spring.kafka.consumer.valueDeserializer=org.apache.kafka.common.serialization.StringDeserializer
+spring.kafka.consumer.autoOffsetReset=latest
+spring.kafka.consumer.heartbeatInterval=10000
+
+#监听
+spring.kafka.listener.type=batch
+spring.kafka.listener.ack-mode=batch

+ 50 - 0
src/main/resources/confback/bootstrap.properties

@@ -0,0 +1,50 @@
+#大唐部署环境
+#============================nacos配置=========================================
+spring.cloud.nacos.config.server-addr = 127.0.0.1:8848
+spring.cloud.nacos.config.namespace = 625e87f5-ead5-4867-8aa5-cb855949b2a3
+spring.cloud.nacos.config.name=application.properties
+spring.cloud.nacos.config.group = @profiles.active@
+spring.cloud.nacos.config.extension-configs[0].data-id=analysis_type_config.properties
+spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
+spring.cloud.nacos.config.extension-configs[0].refresh=true
+
+
+#============================mybatis配置=========================================
+#扫描mapper.xml
+mybatis.mapper-locations = classpath*:mybatis/**/*.xml
+mybatis.type-aliases-package = com.energy.manage.common.po
+mybatis.configuration.mapUnderscoreToCamelCase = true
+#sql打印
+mybatis.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl
+#mappers 多个接口时逗号隔开
+mapper.mappers = com.energy.manage.common.mapper.MyMapper
+mapper.not-empty =false
+mapper.identity = MYSQL
+#分页
+pagehelper.helperDialect = mysql
+pagehelper.reasonable = true
+pagehelper.supportMethodsArguments = true
+
+#============================swagger配置=========================================
+#http://localhost:16200/energy-manage-service/doc.html
+knife4j.enable=true
+
+#============================文件上传配置=========================================
+# 自定义配置文件上传
+spring.servlet.multipart.enabled = true
+spring.servlet.multipart.max-file-size = 314572800
+spring.servlet.multipart.max-request-size= 1048576000
+
+#============================json配置=========================================
+# 全局时间格式转化
+#spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+#spring.jackson.time-zone=GMT+8
+spring.jackson.date-format = yyyy-MM-dd HH:mm
+spring.jackson.time-zone= GMT+8
+spring.jackson.serialization.write-dates-as-timestamps=true
+
+#============================登录拦截器配置=========================================
+#拦截器是否生效
+energy.login.enabled=true
+
+

+ 13 - 0
src/main/resources/logback.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:noNamespaceSchemaLocation="http://www.padual.com/java/logback.xsd">
+
+    <property resource="application.properties"/>
+    <springProperty scope="context" name="path.log" source="path.log"/>
+
+    <!-- 日志最大的历史 30天 -->
+    <property name="maxHistory" value="30"/>
+    <property name="maxFileSize" value="64 MB"/>
+    <include resource="logback/logback-${path.log}.xml"/>
+
+</configuration>

+ 162 - 0
src/main/resources/logback/logback-analyse.xml

@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<included>
+    <!-- 定义日志文件 输入位置 -->
+    <springProperty name="log_dir" source="logging.path" defaultValue="./logs"/>
+    <property name="log.pattern"
+              value="%d{yyyy-MM-dd HH:mm:ss.SSS} %X{THREAD_NOTE} [%thread] %-5level %logger - %msg%n"/>
+    <property name="log.maxHistory" value="90" />
+
+    <!--# Console -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- 典型的日志pattern -->
+        <encoder>
+            <pattern>[%-5level %d{HH:mm:ss.SSS} | %X{THREAD_NOTE} | %thread | %logger.%method] [%L] - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+    </appender>
+
+    <!-- ERROR级别日志 -->
+    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->
+    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录WARN级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+
+        <!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志输出位置  可相对、和绝对路径 -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/error.log</fileNamePattern>
+            <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,
+            则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
+            <maxHistory>${log.maxHistory}</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <!-- WARN级别日志 appender -->
+    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录WARN级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>WARN</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+
+
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/warn.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+        </rollingPolicy>
+
+    </appender>
+
+    <!-- INFO级别日志 appender -->
+    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录INFO级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/info.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+        </rollingPolicy>
+
+
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!-- DEBUG级别日志 appender -->
+    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录DEBUG级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>DEBUG</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/debug.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+            >
+        </rollingPolicy>
+
+    </appender>
+
+    <!-- TRACE级别日志 appender -->
+    <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录ERROR级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>TRACE</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/trace.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+
+        </rollingPolicy>
+        >
+    </appender>
+
+    <!--myibatis log configure-->
+    <logger name="com.apache.ibatis" level="TRACE"/>
+    <logger name="java.sql.Connection" level="DEBUG"/>
+    <logger name="java.sql.Statement" level="DEBUG"/>
+    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
+
+    <!-- root级别   DEBUG -->
+    <root level="INFO">
+        <!-- 控制台输出 STDOUT-->
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="DEBUG"/>
+        <!-- 文件输出 -->
+        <appender-ref ref="ERROR"/>
+        <appender-ref ref="INFO"/>
+        <appender-ref ref="WARN"/>
+        <appender-ref ref="DEBUG"/>
+        <appender-ref ref="TRACE"/>
+    </root>
+
+</included>

+ 162 - 0
src/main/resources/logback/logback-dev.xml

@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<included>
+    <!-- 定义日志文件 输入位置 -->
+    <springProperty name="log_dir" source="logging.path" defaultValue="./logs"/>
+    <property name="log.pattern"
+              value="%d{yyyy-MM-dd HH:mm:ss.SSS} %X{THREAD_NOTE} [%thread] %-5level %logger - %msg%n"/>
+    <property name="log.maxHistory" value="90" />
+
+    <!--# Console -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- 典型的日志pattern -->
+        <encoder>
+            <pattern>[%-5level %d{HH:mm:ss.SSS} | %X{THREAD_NOTE} | %thread | %logger.%method] [%L] - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+    </appender>
+
+    <!-- ERROR级别日志 -->
+    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->
+    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录WARN级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+
+        <!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志输出位置  可相对、和绝对路径 -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/error.log</fileNamePattern>
+            <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,
+            则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
+            <maxHistory>${log.maxHistory}</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <!-- WARN级别日志 appender -->
+    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录WARN级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>WARN</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+
+
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/warn.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+        </rollingPolicy>
+
+    </appender>
+
+    <!-- INFO级别日志 appender -->
+    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录INFO级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/info.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+        </rollingPolicy>
+
+
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!-- DEBUG级别日志 appender -->
+    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录DEBUG级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>DEBUG</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/debug.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+            >
+        </rollingPolicy>
+
+    </appender>
+
+    <!-- TRACE级别日志 appender -->
+    <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 过滤器,只记录ERROR级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>TRACE</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+            <!-- 此处设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/trace.log
+            </fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>${log.maxHistory}</maxHistory>
+
+        </rollingPolicy>
+        >
+    </appender>
+
+    <!--myibatis log configure-->
+    <logger name="com.apache.ibatis" level="TRACE"/>
+    <logger name="java.sql.Connection" level="DEBUG"/>
+    <logger name="java.sql.Statement" level="DEBUG"/>
+    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
+
+    <!-- root级别   DEBUG -->
+    <root level="INFO">
+        <!-- 控制台输出 STDOUT-->
+        <appender-ref ref="STDOUT"/>
+        <appender-ref ref="DEBUG"/>
+        <!-- 文件输出 -->
+        <appender-ref ref="ERROR"/>
+        <appender-ref ref="INFO"/>
+        <appender-ref ref="WARN"/>
+        <appender-ref ref="DEBUG"/>
+        <appender-ref ref="TRACE"/>
+    </root>
+
+</included>

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott