Compare commits

...

16 Commits

  1. 26
      ruoyi-admin/src/main/resources/application-dev.yml
  2. 86
      ruoyi-admin/src/main/resources/application-prod.yml
  3. 6
      ruoyi-admin/src/main/resources/application.yml
  4. 90
      ruoyi-admin/src/test/java/org/dromara/test/AssertUnitTest.java
  5. 140
      ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java
  6. 144
      ruoyi-admin/src/test/java/org/dromara/test/ParamUnitTest.java
  7. 108
      ruoyi-admin/src/test/java/org/dromara/test/TagUnitTest.java
  8. 11
      ruoyi-modules/ruoyi-demo/pom.xml
  9. 118
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/AreaInfoController.java
  10. 58
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/ExcelController.java
  11. 105
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/ProjectFileInfoController.java
  12. 184
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/ProjectInfoController.java
  13. 33
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestController.java
  14. 1
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/package-info.java
  15. 51
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/DEAExample.java
  16. 267
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/DEAUtils.java
  17. 73
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/ExtendedDEAExample.java
  18. 551
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/ExtendedDEAUtils.java
  19. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/MailController.java
  20. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisCacheController.java
  21. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisLockController.java
  22. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisPubSubController.java
  23. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisRateLimiterController.java
  24. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/SmsController.java
  25. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/Swagger3DemoController.java
  26. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestBatchController.java
  27. 3
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestDemoController.java
  28. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestEncryptController.java
  29. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestExcelController.java
  30. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestI18nController.java
  31. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestSensitiveController.java
  32. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestTreeController.java
  33. 2
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/WeSocketController.java
  34. 1
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/package-info.java
  35. 77
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/AreaInfo.java
  36. 15
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/Attachment.java
  37. 89
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/AttachmentSerializer.java
  38. 162
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ProjectFileInfo.java
  39. 222
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ProjectInfo.java
  40. 78
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/AreaInfoBo.java
  41. 180
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/ProjectFileInfoBo.java
  42. 248
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/ProjectInfoBo.java
  43. 15
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AllGoatAchieveDataVo.java
  44. 15
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AllGoatAchieveVo.java
  45. 14
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AreaInfoFinalVo.java
  46. 86
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AreaInfoVo.java
  47. 73
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/DeaResultVo.java
  48. 41
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/PH.java
  49. 188
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ProjectFileInfoVo.java
  50. 259
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ProjectInfoVo.java
  51. 35
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ProjectPerformanceVo.java
  52. 41
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/StationDetailVo.java
  53. 24
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/StationInfoVo.java
  54. 16
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/XY.java
  55. 36
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/AreaListener.java
  56. 32
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ProjectInfoListener.java
  57. 15
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/AreaInfoMapper.java
  58. 15
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/ProjectFileInfoMapper.java
  59. 15
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/ProjectInfoMapper.java
  60. 71
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IAreaInfoService.java
  61. 68
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IProjectFileInfoService.java
  62. 91
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IProjectInfoService.java
  63. 165
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/AreaInfoServiceImpl.java
  64. 153
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ProjectFileInfoServiceImpl.java
  65. 655
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ProjectInfoServiceImpl.java

26
ruoyi-admin/src/main/resources/application-dev.yml

@ -1,7 +1,7 @@
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: true
enabled: false
url: http://localhost:9090/admin
instance:
service-host-type: IP
@ -13,7 +13,7 @@ spring.boot.admin.client:
--- # snail-job 配置
snail-job:
enabled: true
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "ruoyi_group"
# SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表
@ -47,17 +47,17 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://localhost:3306/environment?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: root
password: 1234
# 从库数据源
slave:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username:
password:
# slave:
# lazy: true
# type: ${spring.datasource.type}
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username:
# password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
@ -100,9 +100,9 @@ spring.data:
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
database: 11
# redis 密码必须配置
password: ruoyi123
# password: ruoyi123
# 连接超时时间
timeout: 10s
# 是否开启ssl

86
ruoyi-admin/src/main/resources/application-prod.yml

@ -1,10 +1,7 @@
--- # 临时文件存储位置 避免临时文件被系统清理报错
spring.servlet.multipart.location: /ruoyi/server/temp
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
enabled: true
enabled: false
url: http://localhost:9090/admin
instance:
service-host-type: IP
@ -16,7 +13,7 @@ spring.boot.admin.client:
--- # snail-job 配置
snail-job:
enabled: true
enabled: false
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "ruoyi_group"
# SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表
@ -38,7 +35,7 @@ spring:
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: false
p6spy: true
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
@ -48,37 +45,37 @@ spring:
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 environment
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://10.1.21.250:3306/environment?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: root
password: HXj-6nR|D8xy*h#!I&:(
# 从库数据源
slave:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username:
password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
# slave:
# lazy: true
# type: ${spring.datasource.type}
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username:
# password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
@ -99,13 +96,15 @@ spring:
spring.data:
redis:
# 地址
host: localhost
host: 10.1.21.250
# 端口,默认为6379
port: 6379
port: 6382
# 数据库索引
database: 0
database: 11
# redis 密码必须配置
password: ruoyi123
# password: ruoyi123
# 服务器连接密码(默认为空)
password: F*Nx=BZli+ZCCI-Fil+3
# 连接超时时间
timeout: 10s
# 是否开启ssl
@ -116,17 +115,17 @@ redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 16
threads: 4
# Netty线程池数量
nettyThreads: 32
nettyThreads: 8
# 单节点配置
singleServerConfig:
# 客户端名称
clientName: ${ruoyi.name}
# 最小空闲连接数
connectionMinimumIdleSize: 32
connectionMinimumIdleSize: 8
# 连接池大小
connectionPoolSize: 64
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
@ -188,6 +187,7 @@ sms:
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
--- # 三方授权
justauth:
# 前端外网访问地址
@ -206,7 +206,7 @@ justauth:
client-id: 449c4*********937************759
client-secret: ac7***********1e0************28d
redirect-uri: ${justauth.address}/social-callback?source=topiam
scopes: [ openid, email, phone, profile ]
scopes: [openid, email, phone, profile]
qq:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e

6
ruoyi-admin/src/main/resources/application.yml

@ -21,7 +21,8 @@ captcha:
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
# 服务器的HTTP端口,默认为8080 远程prod:8085
# cd /guoYanXinXi/data/software/app/shuihuanjing
port: 8080
servlet:
# 应用的访问路径
@ -70,7 +71,8 @@ spring:
# 国际化资源文件路径
basename: i18n/messages
profiles:
active: @profiles.active@
# 开发 dev 远程测试 prod
active: dev
# 文件上传
servlet:
multipart:

90
ruoyi-admin/src/test/java/org/dromara/test/AssertUnitTest.java

@ -1,45 +1,45 @@
package org.dromara.test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* 断言单元测试案例
*
* @author Lion Li
*/
@DisplayName("断言单元测试案例")
public class AssertUnitTest {
@DisplayName("测试 assertEquals 方法")
@Test
public void testAssertEquals() {
Assertions.assertEquals("666", new String("666"));
Assertions.assertNotEquals("666", new String("666"));
}
@DisplayName("测试 assertSame 方法")
@Test
public void testAssertSame() {
Object obj = new Object();
Object obj1 = obj;
Assertions.assertSame(obj, obj1);
Assertions.assertNotSame(obj, obj1);
}
@DisplayName("测试 assertTrue 方法")
@Test
public void testAssertTrue() {
Assertions.assertTrue(true);
Assertions.assertFalse(true);
}
@DisplayName("测试 assertNull 方法")
@Test
public void testAssertNull() {
Assertions.assertNull(null);
Assertions.assertNotNull(null);
}
}
//package org.dromara.test;
//
//import org.junit.jupiter.api.Assertions;
//import org.junit.jupiter.api.DisplayName;
//import org.junit.jupiter.api.Test;
//
///**
// * 断言单元测试案例
// *
// * @author Lion Li
// */
//@DisplayName("断言单元测试案例")
//public class AssertUnitTest {
//
// @DisplayName("测试 assertEquals 方法")
// @Test
// public void testAssertEquals() {
// Assertions.assertEquals("666", new String("666"));
// Assertions.assertNotEquals("666", new String("666"));
// }
//
// @DisplayName("测试 assertSame 方法")
// @Test
// public void testAssertSame() {
// Object obj = new Object();
// Object obj1 = obj;
// Assertions.assertSame(obj, obj1);
// Assertions.assertNotSame(obj, obj1);
// }
//
// @DisplayName("测试 assertTrue 方法")
// @Test
// public void testAssertTrue() {
// Assertions.assertTrue(true);
// Assertions.assertFalse(true);
// }
//
// @DisplayName("测试 assertNull 方法")
// @Test
// public void testAssertNull() {
// Assertions.assertNull(null);
// Assertions.assertNotNull(null);
// }
//
//}

140
ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java

@ -1,70 +1,70 @@
package org.dromara.test;
import org.dromara.common.core.config.RuoYiConfig;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
/**
* 单元测试案例
*
* @author Lion Li
*/
@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
@DisplayName("单元测试案例")
public class DemoUnitTest {
@Autowired
private RuoYiConfig ruoYiConfig;
@DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
@Test
public void testTest() {
System.out.println(ruoYiConfig);
}
@Disabled
@DisplayName("测试 @Disabled 注解")
@Test
public void testDisabled() {
System.out.println(ruoYiConfig);
}
@Timeout(value = 2L, unit = TimeUnit.SECONDS)
@DisplayName("测试 @Timeout 注解")
@Test
public void testTimeout() throws InterruptedException {
Thread.sleep(3000);
System.out.println(ruoYiConfig);
}
@DisplayName("测试 @RepeatedTest 注解")
@RepeatedTest(3)
public void testRepeatedTest() {
System.out.println(666);
}
@BeforeAll
public static void testBeforeAll() {
System.out.println("@BeforeAll ==================");
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
@AfterAll
public static void testAfterAll() {
System.out.println("@AfterAll ==================");
}
}
//package org.dromara.test;
//
//import org.dromara.common.core.config.RuoYiConfig;
//import org.junit.jupiter.api.*;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//
//import java.util.concurrent.TimeUnit;
//
///**
// * 单元测试案例
// *
// * @author Lion Li
// */
//@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
//@DisplayName("单元测试案例")
//public class DemoUnitTest {
//
// @Autowired
// private RuoYiConfig ruoYiConfig;
//
// @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
// @Test
// public void testTest() {
// System.out.println(ruoYiConfig);
// }
//
// @Disabled
// @DisplayName("测试 @Disabled 注解")
// @Test
// public void testDisabled() {
// System.out.println(ruoYiConfig);
// }
//
// @Timeout(value = 2L, unit = TimeUnit.SECONDS)
// @DisplayName("测试 @Timeout 注解")
// @Test
// public void testTimeout() throws InterruptedException {
// Thread.sleep(3000);
// System.out.println(ruoYiConfig);
// }
//
//
// @DisplayName("测试 @RepeatedTest 注解")
// @RepeatedTest(3)
// public void testRepeatedTest() {
// System.out.println(666);
// }
//
// @BeforeAll
// public static void testBeforeAll() {
// System.out.println("@BeforeAll ==================");
// }
//
// @BeforeEach
// public void testBeforeEach() {
// System.out.println("@BeforeEach ==================");
// }
//
// @AfterEach
// public void testAfterEach() {
// System.out.println("@AfterEach ==================");
// }
//
// @AfterAll
// public static void testAfterAll() {
// System.out.println("@AfterAll ==================");
// }
//
//}

144
ruoyi-admin/src/test/java/org/dromara/test/ParamUnitTest.java

@ -1,72 +1,72 @@
package org.dromara.test;
import org.dromara.common.core.enums.UserType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* 带参数单元测试案例
*
* @author Lion Li
*/
@DisplayName("带参数单元测试案例")
public class ParamUnitTest {
@DisplayName("测试 @ValueSource 注解")
@ParameterizedTest
@ValueSource(strings = {"t1", "t2", "t3"})
public void testValueSource(String str) {
System.out.println(str);
}
@DisplayName("测试 @NullSource 注解")
@ParameterizedTest
@NullSource
public void testNullSource(String str) {
System.out.println(str);
}
@DisplayName("测试 @EnumSource 注解")
@ParameterizedTest
@EnumSource(UserType.class)
public void testEnumSource(UserType type) {
System.out.println(type.getUserType());
}
@DisplayName("测试 @MethodSource 注解")
@ParameterizedTest
@MethodSource("getParam")
public void testMethodSource(String str) {
System.out.println(str);
}
public static Stream<String> getParam() {
List<String> list = new ArrayList<>();
list.add("t1");
list.add("t2");
list.add("t3");
return list.stream();
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
}
//package org.dromara.test;
//
//import org.dromara.common.core.enums.UserType;
//import org.junit.jupiter.api.AfterEach;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.DisplayName;
//import org.junit.jupiter.params.ParameterizedTest;
//import org.junit.jupiter.params.provider.EnumSource;
//import org.junit.jupiter.params.provider.MethodSource;
//import org.junit.jupiter.params.provider.NullSource;
//import org.junit.jupiter.params.provider.ValueSource;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.stream.Stream;
//
///**
// * 带参数单元测试案例
// *
// * @author Lion Li
// */
//@DisplayName("带参数单元测试案例")
//public class ParamUnitTest {
//
// @DisplayName("测试 @ValueSource 注解")
// @ParameterizedTest
// @ValueSource(strings = {"t1", "t2", "t3"})
// public void testValueSource(String str) {
// System.out.println(str);
// }
//
// @DisplayName("测试 @NullSource 注解")
// @ParameterizedTest
// @NullSource
// public void testNullSource(String str) {
// System.out.println(str);
// }
//
// @DisplayName("测试 @EnumSource 注解")
// @ParameterizedTest
// @EnumSource(UserType.class)
// public void testEnumSource(UserType type) {
// System.out.println(type.getUserType());
// }
//
// @DisplayName("测试 @MethodSource 注解")
// @ParameterizedTest
// @MethodSource("getParam")
// public void testMethodSource(String str) {
// System.out.println(str);
// }
//
// public static Stream<String> getParam() {
// List<String> list = new ArrayList<>();
// list.add("t1");
// list.add("t2");
// list.add("t3");
// return list.stream();
// }
//
// @BeforeEach
// public void testBeforeEach() {
// System.out.println("@BeforeEach ==================");
// }
//
// @AfterEach
// public void testAfterEach() {
// System.out.println("@AfterEach ==================");
// }
//
//
//}

108
ruoyi-admin/src/test/java/org/dromara/test/TagUnitTest.java

@ -1,54 +1,54 @@
package org.dromara.test;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 标签单元测试案例
*
* @author Lion Li
*/
@SpringBootTest
@DisplayName("标签单元测试案例")
public class TagUnitTest {
@Tag("dev")
@DisplayName("测试 @Tag dev")
@Test
public void testTagDev() {
System.out.println("dev");
}
@Tag("prod")
@DisplayName("测试 @Tag prod")
@Test
public void testTagProd() {
System.out.println("prod");
}
@Tag("local")
@DisplayName("测试 @Tag local")
@Test
public void testTagLocal() {
System.out.println("local");
}
@Tag("exclude")
@DisplayName("测试 @Tag exclude")
@Test
public void testTagExclude() {
System.out.println("exclude");
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
}
//package org.dromara.test;
//
//import org.junit.jupiter.api.*;
//import org.springframework.boot.test.context.SpringBootTest;
//
///**
// * 标签单元测试案例
// *
// * @author Lion Li
// */
//@SpringBootTest
//@DisplayName("标签单元测试案例")
//public class TagUnitTest {
//
// @Tag("dev")
// @DisplayName("测试 @Tag dev")
// @Test
// public void testTagDev() {
// System.out.println("dev");
// }
//
// @Tag("prod")
// @DisplayName("测试 @Tag prod")
// @Test
// public void testTagProd() {
// System.out.println("prod");
// }
//
// @Tag("local")
// @DisplayName("测试 @Tag local")
// @Test
// public void testTagLocal() {
// System.out.println("local");
// }
//
// @Tag("exclude")
// @DisplayName("测试 @Tag exclude")
// @Test
// public void testTagExclude() {
// System.out.println("exclude");
// }
//
// @BeforeEach
// public void testBeforeEach() {
// System.out.println("@BeforeEach ==================");
// }
//
// @AfterEach
// public void testAfterEach() {
// System.out.println("@AfterEach ==================");
// }
//
//
//}

11
ruoyi-modules/ruoyi-demo/pom.xml

@ -16,6 +16,17 @@
</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.4.1</version>
</dependency>
<!-- 通用工具-->
<dependency>

118
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/AreaInfoController.java

@ -0,0 +1,118 @@
package org.dromara.demo.controller;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.demo.domain.AreaInfo;
import org.dromara.demo.domain.vo.AreaInfoFinalVo;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.demo.domain.vo.AreaInfoVo;
import org.dromara.demo.domain.bo.AreaInfoBo;
import org.dromara.demo.service.IAreaInfoService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 区域信息
*
* @author GJH
* @date 2025-08-19
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/evr/area")
public class AreaInfoController extends BaseController {
private final IAreaInfoService areaInfoService;
/**
* 查询区域信息列表
*/
//@SaCheckPermission("area:area:list")
@GetMapping("/list")
public TableDataInfo<AreaInfoVo> list(AreaInfoBo bo, PageQuery pageQuery) {
return areaInfoService.queryPageList(bo, pageQuery);
}
/**
* 导出区域信息列表
*/
//@SaCheckPermission("area:area:export")
@Log(title = "区域信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(AreaInfoBo bo, HttpServletResponse response) {
List<AreaInfoVo> list = areaInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "区域信息", AreaInfoVo.class, response);
}
/**
* 获取区域信息列表+AI描述
*/
@GetMapping("/getList")
public R<List<AreaInfoFinalVo>> getList(AreaInfoBo bo) {
List<AreaInfoFinalVo> rs = areaInfoService.getList(bo);
return R.ok(rs);
}
/**
* 获取区域信息详细信息
*
* @param id 主键
*/
//@SaCheckPermission("area:area:query")
@GetMapping("/{id}")
public R<AreaInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable String id) {
return R.ok(areaInfoService.queryById(id));
}
/**
* 新增区域信息
*/
//@SaCheckPermission("area:area:add")
@Log(title = "区域信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody AreaInfoBo bo) {
return toAjax(areaInfoService.insertByBo(bo));
}
/**
* 修改区域信息
*/
//@SaCheckPermission("area:area:edit")
@Log(title = "区域信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AreaInfoBo bo) {
return toAjax(areaInfoService.updateByBo(bo));
}
/**
* 删除区域信息
*
* @param ids 主键串
*/
//@SaCheckPermission("area:area:remove")
@Log(title = "区域信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String[] ids) {
return toAjax(areaInfoService.deleteWithValidByIds(List.of(ids), true));
}
}

58
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/ExcelController.java

@ -0,0 +1,58 @@
package org.dromara.demo.controller;
import com.alibaba.excel.EasyExcel;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.demo.domain.vo.AreaInfoVo;
import org.dromara.demo.domain.vo.ProjectInfoVo;
import org.dromara.demo.listener.AreaListener;
import org.dromara.demo.listener.ProjectInfoListener;
import org.dromara.demo.service.IAreaInfoService;
import org.dromara.demo.service.IProjectInfoService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/evr/excel")
public class ExcelController {
@Resource
private IProjectInfoService projectInfoService ;
@Resource
private IAreaInfoService areaInfoService ;
@PostMapping("/uploadProjectInfo")
public void uploadPointInfo(MultipartFile file, HttpServletResponse response) throws IOException {
long t1 = System.currentTimeMillis();
// 业务层
EasyExcel.read(file.getInputStream(), ProjectInfoVo.class, new ProjectInfoListener(projectInfoService)).sheet().doRead();
response.setContentType("text/html;charset=utf8");
long t2 = System.currentTimeMillis();
response.getWriter().println("导入数据成功!,共用时:"+(t2-t1)+"ms");
log.info("批量项目信息成功! 共用时:{}ms",(t2-t1));
}
@PostMapping("/uploadAreaInfo")
public void uploadAreaInfo(MultipartFile file, HttpServletResponse response) throws IOException {
long t1 = System.currentTimeMillis();
// 业务层
EasyExcel.read(file.getInputStream(), AreaInfoVo.class, new AreaListener(areaInfoService)).sheet().doRead();
response.setContentType("text/html;charset=utf8");
long t2 = System.currentTimeMillis();
response.getWriter().println("导入数据成功!,共用时:"+(t2-t1)+"ms");
log.info("批量区域信息成功! 共用时:{}ms",(t2-t1));
}
}

105
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/ProjectFileInfoController.java

@ -0,0 +1,105 @@
package org.dromara.demo.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.demo.domain.vo.ProjectFileInfoVo;
import org.dromara.demo.domain.bo.ProjectFileInfoBo;
import org.dromara.demo.service.IProjectFileInfoService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 项目文件信息
*
* @author GJH
* @date 2025-08-19
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/project/fileInfo")
public class ProjectFileInfoController extends BaseController {
private final IProjectFileInfoService projectFileInfoService;
/**
* 查询项目文件信息列表
*/
//@SaCheckPermission("project:fileInfo:list")
@GetMapping("/list")
public TableDataInfo<ProjectFileInfoVo> list(ProjectFileInfoBo bo, PageQuery pageQuery) {
return projectFileInfoService.queryPageList(bo, pageQuery);
}
/**
* 导出项目文件信息列表
*/
//@SaCheckPermission("project:fileInfo:export")
@Log(title = "项目文件信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ProjectFileInfoBo bo, HttpServletResponse response) {
List<ProjectFileInfoVo> list = projectFileInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "项目文件信息", ProjectFileInfoVo.class, response);
}
/**
* 获取项目文件信息详细信息
*
* @param id 主键
*/
//@SaCheckPermission("project:fileInfo:query")
@GetMapping("/{id}")
public R<ProjectFileInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable String id) {
return R.ok(projectFileInfoService.queryById(id));
}
/**
* 新增项目文件信息
*/
//@SaCheckPermission("project:fileInfo:add")
@Log(title = "项目文件信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ProjectFileInfoBo bo) {
return toAjax(projectFileInfoService.insertByBo(bo));
}
/**
* 修改项目文件信息
*/
//@SaCheckPermission("project:fileInfo:edit")
@Log(title = "项目文件信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProjectFileInfoBo bo) {
return toAjax(projectFileInfoService.updateByBo(bo));
}
/**
* 删除项目文件信息
*
* @param ids 主键串
*/
//@SaCheckPermission("project:fileInfo:remove")
@Log(title = "项目文件信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String[] ids) {
return toAjax(projectFileInfoService.deleteWithValidByIds(List.of(ids), true));
}
}

