mitao
2024-04-19 604d00f67ddcf25a9d079ceddd1c668b2a4e5288
bug修复
19个文件已修改
2个文件已删除
3个文件已添加
1148 ■■■■ 已修改文件
pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin-dept/src/main/resources/application-dev.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin-dept/src/main/resources/application-druid.yml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin-dept/src/main/resources/application-prod.yml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin-dept/src/main/resources/application-test.yml 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/CurrentQuarterController.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/HistoryDataController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-druid.yml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-prod.yml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-test.yml 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 153 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/update/BasicDataUpdDTO.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/update/RiskLevelUpdDTO.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/ScoreCalculateDetailQuery.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TbBasicDataService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbBasicDataConfigServiceImpl.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbBasicDataServiceImpl.java 179 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbDataScreenConfigServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbDeptServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/FieldBuildUtil.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/CurrentFieldsDetailVO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/FieldsTreeVO.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TbBasicDataConfigMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -263,5 +263,12 @@
        <logging.level>warn</logging.level>
      </properties>
    </profile>
    <profile>
      <id>test</id>
      <properties>
        <profiles.active>test</profiles.active>
        <logging.level>warn</logging.level>
      </properties>
    </profile>
  </profiles>
</project>
ruoyi-admin-dept/src/main/resources/application-dev.yml
@@ -102,9 +102,9 @@
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        url: jdbc:mysql://1.95.13.179:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: 123456
        password: Si8bnm5KPGSZkF3F
        #                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
        #                username: root
        #                password: shms#123~
ruoyi-admin-dept/src/main/resources/application-druid.yml
File was deleted
ruoyi-admin-dept/src/main/resources/application-prod.yml
@@ -18,7 +18,7 @@
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8082
  port: 8002
  servlet:
    # 应用的访问路径
    context-path: /
@@ -75,11 +75,11 @@
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    port: 16379
    # 数据库索引
    database: 0
    database: 6
    # 密码
    password: 123456
    password: mPMHThYzlT8DWgl8HLqwPEyPOiHDPPB5
    # 连接超时时间
    timeout: 10s
    lettuce:
@@ -102,9 +102,9 @@
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        url: jdbc:mysql://1.95.13.179:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: 123456
        password: Si8bnm5KPGSZkF3F
      #                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
      #                username: root
      #                password: shms#123~
ruoyi-admin-dept/src/main/resources/application-test.yml
New file
@@ -0,0 +1,235 @@
# 项目相关配置
ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 3.8.6
  # 版权年份
  copyrightYear: 2023
  # 实例演示开关
  demoEnabled: true
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: false
  # 验证码类型 math 数字计算 char 字符验证
  captchaType: math
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8082
  servlet:
    # 应用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # 连接数满后的排队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# 日志配置
logging:
  level:
    com.ruoyi: debug
    org.springframework: warn
# 用户配置
user:
  password:
    # 密码最大错误次数
    maxRetryCount: 5
    # 密码锁定时间(默认10分钟)
    lockTime: 10
# Spring配置
spring:
  main:
    allow-bean-definition-overriding: true
  # 资源信息
  messages:
    # 国际化资源文件路径
    basename: i18n/messages
  config:
    activate:
      on-profile: prod
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 500MB
      # 设置总上传的文件大小
      max-request-size: 2000MB
  # 服务模块
  devtools:
    restart:
      # 热部署开关
      enabled: true
  # redis 配置
  redis:
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 6
    # 密码
    password: mPMHThYzlT8DWgl8HLqwPEyPOiHDPPB5
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
  jackson:
    default-property-inclusion: non_null
    deserialization:
      read-unknown-enum-values-as-null: true
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: Si8bnm5KPGSZkF3F
      #                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
      #                username: root
      #                password: shms#123~
      # 从库数据源
      slave:
        # 从数据源开关/默认关闭
        enabled: false
        url:
        username:
        password:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置连接超时时间
      connectTimeout: 30000
      # 配置网络超时时间
      socketTimeout: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # 控制台管理用户名和密码
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
# token配置
token:
  # 令牌自定义标识
  header: Authorization
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 120
# MyBatis配置
#mybatis:
#  # 搜索指定包别名
#  typeAliasesPackage: com.ruoyi.**.domain
#  # 配置mapper的扫描,找到所有的mapper.xml映射文件
#  mapperLocations: classpath*:mapper/**/*Mapper.xml
#  # 加载全局的配置文件
#  configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
#pagehelper:
#  helperDialect: mysql
#  supportMethodsArguments: true
#  params: count=countSql
mybatis-plus:
  # 此处在多数据源中生效
  #  config-location: classpath:/mybatis-config.xml
  global-config:
    banner: false
    db-config:
      logic-not-delete-value: 0
      logic-delete-value: 1
  configuration:
    map-underscore-to-camel-case: true
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    cache-enabled: true
    local-cache-scope: statement
  type-aliases-package: com.ruoyi.**.domain,com.ruoyi.**.vo
  # 指定Mapper文件位置
  mapper-locations: classpath*:mapper/**/*.xml
# Swagger配置
swagger:
  # 是否开启swagger
  enabled: true
  # 请求前缀
  pathMapping: /
# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /system/notice
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
file:
  upload:
    location: /file/
    qrLocation: /file/qrCode/
    accessPath: /file/
    allowExt: .jpg|.png|.gif|.jpeg|.doc|.docx|.apk|.MP4|.mp4|.pdf|.PDF