184
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/ProjectInfoController.java

@ -0,0 +1,184 @@
package org.dromara.demo.controller;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import org.dromara.demo.domain.vo.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.demo.domain.bo.ProjectInfoBo;
import org.dromara.demo.service.IProjectInfoService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 项目信息
*
* @author GJH
* @date 2025-08-19
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("evr/project")
public class ProjectInfoController extends BaseController {
private final IProjectInfoService projectInfoService;
/**
* 查询项目信息列表
*/
//@SaCheckPermission("project:info:list")
@GetMapping("/list")
public TableDataInfo<ProjectInfoVo> list(ProjectInfoBo bo, PageQuery pageQuery) {
return projectInfoService.queryPageList(bo, pageQuery);
}
/**
* 导出项目信息列表
*/
//@SaCheckPermission("project:info:export")
@Log(title = "项目信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ProjectInfoBo bo, HttpServletResponse response) {
List<ProjectInfoVo> list = projectInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "项目信息", ProjectInfoVo.class, response);
}
/**
* 获取项目信息详细信息
*
* @param id 主键
*/
//@SaCheckPermission("project:info:query")
@GetMapping("/{id}")
public R<ProjectInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable String id) {
return R.ok(projectInfoService.queryById(id));
}
/**
* 新增项目信息
*/
//@SaCheckPermission("project:info:add")
@Log(title = "项目信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ProjectInfoBo bo) {
return toAjax(projectInfoService.insertByBo(bo));
}
/**
* 修改项目信息
*/
//@SaCheckPermission("project:info:edit")
@Log(title = "项目信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProjectInfoBo bo) {
return toAjax(projectInfoService.updateByBo(bo));
}
/**
* 删除项目信息
*
* @param ids 主键串
*/
//@SaCheckPermission("project:info:remove")
@Log(title = "项目信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String[] ids) {
return toAjax(projectInfoService.deleteWithValidByIds(List.of(ids), true));
}
// @GetMapping("/getInvestmentStats")
// public R<List<AllGoatAchieveDataVo>> getInvestmentStats() {
// return R.ok(projectInfoService.getYearlyInvestmentStats());
// }
@GetMapping("/getInvestmentStats")
public R<AllGoatAchieveVo> getInvestmentStats() {
List<AllGoatAchieveDataVo> data = projectInfoService.getYearlyInvestmentStats();
AllGoatAchieveVo rs = new AllGoatAchieveVo();
rs.setProjectInfo(data);
rs.setDescription(getFiveYearPlanAchievements());
return R.ok(rs);
}
private List<String> getFiveYearPlanAchievements() {
List<String> achievements = new ArrayList<>();
achievements.add("“九五”:建成1座城镇污水处理厂;完成XX截污工程;完成XX河道截污疏浚工程。");
achievements.add("“十五”:新增流域污水处理能力22万立方米/天;形成了5大排水系统,排水管网总长933.17公里。");
achievements.add("“十一五”:新建污水管网251.66公里;城镇污水处理厂处理规模提升55万方/天。");
achievements.add("“十二五”:截污治污系统基本建成;实施了补水工程;");
achievements.add("“十三五”:新建再生水厂工程;分别完成排水和再生水管网建设719和123公里;完成30余条河沟水环境整治;新建修缮农村污水处理设施533座。");
return achievements;
}
/**
* 查询项目信息 (不分页)
* @param bo
* @return
*/
@GetMapping("/getInfoList")
public R< List<ProjectInfoVo>> getInfoList(ProjectInfoBo bo) {
List<ProjectInfoVo> rs = projectInfoService.queryList(bo);
return R.ok(rs);
}
@GetMapping("/getPerformanceScore")
public R<List<ProjectPerformanceVo>> getPerformanceScore(ProjectInfoBo bo) {
List<ProjectPerformanceVo> rs =projectInfoService.getPerformanceScore(bo);
return R.ok(rs);
}
@GetMapping("/calculateAverageByType")
public R<ProjectPerformanceVo> calculateAverageByType(ProjectInfoBo bo) {
ProjectPerformanceVo rs =projectInfoService.calculateAverageByType(bo);
return R.ok(rs);
}
@GetMapping("/getDeaResults")
public R<List<DeaResultVo>> getDeaResults() {
List<DeaResultVo> rs = projectInfoService.getDeaSimulationResults();
return R.ok(rs);
}
/**
* 获取检测点位列表 默认1个提供演示
* @return
*/
@GetMapping("/getStations")
public R<List<StationInfoVo>> getStations() {
List<StationInfoVo> rs= projectInfoService.getStations();
return R.ok(rs);
}
@GetMapping("/getPH")
public R<PH> getPH() {
PH rs = projectInfoService.getPH();
return R.ok(rs);
}
@GetMapping("/getWaterQuality")
public R<StationDetailVo> getWaterQuality(@RequestParam String type) {
StationDetailVo rs = projectInfoService.getWaterQualityData(type);
return R.ok(rs);
}
}

33
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestController.java

@ -0,0 +1,33 @@
package org.dromara.demo.controller;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
* @Author gejunhao
* @Date 2025/1/10 14:11
* @Description: 测试接口
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/hello")
public void test(HttpServletResponse response) throws IOException {
log.info("hello word!");
response.setContentType("text/html;charset=utf8");
response.getWriter().println("GJH-调用接口成功修改版本!");
}
}

1
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/package-info.java

@ -1 +0,0 @@
package org.dromara.demo.controller;

51
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/DEAExample.java

@ -0,0 +1,51 @@
package org.dromara.demo.controller.test;
import java.util.List;
/**
* DEA模型使用示例
*/
public class DEAExample {
public static void main(String[] args) {
// 示例:3个DMU,2个投入指标,1个产出指标
// 投入矩阵: 每行代表一个DMU的投入
// 例如: 投入可以是员工数量和资金投入
// 1 2 3 4
double[][] inputs = {
{2,2,1,2,1,1}, // DMU 0的投入
{3,2,5,4,4,1}, // DMU 0的投入
{2,3,3,3,5,3}, // DMU 0的投入
{5,4,1,2,2,1}, // DMU 0的投入
{2,3,3,3,5,3}, // DMU 0的投入
{5,4,1,2,2,1}, // DMU 0的投入
};
// 产出矩阵: 每行代表一个DMU的产出
// 例如: 产出可以是利润
double[][] outputs = {
{4}, // DMU 0的产出
{3}, // DMU 0的产出
{2}, // DMU 0的产出
{3}, // DMU 0的产出
{5}, // DMU 0的产出
{5}, // DMU 0的产出
};
// 计算所有DMU的效率值
List<DEAUtils.DEAResult> results = DEAUtils.calculateAllDMUs(inputs, outputs);
// 输出结果
for (DEAUtils.DEAResult result : results) {
System.out.println(result);
}
// 单独计算某个DMU的效率值
int targetDMU = 1;
DEAUtils.DEAResult specificResult = DEAUtils.calculateDEA(inputs, outputs, targetDMU);
System.out.println("\n单独评估DMU " + targetDMU + " 的详细结果:");
System.out.println("效率值: " + specificResult.getEfficiency());
System.out.println("是否DEA有效: " + specificResult.isEfficient());
}
}

267
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/DEAUtils.java

@ -0,0 +1,267 @@
package org.dromara.demo.controller.test;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.optim.*;
import org.apache.commons.math3.optim.linear.*;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import java.util.ArrayList;
import java.util.List;
/**
* DEA(数据包络分析)工具类实现面向投入的CCR模型
*/
public class DEAUtils {
/**
* 计算指定DMU的效率值
*
* @param inputs 投入矩阵每行代表一个DMU的所有投入行数为DMU数量列数为投入指标数量
* @param outputs 产出矩阵每行代表一个DMU的所有产出行数为DMU数量列数为产出指标数量
* @param dmuIndex 要评估的DMU索引(从0开始)
* @return DEA计算结果包含效率值和松弛变量等信息
* @throws IllegalArgumentException 输入数据不合法时抛出
*/
public static DEAResult calculateDEA(double[][] inputs, double[][] outputs, int dmuIndex) {
// 验证输入数据合法性
validateInput(inputs, outputs, dmuIndex);
int n = inputs.length; // DMU数量
int m = inputs[0].length; // 投入指标数量
int s = outputs[0].length; // 产出指标数量
// 变量数量: n个lambda + 1个theta + m个投入松弛变量 + s个产出松弛变量
int varCount = n + 1 + m + s;
// 目标函数: 最小化theta(第n个变量)
double[] objectiveCoefficients = new double[varCount];
objectiveCoefficients[n] = 1.0; // theta的系数为1,其他变量系数为0
// 创建线性规划问题
LinearObjectiveFunction objective = new LinearObjectiveFunction(objectiveCoefficients, 0);
// 约束条件列表
List<LinearConstraint> constraints = new ArrayList<>();
// 1. 投入约束: sum(lambda_j * x_ij) + s_i^- = theta * x_ik (i=1..m)
for (int i = 0; i < m; i++) {
double[] coefficients = new double[varCount];
// 设置lambda_j的系数
for (int j = 0; j < n; j++) {
coefficients[j] = inputs[j][i];
}
// 设置theta的系数
coefficients[n] = -inputs[dmuIndex][i];
// 设置投入松弛变量的系数
coefficients[n + 1 + i] = 1.0;
// sum(lambda_j * x_ij) - theta * x_ik + s_i^- = 0
constraints.add(new LinearConstraint(coefficients, Relationship.EQ, 0.0));
}
// 2. 产出约束: sum(lambda_j * y_rj) - s_r^+ = y_rk (r=1..s)
for (int r = 0; r < s; r++) {
double[] coefficients = new double[varCount];
// 设置lambda_j的系数
for (int j = 0; j < n; j++) {
coefficients[j] = outputs[j][r];
}
// 设置产出松弛变量的系数
coefficients[n + 1 + m + r] = -1.0;
// sum(lambda_j * y_rj) - s_r^+ = y_rk
constraints.add(new LinearConstraint(coefficients, Relationship.EQ, outputs[dmuIndex][r]));
}
// 3. 变量非负约束
// lambda_j >= 0 (j=1..n)
// theta无符号限制,但在CCR模型中通常theta <= 1
// s_i^- >= 0 (i=1..m)
// s_r^+ >= 0 (r=1..s)
for (int j = 0; j < n; j++) {
double[] coefficients = new double[varCount];
coefficients[j] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.GEQ, 0.0));
}
// 投入松弛变量非负
for (int i = 0; i < m; i++) {
double[] coefficients = new double[varCount];
coefficients[n + 1 + i] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.GEQ, 0.0));
}
// 产出松弛变量非负
for (int r = 0; r < s; r++) {
double[] coefficients = new double[varCount];
coefficients[n + 1 + m + r] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.GEQ, 0.0));
}
// 4. theta <= 1约束
double[] thetaCoeff = new double[varCount];
thetaCoeff[n] = 1.0;
constraints.add(new LinearConstraint(thetaCoeff, Relationship.LEQ, 1.0));
// 求解器配置
SimplexSolver solver = new SimplexSolver();
LinearOptimizer optimizer = solver;
// 求解线性规划问题
PointValuePair solution = optimizer.optimize(
new LinearConstraintSet(constraints),
objective,
GoalType.MINIMIZE,
new NonNegativeConstraint(false), // 已单独设置非负约束
new MaxIter(1000)
);
// 解析结果
double[] solutionPoint = solution.getPoint();
double theta = solutionPoint[n]; // 效率值
// 投入松弛变量
double[] inputSlacks = new double[m];
System.arraycopy(solutionPoint, n + 1, inputSlacks, 0, m);
// 产出松弛变量
double[] outputSlacks = new double[s];
System.arraycopy(solutionPoint, n + 1 + m, outputSlacks, 0, s);
// lambda值
double[] lambdas = new double[n];
System.arraycopy(solutionPoint, 0, lambdas, 0, n);
return new DEAResult(theta, inputSlacks, outputSlacks, lambdas, dmuIndex);
}
/**
* 计算所有DMU的效率值
*
* @param inputs 投入矩阵
* @param outputs 产出矩阵
* @return 所有DMU的DEA计算结果列表
*/
public static List<DEAResult> calculateAllDMUs(double[][] inputs, double[][] outputs) {
List<DEAResult> results = new ArrayList<>();
for (int i = 0; i < inputs.length; i++) {
results.add(calculateDEA(inputs, outputs, i));
}
return results;
}
/**
* 验证输入数据的合法性
*/
private static void validateInput(double[][] inputs, double[][] outputs, int dmuIndex) {
if (inputs == null || outputs == null) {
throw new IllegalArgumentException("投入和产出矩阵不能为null");
}
if (inputs.length != outputs.length) {
throw new IllegalArgumentException("投入和产出矩阵的行数(DMU数量)必须一致");
}
if (inputs.length == 0) {
throw new IllegalArgumentException("至少需要一个DMU");
}
int m = inputs[0].length;
for (double[] input : inputs) {
if (input.length != m) {
throw new IllegalArgumentException("所有DMU的投入指标数量必须一致");
}
}
int s = outputs[0].length;
for (double[] output : outputs) {
if (output.length != s) {
throw new IllegalArgumentException("所有DMU的产出指标数量必须一致");
}
}
if (dmuIndex < 0 || dmuIndex >= inputs.length) {
throw new IllegalArgumentException("DMU索引超出范围");
}
}
/**
* DEA计算结果封装类
*/
public static class DEAResult {
private final double efficiency; // 效率值(theta)
private final double[] inputSlacks; // 投入松弛变量
private final double[] outputSlacks; // 产出松弛变量
private final double[] lambdas; // 各DMU的权重
private final int dmuIndex; // 对应的DMU索引
public DEAResult(double efficiency, double[] inputSlacks, double[] outputSlacks,
double[] lambdas, int dmuIndex) {
this.efficiency = efficiency;
this.inputSlacks = inputSlacks;
this.outputSlacks = outputSlacks;
this.lambdas = lambdas;
this.dmuIndex = dmuIndex;
}
/**
* 判断该DMU是否为DEA有效
* 当效率值=1且所有松弛变量为0时DMU为DEA有效
*/
public boolean isEfficient() {
if (Math.abs(efficiency - 1.0) > 1e-9) {
return false;
}
for (double slack : inputSlacks) {
if (Math.abs(slack) > 1e-9) {
return false;
}
}
for (double slack : outputSlacks) {
if (Math.abs(slack) > 1e-9) {
return false;
}
}
return true;
}
// getter方法
public double getEfficiency() {
return efficiency;
}
public double[] getInputSlacks() {
return inputSlacks.clone();
}
public double[] getOutputSlacks() {
return outputSlacks.clone();
}
public double[] getLambdas() {
return lambdas.clone();
}
public int getDmuIndex() {
return dmuIndex;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("DMU ").append(dmuIndex).append(" 评估结果:\n");
sb.append(" 效率值: ").append(String.format("%.4f", efficiency)).append("\n");
sb.append(" 是否DEA有效: ").append(isEfficient()).append("\n");
sb.append(" 投入松弛变量: ");
for (double slack : inputSlacks) {
sb.append(String.format("%.4f ", slack));
}
sb.append("\n 产出松弛变量: ");
for (double slack : outputSlacks) {
sb.append(String.format("%.4f ", slack));
}
return sb.toString();
}
}
}

73
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/ExtendedDEAExample.java

@ -0,0 +1,73 @@
package org.dromara.demo.controller.test;
import java.util.List;
/**
* 扩展DEA模型BCC和非期望SBM使用示例
*/
public class ExtendedDEAExample {
public static void main(String[] args) {
// 示例1:BCC模型使用示例
System.out.println("===== BCC模型示例 =====");
// 3个DMU,2个投入指标,1个产出指标
double[][] inputsBCC = {
{2,2,1,2,1,1}, // DMU 0的投入
{3,2,5,4,4,1}, // DMU 0的投入
{2,3,3,3,5,3}, // DMU 0的投入
{5,4,1,2,2,1}, // DMU 0的投入
{2,3,3,3,5,3}, // DMU 0的投入
{5,4,1,2,2,1}, // DMU 0的投入
};
double[][] outputsBCC = {
{4}, // DMU 0的产出
{3}, // DMU 0的产出
{2}, // DMU 0的产出
{3}, // DMU 0的产出
{5}, // DMU 0的产出
{5}, // DMU 0的产出
};
List<ExtendedDEAUtils.DEAResult> bccResults =
ExtendedDEAUtils.calculateAllBCC(inputsBCC, outputsBCC);
for (ExtendedDEAUtils.DEAResult result : bccResults) {
System.out.println(result);
}
// 示例2:非期望SBM模型使用示例
System.out.println("\n===== 非期望SBM模型示例 =====");
// 3个企业(DMU),2个投入(资本、劳动),1个期望产出(利润),1个非期望产出(污染)
double[][] inputsSBM = {
{2,2,1,2,1,1}, // DMU 0的投入
{3,2,5,4,4,1}, // DMU 0的投入
{2,3,3,3,5,3}, // DMU 0的投入
{5,4,1,2,2,1}, // DMU 0的投入
{2,3,3,3,5,3}, // DMU 0的投入
{5,4,1,2,2,1}, // DMU 0的投入
};
double[][] desirableOutputs = {
{4}, // DMU 0的产出
{3}, // DMU 0的产出
{2}, // DMU 0的产出
{3}, // DMU 0的产出
{5}, // DMU 0的产出
{5}, // DMU 0的产出
};
double[][] undesirableOutputs = {
{4}, // DMU 0的产出
{3}, // DMU 0的产出
{2}, // DMU 0的产出
{3}, // DMU 0的产出
{5}, // DMU 0的产出
{5}, // DMU 0的产出
};
List<ExtendedDEAUtils.DEAResult> sbmResults =
ExtendedDEAUtils.calculateAllUndesirableSBM(inputsSBM, desirableOutputs, undesirableOutputs);
for (ExtendedDEAUtils.DEAResult result : sbmResults) {
System.out.println(result);
}
}
}

551
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/ExtendedDEAUtils.java