wx:
  config:
    appId: wxc3985a05da7d86dc
    secret: 5cca42633c25439613b328c08ef20cc9
#OSS及短信配置
code:
  config:
    templateCodeTest: "SMS_154950909"
    signNameTest: "阿里云短信测试"
    accessKeyId: LTAI5tAdba8HtT1C6UqtSxBt
    accessKeySecret: 0SRb6XGkciQDPWn2rYqbJtq2qRMDY8
    signName: "四川金达通信工程"
    templateCode: "SMS_293985284"
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/CurrentQuarterController.java
@@ -7,6 +7,7 @@
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.TbQuestion;
import com.ruoyi.system.dto.QuestionDTO;
import com.ruoyi.system.dto.update.BasicDataUpdDTO;
import com.ruoyi.system.dto.update.QuestionUpdDTO;
import com.ruoyi.system.query.CurrentFieldsQuery;
import com.ruoyi.system.query.QuestionQuery;
@@ -90,6 +91,27 @@
    }
    /**
     * 字段统计-保存数据
     *
     * @param dto
     * @return
     */
    @PostMapping("/save-basic-data")
    @ApiOperation("字段统计-保存数据")
    public R<Void> editBasicData(@RequestBody BasicDataUpdDTO dto) {
        try {
            tbBasicDataService.editBasicData(dto);
        } catch (Exception e) {
            if (e instanceof ServiceException) {
                return R.fail(e.getMessage());
            }
            log.error("保存数据异常", e);
            return R.fail();
        }
        return R.ok();
    }
    /**
     * 查看全部
     *
     * @return R<CurrentFieldsAllVO>
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/HistoryDataController.java
@@ -9,6 +9,7 @@
import com.ruoyi.common.enums.ReportingStatusEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.TbBasicData;
import com.ruoyi.system.dto.update.BasicDataUpdDTO;
import com.ruoyi.system.query.CurrentFieldsQuery;
import com.ruoyi.system.query.HistoryDataQuery;
import com.ruoyi.system.query.QuestionQuery;
@@ -74,7 +75,7 @@
                tbBasicDataService
                        .lambdaQuery()
                        .eq(TbBasicData::getStatus, ReportingStatusEnum.FILLED)
                        .between(flag, TbBasicData::getCreateTime, startTime, endTime)
                        .between(flag, TbBasicData::getReportingTime, startTime, endTime)
                        .groupBy(TbBasicData::getQuarter)
                        .orderByDesc(TbBasicData::getReportingTime)
                        .page(new Page<>(dto.getPageNum(), dto.getPageSize()));
@@ -105,7 +106,7 @@
     * @return R<CurrentFieldsDetailVO>
     */
    @GetMapping("/fields-details")
    @ApiOperation(value = "查看详情", notes = "字段统计")
    @ApiOperation(value = "字段统计-查看详情", notes = "字段统计")
    @ApiImplicitParam(
            name = "id",
            value = "基础数据id",
@@ -125,6 +126,21 @@
        }
    }
    @PostMapping("/save-basic-data")
    @ApiOperation("字段统计-保存数据")
    public R<Void> editBasicData(@RequestBody BasicDataUpdDTO dto) {
        try {
            tbBasicDataService.editBasicData(dto);
        } catch (Exception e) {
            if (e instanceof ServiceException) {
                return R.fail(e.getMessage());
            }
            log.error("保存数据异常", e);
            return R.fail();
        }
        return R.ok();
    }
    /**
     * 查看全部
     *
ruoyi-admin/src/main/resources/application-dev.yml
@@ -103,9 +103,9 @@
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://192.168.110.188:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
        url: jdbc:mysql://1.95.13.179:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
        username: root
        password: 123456
        password: Si8bnm5KPGSZkF3F
      #                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
      #                username: root
      #                password: shms#123~
ruoyi-admin/src/main/resources/application-druid.yml
File was deleted
ruoyi-admin/src/main/resources/application-prod.yml
@@ -18,7 +18,7 @@
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8081
  port: 8001
  servlet:
    # 应用的访问路径
    context-path: /
@@ -76,11 +76,11 @@
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    port: 16379
    # 数据库索引
    database: 0
    database: 6
    # 密码
    password: 123456
    password: mPMHThYzlT8DWgl8HLqwPEyPOiHDPPB5
    # 连接超时时间
    timeout: 10s
    lettuce:
@@ -103,9 +103,9 @@
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
        url: jdbc:mysql://1.95.13.179:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
        username: root
        password: 123456
        password: Si8bnm5KPGSZkF3F
      #                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
      #                username: root
      #                password: shms#123~
ruoyi-admin/src/main/resources/application-test.yml
New file
@@ -0,0 +1,238 @@
# 项目相关配置
ruoyi:
  # 名称
  name: mitao
  # 版本
  version: 3.8.6
  # 版权年份
  copyrightYear: 2023
  # 实例演示开关
  demoEnabled: true
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: true
  # 验证码类型 math 数字计算 char 字符验证
  captchaType: math
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8001
  servlet:
    # 应用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # 连接数满后的排队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# 日志配置
logging:
  level:
    com.ruoyi: debug
    org.springframework: warn
# 用户配置
user:
  password:
    # 密码最大错误次数
    maxRetryCount: 5
    # 密码锁定时间(默认10分钟)
    lockTime: 10
# Spring配置
spring:
  main:
    allow-bean-definition-overriding: true
  # 资源信息
  messages:
    # 国际化资源文件路径
    basename: i18n/messages
  config:
    activate:
      on-profile:
        - prod
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 500MB
      # 设置总上传的文件大小
      max-request-size: 2000MB
  # 服务模块
  devtools:
    restart:
      # 热部署开关
      enabled: true
  # redis 配置
  redis:
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 6
    # 密码
    password: mPMHThYzlT8DWgl8HLqwPEyPOiHDPPB5
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
  jackson:
    default-property-inclusion: non_null
    deserialization:
      read-unknown-enum-values-as-null: true
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/financialdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
        username: root
        password: 123456
      #                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
      #                username: root
      #                password: shms#123~
      # 从库数据源
      slave:
        # 从数据源开关/默认关闭
        enabled: false
        url:
        username:
        password:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置连接超时时间
      connectTimeout: 30000
      # 配置网络超时时间
      socketTimeout: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # 控制台管理用户名和密码
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
# token配置
token:
  # 令牌自定义标识
  header: Authorization
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 120
# MyBatis配置
#mybatis:
#  # 搜索指定包别名
#  typeAliasesPackage: com.ruoyi.**.domain
#  # 配置mapper的扫描,找到所有的mapper.xml映射文件
#  mapperLocations: classpath*:mapper/**/*Mapper.xml
#  # 加载全局的配置文件
#  configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
#pagehelper:
#  helperDialect: mysql
#  supportMethodsArguments: true
#  params: count=countSql
mybatis-plus:
  # 此处在多数据源中生效
  #  config-location: classpath:/mybatis-config.xml
  configuration:
    map-underscore-to-camel-case: true
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    cache-enabled: true
    local-cache-scope: statement
  global-config:
    banner: false
    db-config:
      logic-not-delete-value: 0
      logic-delete-value: 1
      logic-delete-field: del_flag
  type-aliases-package: com.ruoyi.**.domain,com.ruoyi.**.vo
  # 指定Mapper文件位置
  mapper-locations: classpath*:mapper/**/*.xml