@ -0,0 +1,551 @@
package org.dromara.demo.controller.test;
import org.apache.commons.math3.analysis.MultivariateFunction;
import org.apache.commons.math3.optim.*;
import org.apache.commons.math3.optim.linear.*;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer;
import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer;
import java.util.ArrayList;
import java.util.List;
/**
* 扩展的DEA工具类包含BCC模型和非期望SBM模型
*/
public class ExtendedDEAUtils {
// ===================== BCC模型(规模报酬可变) =====================
/**
* 计算指定DMU的BCC模型效率值面向投入
* BCC模型在CCR基础上增加了sum(λ_j) = 1的约束考虑规模报酬可变
*/
public static DEAResult calculateBCC(double[][] inputs, double[][] outputs, int dmuIndex) {
// 验证输入数据合法性
validateInput(inputs, outputs, dmuIndex);
int n = inputs.length; // DMU数量
int m = inputs[0].length; // 投入指标数量
int s = outputs[0].length; // 产出指标数量
// 变量数量: n个lambda + 1个theta + m个投入松弛变量 + s个产出松弛变量
int varCount = n + 1 + m + s;
// 目标函数: 最小化theta(第n个变量)
double[] objectiveCoefficients = new double[varCount];
objectiveCoefficients[n] = 1.0; // theta的系数为1,其他变量系数为0
// 创建线性规划问题
LinearObjectiveFunction objective = new LinearObjectiveFunction(objectiveCoefficients, 0);
// 约束条件列表
List<LinearConstraint> constraints = new ArrayList<>();
// 1. 投入约束: sum(lambda_j * x_ij) + s_i^- = theta * x_ik (i=1..m)
for (int i = 0; i < m; i++) {
double[] coefficients = new double[varCount];
// 设置lambda_j的系数
for (int j = 0; j < n; j++) {
coefficients[j] = inputs[j][i];
}
// 设置theta的系数
coefficients[n] = -inputs[dmuIndex][i];
// 设置投入松弛变量的系数
coefficients[n + 1 + i] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.EQ, 0.0));
}
// 2. 产出约束: sum(lambda_j * y_rj) - s_r^+ = y_rk (r=1..s)
for (int r = 0; r < s; r++) {
double[] coefficients = new double[varCount];
for (int j = 0; j < n; j++) {
coefficients[j] = outputs[j][r];
}
coefficients[n + 1 + m + r] = -1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.EQ, outputs[dmuIndex][r]));
}
// 3. 变量非负约束
for (int j = 0; j < n; j++) {
double[] coefficients = new double[varCount];
coefficients[j] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.GEQ, 0.0));
}
// 投入松弛变量非负
for (int i = 0; i < m; i++) {
double[] coefficients = new double[varCount];
coefficients[n + 1 + i] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.GEQ, 0.0));
}
// 产出松弛变量非负
for (int r = 0; r < s; r++) {
double[] coefficients = new double[varCount];
coefficients[n + 1 + m + r] = 1.0;
constraints.add(new LinearConstraint(coefficients, Relationship.GEQ, 0.0));
}
// 4. theta <= 1约束
double[] thetaCoeff = new double[varCount];
thetaCoeff[n] = 1.0;
constraints.add(new LinearConstraint(thetaCoeff, Relationship.LEQ, 1.0));
// 5. BCC模型特有约束:sum(lambda_j) = 1(规模报酬可变)
double[] sumLambdaCoeff = new double[varCount];
for (int j = 0; j < n; j++) {
sumLambdaCoeff[j] = 1.0;
}
constraints.add(new LinearConstraint(sumLambdaCoeff, Relationship.EQ, 1.0));
// 求解线性规划问题
SimplexSolver solver = new SimplexSolver();
PointValuePair solution = solver.optimize(
new LinearConstraintSet(constraints),
objective,
GoalType.MINIMIZE,
new NonNegativeConstraint(false),
new MaxIter(1000)
);
// 解析结果
double[] solutionPoint = solution.getPoint();
double theta = solutionPoint[n]; // 效率值
// 投入松弛变量
double[] inputSlacks = new double[m];
System.arraycopy(solutionPoint, n + 1, inputSlacks, 0, m);
// 产出松弛变量
double[] outputSlacks = new double[s];
System.arraycopy(solutionPoint, n + 1 + m, outputSlacks, 0, s);
// lambda值
double[] lambdas = new double[n];
System.arraycopy(solutionPoint, 0, lambdas, 0, n);
return new DEAResult(theta, inputSlacks, outputSlacks, lambdas, dmuIndex, "BCC");
}
/**
* 计算所有DMU的BCC模型效率值
*/
public static List<DEAResult> calculateAllBCC(double[][] inputs, double[][] outputs) {
List<DEAResult> results = new ArrayList<>();
for (int i = 0; i < inputs.length; i++) {
results.add(calculateBCC(inputs, outputs, i));
}
return results;
}
// ===================== 非期望SBM模型 =====================
/**
* 计算指定DMU的非期望SBM模型效率值
* SBM模型考虑非期望产出如污染浪费等
*/
public static DEAResult calculateUndesirableSBM(
double[][] inputs,
double[][] desirableOutputs,
double[][] undesirableOutputs,
int dmuIndex) {
// 验证输入数据
validateSBMInput(inputs, desirableOutputs, undesirableOutputs, dmuIndex);
int n = inputs.length; // DMU数量
int m = inputs[0].length; // 投入指标数量
int s1 = desirableOutputs[0].length; // 期望产出指标数量
int s2 = undesirableOutputs[0].length; // 非期望产出指标数量
// SBM模型参数:lambda(n) + s^-(m) + s^+(s1) + s^b(s2)
int paramCount = n + m + s1 + s2;
// 初始值
double[] initialGuess = new double[paramCount];
for (int i = 0; i < paramCount; i++) {
initialGuess[i] = 0.1;
}
// 创建目标函数(显式实现MultivariateFunction接口,解决类型转换问题)
MultivariateFunction objectiveFunction = new SBMObjectiveFunction(
inputs, desirableOutputs, undesirableOutputs, dmuIndex, m, s1, s2, n);
// 创建优化器
MultivariateOptimizer optimizer = new SimplexOptimizer(1e-9, 1e-9);
NelderMeadSimplex simplex = new NelderMeadSimplex(paramCount, 0.1);
// 设置约束:参数非负
List<OptimizationData> optData = new ArrayList<>();
optData.add(new ObjectiveFunction(objectiveFunction));
optData.add(GoalType.MAXIMIZE); // SBM模型目标是最大化效率值
optData.add(simplex);
optData.add(new InitialGuess(initialGuess));
optData.add(new MaxIter(10000));
optData.add(new MaxEval(100000));
// 执行优化
PointValuePair solution = optimizer.optimize(optData.toArray(new OptimizationData[0]));
double[] solutionPoint = solution.getPoint();
double efficiency = solution.getValue();
// 解析结果
double[] lambda = new double[n];
double[] inputSlacks = new double[m];
double[] desirableOutputSlacks = new double[s1];
double[] undesirableOutputSlacks = new double[s2];
System.arraycopy(solutionPoint, 0, lambda, 0, n);
System.arraycopy(solutionPoint, n, inputSlacks, 0, m);
System.arraycopy(solutionPoint, n + m, desirableOutputSlacks, 0, s1);
System.arraycopy(solutionPoint, n + m + s1, undesirableOutputSlacks, 0, s2);
// 构建结果对象
DEAResult result = new DEAResult(efficiency, inputSlacks, desirableOutputSlacks,
lambda, dmuIndex, "UndesirableSBM");
result.setUndesirableOutputSlacks(undesirableOutputSlacks);
return result;
}
/**
* SBM模型的目标函数实现显式实现MultivariateFunction接口
*/
private static class SBMObjectiveFunction implements MultivariateFunction {
private final double[][] inputs;
private final double[][] desirableOutputs;
private final double[][] undesirableOutputs;
private final int dmuIndex;
private final int m;
private final int s1;
private final int s2;
private final int n;
public SBMObjectiveFunction(double[][] inputs, double[][] desirableOutputs,
double[][] undesirableOutputs, int dmuIndex,
int m, int s1, int s2, int n) {
this.inputs = inputs;
this.desirableOutputs = desirableOutputs;
this.undesirableOutputs = undesirableOutputs;
this.dmuIndex = dmuIndex;
this.m = m;
this.s1 = s1;
this.s2 = s2;
this.n = n;
}
@Override
public double value(double[] params) {
// 分离参数
double[] lambda = new double[n];
double[] sMinus = new double[m];
double[] sPlus = new double[s1];
double[] sBad = new double[s2];
System.arraycopy(params, 0, lambda, 0, n);
System.arraycopy(params, n, sMinus, 0, m);
System.arraycopy(params, n + m, sPlus, 0, s1);
System.arraycopy(params, n + m + s1, sBad, 0, s2);
// 计算分子:1 - (1/m)sum(s_i^-/x_ik)
double sumInputSlack = 0.0;
for (int i = 0; i < m; i++) {
sumInputSlack += sMinus[i] / inputs[dmuIndex][i];
}
double numerator = 1 - (sumInputSlack / m);
// 计算分母:1 + (1/(s1+s2))(sum(s_r^+/y_rk) + sum(s_b^b/z_bk))
double sumDesirableSlack = 0.0;
for (int r = 0; r < s1; r++) {
sumDesirableSlack += sPlus[r] / desirableOutputs[dmuIndex][r];
}
double sumUndesirableSlack = 0.0;
for (int b = 0; b < s2; b++) {
sumUndesirableSlack += sBad[b] / undesirableOutputs[dmuIndex][b];
}
double denominator = 1 + (sumDesirableSlack + sumUndesirableSlack) / (s1 + s2);
// 防止除零错误
if (denominator < 1e-10) {
return Double.NEGATIVE_INFINITY;
}
// 计算约束违反惩罚
double penalty = calculateConstraintPenalty(params, lambda, sMinus, sPlus, sBad);
// 返回目标函数值减去惩罚项
return (numerator / denominator) - penalty;
}
/**
* 计算约束违反的惩罚值
*/
private double calculateConstraintPenalty(double[] params, double[] lambda,
double[] sMinus, double[] sPlus, double[] sBad) {
double penalty = 0.0;
// 投入约束:sum(lambda_j * x_ij) + s_i^- = x_ik
for (int i = 0; i < m; i++) {
double sum = 0.0;
for (int j = 0; j < n; j++) {
sum += lambda[j] * inputs[j][i];
}
double constraint = sum + sMinus[i] - inputs[dmuIndex][i];
penalty += Math.abs(constraint) * 1e6; // 对违反约束进行惩罚
}
// 期望产出约束:sum(lambda_j * y_rj) - s_r^+ = y_rk
for (int r = 0; r < s1; r++) {
double sum = 0.0;
for (int j = 0; j < n; j++) {
sum += lambda[j] * desirableOutputs[j][r];
}
double constraint = sum - sPlus[r] - desirableOutputs[dmuIndex][r];
penalty += Math.abs(constraint) * 1e6;
}
// 非期望产出约束:sum(lambda_j * z_bj) + s_b^b = z_bk
for (int b = 0; b < s2; b++) {
double sum = 0.0;
for (int j = 0; j < n; j++) {
sum += lambda[j] * undesirableOutputs[j][b];
}
double constraint = sum + sBad[b] - undesirableOutputs[dmuIndex][b];
penalty += Math.abs(constraint) * 1e6;
}
// 变量非负约束惩罚
for (double param : params) {
if (param < 0) {
penalty += Math.abs(param) * 1e6;
}
}
// SBM模型的凸性约束 sum(lambda_j) = 1
double sumLambda = 0.0;
for (double l : lambda) {
sumLambda += l;
}
penalty += Math.abs(sumLambda - 1.0) * 1e6;
return penalty;
}
}
/**
* 计算所有DMU的非期望SBM模型效率值
*/
public static List<DEAResult> calculateAllUndesirableSBM(
double[][] inputs,
double[][] desirableOutputs,
double[][] undesirableOutputs) {
List<DEAResult> results = new ArrayList<>();
for (int i = 0; i < inputs.length; i++) {
results.add(calculateUndesirableSBM(inputs, desirableOutputs, undesirableOutputs, i));
}
return results;
}
// ===================== 验证方法 =====================
/**
* 验证SBM模型输入数据的合法性
*/
private static void validateSBMInput(double[][] inputs, double[][] desirableOutputs,
double[][] undesirableOutputs, int dmuIndex) {
validateInput(inputs, desirableOutputs, dmuIndex);
if (undesirableOutputs == null) {
throw new IllegalArgumentException("非期望产出矩阵不能为null");
}
if (undesirableOutputs.length != inputs.length) {
throw new IllegalArgumentException("非期望产出矩阵的行数必须与投入矩阵一致");
}
int s2 = undesirableOutputs[0].length;
for (double[] output : undesirableOutputs) {
if (output.length != s2) {
throw new IllegalArgumentException("所有DMU的非期望产出指标数量必须一致");
}
}
// 检查非期望产出是否为正值
for (int i = 0; i < undesirableOutputs.length; i++) {
for (int j = 0; j < s2; j++) {
if (undesirableOutputs[i][j] <= 0) {
throw new IllegalArgumentException("非期望产出必须为正值");
}
}
}
}
/**
* 验证基本DEA输入数据的合法性
*/
private static void validateInput(double[][] inputs, double[][] outputs, int dmuIndex) {
if (inputs == null || outputs == null) {
throw new IllegalArgumentException("投入和产出矩阵不能为null");
}
if (inputs.length != outputs.length) {
throw new IllegalArgumentException("投入和产出矩阵的行数(DMU数量)必须一致");
}
if (inputs.length == 0) {
throw new IllegalArgumentException("至少需要一个DMU");
}
int m = inputs[0].length;
for (double[] input : inputs) {
if (input.length != m) {
throw new IllegalArgumentException("所有DMU的投入指标数量必须一致");
}
for (double val : input) {
if (val <= 0) {
throw new IllegalArgumentException("投入必须为正值");
}
}
}
int s = outputs[0].length;
for (double[] output : outputs) {
if (output.length != s) {
throw new IllegalArgumentException("所有DMU的产出指标数量必须一致");
}
for (double val : output) {
if (val <= 0) {
throw new IllegalArgumentException("产出必须为正值");
}
}
}
if (dmuIndex < 0 || dmuIndex >= inputs.length) {
throw new IllegalArgumentException("DMU索引超出范围");
}
}
// ===================== 结果封装类 =====================
/**
* DEA计算结果封装类支持BCC和非期望SBM模型
*/
public static class DEAResult {
private final double efficiency; // 效率值
private final double[] inputSlacks; // 投入松弛变量
private final double[] outputSlacks; // 产出松弛变量(期望产出)
private double[] undesirableOutputSlacks; // 非期望产出松弛变量
private final double[] lambdas; // 各DMU的权重
private final int dmuIndex; // 对应的DMU索引
private final String modelType; // 模型类型
public DEAResult(double efficiency, double[] inputSlacks, double[] outputSlacks,
double[] lambdas, int dmuIndex, String modelType) {
this.efficiency = efficiency;
this.inputSlacks = inputSlacks;
this.outputSlacks = outputSlacks;
this.lambdas = lambdas;
this.dmuIndex = dmuIndex;
this.modelType = modelType;
}
/**
* 判断该DMU是否为DEA有效
*/
public boolean isEfficient() {
if (Math.abs(efficiency - 1.0) > 1e-9) {
return false;
}
// 检查所有松弛变量是否为0
for (double slack : inputSlacks) {
if (Math.abs(slack) > 1e-9) {
return false;
}
}
for (double slack : outputSlacks) {
if (Math.abs(slack) > 1e-9) {
return false;
}
}
// 检查非期望产出松弛变量
if (undesirableOutputSlacks != null) {
for (double slack : undesirableOutputSlacks) {
if (Math.abs(slack) > 1e-9) {
return false;
}
}
}
return true;
}
// setter和getter方法
public double getEfficiency() {
return efficiency;
}
public double[] getInputSlacks() {
return inputSlacks.clone();
}
public double[] getOutputSlacks() {
return outputSlacks.clone();
}
public double[] getUndesirableOutputSlacks() {
return undesirableOutputSlacks != null ? undesirableOutputSlacks.clone() : null;
}
public void setUndesirableOutputSlacks(double[] undesirableOutputSlacks) {
this.undesirableOutputSlacks = undesirableOutputSlacks;
}
public double[] getLambdas() {
return lambdas.clone();
}
public int getDmuIndex() {
return dmuIndex;
}
public String getModelType() {
return modelType;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(modelType).append("模型 - DMU ").append(dmuIndex).append(" 评估结果:\n");
sb.append(" 效率值: ").append(String.format("%.4f", efficiency)).append("\n");
sb.append(" 是否DEA有效: ").append(isEfficient()).append("\n");
sb.append(" 投入松弛变量: ");
for (double slack : inputSlacks) {
sb.append(String.format("%.4f ", slack));
}
sb.append("\n 期望产出松弛变量: ");
for (double slack : outputSlacks) {
sb.append(String.format("%.4f ", slack));
}
if (undesirableOutputSlacks != null) {
sb.append("\n 非期望产出松弛变量: ");
for (double slack : undesirableOutputSlacks) {
sb.append(String.format("%.4f ", slack));
}
}
return sb.toString();
}
}
}

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/MailController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.common.mail.utils.MailUtils;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisCacheController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.domain.R;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisLockController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisPubSubController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisPubSubController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.RedisUtils;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisRateLimiterController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/RedisRateLimiterController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.common.ratelimiter.annotation.RateLimiter;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/SmsController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/SmsController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/Swagger3DemoController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/Swagger3DemoController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.springframework.http.MediaType;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestBatchController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestBatchController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.dromara.common.core.domain.R;

3
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestDemoController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestDemoController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.R;
@ -30,6 +30,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestEncryptController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestEncryptController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.demo.domain.TestDemoEncrypt;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestExcelController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import cn.hutool.core.collection.CollUtil;
import jakarta.servlet.http.HttpServletResponse;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestI18nController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestI18nController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MessageUtils;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestSensitiveController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestSensitiveController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestTreeController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/TestTreeController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.R;

2
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/WeSocketController.java → ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/WeSocketController.java

@ -1,4 +1,4 @@
package org.dromara.demo.controller;
package org.dromara.demo.controller.test;
import org.dromara.common.core.domain.R;
import org.dromara.common.websocket.dto.WebSocketMessageDto;

1
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/test/package-info.java

@ -0,0 +1 @@
package org.dromara.demo.controller.test;

77
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/AreaInfo.java

@ -0,0 +1,77 @@
package org.dromara.demo.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 区域信息对象 area_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("area_info")
public class AreaInfo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private String id;
/**
* 控制区
*/
private String district;
/**
* 水体
*/
private String river;
/**
* 控制断面
*/
private String controlSection;
/**
* 目标
*/
private String goal;
/**
* 十一五
*/
private String thirdFive;
/**
* 十二五
*/
private String fourthFive;
/**
* 十三五
*/
private String fifthFive;
/**
* 当前状态
*/
private Long status;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
}

15
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/Attachment.java

@ -0,0 +1,15 @@
package org.dromara.demo.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Attachment {
private String url;
private String name;
private String ossId;
}

89
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/AttachmentSerializer.java

@ -0,0 +1,89 @@
package org.dromara.demo.domain;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.List;
public class AttachmentSerializer {
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* 将List<Attachment>序列化为JSON字符串
*
* @param attachment 包含附件信息的列表
* @return 序列化后的JSON字符串
*/
public String serializeAttachments(List<Attachment> attachment) {
try {
// 使用ObjectMapper将List<Attachment>转换为JSON字符串
return objectMapper.writeValueAsString(attachment);
} catch (JsonProcessingException e) {
// 处理可能发生的异常
e.printStackTrace();
// 根据实际情况决定如何处理错误,这里简单地返回null
return null;
}
}
/**
* 将JSON字符串反序列化为List<Attachment>
*
* @param attachmentJson JSON格式的字符串
* @return 反序列化后的List<Attachment>
*/
public List<Attachment> deserializeAttachments(String attachmentJson) {
try {
// 使用ObjectMapper将JSON字符串转换回List<Attachment>
return objectMapper.readValue(attachmentJson, new TypeReference<List<Attachment>>() {});
} catch (JsonProcessingException e) {
// 处理可能发生的异常
e.printStackTrace();
// 根据实际情况决定如何处理错误,这里简单地返回null
return null;
}
}
// 测试方法
public static void main(String[] args) {
AttachmentSerializer serializer = new AttachmentSerializer();
// 创建一些模拟数据
List<Attachment> attachmentList = List.of(
new Attachment("http://example.com/file1.pdf", "File One", "ossId1"),
new Attachment("http://example.com/file2.docx", "File Two", "ossId2")
);
// 序列化
String serialized = serializer.serializeAttachments(attachmentList);
System.out.println(serialized); // 输出序列化后的JSON字符串
// 反序列化
List<Attachment> deserializedAttachments = serializer.deserializeAttachments(serialized);
System.out.println("Deserialized:");
if (deserializedAttachments != null) {
for (Attachment attachment : deserializedAttachments) {
System.out.println("URL: " + attachment.getUrl() + ", Name: " + attachment.getName() + ", ossId: " + attachment.getOssId());
}
} else {
System.out.println("Failed to deserialize the JSON string.");
}
// 模拟前端传来的字符串数组
String[] inputArray = {"A", "B", "C"};
System.out.println("输入的数组:"+ Arrays.toString(inputArray));
// 使用 String.join() 将数组元素用 "/" 连接
String result = String.join("/", inputArray);
// 输出结果
System.out.println("存入数据库中的结果:"+result); // 输出: A/B/C
// 使用 split 方法按 "/" 分割
String[] oldInputArray = result.split("/");
System.out.println("还原输入的数组:"+ Arrays.toString(oldInputArray));
}
}

162
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ProjectFileInfo.java

@ -0,0 +1,162 @@
package org.dromara.demo.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 项目文件信息对象 project_file_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("project_file_info")
public class ProjectFileInfo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private String id;
/**
* 项目id
*/
private String projectId;
/**
* 项目建议书
*/
private String projectProposal;
/**
* 可行性研究
*/
private String feasibilityStudy;
/**
* 初步设计
*/
private String preliminaryDesign;
/**
* 其他程序(项目前期立项)
*/
private String otherProcedure1;
/**
* 招标文件
*/
private String tenderDocument;
/**
* 投标文件
*/
private String bidDocument;
/**
* 其他程序(联合体招投标)
*/
private String otherProcedure2;
/**
* 工程开工
*/
private String projectCommencement;
/**
* 施工设计
*/
private String constructionDesign;
/**
* 资金来源
*/
private String fundingSource;
/**
* 进度管理
*/
private String scheduleManagement;
/**
* 成本管理
*/
private String costManagement;
/**
* 质量管理
*/
private String qualityManagement;
/**
* 合同管理
*/
private String contractManagement;
/**
* 技术管理
*/
private String technicalManagement;
/**
* 调试运行
*/
private String commissioningOperation;
/**
* 环保验收
*/
private String environmentalAcceptance;
/**
* 竣工验收
*/
private String finalAcceptance;
/**
* 工程结算
*/
private String projectSettlement;
/**
* 项目总结
*/
private String projectSummary;
/**
* 定期巡查
*/
private String regularInspection;
/**
* 管理模式
*/
private String managementModel;
/**
* 运行日志
*/
private String operationLog;
/**
* 当前状态
*/
private Long status;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
}

222
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/ProjectInfo.java

@ -0,0 +1,222 @@
package org.dromara.demo.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
/**
* 项目信息对象 project_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("project_info")
public class ProjectInfo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private String id;
/**
* 项目名称
*/
private String projectName;
/**
* 项目时期年月日
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date projectDate;
/**
* 规划投资(万元)
*/
private String planInvest;
/**
* 实际完成投资(万元)
*/
private String actualInvest;
/**
* 资金来源
*/
private String investResource;
/**
* 是否为规划内项目
*/
private String ifPlan;
/**
* 审批级别
*/
private String approvalLevel;
/**
* 预期目标
*/
private String expect;
/**
* 前期设计字符串数组JSON格式存储
*/
private String earlyDesign;
/**
* 所属区县
*/
private String district;
/**
* 所属控制区
*/
private String controlArea;
/**
* 所属小流域
*/
private String riverBasin;
/**
* 项目类别字符串数组JSON格式存储
*/
private String projectTypeList;
/**
* 水环境保护治理技术
*/
private String projectTech;
/**
* 技术名称
*/
private String techName;
/**
* 技术成本(/m²)
*/
private String techCost;
/**
* 运行成本(/m²)
*/
private String devCost;
/**
* 技术适用性
*/
private String techUsability;
/**
* 技术稳定性
*/
private String techStability;
/**
* 管理操作难易程度
*/
private String operationLevel;
/**
* 规划项目内容
*/
private String projectContent;
/**
* 完工情况
*/
private String projectProgress;
/**
* 验收方式
*/
private String acceptMethod;
/**
* 运行效果
*/
private String devResult;
/**
* 运行情况
*/
private String devStatus;
/**
* 目标实现(%)
*/
private String goal;
/**
* 巡查模式
*/
private String patrolType;
/**
* 管理模式
*/
private String manageType;
/**
* 长期运营
*/
private String longOperation;
/**
* COD削减率(%)
*/
private String cod;
/**
* TN削减(%)
*/
private String tn;
/**
* TP削减率(%)
*/
private String tp;
/**
* 资金完成率评分
*/
private String fundingCompletionScore;
/**
* 环境绩效评分
*/
private String environmentalPerformanceScore;
/**
* 长效运营评分
*/
private String longTermOperationScore;
/**
* 当前状态
*/
private Long status;
/**
* 删除标志0代表存在 2代表删除
*/
@TableLogic
private String delFlag;
}

78
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/AreaInfoBo.java

@ -0,0 +1,78 @@
package org.dromara.demo.domain.bo;
import org.dromara.demo.domain.AreaInfo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 区域信息业务对象 area_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = AreaInfo.class, reverseConvertGenerate = false)
public class AreaInfoBo extends BaseEntity {
/**
* 主键
*/
//@NotBlank(message = "主键不能为空", groups = { EditGroup.class })
private String id;
/**
* 控制区
*/
//@NotBlank(message = "控制区不能为空", groups = { AddGroup.class, EditGroup.class })
private String district;
/**
* 水体
*/
//@NotBlank(message = "水体不能为空", groups = { AddGroup.class, EditGroup.class })
private String river;
/**
* 控制断面
*/
//@NotBlank(message = "控制断面不能为空", groups = { AddGroup.class, EditGroup.class })
private String controlSection;
/**
* 目标
*/
//@NotBlank(message = "目标不能为空", groups = { AddGroup.class, EditGroup.class })
private String goal;
/**
* 十一五
*/
//@NotBlank(message = "十一五不能为空", groups = { AddGroup.class, EditGroup.class })
private String thirdFive;
/**
* 十二五
*/
//@NotBlank(message = "十二五不能为空", groups = { AddGroup.class, EditGroup.class })
private String fourthFive;
/**
* 十三五
*/
//@NotBlank(message = "十三五不能为空", groups = { AddGroup.class, EditGroup.class })
private String fifthFive;
/**
* 当前状态
*/
//@NotNull(message = "当前状态不能为空", groups = { AddGroup.class, EditGroup.class })
private Long status;
}

180
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/ProjectFileInfoBo.java

@ -0,0 +1,180 @@
package org.dromara.demo.domain.bo;
import org.dromara.demo.domain.ProjectFileInfo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 项目文件信息业务对象 project_file_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ProjectFileInfo.class, reverseConvertGenerate = false)
public class ProjectFileInfoBo extends BaseEntity {
/**
* 主键
*/
// @NotBlank(message = "主键不能为空", groups = { EditGroup.class })
private String id;
/**
* 项目id
*/
// @NotBlank(message = "项目id不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectId;
/**
* 项目建议书
*/
// @NotBlank(message = "项目建议书不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectProposal;
/**
* 可行性研究
*/
// @NotBlank(message = "可行性研究不能为空", groups = { AddGroup.class, EditGroup.class })
private String feasibilityStudy;
/**
* 初步设计
*/
// @NotBlank(message = "初步设计不能为空", groups = { AddGroup.class, EditGroup.class })
private String preliminaryDesign;
/**
* 其他程序(项目前期立项)
*/
// @NotBlank(message = "其他程序(项目前期立项)不能为空", groups = { AddGroup.class, EditGroup.class })
private String otherProcedure1;
/**
* 招标文件
*/
// @NotBlank(message = "招标文件不能为空", groups = { AddGroup.class, EditGroup.class })
private String tenderDocument;
/**
* 投标文件
*/
// @NotBlank(message = "投标文件不能为空", groups = { AddGroup.class, EditGroup.class })
private String bidDocument;
/**
* 其他程序(联合体招投标)
*/
// @NotBlank(message = "其他程序(联合体招投标)不能为空", groups = { AddGroup.class, EditGroup.class })
private String otherProcedure2;
/**
* 工程开工
*/
// @NotBlank(message = "工程开工不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectCommencement;
/**
* 施工设计
*/
// @NotBlank(message = "施工设计不能为空", groups = { AddGroup.class, EditGroup.class })
private String constructionDesign;
/**
* 资金来源
*/
// @NotBlank(message = "资金来源不能为空", groups = { AddGroup.class, EditGroup.class })
private String fundingSource;
/**
* 进度管理
*/
// @NotBlank(message = "进度管理不能为空", groups = { AddGroup.class, EditGroup.class })
private String scheduleManagement;
/**
* 成本管理
*/
// @NotBlank(message = "成本管理不能为空", groups = { AddGroup.class, EditGroup.class })
private String costManagement;
/**
* 质量管理
*/
// @NotBlank(message = "质量管理不能为空", groups = { AddGroup.class, EditGroup.class })
private String qualityManagement;
/**
* 合同管理
*/
// @NotBlank(message = "合同管理不能为空", groups = { AddGroup.class, EditGroup.class })
private String contractManagement;
/**
* 技术管理
*/
// @NotBlank(message = "技术管理不能为空", groups = { AddGroup.class, EditGroup.class })
private String technicalManagement;
/**
* 调试运行
*/
// @NotBlank(message = "调试运行不能为空", groups = { AddGroup.class, EditGroup.class })
private String commissioningOperation;
/**
* 环保验收
*/
// @NotBlank(message = "环保验收不能为空", groups = { AddGroup.class, EditGroup.class })
private String environmentalAcceptance;
/**
* 竣工验收
*/
// @NotBlank(message = "竣工验收不能为空", groups = { AddGroup.class, EditGroup.class })
private String finalAcceptance;
/**
* 工程结算
*/
// @NotBlank(message = "工程结算不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectSettlement;
/**
* 项目总结
*/
// @NotBlank(message = "项目总结不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectSummary;
/**
* 定期巡查
*/
// @NotBlank(message = "定期巡查不能为空", groups = { AddGroup.class, EditGroup.class })
private String regularInspection;
/**
* 管理模式
*/
// @NotBlank(message = "管理模式不能为空", groups = { AddGroup.class, EditGroup.class })
private String managementModel;
/**
* 运行日志
*/
// @NotBlank(message = "运行日志不能为空", groups = { AddGroup.class, EditGroup.class })
private String operationLog;
/**
* 当前状态
*/
// @NotNull(message = "当前状态不能为空", groups = { AddGroup.class, EditGroup.class })
private Long status;
}

248
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/ProjectInfoBo.java

@ -0,0 +1,248 @@
package org.dromara.demo.domain.bo;
import org.dromara.demo.domain.ProjectInfo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 项目信息业务对象 project_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ProjectInfo.class, reverseConvertGenerate = false)
public class ProjectInfoBo extends BaseEntity {
/**
* 主键ID
*/
//@NotBlank(message = "主键ID不能为空", groups = { EditGroup.class })
private String id;
/**
* 项目名称
*/
//@NotBlank(message = "项目名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectName;
/**
* 项目时期年月日
*/
//@NotNull(message = "项目时期(年月日)不能为空", groups = { AddGroup.class, EditGroup.class })
private Date projectDate;
/**
* 规划投资(万元)
*/
//@NotBlank(message = "规划投资(万元)不能为空", groups = { AddGroup.class, EditGroup.class })
private String planInvest;
/**
* 实际完成投资(万元)
*/
//@NotBlank(message = "实际完成投资(万元)不能为空", groups = { AddGroup.class, EditGroup.class })
private String actualInvest;
/**
* 资金来源
*/
//@NotBlank(message = "资金来源不能为空", groups = { AddGroup.class, EditGroup.class })
private String investResource;
/**
* 是否为规划内项目
*/
//@NotBlank(message = "是否为规划内项目不能为空", groups = { AddGroup.class, EditGroup.class })
private String ifPlan;
/**
* 批复等级
*/
//@NotBlank(message = "审批级别不能为空", groups = { AddGroup.class, EditGroup.class })
private String approvalLevel;
/**
* 预期目标
*/
//@NotBlank(message = "预期目标不能为空", groups = { AddGroup.class, EditGroup.class })
private String expect;
/**
* 前期设计字符串数组JSON格式存储
*/
//@NotBlank(message = "前期设计(字符串数组,JSON格式存储)不能为空", groups = { AddGroup.class, EditGroup.class })
private String earlyDesign;
/**
* 所属区县
*/
//@NotBlank(message = "所属区县不能为空", groups = { AddGroup.class, EditGroup.class })
private String district;
/**
* 所属控制区
*/
//@NotBlank(message = "所属控制区不能为空", groups = { AddGroup.class, EditGroup.class })
private String controlArea;
/**
* 所属小流域
*/
//@NotBlank(message = "所属小流域不能为空", groups = { AddGroup.class, EditGroup.class })
private String riverBasin;
/**
* 项目类别字符串数组JSON格式存储
*/
//@NotBlank(message = "项目类别(字符串数组,JSON格式存储)不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectTypeList;
/**
* 水环境保护治理技术
*/
//@NotBlank(message = "水环境保护治理技术不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectTech;
/**
* 技术名称
*/
//@NotBlank(message = "技术名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String techName;
/**
* 技术成本(/m²)
*/
//@NotBlank(message = "技术成本(元/m²)不能为空", groups = { AddGroup.class, EditGroup.class })
private String techCost;
/**
* 运行成本(/m²)
*/
//@NotBlank(message = "运行成本(元/m²)不能为空", groups = { AddGroup.class, EditGroup.class })
private String devCost;
/**
* 技术适用性
*/
//@NotBlank(message = "技术适用性不能为空", groups = { AddGroup.class, EditGroup.class })
private String techUsability;
/**
* 技术稳定性
*/
//@NotBlank(message = "技术稳定性不能为空", groups = { AddGroup.class, EditGroup.class })
private String techStability;
/**
* 管理操作难易程度
*/
//@NotBlank(message = "管理操作难易程度不能为空", groups = { AddGroup.class, EditGroup.class })
private String operationLevel;
/**
* 规划项目内容
*/
//@NotBlank(message = "规划项目内容不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectContent;
/**
* 完工情况
*/
//@NotBlank(message = "完工情况不能为空", groups = { AddGroup.class, EditGroup.class })
private String projectProgress;
/**
* 验收方式
*/
//@NotBlank(message = "验收方式不能为空", groups = { AddGroup.class, EditGroup.class })
private String acceptMethod;
/**
* 运行效果
*/
//@NotBlank(message = "运行效果不能为空", groups = { AddGroup.class, EditGroup.class })
private String devResult;
/**
* 运行情况
*/
//@NotBlank(message = "运行情况不能为空", groups = { AddGroup.class, EditGroup.class })
private String devStatus;
/**
* 目标实现(%)
*/
//@NotBlank(message = "目标实现(%)不能为空", groups = { AddGroup.class, EditGroup.class })
private String goal;
/**
* 巡查模式
*/
//@NotBlank(message = "巡查模式不能为空", groups = { AddGroup.class, EditGroup.class })
private String patrolType;
/**
* 管理模式
*/
//@NotBlank(message = "管理模式不能为空", groups = { AddGroup.class, EditGroup.class })
private String manageType;
/**
* 长期运营
*/
//@NotBlank(message = "长期运营不能为空", groups = { AddGroup.class, EditGroup.class })
private String longOperation;
/**
* COD削减率(%)
*/
//@NotBlank(message = "COD削减率(%)不能为空", groups = { AddGroup.class, EditGroup.class })
private String cod;
/**
* TN削减(%)
*/
//@NotBlank(message = "TN削减(%)不能为空", groups = { AddGroup.class, EditGroup.class })
private String tn;
/**
* TP削减率(%)
*/
//@NotBlank(message = "TP削减率(%)不能为空", groups = { AddGroup.class, EditGroup.class })
private String tp;
/**
* 资金完成率评分
*/
//@NotBlank(message = "资金完成率评分不能为空", groups = { AddGroup.class, EditGroup.class })
private String fundingCompletionScore;
/**
* 环境绩效评分
*/
//@NotBlank(message = "环境绩效评分不能为空", groups = { AddGroup.class, EditGroup.class })
private String environmentalPerformanceScore;
/**
* 长效运营评分
*/
//@NotBlank(message = "长效运营评分不能为空", groups = { AddGroup.class, EditGroup.class })
private String longTermOperationScore;
/**
* 当前状态
*/
//@NotNull(message = "当前状态不能为空", groups = { AddGroup.class, EditGroup.class })
private Long status;
}

15
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AllGoatAchieveDataVo.java

@ -0,0 +1,15 @@
package org.dromara.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AllGoatAchieveDataVo {
private String date;
private String planInvest;
private String actualInvest;
private String investPercent;
}

15
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AllGoatAchieveVo.java

@ -0,0 +1,15 @@
package org.dromara.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AllGoatAchieveVo {
private List<AllGoatAchieveDataVo> projectInfo;
private List<String> description;
}

14
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AreaInfoFinalVo.java

@ -0,0 +1,14 @@
package org.dromara.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AreaInfoFinalVo {
private List<AreaInfoVo> areaInfo;
private String description;
}

86
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/AreaInfoVo.java

@ -0,0 +1,86 @@
package org.dromara.demo.domain.vo;
import org.dromara.demo.domain.AreaInfo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 区域信息视图对象 area_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = AreaInfo.class)
public class AreaInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private String id;
/**
* 控制区
*/
@ExcelProperty(value = "控制区")
private String district;
/**
* 水体
*/
@ExcelProperty(value = "水体")
private String river;
/**
* 控制断面
*/
@ExcelProperty(value = "控制断面")
private String controlSection;
/**
* 目标
*/
@ExcelProperty(value = "目标")
private String goal;
/**
* 十一五
*/
@ExcelProperty(value = "十一五")
private String thirdFive;
/**
* 十二五
*/
@ExcelProperty(value = "十二五")
private String fourthFive;
/**
* 十三五
*/
@ExcelProperty(value = "十三五")
private String fifthFive;
/**
* 当前状态
*/
@ExcelProperty(value = "当前状态")
private Long status;
}

73
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/DeaResultVo.java

@ -0,0 +1,73 @@
package org.dromara.demo.domain.vo;
// DeaResultVo.java
public class DeaResultVo {
private String dmu;
private Double overallEfficiency;
private Double scale;
private Double scaleEfficiency;
private String scalePay;
private Double beyondEfficiency;
// 构造函数(可选)
public DeaResultVo() {}
public DeaResultVo(String dmu, Double overallEfficiency, Double scale,
Double scaleEfficiency, String scalePay, Double beyondEfficiency) {
this.dmu = dmu;
this.overallEfficiency = overallEfficiency;
this.scale = scale;
this.scaleEfficiency = scaleEfficiency;
this.scalePay = scalePay;
this.beyondEfficiency = beyondEfficiency;
}
// Getter 和 Setter
public String getDmu() {
return dmu;
}
public void setDmu(String dmu) {
this.dmu = dmu;
}
public Double getOverallEfficiency() {
return overallEfficiency;
}
public void setOverallEfficiency(Double overallEfficiency) {
this.overallEfficiency = overallEfficiency;
}
public Double getScale() {
return scale;
}
public void setScale(Double scale) {
this.scale = scale;
}
public Double getScaleEfficiency() {
return scaleEfficiency;
}
public void setScaleEfficiency(Double scaleEfficiency) {
this.scaleEfficiency = scaleEfficiency;
}
public String getScalePay() {
return scalePay;
}
public void setScalePay(String scalePay) {
this.scalePay = scalePay;
}
public Double getBeyondEfficiency() {
return beyondEfficiency;
}
public void setBeyondEfficiency(Double beyondEfficiency) {
this.beyondEfficiency = beyondEfficiency;
}
}

41
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/PH.java

@ -0,0 +1,41 @@
package org.dromara.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PH {
private List<Integer> timeList = new ArrayList<>(); // ✅ 初始化!
private List<Double> phList = new ArrayList<>(); // ✅ 初始化!
/**
* 检测时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime currentTime;
/**
* 检测值
*/
private Double currentValue;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
}