# Swagger配置
swagger:
  # 是否开启swagger
  enabled: true
  # 请求前缀
  pathMapping: /
# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /system/notice
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
# file upload
file:
  upload:
    location: /file/
    qrLocation: /file/qrCode/
    accessPath: /file/
    allowExt: .jpg|.png|.gif|.jpeg|.doc|.docx|.apk|.MP4|.mp4|.pdf|.PDF
wx:
  config:
    appId: wxc3985a05da7d86dc
    secret: 5cca42633c25439613b328c08ef20cc9
#OSS及短信配置
code:
  config:
    templateCodeTest: "SMS_154950909"
    signNameTest: "阿里云短信测试"
    accessKeyId: LTAI5tAdba8HtT1C6UqtSxBt
    accessKeySecret: 0SRb6XGkciQDPWn2rYqbJtq2qRMDY8
    signName: "四川金达通信工程"
    templateCode: "SMS_293985284"
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -8,7 +8,11 @@
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.*;
import com.ruoyi.common.exception.user.BlackListException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
@@ -19,6 +23,7 @@
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.TbDeptService;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
@@ -27,8 +32,6 @@
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * 登录校验方法
 * 
@@ -36,8 +39,8 @@
 */
@Slf4j
@Component
public class SysLoginService
{
public class SysLoginService {
    @Autowired
    private TokenService tokenService;
@@ -66,10 +69,9 @@
     * @param uuid 唯一标识
     * @return 结果
     */
    public LoginUser login(String username, String password, String code, String uuid)
    {
    public LoginUser login(String username, String password, String code, String uuid) {
        // 验证码校验
        validateCaptcha(username, code, uuid);
//        validateCaptcha(username, code, uuid);
        // 登录前置校验
        loginPreCheck(username, password);
        // 用户验证
@@ -86,31 +88,29 @@
            log.info("登录用户:{} 已被停用.", username);
            throw new ServiceException(MessageUtils.message("user.blocked"));
        }
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                    username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                AsyncManager.me().execute(
                        AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                                MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
            } else {
                AsyncManager.me().execute(
                        AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                                e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
        } finally {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS,
                MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
@@ -124,13 +124,12 @@
     * @param code 验证码
     * @return 结果
     */
    public LoginUser loginCode(String username,String code)
    {
    public LoginUser loginCode(String username, String code) {
        // 登录前置校验
        if (StringUtils.isEmpty(username)){
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                    MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 用户验证
@@ -155,8 +154,10 @@
            log.info("登录用户:{} 短信验证码错误{}", username,code);
            throw new ServiceException("短信验证码错误");
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS,
                MessageUtils.message("user.login.success")));
        LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user,
                permissionService.getMenuPermission(user));
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return loginUser;
@@ -168,13 +169,11 @@
     * @param username       用户名
     * @param password      密码
     * @param uuid          uuid
     * @return 结果
     */
    public LoginUser loginPwd(String username, String password, String code, String uuid)
    {
    public LoginUser loginPwd(String username, String password, String code, String uuid) {
        // 验证码校验
        validateCaptcha(username, code, uuid);
//        validateCaptcha(username, code, uuid);
        // 登录前置校验
        loginPreCheck(username, password);
        // 用户验证
@@ -185,36 +184,35 @@
            log.info("登录用户:{} 不存在.", username);
            throw new ServiceException(MessageUtils.message("user.not.exists"));
        }
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                    username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                AsyncManager.me().execute(
                        AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                                MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
            } else {
                AsyncManager.me().execute(
                        AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                                e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
        } finally {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS,
                MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return loginUser;
    }
    /**
     * 校验验证码
     * 
@@ -223,22 +221,22 @@
     * @param uuid 唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid)
    {
    public void validateCaptcha(String username, String code, String uuid) {
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        if (captchaEnabled)
        {
        if (captchaEnabled) {
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
            String captcha = redisCache.getCacheObject(verifyKey);
            redisCache.deleteObject(verifyKey);
            if (captcha == null)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
            if (captcha == null) {
                AsyncManager.me().execute(
                        AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                                MessageUtils.message("user.jcaptcha.expire")));
                throw new CaptchaExpireException();
            }
            if (!code.equalsIgnoreCase(captcha))
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            if (!code.equalsIgnoreCase(captcha)) {
                AsyncManager.me().execute(
                        AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                                MessageUtils.message("user.jcaptcha.error")));
                throw new CaptchaException();
            }
        }
@@ -246,36 +244,36 @@
    /**
     * 登录前置校验
     *
     * @param username 用户名
     * @param password 用户密码
     */
    public void loginPreCheck(String username, String password)
    {
    public void loginPreCheck(String username, String password) {
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                    MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                    MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                    MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
        // IP黑名单校验
        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
                    MessageUtils.message("login.blocked")));
            throw new BlackListException();
        }
    }
@@ -285,8 +283,7 @@
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
    public void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
ruoyi-system/src/main/java/com/ruoyi/system/dto/update/BasicDataUpdDTO.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.system.dto.update;
import com.ruoyi.system.dto.BasicDataFieldDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.Data;
/**
 * @author mitao
 * @date 2024/3/21
 */
@Data
@ApiModel(value = "基础数据数据传输对象")
public class BasicDataUpdDTO implements Serializable {
    private static final long serialVersionUID = -519305267336964392L;
    @ApiModelProperty(value = "基础数据id")
    @NotNull(message = "基础数据id不能为空")
    private Long id;
    @ApiModelProperty(value = "转移支付规模")
    private String transferPaymentScale;
    @ApiModelProperty(value = "当期GDP")
    private String currentGdp;
    @ApiModelProperty(value = "动态字段")
    private List<BasicDataFieldDTO> fields = new ArrayList<>();
    @ApiModelProperty(value = "备注")
    private String remark;
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/update/RiskLevelUpdDTO.java
@@ -40,8 +40,17 @@
    private String noRisk;
    public boolean areRiskLevelsDistinct() {
        return !highRisk.equals(mediumRisk) && !highRisk.equals(lowRisk) && !highRisk.equals(noRisk)
                && !mediumRisk.equals(lowRisk) && !mediumRisk.equals(noRisk) && !lowRisk.equals(
        return highRisk.equals(mediumRisk) || highRisk.equals(lowRisk) || highRisk.equals(noRisk)
                || mediumRisk.equals(lowRisk) || mediumRisk.equals(noRisk) || lowRisk.equals(
                noRisk);
    }
    public static void main(String[] args) {
        RiskLevelUpdDTO riskLevelUpdDTO = new RiskLevelUpdDTO();
        riskLevelUpdDTO.setNoRisk("0_10");
        riskLevelUpdDTO.setLowRisk("10_20");
        riskLevelUpdDTO.setMediumRisk("20_30");
        riskLevelUpdDTO.setHighRisk("30_40");
        System.out.println(riskLevelUpdDTO.areRiskLevelsDistinct());
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/query/ScoreCalculateDetailQuery.java
@@ -21,5 +21,5 @@
    private Long id;
    @ApiModelProperty(value = "部门名称")
    private String areaCode;
    private String areaName;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TbBasicDataService.java
@@ -6,6 +6,7 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TbBasicData;
import com.ruoyi.system.dto.BasicDataDTO;
import com.ruoyi.system.dto.update.BasicDataUpdDTO;
import com.ruoyi.system.query.CurrentFieldsQuery;
import com.ruoyi.system.query.ScoreCalculateQuery;
import com.ruoyi.system.query.ScoreQuery;
@@ -57,4 +58,6 @@
            String quarter);
    List<FieldAndScoreDataVO> selectBasicDataFieldsConfig(String areaCode, String nowQuarter);
    void editBasicData(BasicDataUpdDTO dto) throws Exception;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbBasicDataConfigServiceImpl.java
@@ -38,7 +38,6 @@
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -101,11 +100,18 @@
        }
    }
    public boolean hasConsecutiveDuplicates(List<CalculateItemDTO> calculateItemList) {
        return IntStream.range(1, calculateItemList.size())
                .anyMatch(i -> calculateItemList.get(i - 1).getValueType()
                        .equals(calculateItemList.get(i).getValueType()));
    public static boolean hasConsecutiveDuplicates(List<CalculateItemDTO> calculateItemList) {
        for (int i = 0; i < calculateItemList.size() - 1; i++) {
            if (calculateItemList.get(i).getValueType()
                    .equals(calculateItemList.get(i + 1).getValueType()) && !calculateItemList.get(
                            i + 1)
                    .getContent().equals("(")) {
                return true;
    }
        }
        return false;
    }
    private String getFieldIdStr(List<CalculateItemDTO> calculateItemList,
            TbBasicDataConfig tbBasicDataConfig) {
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbBasicDataServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
@@ -15,6 +16,8 @@
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.CalculateTypeEnum;
import com.ruoyi.common.enums.DataScreenConfigEnum;
import com.ruoyi.common.enums.FieldInputTypeEnum;
import com.ruoyi.common.enums.FieldTypeEnum;
import com.ruoyi.common.enums.ReportingStatusEnum;
import com.ruoyi.common.enums.ShowStatusEnum;
import com.ruoyi.common.enums.UserTypeEnum;
@@ -38,6 +41,7 @@
import com.ruoyi.system.dto.BasicDataDTO;
import com.ruoyi.system.dto.BasicDataFieldDTO;
import com.ruoyi.system.dto.CalculateItemDTO;
import com.ruoyi.system.dto.update.BasicDataUpdDTO;
import com.ruoyi.system.handler.CustomCellWriteHandler;
import com.ruoyi.system.listener.BasicDataListener;
import com.ruoyi.system.listener.HistoryDataListener;
@@ -118,7 +122,7 @@
            TbBasicDataField tbBasicDataField = fieldMap.get(field.getId());
            if (tbBasicDataField != null) {
                field.setValue(
                        FieldBuildUtil.formatNumberWithCommas(tbBasicDataField.getFieldValue()));
                        tbBasicDataField.getFieldValue());
            }
            if (field.getChildren() != null && !field.getChildren().isEmpty()) {
                setFieldValues(field.getChildren(), fieldMap);
@@ -139,12 +143,8 @@
            throw new ServiceException(String.format("区划代码%s不存在", deptAreaCode));
        }
        Date date = new Date();
        Map<String, Date> quarterDate = DateUtils.getQuarterDate(date);
        // 当前季度开始
        Date quarterStart = quarterDate.get("first");
        // 当前季度结束
        Date quarterEnd = quarterDate.get("last");
        // 判断当前时间是否在季度初1-15号
        Date quarterStart = DateUtil.beginOfQuarter(date);
        Date quarterEnd = DateUtil.endOfQuarter(date);
        Instant instant = quarterStart.toInstant();
        LocalDate quarterStartLocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate fifteenDaysLimit = quarterStartLocalDate.plusDays(14);
@@ -229,6 +229,7 @@
        TbBasicData tbBasicData = BeanUtils.copyBean(dto, TbBasicData.class);
        if (basicDataOpt.isPresent()) {
            tbBasicData.setId(basicDataOpt.get().getId());
            tbBasicData.setDeptAreaCode(areaCode);
            this.updateById(tbBasicData);
            //查询该基础数据的动态字端
            List<TbBasicDataField> originFields = tbBasicDataFieldService.lambdaQuery()
@@ -244,15 +245,44 @@
            this.save(tbBasicData);
        }
        // 保存基础数据动态字段数据
        List<TbBasicDataField> tbBasicDataFields =
        List<TbBasicDataField> tbBasicDataFieldsOrg =
                BeanUtils.copyList(dto.getFields(), TbBasicDataField.class);
        List<TbBasicDataField> tbBasicDataFields = tbBasicDataFieldsOrg.stream()
                .filter(item -> Objects.nonNull(item.getFieldValue())).collect(
                        Collectors.toList());
        tbBasicDataFields.forEach(
                item -> {
                    item.setBasicDataId(tbBasicData.getId());
                    TbField tbField = fieldMap.get(item.getFieldId());
                    if (Objects.nonNull(tbField)) {
                        item.setFieldName(tbField.getFieldName());
                    }
                    Integer numMax = tbField.getNumMax();
                    Integer numMin = tbField.getNumMin();
                    Integer textMaxNum = tbField.getTextMaxNum();
                    Integer textMinNum = tbField.getTextMinNum();
                    if (FieldTypeEnum.NUMBER.equals(tbField.getFieldType()) && Objects.nonNull(
                            numMax) && Objects.nonNull(numMin)) {
                        double fieldValue = Double.parseDouble(item.getFieldValue());
                        if (fieldValue < numMin || fieldValue > numMax) {
                            throw new ServiceException(
                                    String.format("字段%s的值不在范围%d-%d内",
                                            tbField.getFieldName(),
                                            numMin, numMax));
                        }
                    }
                    if (FieldTypeEnum.TEXT.equals(tbField.getFieldType())
                            && FieldInputTypeEnum.MANUAL_INPUT.equals(
                            tbField.getTextInputType())
                            && Objects.nonNull(
                            textMaxNum) && Objects.nonNull(textMinNum)) {
                        String fieldValue = item.getFieldValue();
                        if (fieldValue.length() < numMin || fieldValue.length() > numMax) {
                            throw new ServiceException(
                                    String.format("字段%s的值的长度不在范围%d-%d内",
                                            tbField.getFieldName(),
                                            textMinNum, textMaxNum));
                        }
                    }
                });
        // 添加固定字段 转移支付规模、当期GDP
@@ -412,10 +442,15 @@
    private static void wrapOperLog(LoginUser loginUser, TbBasicData tbBasicData, String before,
            String after, List<TbOperLog> tbOperlogList, String fieldName) {
        SysUser user = loginUser.getUser();
        TbOperLog tbOperLog = new TbOperLog();
        tbOperLog.setOperation(tbBasicData.getQuarter());
        tbOperLog.setStaffName(loginUser.getUser().getNickName());
        tbOperLog.setAreaName(loginUser.getUser().getAreaName());
        tbOperLog.setStaffName(
                user.getUserType() == UserTypeEnum.PLATFORM ? user
                        .getUserName()
                        : user.getNickName());
        tbOperLog.setAreaName(
                user.getUserType() == UserTypeEnum.PLATFORM ? "平台" : user.getAreaName());
        tbOperLog.setFieldName(fieldName);
        tbOperLog.setBusinessType(BusinessType.UPDBASICDATA.ordinal());
        tbOperLog.setBeforeEdit(before);
@@ -425,17 +460,15 @@
    @Override
    public void importBasicData(MultipartFile file) throws Exception {
        Map<String, Date> quarterDate = DateUtils.getQuarterDate(new Date());
        // 当前季度开始
        Date quarterStart = quarterDate.get("first");
        // 当前季度结束
        Date quarterEnd = quarterDate.get("last");
        Date date = new Date();
        Date quarterStart = DateUtil.beginOfQuarter(date);
        Date quarterEnd = DateUtil.endOfQuarter(date);
        // 判断当前时间是否在季度初1-15号
        Instant instant = quarterStart.toInstant();
        LocalDate quarterStartLocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate fifteenDaysLimit = quarterStartLocalDate.plusDays(14);
        LocalDate now = LocalDate.now();
        //todo
        //TODO
      /*  if (now.isBefore(quarterStartLocalDate) || now.isAfter(fifteenDaysLimit)) {
            throw new ServiceException("请于季度初1-15号上传季度数据。");
        }*/
@@ -553,17 +586,15 @@
        Page<ScoreVO> page = new Page<>(query.getPageNum(), query.getPageSize());
        SysUser user = SecurityUtils.getLoginUser().getUser();
        String areaCode = user.getAreaCode();
        Map<String, Date> quarterDate = DateUtils.getQuarterDate(new Date());
        // 当前季度开始
        Date quarterStart = quarterDate.get("first");
        // 当前季度结束
        Date quarterEnd = quarterDate.get("last");
        Date date = new Date();
        Date quarterStart = DateUtil.beginOfQuarter(date);
        Date quarterEnd = DateUtil.endOfQuarter(date);
        // 查询是否有当前季度的填报记录
        TbBasicData basicData =
                this.getOne(
                        Wrappers.<TbBasicData>lambdaQuery()
                                .eq(TbBasicData::getDeptAreaCode, areaCode)
                                .between(TbBasicData::getCreateTime, quarterStart, quarterEnd));
                                .between(TbBasicData::getReportingTime, quarterStart, quarterEnd));
        if (Objects.isNull(basicData)) {
            return PageDTO.empty(page);
        }
@@ -581,6 +612,7 @@
            throw new ServiceException("非法参数");
        }
        CurrentFieldsDetailVO vo = BeanUtils.copyBean(basicData, CurrentFieldsDetailVO.class);
        vo.setId(basicData.getId());
        // 查询用户信息
        sysUserService
                .lambdaQuery()
@@ -727,8 +759,7 @@
                    TbBasicDataField tbBasicDataField = basicDataFieldMap.get(tbField.getId());
                    item.add(
                            Objects.nonNull(tbBasicDataField)
                                    ? FieldBuildUtil.formatNumberWithCommas(
                                    tbBasicDataField.getFieldValue())
                                    ? tbBasicDataField.getFieldValue()
                                    : "");
                }
                item.add(tbBasicData.getRemark());
@@ -835,8 +866,7 @@
                TbBasicDataField tbBasicDataField = basicDataFieldMap.get(tbField.getId());
                item.add(
                        Objects.nonNull(tbBasicDataField)
                                ? FieldBuildUtil.formatNumberWithCommas(
                                tbBasicDataField.getFieldValue())
                                ? tbBasicDataField.getFieldValue()
                                : "");
            }
            item.add(tbBasicData.getRemark());
@@ -1030,4 +1060,99 @@
        return baseMapper.selectBasicDataFieldsConfig(areaCode, nowQuarter);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editBasicData(BasicDataUpdDTO dto) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 数据校验
        if (Objects.isNull(dto)) {
            return;
        }
        //查询基础数据
        TbBasicData basicData = this.getById(dto.getId());
        if (Objects.isNull(basicData)) {
            throw new ServiceException("非法参数");
        }
        String nowQuarter = DateUtils.getNowQuarter();
        this.updateById(basicData);
        //查询该基础数据的动态字端
        List<TbBasicDataField> originFields = tbBasicDataFieldService.lambdaQuery()
                .eq(TbBasicDataField::getBasicDataId, basicData.getId()).list();
        Set<Long> fieldIdList = originFields.stream().map(TbBasicDataField::getFieldId)
                .collect(Collectors.toSet());
        Map<Long, TbField> fieldMap = tbFieldService.lambdaQuery().in(TbField::getId, fieldIdList)
                .list().stream().collect(Collectors.toMap(TbField::getId, e -> e));
        CompletableFuture.runAsync(
                () -> saveExchangeLog(loginUser, basicData, originFields,
                        BeanUtils.copyBean(dto, BasicDataDTO.class),
                        fieldMap));
        TbBasicData tbBasicData = BeanUtils.copyBean(dto, TbBasicData.class);
        // 保存基础数据动态字段数据
        List<TbBasicDataField> tbBasicDataFields =
                BeanUtils.copyList(dto.getFields(), TbBasicDataField.class);
        for (TbBasicDataField item : tbBasicDataFields) {
            TbField tbField = fieldMap.get(item.getFieldId());
            Integer numMax = tbField.getNumMax();
            Integer numMin = tbField.getNumMin();
            Integer textMaxNum = tbField.getTextMaxNum();
            Integer textMinNum = tbField.getTextMinNum();
            if (FieldTypeEnum.NUMBER.equals(tbField.getFieldType()) && Objects.nonNull(
                    numMax) && Objects.nonNull(numMin)) {
                double fieldValue = Double.parseDouble(item.getFieldValue());
                if (fieldValue < numMin || fieldValue > numMax) {
                    throw new ServiceException(
                            String.format("字段%s的值不在范围%d-%d内", tbField.getFieldName(),
                                    numMin, numMax));
                }
            }
            if (FieldTypeEnum.TEXT.equals(tbField.getFieldType())
                    && FieldInputTypeEnum.MANUAL_INPUT.equals(tbField.getTextInputType())
                    && Objects.nonNull(
                    textMaxNum) && Objects.nonNull(textMinNum)) {
                String fieldValue = item.getFieldValue();
                if (fieldValue.length() < numMin || fieldValue.length() > numMax) {
                    throw new ServiceException(
                            String.format("字段%s的值的长度不在范围%d-%d内", tbField.getFieldName(),
                                    textMinNum, textMaxNum));
                }
            }
        }
        tbBasicDataFields.forEach(
                item -> {
                    item.setBasicDataId(tbBasicData.getId());
                    TbField tbField = fieldMap.get(item.getFieldId());
                    if (Objects.nonNull(tbField)) {
                        item.setFieldName(tbField.getFieldName());
                    }
                });
        // 添加固定字段 转移支付规模、当期GDP
        TbBasicDataField transferPaymentScale = new TbBasicDataField();
        transferPaymentScale.setBasicDataId(tbBasicData.getId());
        transferPaymentScale.setFieldId(-1L);
        transferPaymentScale.setFieldValue(tbBasicData.getTransferPaymentScale());
        tbBasicDataFields.add(transferPaymentScale);
        TbBasicDataField currentGdp = new TbBasicDataField();
        currentGdp.setBasicDataId(tbBasicData.getId());
        currentGdp.setFieldId(-2L);
        currentGdp.setFieldValue(tbBasicData.getCurrentGdp());
        tbBasicDataFields.add(currentGdp);
        TbBasicDataField remark = new TbBasicDataField();
        remark.setBasicDataId(tbBasicData.getId());
        remark.setFieldId(-3L);
        remark.setFieldValue(tbBasicData.getRemark());
        tbBasicDataFields.add(remark);
        // 将该基础数据的动态字段数据全部删除
        tbBasicDataFieldService.remove(
                Wrappers.<TbBasicDataField>lambdaQuery()
                        .eq(TbBasicDataField::getBasicDataId, tbBasicData.getId()));
        tbBasicDataFieldService.saveBatch(tbBasicDataFields);
        if (ReportingStatusEnum.FILLED.equals(tbBasicData.getStatus())) {
            CompletableFuture.runAsync(() -> {
                calculateScore(tbBasicData, tbBasicDataFields);
                calculateScreenScore(tbBasicData, tbBasicDataFields);
            });
        }
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbDataScreenConfigServiceImpl.java
@@ -60,9 +60,9 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DataScreenConfigVO editRiskLevel(RiskLevelUpdDTO dto) {
       /* if (dto.areRiskLevelsDistinct()) {
        if (dto.areRiskLevelsDistinct()) {
            throw new ServiceException("得分范围不能重叠");
        }*/
        }
        //查询是否有该指标配置
        TbDataScreenConfig tbDataScreenConfig = this.lambdaQuery()
                .eq(TbDataScreenConfig::getType, DataScreenConfigEnum.RISK_LEVEL)
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TbDeptServiceImpl.java
@@ -3,6 +3,7 @@
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.basic.PageDTO;
@@ -13,7 +14,6 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.BeanUtils;
import com.ruoyi.common.utils.CollUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.TbBasicData;
@@ -35,7 +35,6 @@
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -145,11 +144,9 @@
    @Override
    public R<Void> reportingMessage() {
        Map<String, Date> quarterDate = DateUtils.getQuarterDate(new Date());
        //当前季度开始
        Date quarterStart = quarterDate.get("first");
        //当前季度结束
        Date quarterEnd = quarterDate.get("last");
        Date date = new Date();
        Date quarterStart = DateUtil.beginOfQuarter(date);
        Date quarterEnd = DateUtil.endOfQuarter(date);
        //判断当前时间是否在季度初1-15号
        Instant instant = quarterStart.toInstant();
        LocalDate quarterStartLocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
@@ -164,7 +161,7 @@
                    .collect(Collectors.toSet());
            //查询当前季度填报了数据的部门
            List<TbBasicData> filledBasicData = tbBasicDataService.lambdaQuery()
                    .between(TbBasicData::getCreateTime, quarterStartLocalDate, fifteenDaysLimit)
                    .between(TbBasicData::getReportingTime, quarterStartLocalDate, fifteenDaysLimit)
                    .eq(TbBasicData::getStatus, ReportingStatusEnum.FILLED).list();
            Set<String> filledDeptCodes = filledBasicData.stream().map(TbBasicData::getDeptAreaCode)
                    .collect(Collectors.toSet());
ruoyi-system/src/main/java/com/ruoyi/system/utils/FieldBuildUtil.java
@@ -1,10 +1,11 @@
package com.ruoyi.system.utils;
import com.ruoyi.common.enums.FieldInputTypeEnum;
import com.ruoyi.common.enums.FieldTypeEnum;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.TbBasicDataField;
import com.ruoyi.system.domain.TbField;
import com.ruoyi.system.vo.FieldsTreeVO;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
@@ -15,6 +16,7 @@
 * @date 2024/4/3
 */
public class FieldBuildUtil {
    /**
     * 构建基础数据字段树形层级
     *
@@ -22,7 +24,8 @@
     * @param fieldMap        字段Map
     * @param roots           返回的vo
     */
    public static void buildTreeStructure(List<TbBasicDataField> basicDataFields, Map<Long, TbField> fieldMap, List<FieldsTreeVO> roots) {
    public static void buildTreeStructure(List<TbBasicDataField> basicDataFields,
            Map<Long, TbField> fieldMap, List<FieldsTreeVO> roots) {
        Map<String, FieldsTreeVO> levelTwoMap = new HashMap<>();
        Map<String, FieldsTreeVO> levelThreeMap = new HashMap<>();
@@ -34,12 +37,18 @@
                String levelThreeCategory = tbField.getLevelThreeCategory();
                Long id = tbField.getId();
                String fieldName = tbField.getFieldName();
                String fieldValue = formatNumberWithCommas(item.getFieldValue());
                String fieldValue = item.getFieldValue();
                FieldsTreeVO field = new FieldsTreeVO();
                field.setId(id);
                field.setName(fieldName);
                field.setValue(fieldValue);
                field.setCategory(Boolean.FALSE);
                field.setFieldType(tbField.getFieldType());
                if (tbField.getFieldType().equals(FieldTypeEnum.TEXT) && tbField.getTextInputType()
                        .equals(FieldInputTypeEnum.FIXED_CONTENT)) {
                    field.setDropdown(tbField.getTextContent());
                    field.setDropdownState(Boolean.TRUE);
                }
                FieldsTreeVO levelOneField = null;
                for (FieldsTreeVO root : roots) {
                    if (root.getName().equals(levelOneCategory)) {
@@ -63,7 +72,8 @@
                    }
                    if (StringUtils.isNotBlank(levelThreeCategory)) {
                        FieldsTreeVO levelThreeField = levelThreeMap.getOrDefault(levelThreeCategory, null);
                        FieldsTreeVO levelThreeField = levelThreeMap.getOrDefault(
                                levelThreeCategory, null);
                        if (levelThreeField == null) {
                            levelThreeField = new FieldsTreeVO();
                            levelThreeField.setName(levelThreeCategory);
@@ -86,7 +96,8 @@
     *
     * @param tbFieldList 字段列表
     */
    public static void buildTreeFromTbFieldList(List<TbField> tbFieldList, List<FieldsTreeVO> roots) {
    public static void buildTreeFromTbFieldList(List<TbField> tbFieldList,
            List<FieldsTreeVO> roots) {
        Map<String, FieldsTreeVO> levelOneMap = new HashMap<>();
        Map<String, FieldsTreeVO> levelTwoMap = new HashMap<>();
@@ -100,6 +111,12 @@
            field.setId(id);
            field.setName(fieldName);
            field.setCategory(Boolean.FALSE);
            field.setFieldType(tbField.getFieldType());
            if (tbField.getFieldType().equals(FieldTypeEnum.TEXT) &&
                    tbField.getTextInputType().equals(FieldInputTypeEnum.FIXED_CONTENT)) {
                field.setDropdown(tbField.getTextContent());
                field.setDropdownState(Boolean.TRUE);
            }
            FieldsTreeVO levelOneField = null;
            for (FieldsTreeVO root : roots) {
                if (root.getName().equals(levelOneCategory)) {
ruoyi-system/src/main/java/com/ruoyi/system/vo/CurrentFieldsDetailVO.java
@@ -5,11 +5,10 @@
import com.ruoyi.common.enums.ReportingStatusEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
/**
 * @author mitao
@@ -20,6 +19,8 @@
public class CurrentFieldsDetailVO implements Serializable {
    private static final long serialVersionUID = -4453903771078396720L;
    @ApiModelProperty(value = "基础数据id")
    private Long id;
    @ApiModelProperty(value = "填报部门")
    private String areaName;
ruoyi-system/src/main/java/com/ruoyi/system/vo/FieldsTreeVO.java
@@ -1,12 +1,12 @@
package com.ruoyi.system.vo;
import com.ruoyi.common.enums.FieldTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
/**
 * @author mitao
@@ -30,6 +30,15 @@
    @ApiModelProperty(value = "是否为分类")
    private Boolean category = Boolean.TRUE;
    @ApiModelProperty(value = "字段类型")
    private FieldTypeEnum fieldType;
    @ApiModelProperty(value = "下拉参数")
    private String dropdown;
    @ApiModelProperty(value = "是否为下拉参数 true =是 false 否")
    private Boolean dropdownState;
    @ApiModelProperty(value = "字段列表")
    private List<FieldsTreeVO> children = new ArrayList<>();
ruoyi-system/src/main/resources/mapper/system/TbBasicDataConfigMapper.xml
@@ -52,7 +52,7 @@
    <where>
      tbdc.del_flag = 0 AND tbdc2.del_flag = 0
      <if test="query.typeName != null and query.typeName !=''">
        AND tbdc.type_name LIKE CONCAT('%',#{typeName},'%')
        AND tbdc.type_name LIKE CONCAT('%',#{query.typeName},'%')
      </if>
      <if test="query.status !=null">
        AND tbdc.status = #{query.status}