188
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ProjectFileInfoVo.java

@ -0,0 +1,188 @@
package org.dromara.demo.domain.vo;
import org.dromara.demo.domain.ProjectFileInfo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 项目文件信息视图对象 project_file_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ProjectFileInfo.class)
public class ProjectFileInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private String id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private String projectId;
/**
* 项目建议书
*/
@ExcelProperty(value = "项目建议书")
private String projectProposal;
/**
* 可行性研究
*/
@ExcelProperty(value = "可行性研究")
private String feasibilityStudy;
/**
* 初步设计
*/
@ExcelProperty(value = "初步设计")
private String preliminaryDesign;
/**
* 其他程序(项目前期立项)
*/
@ExcelProperty(value = "其他程序(项目前期立项)")
private String otherProcedure1;
/**
* 招标文件
*/
@ExcelProperty(value = "招标文件")
private String tenderDocument;
/**
* 投标文件
*/
@ExcelProperty(value = "投标文件")
private String bidDocument;
/**
* 其他程序(联合体招投标)
*/
@ExcelProperty(value = "其他程序(联合体招投标)")
private String otherProcedure2;
/**
* 工程开工
*/
@ExcelProperty(value = "工程开工")
private String projectCommencement;
/**
* 施工设计
*/
@ExcelProperty(value = "施工设计")
private String constructionDesign;
/**
* 资金来源
*/
@ExcelProperty(value = "资金来源")
private String fundingSource;
/**
* 进度管理
*/
@ExcelProperty(value = "进度管理")
private String scheduleManagement;
/**
* 成本管理
*/
@ExcelProperty(value = "成本管理")
private String costManagement;
/**
* 质量管理
*/
@ExcelProperty(value = "质量管理")
private String qualityManagement;
/**
* 合同管理
*/
@ExcelProperty(value = "合同管理")
private String contractManagement;
/**
* 技术管理
*/
@ExcelProperty(value = "技术管理")
private String technicalManagement;
/**
* 调试运行
*/
@ExcelProperty(value = "调试运行")
private String commissioningOperation;
/**
* 环保验收
*/
@ExcelProperty(value = "环保验收")
private String environmentalAcceptance;
/**
* 竣工验收
*/
@ExcelProperty(value = "竣工验收")
private String finalAcceptance;
/**
* 工程结算
*/
@ExcelProperty(value = "工程结算")
private String projectSettlement;
/**
* 项目总结
*/
@ExcelProperty(value = "项目总结")
private String projectSummary;
/**
* 定期巡查
*/
@ExcelProperty(value = "定期巡查")
private String regularInspection;
/**
* 管理模式
*/
@ExcelProperty(value = "管理模式")
private String managementModel;
/**
* 运行日志
*/
@ExcelProperty(value = "运行日志")
private String operationLog;
/**
* 当前状态
*/
@ExcelProperty(value = "当前状态")
private Long status;
}

259
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ProjectInfoVo.java

@ -0,0 +1,259 @@
package org.dromara.demo.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.demo.domain.ProjectInfo;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 项目信息视图对象 project_info
*
* @author GJH
* @date 2025-08-19
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ProjectInfo.class)
public class ProjectInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private String id;
/**
* 项目名称
*/
@ExcelProperty(value = "项目名称")
private String projectName;
/**
* 项目时期年月日
*/
@ExcelProperty(value = "项目时期")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date projectDate;
/**
* 规划投资(万元)
*/
@ExcelProperty(value = "规划投资(万元)")
private String planInvest;
/**
* 实际完成投资(万元)
*/
@ExcelProperty(value = "实际完成投资(万元)")
private String actualInvest;
/**
* 资金来源
*/
@ExcelProperty(value = "资金来源")
private String investResource;
/**
* 是否为规划内项目
*/
@ExcelProperty(value = "是否为规划内项目")
private String ifPlan;
/**
* 批复等级
*/
@ExcelProperty(value = "批复等级")
private String approvalLevel;
/**
* 预期目标
*/
@ExcelProperty(value = "预期目标")
private String expect;
/**
* 前期设计字符串数组JSON格式存储
*/
@ExcelProperty(value = "前期设计")
//@ExcelDictFormat(readConverterExp = "字=符串数组,JSON格式存储")
private String earlyDesign;
/**
* 所属区县
*/
@ExcelProperty(value = "所属区县")
private String district;
/**
* 所属控制区
*/
@ExcelProperty(value = "所属控制区")
private String controlArea;
/**
* 所属小流域
*/
@ExcelProperty(value = "所属小流域")
private String riverBasin;
/**
* 项目类别字符串数组JSON格式存储
*/
@ExcelProperty(value = "项目类别")
//@ExcelDictFormat(readConverterExp = "字=符串数组,JSON格式存储")
private String projectTypeList;
/**
* 水环境保护治理技术
*/
@ExcelProperty(value = "水环境保护治理技术")
private String projectTech;
/**
* 技术名称
*/
@ExcelProperty(value = "技术名称")
private String techName;
/**
* 技术成本(/m²)
*/
@ExcelProperty(value = "技术成本(元/m²)")
private String techCost;
/**
* 运行成本(/m²)
*/
@ExcelProperty(value = "运行成本(元/m²)")
private String devCost;
/**
* 技术适用性
*/
@ExcelProperty(value = "技术适用性")
private String techUsability;
/**
* 技术稳定性
*/
@ExcelProperty(value = "技术稳定性")
private String techStability;
/**
* 管理操作难易程度
*/
@ExcelProperty(value = "管理操作难易程度")
private String operationLevel;
/**
* 规划项目内容
*/
@ExcelProperty(value = "规划项目内容")
private String projectContent;
/**
* 完工情况
*/
@ExcelProperty(value = "完工情况")
private String projectProgress;
/**
* 验收方式
*/
@ExcelProperty(value = "验收方式")
private String acceptMethod;
/**
* 运行效果
*/
@ExcelProperty(value = "运行效果")
private String devResult;
/**
* 运行情况
*/
@ExcelProperty(value = "运行情况")
private String devStatus;
/**
* 目标实现(%)
*/
@ExcelProperty(value = "目标实现(%)")
private String goal;
/**
* 巡查模式
*/
@ExcelProperty(value = "巡查模式")
private String patrolType;
/**
* 管理模式
*/
@ExcelProperty(value = "管理模式")
private String manageType;
/**
* 长期运营
*/
@ExcelProperty(value = "长期运营")
private String longOperation;
/**
* COD削减率(%)
*/
@ExcelProperty(value = "COD削减率(%)")
private String cod;
/**
* TN削减(%)
*/
@ExcelProperty(value = "TN削减(%)")
private String tn;
/**
* TP削减率(%)
*/
@ExcelProperty(value = "TP削减率(%)")
private String tp;
/**
* 资金完成率评分
*/
@ExcelProperty(value = "资金完成率评分")
private String fundingCompletionScore;
/**
* 环境绩效评分
*/
@ExcelProperty(value = "环境绩效评分")
private String environmentalPerformanceScore;
/**
* 长效运营评分
*/
@ExcelProperty(value = "长效运营评分")
private String longTermOperationScore;
/**
* 当前状态
*/
@ExcelProperty(value = "当前状态")
private Long status;
}

35
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ProjectPerformanceVo.java

@ -0,0 +1,35 @@
package org.dromara.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProjectPerformanceVo {
private String projectName;
// 总体描述
private String description;
private String projectType;
// 批复等级得分
private Double approvalLevelScore;
// 前期设计得分
private Double earlyDesignScore;
// 资金来源得分
private Double investResourceScore;
// 验收方式得分
private Double acceptMethodScore;
// 巡查模式得分
private Double patrolTypeScore;
// 管理方式得分
private Double manageTypeScore;
// 运行情况得分
private Double devStatusScore;
}

41
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/StationDetailVo.java

@ -0,0 +1,41 @@
package org.dromara.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StationDetailVo {
private List<XY> xyList = new ArrayList<>();
/**
* 检测时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime currentTime;
/**
* 检测值
*/
private Double currentValue;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
}

24
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/StationInfoVo.java

@ -0,0 +1,24 @@
package org.dromara.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StationInfoVo {
/**
* 站点名称
*/
private String stationName;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
}

16
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/XY.java

@ -0,0 +1,16 @@
package org.dromara.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
/**
* 坐标对象
*/
public class XY {
private Integer x;
private Double y;
}

36
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/AreaListener.java

@ -0,0 +1,36 @@
package org.dromara.demo.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import jakarta.annotation.Resource;
import org.dromara.demo.domain.AreaInfo;
import org.dromara.demo.domain.bo.AreaInfoBo;
import org.dromara.demo.domain.bo.ProjectInfoBo;
import org.dromara.demo.domain.vo.AreaInfoVo;
import org.dromara.demo.domain.vo.ProjectInfoVo;
import org.dromara.demo.service.IAreaInfoService;
import org.dromara.demo.service.IProjectInfoService;
import org.springframework.beans.BeanUtils;
public class AreaListener implements ReadListener<AreaInfoVo> {
@Resource
private IAreaInfoService areaInfoService ;
public AreaListener(IAreaInfoService areaInfoService) {
this.areaInfoService = areaInfoService;
}
@Override
public void invoke(AreaInfoVo areaInfoVo, AnalysisContext analysisContext) {
AreaInfoBo areaInfo = new AreaInfoBo();
BeanUtils.copyProperties(areaInfoVo,areaInfo);
areaInfoService.insertByBo(areaInfo);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}

32
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ProjectInfoListener.java

@ -0,0 +1,32 @@
package org.dromara.demo.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import jakarta.annotation.Resource;
import org.dromara.demo.domain.bo.ProjectInfoBo;
import org.dromara.demo.domain.vo.ProjectInfoVo;
import org.dromara.demo.service.IProjectInfoService;
import org.springframework.beans.BeanUtils;
public class ProjectInfoListener implements ReadListener<ProjectInfoVo> {
@Resource
private IProjectInfoService projectInfoService ;
public ProjectInfoListener(IProjectInfoService projectInfoService) {
this.projectInfoService = projectInfoService;
}
@Override
public void invoke(ProjectInfoVo projectInfoVo, AnalysisContext analysisContext) {
ProjectInfoBo projectInfo = new ProjectInfoBo();
BeanUtils.copyProperties(projectInfoVo,projectInfo);
projectInfoService.insertByBo(projectInfo);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}

15
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/AreaInfoMapper.java

@ -0,0 +1,15 @@
package org.dromara.demo.mapper;
import org.dromara.demo.domain.AreaInfo;
import org.dromara.demo.domain.vo.AreaInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 区域信息Mapper接口
*
* @author GJH
* @date 2025-08-19
*/
public interface AreaInfoMapper extends BaseMapperPlus<AreaInfo, AreaInfoVo> {
}

15
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/ProjectFileInfoMapper.java

@ -0,0 +1,15 @@
package org.dromara.demo.mapper;
import org.dromara.demo.domain.ProjectFileInfo;
import org.dromara.demo.domain.vo.ProjectFileInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 项目文件信息Mapper接口
*
* @author GJH
* @date 2025-08-19
*/
public interface ProjectFileInfoMapper extends BaseMapperPlus<ProjectFileInfo, ProjectFileInfoVo> {
}

15
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/ProjectInfoMapper.java

@ -0,0 +1,15 @@
package org.dromara.demo.mapper;
import org.dromara.demo.domain.ProjectInfo;
import org.dromara.demo.domain.vo.ProjectInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 项目信息Mapper接口
*
* @author GJH
* @date 2025-08-19
*/
public interface ProjectInfoMapper extends BaseMapperPlus<ProjectInfo, ProjectInfoVo> {
}

71
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IAreaInfoService.java

@ -0,0 +1,71 @@
package org.dromara.demo.service;
import org.dromara.demo.domain.vo.AreaInfoFinalVo;
import org.dromara.demo.domain.vo.AreaInfoVo;
import org.dromara.demo.domain.bo.AreaInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 区域信息Service接口
*
* @author GJH
* @date 2025-08-19
*/
public interface IAreaInfoService {
/**
* 查询区域信息
*
* @param id 主键
* @return 区域信息
*/
AreaInfoVo queryById(String id);
/**
* 分页查询区域信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 区域信息分页列表
*/
TableDataInfo<AreaInfoVo> queryPageList(AreaInfoBo bo, PageQuery pageQuery);
/**
* 查询符合条件的区域信息列表
*
* @param bo 查询条件
* @return 区域信息列表
*/
List<AreaInfoVo> queryList(AreaInfoBo bo);
/**
* 新增区域信息
*
* @param bo 区域信息
* @return 是否新增成功
*/
Boolean insertByBo(AreaInfoBo bo);
/**
* 修改区域信息
*
* @param bo 区域信息
* @return 是否修改成功
*/
Boolean updateByBo(AreaInfoBo bo);
/**
* 校验并批量删除区域信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
List<AreaInfoFinalVo> getList(AreaInfoBo bo);
}

68
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IProjectFileInfoService.java

@ -0,0 +1,68 @@
package org.dromara.demo.service;
import org.dromara.demo.domain.vo.ProjectFileInfoVo;
import org.dromara.demo.domain.bo.ProjectFileInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 项目文件信息Service接口
*
* @author GJH
* @date 2025-08-19
*/
public interface IProjectFileInfoService {
/**
* 查询项目文件信息
*
* @param id 主键
* @return 项目文件信息
*/
ProjectFileInfoVo queryById(String id);
/**
* 分页查询项目文件信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 项目文件信息分页列表
*/
TableDataInfo<ProjectFileInfoVo> queryPageList(ProjectFileInfoBo bo, PageQuery pageQuery);
/**
* 查询符合条件的项目文件信息列表
*
* @param bo 查询条件
* @return 项目文件信息列表
*/
List<ProjectFileInfoVo> queryList(ProjectFileInfoBo bo);
/**
* 新增项目文件信息
*
* @param bo 项目文件信息
* @return 是否新增成功
*/
Boolean insertByBo(ProjectFileInfoBo bo);
/**
* 修改项目文件信息
*
* @param bo 项目文件信息
* @return 是否修改成功
*/
Boolean updateByBo(ProjectFileInfoBo bo);
/**
* 校验并批量删除项目文件信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
}

91
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IProjectInfoService.java

@ -0,0 +1,91 @@
package org.dromara.demo.service;
import org.dromara.demo.domain.ProjectInfo;
import org.dromara.demo.domain.vo.*;
import org.dromara.demo.domain.bo.ProjectInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 项目信息Service接口
*
* @author GJH
* @date 2025-08-19
*/
public interface IProjectInfoService {
/**
* 查询项目信息
*
* @param id 主键
* @return 项目信息
*/
ProjectInfoVo queryById(String id);
/**
* 分页查询项目信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 项目信息分页列表
*/
TableDataInfo<ProjectInfoVo> queryPageList(ProjectInfoBo bo, PageQuery pageQuery);
/**
* 查询符合条件的项目信息列表
*
* @param bo 查询条件
* @return 项目信息列表
*/
List<ProjectInfoVo> queryList(ProjectInfoBo bo);
/**
* 新增项目信息
*
* @param bo 项目信息
* @return 是否新增成功
*/
Boolean insertByBo(ProjectInfoBo bo);
/**
* 修改项目信息
*
* @param bo 项目信息
* @return 是否修改成功
*/
Boolean updateByBo(ProjectInfoBo bo);
/**
* 校验并批量删除项目信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
void addData(List<ProjectInfo> list);
/**
* 获取项目投资年度统计按年份累加计划/实际投资并计算完成率只返回数字不带%
* @return AllGoatAchieve 列表date 字段为年份
*/
List<AllGoatAchieveDataVo> getYearlyInvestmentStats();
List<ProjectPerformanceVo> getPerformanceScore(ProjectInfoBo bo);
ProjectPerformanceVo calculateAverageByType(ProjectInfoBo bo);
List<DeaResultVo> getDeaSimulationResults();
PH getPH();
List<StationInfoVo> getStations();
StationDetailVo getWaterQualityData(String type);
}

165
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/AreaInfoServiceImpl.java

@ -0,0 +1,165 @@
package org.dromara.demo.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.demo.domain.vo.AreaInfoFinalVo;
import org.springframework.stereotype.Service;
import org.dromara.demo.domain.bo.AreaInfoBo;
import org.dromara.demo.domain.vo.AreaInfoVo;
import org.dromara.demo.domain.AreaInfo;
import org.dromara.demo.mapper.AreaInfoMapper;
import org.dromara.demo.service.IAreaInfoService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* 区域信息Service业务层处理
*
* @author GJH
* @date 2025-08-19
*/
@RequiredArgsConstructor
@Service
public class AreaInfoServiceImpl implements IAreaInfoService {
private final AreaInfoMapper baseMapper;
/**
* 查询区域信息
*
* @param id 主键
* @return 区域信息
*/
@Override
public AreaInfoVo queryById(String id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询区域信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 区域信息分页列表
*/
@Override
public TableDataInfo<AreaInfoVo> queryPageList(AreaInfoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<AreaInfo> lqw = buildQueryWrapper(bo);
Page<AreaInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的区域信息列表
*
* @param bo 查询条件
* @return 区域信息列表
*/
@Override
public List<AreaInfoVo> queryList(AreaInfoBo bo) {
LambdaQueryWrapper<AreaInfo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<AreaInfo> buildQueryWrapper(AreaInfoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<AreaInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getDistrict()), AreaInfo::getDistrict, bo.getDistrict());
lqw.eq(StringUtils.isNotBlank(bo.getRiver()), AreaInfo::getRiver, bo.getRiver());
lqw.eq(StringUtils.isNotBlank(bo.getControlSection()), AreaInfo::getControlSection, bo.getControlSection());
lqw.eq(StringUtils.isNotBlank(bo.getGoal()), AreaInfo::getGoal, bo.getGoal());
lqw.eq(StringUtils.isNotBlank(bo.getThirdFive()), AreaInfo::getThirdFive, bo.getThirdFive());
lqw.eq(StringUtils.isNotBlank(bo.getFourthFive()), AreaInfo::getFourthFive, bo.getFourthFive());
lqw.eq(StringUtils.isNotBlank(bo.getFifthFive()), AreaInfo::getFifthFive, bo.getFifthFive());
lqw.eq(bo.getStatus() != null, AreaInfo::getStatus, bo.getStatus());
return lqw;
}
/**
* 新增区域信息
*
* @param bo 区域信息
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(AreaInfoBo bo) {
AreaInfo add = MapstructUtils.convert(bo, AreaInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改区域信息
*
* @param bo 区域信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(AreaInfoBo bo) {
AreaInfo update = MapstructUtils.convert(bo, AreaInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(AreaInfo entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除区域信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public List<AreaInfoFinalVo> getList(AreaInfoBo bo) {
String des = "从“九五~十三五”期间,XX区实际实施项目208项,其中完工168项。累计完成总投资为199.38亿元。" +
"累积完成4座污水处理厂新建与扩建,新建8座调蓄池;管道建设641.45km;河道清淤14.86万m3;生态修复2193.96亩。";
// 从数据库中获取的所有区域信息
List<AreaInfoVo> areaInfoVos = this.queryList(bo);
if (CollectionUtil.isNotEmpty(areaInfoVos)){
// 按 district(区域)分组
Map<String, List<AreaInfoVo>> groupedByDistrict = areaInfoVos.stream()
.collect(Collectors.groupingBy(AreaInfoVo::getDistrict));
// 转换为 List<AreaInfoFinalVo>
// TODO 各区AI描述待提供
List<AreaInfoFinalVo> result = new ArrayList<>();
for (Map.Entry<String, List<AreaInfoVo>> entry : groupedByDistrict.entrySet()) {
result.add(new AreaInfoFinalVo(entry.getValue(), des)); // description 先为默认
}
return result;
}
return new ArrayList<>();
}
}

153
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ProjectFileInfoServiceImpl.java

@ -0,0 +1,153 @@
package org.dromara.demo.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.demo.domain.bo.ProjectFileInfoBo;
import org.dromara.demo.domain.vo.ProjectFileInfoVo;
import org.dromara.demo.domain.ProjectFileInfo;
import org.dromara.demo.mapper.ProjectFileInfoMapper;
import org.dromara.demo.service.IProjectFileInfoService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 项目文件信息Service业务层处理
*
* @author GJH
* @date 2025-08-19
*/
@RequiredArgsConstructor
@Service
public class ProjectFileInfoServiceImpl implements IProjectFileInfoService {
private final ProjectFileInfoMapper baseMapper;
/**
* 查询项目文件信息
*
* @param id 主键
* @return 项目文件信息
*/
@Override
public ProjectFileInfoVo queryById(String id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询项目文件信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 项目文件信息分页列表
*/
@Override
public TableDataInfo<ProjectFileInfoVo> queryPageList(ProjectFileInfoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ProjectFileInfo> lqw = buildQueryWrapper(bo);
Page<ProjectFileInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的项目文件信息列表
*
* @param bo 查询条件
* @return 项目文件信息列表
*/
@Override
public List<ProjectFileInfoVo> queryList(ProjectFileInfoBo bo) {
LambdaQueryWrapper<ProjectFileInfo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ProjectFileInfo> buildQueryWrapper(ProjectFileInfoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ProjectFileInfo> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getProjectId()), ProjectFileInfo::getProjectId, bo.getProjectId());
lqw.eq(StringUtils.isNotBlank(bo.getProjectProposal()), ProjectFileInfo::getProjectProposal, bo.getProjectProposal());
lqw.eq(StringUtils.isNotBlank(bo.getFeasibilityStudy()), ProjectFileInfo::getFeasibilityStudy, bo.getFeasibilityStudy());
lqw.eq(StringUtils.isNotBlank(bo.getPreliminaryDesign()), ProjectFileInfo::getPreliminaryDesign, bo.getPreliminaryDesign());
lqw.eq(StringUtils.isNotBlank(bo.getOtherProcedure1()), ProjectFileInfo::getOtherProcedure1, bo.getOtherProcedure1());
lqw.eq(StringUtils.isNotBlank(bo.getTenderDocument()), ProjectFileInfo::getTenderDocument, bo.getTenderDocument());
lqw.eq(StringUtils.isNotBlank(bo.getBidDocument()), ProjectFileInfo::getBidDocument, bo.getBidDocument());
lqw.eq(StringUtils.isNotBlank(bo.getOtherProcedure2()), ProjectFileInfo::getOtherProcedure2, bo.getOtherProcedure2());
lqw.eq(StringUtils.isNotBlank(bo.getProjectCommencement()), ProjectFileInfo::getProjectCommencement, bo.getProjectCommencement());
lqw.eq(StringUtils.isNotBlank(bo.getConstructionDesign()), ProjectFileInfo::getConstructionDesign, bo.getConstructionDesign());
lqw.eq(StringUtils.isNotBlank(bo.getFundingSource()), ProjectFileInfo::getFundingSource, bo.getFundingSource());
lqw.eq(StringUtils.isNotBlank(bo.getScheduleManagement()), ProjectFileInfo::getScheduleManagement, bo.getScheduleManagement());
lqw.eq(StringUtils.isNotBlank(bo.getCostManagement()), ProjectFileInfo::getCostManagement, bo.getCostManagement());
lqw.eq(StringUtils.isNotBlank(bo.getQualityManagement()), ProjectFileInfo::getQualityManagement, bo.getQualityManagement());
lqw.eq(StringUtils.isNotBlank(bo.getContractManagement()), ProjectFileInfo::getContractManagement, bo.getContractManagement());
lqw.eq(StringUtils.isNotBlank(bo.getTechnicalManagement()), ProjectFileInfo::getTechnicalManagement, bo.getTechnicalManagement());
lqw.eq(StringUtils.isNotBlank(bo.getCommissioningOperation()), ProjectFileInfo::getCommissioningOperation, bo.getCommissioningOperation());
lqw.eq(StringUtils.isNotBlank(bo.getEnvironmentalAcceptance()), ProjectFileInfo::getEnvironmentalAcceptance, bo.getEnvironmentalAcceptance());
lqw.eq(StringUtils.isNotBlank(bo.getFinalAcceptance()), ProjectFileInfo::getFinalAcceptance, bo.getFinalAcceptance());
lqw.eq(StringUtils.isNotBlank(bo.getProjectSettlement()), ProjectFileInfo::getProjectSettlement, bo.getProjectSettlement());
lqw.eq(StringUtils.isNotBlank(bo.getProjectSummary()), ProjectFileInfo::getProjectSummary, bo.getProjectSummary());
lqw.eq(StringUtils.isNotBlank(bo.getRegularInspection()), ProjectFileInfo::getRegularInspection, bo.getRegularInspection());
lqw.eq(StringUtils.isNotBlank(bo.getManagementModel()), ProjectFileInfo::getManagementModel, bo.getManagementModel());
lqw.eq(StringUtils.isNotBlank(bo.getOperationLog()), ProjectFileInfo::getOperationLog, bo.getOperationLog());
lqw.eq(bo.getStatus() != null, ProjectFileInfo::getStatus, bo.getStatus());
return lqw;
}
/**
* 新增项目文件信息
*
* @param bo 项目文件信息
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(ProjectFileInfoBo bo) {
ProjectFileInfo add = MapstructUtils.convert(bo, ProjectFileInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改项目文件信息
*
* @param bo 项目文件信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(ProjectFileInfoBo bo) {
ProjectFileInfo update = MapstructUtils.convert(bo, ProjectFileInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ProjectFileInfo entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除项目文件信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

655
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ProjectInfoServiceImpl.java

@ -0,0 +1,655 @@
package org.dromara.demo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.demo.domain.vo.*;
import org.springframework.stereotype.Service;
import org.dromara.demo.domain.bo.ProjectInfoBo;
import org.dromara.demo.domain.ProjectInfo;
import org.dromara.demo.mapper.ProjectInfoMapper;
import org.dromara.demo.service.IProjectInfoService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* 项目信息Service业务层处理
*
* @author GJH
* @date 2025-08-19
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class ProjectInfoServiceImpl extends ServiceImpl<ProjectInfoMapper, ProjectInfo> implements IProjectInfoService {
private final ProjectInfoMapper baseMapper;
/**
* 查询项目信息
*
* @param id 主键
* @return 项目信息
*/
@Override
public ProjectInfoVo queryById(String id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询项目信息列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 项目信息分页列表
*/
@Override
public TableDataInfo<ProjectInfoVo> queryPageList(ProjectInfoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ProjectInfo> lqw = buildQueryWrapper(bo);
Page<ProjectInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的项目信息列表
*
* @param bo 查询条件
* @return 项目信息列表
*/
@Override
public List<ProjectInfoVo> queryList(ProjectInfoBo bo) {
LambdaQueryWrapper<ProjectInfo> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ProjectInfo> buildQueryWrapper(ProjectInfoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ProjectInfo> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getProjectName()), ProjectInfo::getProjectName, bo.getProjectName());
lqw.eq(bo.getProjectDate() != null, ProjectInfo::getProjectDate, bo.getProjectDate());
lqw.eq(StringUtils.isNotBlank(bo.getPlanInvest()), ProjectInfo::getPlanInvest, bo.getPlanInvest());
lqw.eq(StringUtils.isNotBlank(bo.getActualInvest()), ProjectInfo::getActualInvest, bo.getActualInvest());
lqw.eq(StringUtils.isNotBlank(bo.getInvestResource()), ProjectInfo::getInvestResource, bo.getInvestResource());
lqw.eq(StringUtils.isNotBlank(bo.getIfPlan()), ProjectInfo::getIfPlan, bo.getIfPlan());
lqw.eq(StringUtils.isNotBlank(bo.getApprovalLevel()), ProjectInfo::getApprovalLevel, bo.getApprovalLevel());
lqw.eq(StringUtils.isNotBlank(bo.getExpect()), ProjectInfo::getExpect, bo.getExpect());
lqw.eq(StringUtils.isNotBlank(bo.getEarlyDesign()), ProjectInfo::getEarlyDesign, bo.getEarlyDesign());
lqw.eq(StringUtils.isNotBlank(bo.getDistrict()), ProjectInfo::getDistrict, bo.getDistrict());
lqw.eq(StringUtils.isNotBlank(bo.getControlArea()), ProjectInfo::getControlArea, bo.getControlArea());
lqw.eq(StringUtils.isNotBlank(bo.getRiverBasin()), ProjectInfo::getRiverBasin, bo.getRiverBasin());
lqw.like(StringUtils.isNotBlank(bo.getProjectTypeList()), ProjectInfo::getProjectTypeList, bo.getProjectTypeList());
lqw.eq(StringUtils.isNotBlank(bo.getProjectTech()), ProjectInfo::getProjectTech, bo.getProjectTech());
lqw.like(StringUtils.isNotBlank(bo.getTechName()), ProjectInfo::getTechName, bo.getTechName());
lqw.eq(StringUtils.isNotBlank(bo.getTechCost()), ProjectInfo::getTechCost, bo.getTechCost());
lqw.eq(StringUtils.isNotBlank(bo.getDevCost()), ProjectInfo::getDevCost, bo.getDevCost());
lqw.eq(StringUtils.isNotBlank(bo.getTechUsability()), ProjectInfo::getTechUsability, bo.getTechUsability());
lqw.eq(StringUtils.isNotBlank(bo.getTechStability()), ProjectInfo::getTechStability, bo.getTechStability());
lqw.eq(StringUtils.isNotBlank(bo.getOperationLevel()), ProjectInfo::getOperationLevel, bo.getOperationLevel());
lqw.eq(StringUtils.isNotBlank(bo.getProjectContent()), ProjectInfo::getProjectContent, bo.getProjectContent());
lqw.eq(StringUtils.isNotBlank(bo.getProjectProgress()), ProjectInfo::getProjectProgress, bo.getProjectProgress());
lqw.eq(StringUtils.isNotBlank(bo.getAcceptMethod()), ProjectInfo::getAcceptMethod, bo.getAcceptMethod());
lqw.eq(StringUtils.isNotBlank(bo.getDevResult()), ProjectInfo::getDevResult, bo.getDevResult());
lqw.eq(StringUtils.isNotBlank(bo.getDevStatus()), ProjectInfo::getDevStatus, bo.getDevStatus());
lqw.eq(StringUtils.isNotBlank(bo.getGoal()), ProjectInfo::getGoal, bo.getGoal());
lqw.eq(StringUtils.isNotBlank(bo.getPatrolType()), ProjectInfo::getPatrolType, bo.getPatrolType());
lqw.eq(StringUtils.isNotBlank(bo.getManageType()), ProjectInfo::getManageType, bo.getManageType());
lqw.eq(StringUtils.isNotBlank(bo.getLongOperation()), ProjectInfo::getLongOperation, bo.getLongOperation());
lqw.eq(StringUtils.isNotBlank(bo.getCod()), ProjectInfo::getCod, bo.getCod());
lqw.eq(StringUtils.isNotBlank(bo.getTn()), ProjectInfo::getTn, bo.getTn());
lqw.eq(StringUtils.isNotBlank(bo.getTp()), ProjectInfo::getTp, bo.getTp());
lqw.eq(StringUtils.isNotBlank(bo.getFundingCompletionScore()), ProjectInfo::getFundingCompletionScore, bo.getFundingCompletionScore());
lqw.eq(StringUtils.isNotBlank(bo.getEnvironmentalPerformanceScore()), ProjectInfo::getEnvironmentalPerformanceScore, bo.getEnvironmentalPerformanceScore());
lqw.eq(StringUtils.isNotBlank(bo.getLongTermOperationScore()), ProjectInfo::getLongTermOperationScore, bo.getLongTermOperationScore());
lqw.eq(bo.getStatus() != null, ProjectInfo::getStatus, bo.getStatus());
return lqw;
}
/**
* 新增项目信息
*
* @param bo 项目信息
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(ProjectInfoBo bo) {
ProjectInfo add = MapstructUtils.convert(bo, ProjectInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改项目信息
*
* @param bo 项目信息
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(ProjectInfoBo bo) {
ProjectInfo update = MapstructUtils.convert(bo, ProjectInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ProjectInfo entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除项目信息信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public void addData(List<ProjectInfo> list) {
this.saveBatch(list);
}
@Override
public List<AllGoatAchieveDataVo> getYearlyInvestmentStats() {
List<ProjectInfo> list = baseMapper.selectList();
// 按年份累加:TreeMap 自动按年份升序排序
Map<Integer, BigDecimal> planMap = new TreeMap<>();
Map<Integer, BigDecimal> actualMap = new TreeMap<>();
for (ProjectInfo item : list) {
int year = extractYear(item.getProjectDate()); // 不管是哪年都保留
BigDecimal plan = parseBigDecimal(item.getPlanInvest());
BigDecimal actual = parseBigDecimal(item.getActualInvest());
planMap.put(year, planMap.getOrDefault(year, BigDecimal.ZERO).add(plan));
actualMap.put(year, actualMap.getOrDefault(year, BigDecimal.ZERO).add(actual));
}
// 转换为返回结果
List<AllGoatAchieveDataVo> result = new ArrayList<>();
for (Integer year : planMap.keySet()) {
BigDecimal plan = planMap.get(year);
BigDecimal actual = actualMap.get(year);
// 计算完成率(只返回数字)
BigDecimal percent = BigDecimal.ZERO;
if (plan.compareTo(BigDecimal.ZERO) != 0) {
percent = actual.divide(plan, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
}
result.add(new AllGoatAchieveDataVo(
year.toString(),
format(plan),
format(actual),
format(percent)
));
}
return result;
}
@Override
public List<ProjectPerformanceVo> getPerformanceScore(ProjectInfoBo bo) {
List<ProjectPerformanceVo> projectPerformanceVoList = new ArrayList<>();
List<ProjectInfoVo> projectInfoVoList = this.queryList(bo);
for (ProjectInfoVo projectInfo : projectInfoVoList) {
ProjectPerformanceVo projectPerformance = new ProjectPerformanceVo();
projectPerformance.setProjectName(projectInfo.getProjectName());
// 1. 批复等级得分
Double approvalLevelScore = getApprovalLevelScore(projectInfo);
projectPerformance.setApprovalLevelScore(approvalLevelScore);
// 2. 前期设计得分
Double earlyDesignScore = getEarlyDesignScore(projectInfo);
projectPerformance.setEarlyDesignScore(earlyDesignScore);
// 3. 资金来源得分
Double investResourceScore = getInvestResourceScore(projectInfo);
projectPerformance.setInvestResourceScore(investResourceScore);
// 4. 验收方式得分
Double acceptMethodResourceScore = getAcceptMethodResourceScore(projectInfo);
projectPerformance.setAcceptMethodScore(acceptMethodResourceScore);
// 5. 巡查模式得分
Double patrolTypeScore = getPatrolTypeScore(projectInfo);
projectPerformance.setPatrolTypeScore(patrolTypeScore);
// 6. 管理方式得分
Double manageTypeScore = getManageTypeScore(projectInfo);
projectPerformance.setManageTypeScore(manageTypeScore);
// 7. 运行情况得分
Double devStatusScore = getDevStatusScore(projectInfo);
projectPerformance.setDevStatusScore(devStatusScore);
// final:加入集合
projectPerformanceVoList.add(projectPerformance);
//log.info("项目:{},批复等级:{} ,批复等级得分:{}", projectInfo.getProjectName(), projectInfo.getApprovalLevel(),approvalLevelScore);
//log.info("项目:{},前期设计:{} ,前期设计得分:{}", projectInfo.getProjectName(), projectInfo.getEarlyDesign(),earlyDesignScore);
//log.info("项目:{},资金来源:{} ,资金来源得分:{}", projectInfo.getProjectName(), projectInfo.getInvestResource(),investResourceScore);
//log.info("项目:{},验收方式:{} ,验收方式得分:{}", projectInfo.getProjectName(), projectInfo.getAcceptMethod(),acceptMethodResourceScore);
//log.info("项目:{},巡查模式:{} ,巡查模式得分:{}", projectInfo.getProjectName(), projectInfo.getPatrolType(),patrolTypeScore);
//log.info("项目:{},管理方式:{} ,管理方式得分:{}", projectInfo.getProjectName(), projectInfo.getManageType(),manageTypeScore);
log.info("项目:{},运行情况:{} ,运行情况得分:{}", projectInfo.getProjectName(), projectInfo.getDevStatus(),devStatusScore);
}
return projectPerformanceVoList;
}
@Override
public ProjectPerformanceVo calculateAverageByType(ProjectInfoBo bo) {
List<ProjectPerformanceVo> projectPerformanceVoList = this.getPerformanceScore(bo);
String projectType = bo.getProjectTypeList();
if (projectPerformanceVoList == null || projectPerformanceVoList.isEmpty()) {
return null; // 没有数据,返回 null
}
// 计算每个字段的平均值,并保留两位小数(四舍五入)
double approvalLevelScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getApprovalLevelScore));
double earlyDesignScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getEarlyDesignScore));
double investResourceScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getInvestResourceScore));
double acceptMethodScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getAcceptMethodScore));
double patrolTypeScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getPatrolTypeScore));
double manageTypeScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getManageTypeScore));
double devStatusScoreAvg = roundTo2DecimalPlaces(calculateAverage(projectPerformanceVoList, ProjectPerformanceVo::getDevStatusScore));
// 创建并设置平均值对象
ProjectPerformanceVo avgVo = new ProjectPerformanceVo();
avgVo.setProjectName(null);
// 设置查询的类型
avgVo.setProjectType(projectType);
avgVo.setApprovalLevelScore(approvalLevelScoreAvg);
avgVo.setEarlyDesignScore(earlyDesignScoreAvg);
avgVo.setInvestResourceScore(investResourceScoreAvg);
avgVo.setAcceptMethodScore(acceptMethodScoreAvg);
avgVo.setPatrolTypeScore(patrolTypeScoreAvg);
avgVo.setManageTypeScore(manageTypeScoreAvg);
avgVo.setDevStatusScore(devStatusScoreAvg);
//TODO 绩效评分AI描述
avgVo.setDescription("城镇污水处理及配套工程的常态化管理水平相对较好,政府资金得到较好的保障。从各阶段来看,可行批复总体" +
"以市级批复为主、初步设计阶段有勘探报告、资金来源充足、验收批复材料基本完整、定期巡查、运营效率的水" +
"平相对较高,但管理部门以区级国企为主,有待进一步改善。" +
"其中,“十二五”和“十三五”期间的项目以及排水管网及调蓄池建设类项目需要加强后期运营管护水平。" +
"常态化管理水平较好的是污水厂建设类项目,较差的是污水处理厂改扩建工程(1)、污水厂改扩建工程(2)。");
return avgVo; // ✅ 返回真实计算出的平均值
}
@Override
public List<DeaResultVo> getDeaSimulationResults() {
List<DeaResultVo> resultList = new ArrayList<>();
resultList.add(new DeaResultVo("城镇污水处理及配套", 0.85, 0.92, 0.92, "递增", 1.10));
resultList.add(new DeaResultVo("河道整治", 1.00, 1.00, 1.00, "不变", 1.42));
resultList.add(new DeaResultVo("农业农村面源污染治理", 0.76, 0.85, 0.89, "递增", 0.88));
resultList.add(new DeaResultVo("饮用水源地保护建设", 1.00, 1.00, 1.00, "不变", 1.25));
resultList.add(new DeaResultVo("内源治理", 0.68, 0.78, 0.87, "递增", 0.75));
resultList.add(new DeaResultVo("水资源综合利用及调度", 0.93, 0.96, 0.97, "递增", 1.05));
return resultList;
}
@Override
public PH getPH() {
PH ph = new PH();
List<Integer> timeList = ph.getTimeList();
List<Double> phList = ph.getPhList();
double[] phValues = {
6.72, 6.71, 6.70, 6.70, 6.71, 6.73, 6.75, 6.77,
6.78, 6.80, 6.82, 6.83, 6.84, 6.85, 6.84, 6.83,
6.82, 6.81, 6.80, 6.78, 6.76, 6.74, 6.73, 6.72
};
for (int hour = 0; hour < 24; hour++) {
timeList.add(hour); // 直接添加小时数字
phList.add(phValues[hour]);
}
ph.setTimeList(timeList);
ph.setPhList(phList);
ph.setCurrentTime(LocalDateTime.now());
ph.setCurrentValue(phValues[ph.getCurrentTime().getHour()]);
ph.setLongitude("121.434112");
ph.setLatitude("29.580099");
return ph;
}
@Override
public List<StationInfoVo> getStations() {
StationInfoVo target = new StationInfoVo("方门江", "121.434112", "29.580099");
List<StationInfoVo> rs= new ArrayList<>();
rs.add(target);
return rs;
}
@Override
public StationDetailVo getWaterQualityData(String type) {
// 模拟站点位置
String longitude = "121.434112";
String latitude = "29.580099";
double[] values;
// 根据 type 分支返回不同数据
switch (type.toUpperCase()) {
case "PH":
values = new double[]{
6.72, 6.71, 6.70, 6.70, 6.71, 6.73, 6.75, 6.77,
6.78, 6.80, 6.82, 6.83, 6.84, 6.85, 6.84, 6.83,
6.82, 6.81, 6.80, 6.78, 6.76, 6.74, 6.73, 6.72
};
break;
case "DO":
values = new double[]{
7.8, 7.6, 7.4, 7.2, 7.3, 7.6, 8.0, 8.5,
8.8, 9.0, 9.2, 9.3, 9.4, 9.3, 9.1, 8.9,
8.7, 8.5, 8.3, 8.1, 7.9, 7.7, 7.6, 7.5
};
break;
case "COD":
values = new double[]{
12.5, 12.4, 12.3, 12.3, 12.2, 12.3, 12.4, 12.5,
12.6, 12.7, 12.8, 12.7, 12.6, 12.5, 12.4, 12.3,
12.3, 12.2, 12.2, 12.3, 12.4, 12.5, 12.5, 12.4
};
break;
case "TP":
values = new double[]{
0.060, 0.059, 0.058, 0.057, 0.058, 0.059, 0.060, 0.062,
0.064, 0.065, 0.066, 0.065, 0.064, 0.063, 0.062, 0.061,
0.060, 0.059, 0.058, 0.057, 0.057, 0.058, 0.059, 0.060
};
break;
case "NH3":
case "NH3-N":
values = new double[]{
0.32, 0.33, 0.35, 0.36, 0.35, 0.34, 0.33, 0.31,
0.30, 0.28, 0.27, 0.26, 0.25, 0.26, 0.27, 0.28,
0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36
};
break;
default:
// 如果类型不支持,返回 PH 作为默认值,避免报错
values = new double[]{
6.72, 6.71, 6.70, 6.70, 6.71, 6.73, 6.75, 6.77,
6.78, 6.80, 6.82, 6.83, 6.84, 6.85, 6.84, 6.83,
6.82, 6.81, 6.80, 6.78, 6.76, 6.74, 6.73, 6.72
};
break;
}
// 构建返回对象
StationDetailVo vo = new StationDetailVo();
List<XY> xyList = new ArrayList<>();
for (int hour = 0; hour < 24; hour++) {
xyList.add(new XY(hour, values[hour]));
}
vo.setXyList(xyList);
LocalDateTime now = LocalDateTime.now();
vo.setCurrentTime(now);
int currentHour = now.getHour();
vo.setCurrentValue(values[currentHour < 24 ? currentHour : 23]);
vo.setLongitude(longitude);
vo.setLatitude(latitude);
return vo;
}
// --------------------- private 辅助方法 ---------------------
private Double getApprovalLevelScore(ProjectInfoVo projectInfo) {
Double score = 0.0;
String approvalLevel = projectInfo.getApprovalLevel();
switch (approvalLevel) {
case "省级部门联合批复":
score = 5.0;
break;
case "省级批复":
score = 4.0;
break;
case "市级批复":
score = 3.0;
break;
case "区级批复":
score = 2.0;
break;
case "审批材料不完整":
score = 1.0;
break;
default:
score = 0.0;
}
return score;
}
public Double getEarlyDesignScore(ProjectInfoVo projectInfo) {
String earlyDesign = projectInfo.getEarlyDesign();
if (earlyDesign == null || earlyDesign.isEmpty()) {
return 0.0;
}
if (earlyDesign.equals("内容基本完善")) {
return 5.0;
} else if (earlyDesign.equals("有勘察或测绘报告/有环境影响评估/有水土保持报告")) {
return 4.0;
} else if (earlyDesign.contains("有环境影响评估/有水土保持报告")) {
return 3.0;
} else if (earlyDesign.contains("有勘察或测绘报告/有环境影响评估")) {
return 3.0;
} else if (earlyDesign.contains("有勘察或测绘报告/有水土保持报告")) {
return 2.0;
} else if (earlyDesign.contains("无")) {
return 1.0;
} else {
return 0.0;
}
}
private Double getInvestResourceScore(ProjectInfoVo projectInfo) {
Double score = 0.0;
String investResource = projectInfo.getInvestResource();
switch (investResource) {
case "国家、省级专项资金":
score = 5.0;
break;
case "市、区级政府专项资金":
score = 4.0;
break;
case "自筹资金且充足":
score = 3.0;
break;
case "自筹资金且无法保障":
score = 2.0;
break;
case "资金不足而搁置":
score = 1.0;
break;
default:
score = 0.0;
}
return score;
}
private Double getAcceptMethodResourceScore(ProjectInfoVo projectInfo) {
Double score = 0.0;
String acceptMethod = projectInfo.getAcceptMethod();
switch (acceptMethod) {
case "联合验收":
score = 5.0;
break;
case "材料基本齐全":
score = 4.0;
break;
case "合同与验收报告缺失":
score = 1.0;
break;
default:
score = 0.0;
}
return score;
}
private Double getPatrolTypeScore(ProjectInfoVo projectInfo) {
Double score = 0.0;
String patrolType = projectInfo.getPatrolType();
switch (patrolType) {
case "实时监控":
score = 5.0;
break;
case "市级部门联合巡查":
score = 4.0;
break;
case "市级部门巡查":
score = 3.0;
break;
case "主管部门定期巡查":
score = 2.0;
break;
case "无":
score = 1.0;
break;
default:
score = 0.0;
}
return score;
}
private Double getManageTypeScore(ProjectInfoVo projectInfo) {
Double score = 0.0;
String manageType = projectInfo.getManageType();
switch (manageType) {
case "多部门联合管理":
score = 5.0;
break;
case "不设置":
score = 4.0;
break;
case "市级部门下属国企管理":
score = 3.0;
break;
case "属地管理且国企运行":
score = 2.0;
break;
case "属地管理并社会招标":
score = 1.0;
break;
default:
score = 0.0;
}
return score;
}
private Double getDevStatusScore(ProjectInfoVo projectInfo) {
Double score = 0.0;
String devStatus = projectInfo.getDevStatus();
switch (devStatus) {
case "远超设计目标实现联合调度":
score = 5.0;
break;
case "基本达到设计目标":
score = 4.0;
break;
case "正常运行并有年度运行报告":
score = 3.0;
break;
case "短暂运行":
score = 2.0;
break;
case "荒废":
score = 1.0;
break;
default:
score = 0.0;
}
return score;
}
/**
* 通用方法计算某个得分字段的平均值保留两位小数
*/
/**
* 通用方法计算某个得分字段的平均值
* 注意返回的 double 值未进行四舍五入保留原始计算结果
*/
private double calculateAverage(List<ProjectPerformanceVo> list,
java.util.function.Function<ProjectPerformanceVo, Double> getter) {
return list.stream()
.mapToDouble(vo -> {
Double value = getter.apply(vo);
return value != null ? value : 0.0;
})
.average() // 返回 OptionalDouble
.orElse(0.0); // 如果列表为空或无有效值,返回 0.0
}
/**
* 使用 BigDecimal 保留两位小数四舍五入
*/
private double roundTo2DecimalPlaces(double value) {
return BigDecimal.valueOf(value)
.setScale(2, RoundingMode.HALF_UP) // 四舍五入
.doubleValue();
}
/**
* 可选将所有分数设为 0.00
*/
private void setAllScoresToZero(ProjectPerformanceVo vo) {
vo.setApprovalLevelScore(0.0);
vo.setEarlyDesignScore(0.0);
vo.setInvestResourceScore(0.0);
vo.setAcceptMethodScore(0.0);
vo.setPatrolTypeScore(0.0);
vo.setManageTypeScore(0.0);
vo.setDevStatusScore(0.0);
}
private int extractYear(Date date) {
if (date == null) return 0;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.YEAR);
}
private BigDecimal parseBigDecimal(String str) {
if (str == null || str.trim().isEmpty()) return BigDecimal.ZERO;
try {
return new BigDecimal(str.trim());
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
private String format(BigDecimal value) {
return value.setScale(2, RoundingMode.HALF_UP).toPlainString();
}
}
Loading…
Cancel
Save