zhaojinyu 1 月之前
當前提交
9711986b8e
共有 100 個文件被更改,包括 6257 次插入0 次删除
  1. 8 0
      .idea/.gitignore
  2. 25 0
      .idea/compiler.xml
  3. 15 0
      .idea/encodings.xml
  4. 20 0
      .idea/jarRepositories.xml
  5. 12 0
      .idea/misc.xml
  6. 4 0
      .idea/vcs.xml
  7. 22 0
      Dockerfile
  8. 383 0
      README.md
  9. 二進制
      allatori/allatori.jar
  10. 35 0
      allatori/allatori.xml
  11. 二進制
      allatori/class-winter-core-enhance-2.9.4.jar
  12. 二進制
      allatori/class-winter-maven-plugin-enhance-2.9.4.jar
  13. 37 0
      allatori/class-winter-maven-plugin-pom.xml
  14. 122 0
      jnpf-datareport-univer-admin/pom.xml
  15. 22 0
      jnpf-datareport-univer-admin/src/main/java/jnpf/ReportUniverApplication.java
  16. 79 0
      jnpf-datareport-univer-admin/src/main/java/jnpf/aop/DataSourceBindAspect.java
  17. 121 0
      jnpf-datareport-univer-admin/src/main/java/jnpf/config/AuthFilter.java
  18. 41 0
      jnpf-datareport-univer-admin/src/main/java/jnpf/config/ReportAutoConfiguration.java
  19. 8 0
      jnpf-datareport-univer-admin/src/main/java/jnpf/properties/GatewayWhiteProperties.java
  20. 167 0
      jnpf-datareport-univer-admin/src/main/resources/application-dev.yml
  21. 166 0
      jnpf-datareport-univer-admin/src/main/resources/application-preview.yml
  22. 166 0
      jnpf-datareport-univer-admin/src/main/resources/application-prod.yml
  23. 166 0
      jnpf-datareport-univer-admin/src/main/resources/application-test.yml
  24. 84 0
      jnpf-datareport-univer-admin/src/main/resources/application.yml
  25. 327 0
      jnpf-datareport-univer-admin/src/main/resources/logback-spring.xml
  26. 42 0
      jnpf-datareport-univer-admin/target/classes/META-INF/spring-configuration-metadata.json
  27. 167 0
      jnpf-datareport-univer-admin/target/classes/application-dev.yml
  28. 166 0
      jnpf-datareport-univer-admin/target/classes/application-preview.yml
  29. 166 0
      jnpf-datareport-univer-admin/target/classes/application-prod.yml
  30. 166 0
      jnpf-datareport-univer-admin/target/classes/application-test.yml
  31. 84 0
      jnpf-datareport-univer-admin/target/classes/application.yml
  32. 二進制
      jnpf-datareport-univer-admin/target/classes/jnpf/ReportUniverApplication.class
  33. 22 0
      jnpf-datareport-univer-admin/target/classes/jnpf/ReportUniverApplication.java
  34. 二進制
      jnpf-datareport-univer-admin/target/classes/jnpf/aop/DataSourceBindAspect.class
  35. 79 0
      jnpf-datareport-univer-admin/target/classes/jnpf/aop/DataSourceBindAspect.java
  36. 二進制
      jnpf-datareport-univer-admin/target/classes/jnpf/config/AuthFilter.class
  37. 121 0
      jnpf-datareport-univer-admin/target/classes/jnpf/config/AuthFilter.java
  38. 二進制
      jnpf-datareport-univer-admin/target/classes/jnpf/config/ReportAutoConfiguration.class
  39. 41 0
      jnpf-datareport-univer-admin/target/classes/jnpf/config/ReportAutoConfiguration.java
  40. 二進制
      jnpf-datareport-univer-admin/target/classes/jnpf/properties/GatewayWhiteProperties.class
  41. 8 0
      jnpf-datareport-univer-admin/target/classes/jnpf/properties/GatewayWhiteProperties.java
  42. 327 0
      jnpf-datareport-univer-admin/target/classes/logback-spring.xml
  43. 二進制
      jnpf-datareport-univer-admin/target/jnpf-datareport-univer-admin-6.0.0-RELEASE.jar
  44. 二進制
      jnpf-datareport-univer-admin/target/jnpf-datareport-univer-admin-6.0.0-RELEASE.jar.original
  45. 3 0
      jnpf-datareport-univer-admin/target/maven-archiver/pom.properties
  46. 6 0
      jnpf-datareport-univer-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  47. 5 0
      jnpf-datareport-univer-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  48. 21 0
      jnpf-datareport-univer-biz/pom.xml
  49. 17 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/CodeNumMapper.java
  50. 18 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/DictionaryDataMapper.java
  51. 14 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/ReportMapper.java
  52. 14 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/ReportVersionMapper.java
  53. 18 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/SystemMapper.java
  54. 14 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/UserMapper.java
  55. 45 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/CodeNumService.java
  56. 20 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/DictionaryDataService.java
  57. 74 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/ReportService.java
  58. 88 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/ReportVersionService.java
  59. 115 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/SystemService.java
  60. 23 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/UserService.java
  61. 88 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/CodeNumServiceImpl.java
  62. 36 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/DictionaryDataServiceImpl.java
  63. 306 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/ReportServiceImpl.java
  64. 282 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/ReportVersionServiceImpl.java
  65. 213 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/SystemServiceImpl.java
  66. 33 0
      jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/UserServiceImpl.java
  67. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/CodeNumMapper.class
  68. 17 0
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/CodeNumMapper.java
  69. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/DictionaryDataMapper.class
  70. 18 0
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/DictionaryDataMapper.java
  71. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportMapper.class
  72. 14 0
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportMapper.java
  73. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportVersionMapper.class
  74. 14 0
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportVersionMapper.java
  75. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/SystemMapper.class
  76. 18 0
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/SystemMapper.java
  77. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/UserMapper.class
  78. 14 0
      jnpf-datareport-univer-biz/target/classes/jnpf/mapper/UserMapper.java
  79. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/CodeNumService.class
  80. 45 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/CodeNumService.java
  81. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/DictionaryDataService.class
  82. 20 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/DictionaryDataService.java
  83. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportService.class
  84. 74 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportService.java
  85. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportVersionService.class
  86. 88 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportVersionService.java
  87. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/SystemService.class
  88. 115 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/SystemService.java
  89. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/UserService.class
  90. 23 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/UserService.java
  91. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/CodeNumServiceImpl.class
  92. 88 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/CodeNumServiceImpl.java
  93. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/DictionaryDataServiceImpl.class
  94. 36 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/DictionaryDataServiceImpl.java
  95. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportServiceImpl.class
  96. 306 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportServiceImpl.java
  97. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportVersionServiceImpl.class
  98. 282 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportVersionServiceImpl.java
  99. 二進制
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/SystemServiceImpl.class
  100. 213 0
      jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/SystemServiceImpl.java

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 25 - 0
.idea/compiler.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile name="Maven default annotation processors profile" enabled="true">
+        <sourceOutputDir name="target/generated-sources/annotations" />
+        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
+        <outputRelativeToContentRoot value="true" />
+        <module name="jnpf-datareport-univer-admin" />
+        <module name="jnpf-datareport-univer-biz" />
+        <module name="jnpf-datareport-univer-entity" />
+        <module name="jnpf-datareport-univer-controller" />
+      </profile>
+    </annotationProcessing>
+  </component>
+  <component name="JavacSettings">
+    <option name="ADDITIONAL_OPTIONS_OVERRIDE">
+      <module name="jnpf-datareport-univer" options="-parameters" />
+      <module name="jnpf-datareport-univer-admin" options="-parameters" />
+      <module name="jnpf-datareport-univer-biz" options="-parameters" />
+      <module name="jnpf-datareport-univer-controller" options="-parameters" />
+      <module name="jnpf-datareport-univer-entity" options="-parameters" />
+    </option>
+  </component>
+</project>

+ 15 - 0
.idea/encodings.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-admin/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-admin/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-biz/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-biz/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-controller/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-controller/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-entity/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/jnpf-datareport-univer-entity/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 20 - 0
.idea/jarRepositories.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Central Repository" />
+      <option name="url" value="http://127.0.0.1:9999/repository/maven-public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+  </component>
+</project>

+ 12 - 0
.idea/misc.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK" />
+</project>

+ 4 - 0
.idea/vcs.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings" defaultProject="true" />
+</project>

+ 22 - 0
Dockerfile

@@ -0,0 +1,22 @@
+# 基础镜像
+FROM bellsoft/liberica-openjre-rocky:21
+# FROM bellsoft/liberica-openjre-rocky:17
+# FROM bellsoft/liberica-openjre-rocky:11
+# FROM bellsoft/liberica-openjre-rocky:8
+LABEL maintainer=jnpf-team
+
+# 设置时区
+ENV TZ=Asia/Shanghai
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+# 指定运行时的工作目录
+WORKDIR /data/jnpfsoft/univerApi
+
+# 将构建产物jar包拷贝到运行时目录中
+COPY jnpf-datareport-univer-admin/target/*.jar ./jnpf-univer-admin.jar
+
+# 指定容器内运行端口
+EXPOSE 32000
+
+# 指定容器启动时要运行的命令
+ENTRYPOINT ["/bin/sh","-c","java -javaagent:./jnpf-univer-admin.jar -Dfile.encoding=utf8 -Djava.security.egd=file:/dev/./urandom --add-opens java.base/java.lang=ALL-UNNAMED -XX:+DisableAttachMechanism -jar jnpf-univer-admin.jar"]

+ 383 - 0
README.md

@@ -0,0 +1,383 @@
+> 特别说明:源码、JDK、数据库、Redis等安装或存放路径禁止包含中文、空格、特殊字符等
+
+## 一 环境要求
+
+### 1.1 开发环境
+
+| 类目 | 版本说明或建议           |
+| --- |------------------|
+| 硬件 | 开发电脑建议使用I3及以上CPU,16G及以上内存  |
+| 操作系统 | Windows 10/11,MacOS |
+| JDK | 默认使用JDK 21,如需要切换JDK 8/11/17版本请参考文档调整代码,推荐使用 `OpenJDK`,如 `Liberica JDK`、`Eclipse Temurin`、`Alibaba Dragonwell`、`BiSheng` 等发行版; |
+| Maven | 依赖管理工具,推荐使用 `3.6.3` 及以上版本  |
+| Redis | 数据缓存,推荐使用 `5.0` 及以上版本 |
+| 数据库 | 兼容 `MySQL 5.7.x/8.x`、`SQLServer 2012+`、`Oracle 11g`、`PostgreSQL 12+`、`达梦数据库(DM8)`、`人大金仓数据库(KingbaseES_V8R6)` |
+| IDE   | 代码集成开发环境,推荐使用 `IDEA2024` 及以上版本,兼容 `Eclipse`、 `Spring Tool Suite` 等IDE工具 |
+| 文件存储 | 默认使用本地存储,兼容 `MinIO` 及多个云对象存储,如 `阿里云 OSS`、`华为云 OBS`、`七牛云 Kodo`、`腾讯云 COS` 等; |
+
+### 1.2 运行环境
+
+> 适用于测试或生产环境
+
+| 类目 | 版本说明或建议                               |
+| --- |-----------------------------------------------|
+| 服务器配置 | 建议至少在 `4C/16G/50G` 的机器配置下运行;|
+| 操作系统 | 建议使用 `Windows Server 2019` 及以上版本或主流 `Linux` 发行版本,推荐使用 `Linux` 环境;兼容 `统信UOS`,`OpenEuler`,`麒麟服务器版` 等信创环境;    |
+| JRE | 默认使用JRE 21,如需要切换JRE 8/11/17版本请参考文档调整代码;推荐使用 `OpenJDK`,如 `Liberica JDK`、`Eclipse Temurin`、`Alibaba Dragonwell`、`BiSheng` 等发行版;   |
+| Redis | 数据缓存,推荐使用 `5.0` 及以上版本 |
+| 数据库 | 兼容 `MySQL 5.7.x/8.x`、`SQLServer 2012+`、`Oracle 11g`、`PostgreSQL 12+`、`达梦数据库(DM8)`、`人大金仓数据库(KingbaseES_V8R6)` |
+| 文件存储 | 默认使用本地存储,兼容 `MinIO` 及多个云对象存储,如 `阿里云 OSS`、`华为云 OBS`、`七牛云 Kodo`、`腾讯云 COS` 等; |
+
+## 二 关联项目
+
+| 项目                 | 分支            | 说明         |
+|--------------------|---------------|------------|
+| jnpf-common | v6.0.x-stable  | 项目基础依赖源码 |
+| jnpf-java-datareport-univer-core | v6.0.x-stable  | Univer报表核心依赖源码 |
+
+## 三 Maven私服配置
+
+> 建议使用 Apache Maven 3.6.3 及以上版本<br>以解决依赖无法从公共Maven仓库下载的问题<br>通过官方私服下载依赖完成后,由于IDEA的缓存可能会出现部分报红,重启IDEA即可
+
+打开Maven安装目录中的 `conf/settings.xml` 文件,<br/>
+在 `<servers></servers>` 中添加如下内容
+
+```xml
+<server>
+  <id>maven-releases</id>
+  <username>您的账号</username>
+  <password>您的密码</password>
+</server>
+```
+
+在 `<mirrors></mirrors>` 中添加
+
+```xml
+<mirror>
+  <id>maven-releases</id>
+  <mirrorOf>*</mirrorOf>
+  <name>maven-releases</name>
+  <url>https://repository.jnpfsoft.com/repository/maven-public/</url>
+</mirror>
+```
+
+## 四 开发环境
+
+### 4.1 导入数据库脚本
+
+> 以 MySQL数据库为例<br>字符集:`utf8mb4` <br/>排序规则:`utf8mb4_general_ci`
+
+在MySQL创建 `jnpf_init` 数据库,并将 `jnpf-database/MySQL/jnpf_db_init.sql` 导入;
+
+### 4.2 导入依赖
+
+详见 `jnpf-java-datareport-univer-core` 项目中的 `README.md` 文档说明
+
+### 4.3 项目配置
+
+打开编辑 `jnpf-datareport-univer-admin/src/main/resources/application.yml`
+
+#### 4.3.1 指定环境配置
+
+环境说明:
+
+- `application-dev.yml` 开发环境(默认)
+- `application-preview.yml` 预生产环境
+- `application-test.yml` 测试环境
+- `application-prod.yml` 生产环境
+
+> 以开发环境为例,根据实际需求修改
+
+```yaml
+# application.yml第 6 行,可选值:dev(开发环境-默认)、test(测试环境)、preview(预生产环境)、prod(生产环境)
+active: dev
+```
+
+#### 4.3.2 配置域名
+
+打开编辑 `jnpf-datareport-univer-admin/src/main/resources/application.yml` ,修改以下配置
+
+```yaml
+  ApiDomain: http://127.0.0.1:30000 #主项目后端域名(文档预览中使用)
+  FrontDomain: http://127.0.0.1:3100 #前端域名(文档预览中使用)
+  AppDomain: http://127.0.0.1:8080 #app/h5端域名配置(文档预览中使用)
+```
+#### 4.3.3 调整运行端口
+> 根据实际需求调整
+
+打开编辑 `jnpf-datareport-univer-admin/src/main/resources/application-dev.yml`,第 5 行
+
+```yaml
+port: 32000 # 默认运行端口
+```
+
+#### 4.3.4 数据源配置
+
+配置参数说明:
+
+- `db-type`:数据库类型(可选值:`MySQL`、`SQLServer`、`Oracle`、`PostgreSQL`、`DM`、`KingbaseES`)
+- `host`:数据库主机地址
+- `port`:数据库端口
+- `dbname`:平台初始库
+- `username`:数据库用户名
+- `password`:数据库密码
+- `db-schema`:数据库模式
+- `prepare-url`:自定义JDBC连接配置
+
+打开编辑 `jnpf-datareport-univer-admin/src/main/resources/application-dev.yml`,修改以下配置
+
+##### 4.3.4.1 MySQL数据库
+
+```yaml
+  datasource:
+    db-type: MySQL
+    host: 127.0.0.1
+    port: 3306
+    db-name: jnpf_init
+    username: dbuser
+    password: dbpasswd
+    db-schema:
+    prepare-url:
+```
+
+##### 4.3.4.2 SQLServer数据库
+
+```yaml
+  datasource:
+    db-type: SQLServer
+    host: 127.0.0.1
+    port: 1433
+    db-name: jnpf_init
+    username: dbuser
+    password: dbpasswd
+    db-schema:
+    prepare-url:
+```
+
+##### 4.3.4.3 Oracle数据库
+
+```yaml
+  datasource:
+    db-type: Oracle
+    host: 127.0.0.1
+    port: 1521
+    db-name:
+    username: JNPF_INIT
+    password: dbpasswd
+    db-schema:
+    prepare-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
+```
+
+##### 4.3.4.4 PostgreSQL数据库配置
+
+```yaml
+  datasource:
+    db-type: PostgreSQL
+    host: 127.0.0.1
+    port: 5432
+    db-name: jnpf_init
+    username: postgres
+    password: dbpasswd
+    db-schema: public
+    prepare-url:
+```
+
+##### 4.3.4.5 达梦(DM8)数据库
+
+```yaml
+  datasource:
+    db-type: DM
+    host: 127.0.0.1
+    port: 5236
+    db-name: JNPF_INIT
+    username: DBUSER
+    password: dbpasswd
+    db-schema:
+    prepare-url:
+    tablespace: MAIN
+```
+
+##### 4.3.4.6 人大金仓(KingbaseES_V8R6)数据库
+
+```yaml
+  datasource:
+    db-type: KingbaseES
+    host: 127.0.0.1
+    port: 54321
+    db-name: jnpf_init
+    username: system
+    password: dbpasswd
+    db-schema: public
+    prepare-url:
+```
+
+#### 4.3.5 Redis配置
+
+打开编辑 `jnpf-datareport-univer-admin/src/main/resources/application-dev.yml`,修改以下配置
+> 支持单机模式和集群模式,配置默认为单机模式
+
+**若使用Redis单机模式**
+> 第 71-82 行
+
+```yaml
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+```
+
+**若使用Redis集群模式**
+> 第 85-101 行
+
+```yaml
+ redis:
+   cluster:
+     nodes:
+       - 192.168.0.225:6380
+       - 192.168.0.225:6381
+       - 192.168.0.225:6382
+       - 192.168.0.225:6383
+       - 192.168.0.225:6384
+       - 192.168.0.225:6385
+   password: 123456 # 密码为空时,请将本行注释
+   timeout: 3000 # 超时时间(单位:秒)
+   lettuce: #Lettuce为Redis的Java驱动包
+     pool:
+       max-active: 8 # 连接池最大连接数
+       max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+       min-idle: 0 # 连接池中的最小空闲连接
+       max-idle: 8 # 连接池中的最大空闲连接
+```
+
+#### 4.3.6 静态资源配置
+
+打开编辑 `jnpf-datareport-univer-admin/src/main/resources/application-dev.yml` ,修改以下配置(第 121-166 行)
+> 默认使用本地存储,兼容 `MinIO` 及多个云对象存储,如阿里云 OSS、华为云 OBS、七牛云 Kodo、腾讯云 COS等
+
+```yaml
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: D:/project/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径
+```
+
+### 4.4 执行调试或运行
+
+#### 4.4.1 `jnpf-java-datareport-univer-core` 项目未使用加密
+
+- 在IDEA中, 展开右侧 `Maven` 中 `Profiles` 去除勾选 `encrypted` 选项, 再点击 Maven `刷新` 图标刷新Maven
+- 找到 `jnpf-datareport-univer-admin/src/main/java/jnpf/ReportUniverApplication.java`,右击运行即可。
+
+若使用JDK9及以上版本,在IDEA中,打开 `Edit Configurations` VM启动参数添加如下参数:
+
+ ```bash
+ --add-opens java.base/java.lang=ALL-UNNAMED
+ ```
+
+#### 4.4.2 `jnpf-java-datareport-univer-core` 项目使用加密
+
+- 在IDEA中,展开右侧 `Maven` 中 `Profiles` 勾选 `encrypted` 选项, 再点击Maven `刷新` 图标刷新Maven
+- 在IDEA中,双击右侧 `Maven` 中 `jnpf-datareport-univer` > `clean` 将会自动安装加密打包插件, 并创建创建 `jnpf-datareport-univer-entity/target/copylib` 复制依赖包用于下一步运行
+
+**参数说明**:
+
+```bash
+# 打开项目中`jnpf-datareport-univer-entity/target/copylib` 目录, 复制Jar包 `jnpf-datareport-univer-model-版本号.jar` 的文件名
+-javaagent:项目存放路径/jnpf-datareport-univer-entity/target/copylib/jnpf-datareport-univer-model-当前版本号.jar(上面复制的文件名)="decryptProjectPathPrefix=jnpf-datareport-univer-common___jnpf-datareport-univer-model"
+```
+
+- 在IDEA中,打开 `Edit Configurations` VM启动参数添加如下参数
+
+若使用 JDK8 运行,需要替换下方命令示例中的Jar包路径
+
+ ``` bash
+-XX:+DisableAttachMechanism
+-javaagent:D:/Projects/IdeaProjects/jnpf-java-datareport-univer/jnpf-datareport-univer-entity/target/copylib/jnpf-datareport-univer-model-5.1.0-RELEASE.jar="decryptProjectPathPrefix=jnpf-datareport-univer-common___jnpf-datareport-univer-model"
+ ```
+
+若使用JDK 9及以上版本,需要替换下方命令示例中的Jar包路径
+
+ ``` bash
+--add-opens java.base/java.lang=ALL-UNNAMED
+-XX:+DisableAttachMechanism
+-javaagent:D:/Projects/IdeaProjects/jnpf-java-datareport-univer/jnpf-datareport-univer-entity/target/copylib/jnpf-datareport-univer-model-5.1.0-RELEASE.jar="decryptProjectPathPrefix=jnpf-datareport-univer-common___jnpf-datareport-univer-model"
+ ```
+## 五 项目发布
+
+### 5.1 `jnpf-java-datareport-univer-core` 项目未使用加密
+
+- 在IDEA中, 展开右侧 `Maven` 中 `Profiles` 去除勾选 `encrypted` 选项, 再点击Maven `刷新` 图标刷新Maven
+- 在IDEA中,双击右侧Maven中 `jnpf-datareport-univer` > `Lifecycle` > `clean` 清理项目
+- 在IDEA中,双击右侧Maven中 `jnpf-datareport-univer` > `Lifecycle` > `package` 打包项目
+- 打开 `jnpf-datareport-univer/jnpf-datareport-univer-entity/target`,将 `jnpf-datareport-univer-admin-5.1.0-RELEASE.jar` 上传至服务器
+
+### 5.2 `jnpf-java-datareport-univer-core` 项目使用加密
+
+- 在IDEA中, 展开右侧 `Maven` 中 `Profiles` 勾选 `encrypted` 选项, 再点击Maven `刷新` 图标刷新Maven
+- 在IDEA中,双击右侧 `Maven` > `jnpf-java-datareport-univer` > `clean` 将会自动安装加密打包插件
+- 在IDEA中,双击右侧 `Maven` > `jnpf-java-datareport-univer` > `Lifecycle` > `package` 打包项目
+- 打开 `jnpf-datareport-univer/jnpf-datareport-univer-admin/target`,将 `jnpf-datareport-univer-admin-5.1.0-RELEASE.jar` 上传至服务器
+- 启动命令
+
+**若使用 JDK/JRE 8 运行**
+
+```bash
+java -javaagent:./jnpf-datareport-univer-admin-5.1.0-RELEASE.jar -XX:+DisableAttachMechanism -jar jnpf-datareport-univer-admin-5.1.0-RELEASE.jar
+ ```
+
+**若使用 JDK/JRE 9及以上版本运行**
+
+```bash
+java -javaagent:./jnpf-datareport-univer-admin-5.1.0-RELEASE.jar --add-opens java.base/java.lang=ALL-UNNAMED -XX:+DisableAttachMechanism -jar jnpf-datareport-univer-admin-5.1.0-RELEASE.jar
+ ```

二進制
allatori/allatori.jar


+ 35 - 0
allatori/allatori.xml

@@ -0,0 +1,35 @@
+<config>
+    <input>
+        <jar in="${project.build.finalName}.jar" out="${project.build.finalName}.jar"/>
+    </input>
+
+    <keep-names>
+        <class access="protected+">
+            <field access="protected+"/>
+            <method access="protected+"/>
+        </class>
+    </keep-names>
+    <ignore-classes>
+        <!-- 注意:spring的框架相关的文件需要排除,避免启动报错 -->
+        <class template="class jnpf.properties.ReportProperties"/>
+    </ignore-classes>
+
+
+    <!-- 混淆设置 -->
+    <!--随机类名保持小写-->
+    <property name="classes-naming" value="abc"/>
+    <!-- 接口形参名保持不变 -->
+    <property name="local-variables-naming" value="keep-parameters"/>
+    <!-- 字符串加密 -->
+    <property name="string-encryption" value="maximum"/>
+    <property name="string-encryption-type" value="strong"/>
+    <property name="string-encryption-version" value="v4"/>
+    <!-- 行数混淆 -->
+    <property name="line-numbers" value="obfuscate"/>
+    <!-- 成员重新排序 -->
+    <property name="member-reorder" value="enable"/>
+    <!-- 数据jar压缩等级 -->
+    <property name="output-jar-compression-level" value="9"/>
+
+    <property name="log-file" value="log.xml"/>
+</config>

二進制
allatori/class-winter-core-enhance-2.9.4.jar


二進制
allatori/class-winter-maven-plugin-enhance-2.9.4.jar


+ 37 - 0
allatori/class-winter-maven-plugin-pom.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.idea-aedi</groupId>
+    <artifactId>class-winter-maven-plugin</artifactId>
+    <version>enhance-2.9.4</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.idea-aedi</groupId>
+            <artifactId>class-winter-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>3.8.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>3.6.1</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-project</artifactId>
+            <version>2.2.1</version>
+        </dependency>
+    </dependencies>
+</project>

+ 122 - 0
jnpf-datareport-univer-admin/pom.xml

@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.jnpf</groupId>
+        <artifactId>jnpf-datareport-univer</artifactId>
+        <version>6.0.0-RELEASE</version>
+    </parent>
+
+    <artifactId>jnpf-datareport-univer-admin</artifactId>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>com.jnpf</groupId>
+            <artifactId>jnpf-common-security</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.jnpf</groupId>
+            <artifactId>jnpf-datareport-univer-controller</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+
+    <profiles>
+        <profile>
+            <!--JAR包加密-->
+            <id>encrypted</id>
+            <build>
+                <plugins>
+                    <!--安装加密打包插件-->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-install-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>install-core</id>
+                                <phase>clean</phase>
+                                <configuration>
+                                    <file>${project.basedir}/../allatori/class-winter-core-${class-winter-maven-plugin.version}.jar</file>
+                                    <repositoryLayout>default</repositoryLayout>
+                                    <groupId>com.idea-aedi</groupId>
+                                    <artifactId>class-winter-core</artifactId>
+                                    <version>${class-winter-maven-plugin.version}</version>
+                                    <packaging>jar</packaging>
+                                    <generatePom>true</generatePom>
+                                </configuration>
+                                <goals>
+                                    <goal>install-file</goal>
+                                </goals>
+                            </execution>
+                            <execution>
+                                <id>install-maven</id>
+                                <phase>clean</phase>
+                                <configuration>
+                                    <file>${project.basedir}/../allatori/class-winter-maven-plugin-${class-winter-maven-plugin.version}.jar</file>
+                                    <repositoryLayout>default</repositoryLayout>
+                                    <groupId>com.idea-aedi</groupId>
+                                    <artifactId>class-winter-maven-plugin</artifactId>
+                                    <version>${class-winter-maven-plugin.version}</version>
+                                    <packaging>jar</packaging>
+                                    <generatePom>false</generatePom>
+                                    <pomFile>${project.basedir}/../allatori/class-winter-maven-plugin-pom.xml</pomFile>
+                                </configuration>
+                                <goals>
+                                    <goal>install-file</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>com.idea-aedi</groupId>
+                        <artifactId>class-winter-maven-plugin</artifactId>
+                        <!-- 相关配置 -->
+                        <configuration>
+                            <!--设置不存在的包表示此项目不加密-->
+                            <includePrefix>jnpf.noexists</includePrefix>
+                            <!--直接覆盖原文件-->
+                            <finalName>${build.finalName}</finalName>
+                            <!--项目中包含的已经加密的包-->
+                            <alreadyProtectedLibs>jnpf-datareport-univer-common${jnpf.datareport.core.jdk.version}-${project.version}.jar,jnpf-datareport-univer-model${jnpf.datareport.core.jdk.version}-${project.version}.jar</alreadyProtectedLibs>
+                            <!--检查启动参数-->
+                            <jvmArgCheck>-XX:+DisableAttachMechanism</jvmArgCheck>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>class-winter</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>jnpf.ReportUniverApplication</mainClass>
+                    <layout>ZIP</layout>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 22 - 0
jnpf-datareport-univer-admin/src/main/java/jnpf/ReportUniverApplication.java

@@ -0,0 +1,22 @@
+package jnpf;
+
+import com.fasterxml.jackson.core.StreamReadConstraints;
+import org.dromara.x.file.storage.spring.EnableFileStorage;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+
+@SpringBootApplication
+@EnableFileStorage
+public class ReportUniverApplication {
+
+    public static void main(String[] args) {
+        StreamReadConstraints.overrideDefaultStreamReadConstraints(
+                StreamReadConstraints.builder().maxStringLength(100000000).build()
+        );
+        SpringApplication springApplication = new SpringApplication(ReportUniverApplication.class);
+        springApplication.run(args);
+        System.out.println("报表启动完成");
+    }
+
+}

+ 79 - 0
jnpf-datareport-univer-admin/src/main/java/jnpf/aop/DataSourceBindAspect.java

@@ -0,0 +1,79 @@
+package jnpf.aop;
+
+import cn.dev33.satoken.context.SaHolder;
+import jnpf.base.UserInfo;
+import jnpf.config.ConfigValueUtil;
+import jnpf.database.util.NotTenantPluginHolder;
+import jnpf.database.util.TenantDataSourceUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.TenantHolder;
+import jnpf.util.UserProvider;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2021/3/15 17:12
+ */
+@Slf4j
+@Aspect
+@Component
+@Order(1)
+public class DataSourceBindAspect {
+
+    @Autowired
+    private ConfigValueUtil configValueUtil;
+
+    @Pointcut("(execution(* jnpf.*.controller.*.*(..)) || execution(* jnpf.controller.*.*(..))))")
+    public void bindDataSource() {
+
+    }
+
+    /**
+     * NoDataSourceBind 不需要绑定数据库的注解
+     *
+     * @param pjp
+     * @return
+     * @throws Throwable
+     */
+    @Around("bindDataSource() && !@annotation(jnpf.util.NoDataSourceBind)")
+    public Object doAroundService(ProceedingJoinPoint pjp) throws Throwable {
+        if (configValueUtil.isMultiTenancy()) {
+            if(StringUtil.isEmpty(TenantHolder.getDatasourceId())){
+                UserInfo userInfo = UserProvider.getUser();
+                String url = null;
+                try{
+                    url = SaHolder.getRequest().getRequestPath();
+                }catch (Exception ee){ }
+                log.error("租户" + userInfo.getTenantId() + "数据库不存在, URL: {}, TOKEN: {}", url, userInfo.getToken());
+                return null;
+            }
+            return pjp.proceed();
+        }
+        Object obj = pjp.proceed();
+        return obj;
+    }
+
+
+
+    @Around("bindDataSource() && @annotation(jnpf.util.NoDataSourceBind)")
+    public Object doAroundService2(ProceedingJoinPoint pjp) throws Throwable {
+        try{
+            NotTenantPluginHolder.setNotSwitchAlwaysFlag();
+            //Filter中提前设置租户信息, 不需要切库的方法进行清除切库
+            TenantDataSourceUtil.clearLocalTenantInfo();
+            return pjp.proceed();
+        }finally {
+            NotTenantPluginHolder.clearNotSwitchAlwaysFlag();
+        }
+    }
+}

+ 121 - 0
jnpf-datareport-univer-admin/src/main/java/jnpf/config/AuthFilter.java

@@ -0,0 +1,121 @@
+package jnpf.config;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.filter.SaServletFilter;
+import cn.dev33.satoken.router.SaHttpMethod;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+import jnpf.base.ActionResultCode;
+import jnpf.constant.MsgCode;
+import jnpf.consts.AuthConsts;
+import jnpf.properties.GatewayWhite;
+import jnpf.util.IpUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.UserProvider;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+
+
+/**
+ * 网关验证token
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司(https://www.jnpfsoft.com)
+ * @date 2021-03-24
+ */
+@Slf4j
+@Configuration
+public class AuthFilter {
+
+    private static final String ALL = "*";
+    private static final String MAX_AGE = "18000L";
+
+    // 注册 Sa-Token全局过滤器
+    @Bean
+    public SaServletFilter getSaReactorFilter(GatewayWhite gatewayWhite) {
+        return new SaServletFilter()
+                // 拦截地址
+                .addInclude("/**")
+                .setExcludeList(gatewayWhite.excludeUrl)
+                // 鉴权方法:每次访问进入
+                .setAuth(obj -> {
+                    if(log.isInfoEnabled()){
+                        log.info("请求路径: {}", SaHolder.getRequest().getRequestPath());
+                    }
+                    //拦截路径
+                    SaRouter.match(gatewayWhite.blockUrl).match(o -> {
+                        //禁止访问URL 排除白名单
+                        String ip = getIpAddr();
+                        for (String o1 : gatewayWhite.whiteIp) {
+                            if(ip.startsWith(o1)){
+                                return false;
+                            }
+                        }
+                        log.info("非白名单IP访问限制接口:{}, {}", SaHolder.getRequest().getRequestPath(), ip);
+                        return true;
+                    }).back(MsgCode.AD101.get());
+                    //测试不验证 鉴权服务重启测试模式不清除Token就够了
+                    //SaRouter.match((r)->"true".equals(configValueUtil.getTestVersion())).stop();
+                    //白名单不拦截
+                    SaRouter.match(gatewayWhite.whiteUrl).stop();
+                    //内部请求不拦截
+                    SaRouter.match(t->{
+                        String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
+                        return UserProvider.isValidInnerToken(innerToken);
+                    }).stop();
+                    // 登录校验 -- 拦截所有路由
+                    SaRouter.match("/**", r -> {
+                        //兼容Net、Java大小写不一致问题
+                        String token = StpUtil.getTokenValueNotCut();
+                        if(!StringUtil.isEmpty(token)){
+                            String[] tokenArr = token.split(" ");
+                            if(StpUtil.getLoginIdByToken(tokenArr[tokenArr.length-1]) != null){
+                                return;
+                            }
+                        }
+                        throw NotLoginException.newInstance(StpUtil.getLoginType(), NotLoginException.INVALID_TOKEN, NotLoginException.INVALID_TOKEN_MESSAGE, token);
+                    }).stop();
+                }).setError(e -> {
+                    SaHolder.getResponse().addHeader("Content-Type","application/json; charset=utf-8");
+                    if(e instanceof NotLoginException){
+                        return SaResult.error(ActionResultCode.SessionOverdue.getMessage()).setCode(ActionResultCode.SessionOverdue.getCode());
+                    }
+                    log.error(e.getMessage(), e);
+                    return SaResult.error(MsgCode.AD102.get()).setCode(ActionResultCode.Exception.getCode());
+                })
+                // 前置函数:在每次认证函数之前执行
+                .setBeforeAuth(obj -> {
+                    HttpServletRequest request = (HttpServletRequest) SaHolder.getRequest().getSource();
+                    // ---------- 设置跨域响应头 ----------
+                    SaHolder.getResponse()
+                            // 允许指定域访问跨域资源
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, request.getHeader(HttpHeaders.ORIGIN))
+                            // 允许的header参数
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, ALL)
+                            // 允许所有请求方式
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, ALL)
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL)
+                            // 有效时间
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
+
+                    // 如果是预检请求,则立即返回到前端
+                    SaRouter.match(SaHttpMethod.OPTIONS)
+                            .back();
+                });
+    }
+
+    public static String getIpAddr() {
+        return IpUtil.getIpAddr();
+    }
+
+
+}

+ 41 - 0
jnpf-datareport-univer-admin/src/main/java/jnpf/config/ReportAutoConfiguration.java

@@ -0,0 +1,41 @@
+package jnpf.config;
+
+import jnpf.consts.ApiConst;
+import jnpf.properties.GatewayWhite;
+import jnpf.properties.GatewayWhiteProperties;
+import jnpf.properties.ReportProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration(proxyBeanMethods = false)
+public class ReportAutoConfiguration {
+
+
+    @Bean
+    @ConfigurationProperties(prefix = GatewayWhite.PREFIX)
+    public GatewayWhite getGateWhite(){
+        return new GatewayWhiteProperties();
+    }
+
+
+    @Bean
+    @ConfigurationProperties(prefix = ReportProperties.PREFIX)
+    public ReportProperties getReportProperties(){
+        return new ReportProperties();
+    }
+
+
+    @Bean
+    public ApiConst initReportApiConst(JnpfOauthConfig jnpfOauthConfig){
+        ApiConst.ME = jnpfOauthConfig.getJnpfDomain() + "/api/oauth/me";
+        ApiConst.DATASET_LIST = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/getList";
+        ApiConst.DATASET_SAVE = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/save";
+        ApiConst.DATASET_DATA = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/Data";
+        ApiConst.SAVE_MENU = jnpfOauthConfig.getJnpfDomain() + "/api/system/Menu/saveReportMenu";
+        ApiConst.GET_MENU = jnpfOauthConfig.getJnpfDomain() + "/api/system/Menu/getReportMenu";
+        ApiConst.PARAMETER_DATA = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/parameterData";
+        return new ApiConst();
+    }
+
+}

+ 8 - 0
jnpf-datareport-univer-admin/src/main/java/jnpf/properties/GatewayWhiteProperties.java

@@ -0,0 +1,8 @@
+package jnpf.properties;
+
+/**
+ * 根据需求重写网关URL
+ */
+public class GatewayWhiteProperties extends GatewayWhite {
+
+}

+ 167 - 0
jnpf-datareport-univer-admin/src/main/resources/application-dev.yml

@@ -0,0 +1,167 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: usky-cloud-mysql
+    port: 3306
+    username: root
+    password: yt123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  data:
+    redis:
+      database: 1
+      host: usky-cloud-redis
+      port: 6379
+      password: 123456
+      timeout: 3000
+      lettuce: #Lettuce为Redis的Java驱动包
+        pool:
+          max-active: 8 # 连接池最大连接数
+          max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+          min-idle: 0 # 连接池中的最小空闲连接
+          max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /home/uskycloud_c01/software/nginx/html/static/  # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 166 - 0
jnpf-datareport-univer-admin/src/main/resources/application-preview.yml

@@ -0,0 +1,166 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: 127.0.0.1
+    port: 3306
+    username: root
+    password: 123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /data/wwwroot/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 166 - 0
jnpf-datareport-univer-admin/src/main/resources/application-prod.yml

@@ -0,0 +1,166 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: 127.0.0.1
+    port: 3306
+    username: root
+    password: 123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /data/wwwroot/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 166 - 0
jnpf-datareport-univer-admin/src/main/resources/application-test.yml

@@ -0,0 +1,166 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: 127.0.0.1
+    port: 3306
+    username: root
+    password: 123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /data/wwwroot/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 84 - 0
jnpf-datareport-univer-admin/src/main/resources/application.yml

@@ -0,0 +1,84 @@
+spring:
+  application:
+    name: jnpf-datareport
+  profiles:
+    # 指定环境配置 dev(开发环境-默认)、test(测试环境)、preview(预生产环境)、prod(生产环境)
+    active: dev
+  servlet:
+    multipart: #文件传输配置
+      max-file-size: 100MB #单个数据大小限制
+      max-request-size: 100MB #请求总数据大小限制
+      enabled: true  #是否启用分段上传支持
+  mvc:
+    hiddenmethod: #隐式方法过滤器
+      filter:
+        enabled: true #默认开启。开启以支持:PUT,DELETE表单提交方法
+  jackson: #序列化和反序列化json框架
+    serialization:
+      write-dates-as-timestamps: true #是否写入日期时间时间戳格式
+    time-zone: GMT+8 #指定日期格式化时区
+  main:
+    allow-bean-definition-overriding: true #允许同名bean后者覆盖,默认:true
+    allow-circular-references: true #允许Bean相互引用,默认:false
+
+config:
+  #===================== 访问域名 =====================
+  WebAnnexFilePath: WebAnnexFile
+  DataBackupFilePath: DataBackupFile
+  TemporaryFilePath: TemporaryFile
+  SystemFilePath: SystemFile
+  TemplateFilePath: TemplateFile
+  EmailFilePath: EmailFile
+  DocumentFilePath: DocumentFile
+  DocumentPreviewPath: DocumentPreview
+  UserAvatarFilePath: UserAvatar
+  IMContentFilePath: IMContentFile
+  MPMaterialFilePath: MPMaterial
+  TemplateCodePath: TemplateCode
+  BiVisualPath: BiVisualPath
+
+  ApiDomain: http://192.168.10.196:30000 #主项目后端域名(文档预览中使用)
+  FrontDomain: http://192.168.10.196:3100 #前端域名(文档预览中使用)
+  AppDomain: http://192.168.10.196:8080 #app/h5端域名配置(文档预览中使用)
+
+  #===================== 多租户 =====================
+  MultiTenancy: false #是否开启
+  MultiTenancyUrl: http://192.168.10.196:30006/api/tenant/DbName/ #多租户项目地址
+
+# 接口放行地址 与GatewayWhite中的默认URL合并
+gateway:
+  # 禁止访问接口
+  block-url:
+  ## 配置示例
+  #- /api/message/Notice
+  #- /api/permission/Users/*
+  # 不验证Token, 放行接口(默认记录日志)
+  white-url:
+  #  # 配置示例
+  #- /api/message/Notice
+  #- /api/permission/Users/*
+  # 放行接口(不记录日志)
+  exclude-url:
+  #  # 配置示例
+  #- /api/message/Notice
+  #- /api/permission/Users/*
+  # 入站IP(禁止配置以外的IP访问block-url配置的接口)
+  white-ip:
+  #- 192.168.0.10
+  #- 192.168.0.20
+
+# 日志配置
+logging:
+  config: classpath:logback-spring.xml
+  level:
+    #自定义第三方包名日志等级
+    # 解除注释后Druid连接池打印SQL语句
+    druid.sql.Statement: debug
+#    druid.sql.DataSource: debug
+#    druid.sql.Connection: debug
+#    druid.sql.ResultSet: debug
+log:
+  level:
+    # 等级 TRACE,DEBUG,INFO,WARN,ERROR(不区分大小写)
+    root: info
+  path: log/${spring.application.name}

+ 327 - 0
jnpf-datareport-univer-admin/src/main/resources/logback-spring.xml

@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+    <!--日志格式应用spring boot默认的格式,也可以自己更改-->
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+    <property name="FILE_LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] [%logger{50}] [%M] [%line] - %msg%n" />
+    <springProperty scope="context" name="SERVICE_NAME" source="spring.application.name" defaultValue="jnpf"/>
+
+    <!--定义日志存放的位置,默认存放在项目启动的相对路径的目录-->
+    <springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="log/${SERVICE_NAME}"/>
+    <!-- 全局日志等级 -->
+    <springProperty scope="context" name="LOG_LEVEL_ROOT" source="log.level.root" defaultValue="INFO"/>
+    <!-- 服务自定义等级 如需自定义服务日志等级 修改下方的【自定义服务名】与nacos上的log.level.自定义服务名=等级 -->
+    <springProperty scope="context" name="LOG_LEVEL" source="log.level.jnpf-boot" defaultValue="${LOG_LEVEL_ROOT}"/>
+
+    <!-- 日志记录器,日期滚动记录,level为 ERROR 日志 -->
+    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_error.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd,aux}/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录error级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>error</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,level为 INFO 日志 -->
+    <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_info.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd,aux}/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,level为 WARN 日志 -->
+    <appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_warn.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>warn</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 日志记录器,日期滚动记录,level为 DEBUG 日志 -->
+    <appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_debug.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd,aux}/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>debug</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,所有日志 -->
+    <appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_total.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/total/%d{yyyy-MM-dd,aux}/log-total-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,level 根据配置动态输出日志 -->
+    <appender name="FILE_RELEASE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_release.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/release/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>${LOG_LEVEL}</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+    <!-- 异步输出 DEBUG -->
+    <appender name="ASYNC_FILE_DEBUG" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_DEBUG"/>
+    </appender>
+    <!-- 异步输出 INFO -->
+    <appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_INFO"/>
+    </appender>
+    <!-- 异步输出 WARN -->
+    <appender name="ASYNC_FILE_WARN" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_WARN"/>
+    </appender>
+    <!-- 异步输出 ERROR -->
+    <appender name="ASYNC_FILE_ERROR" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_ERROR"/>
+    </appender>
+    <!-- 异步输出 ALL -->
+    <appender name="ASYNC_FILE_ALL" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_ALL"/>
+    </appender>
+
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+
+    <!-- 异步输出 控制台 -->
+    <appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="STDOUT"/>
+    </appender>
+
+
+    <!--<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        &lt;!&ndash; 必填:目标:LogStash的 IP:Port &ndash;&gt;
+        <destination>192.168.0.50:50000</destination>
+        &lt;!&ndash; 可选:保持程序存活时间 &ndash;&gt;
+        <keepAliveDuration>5 minutes</keepAliveDuration>
+        &lt;!&ndash; 可选:重连延迟时长 &ndash;&gt;
+        <reconnectionDelay>10 second</reconnectionDelay>
+        &lt;!&ndash; 可选:等待策略 &ndash;&gt;
+        <waitStrategyType>sleeping</waitStrategyType>
+        &lt;!&ndash;  ============ encoder必须配置,有多种可选 ============= &ndash;&gt;
+        &lt;!&ndash; 编码器二:LoggingEventCompositeJsonEncoder &ndash;&gt;
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
+            <providers>
+                &lt;!&ndash; 时间戳:时区 &ndash;&gt;
+                <timestamp>
+                    <timeZone>UTC</timeZone>
+                </timestamp>
+                &lt;!&ndash; 模式 &ndash;&gt;
+                <pattern>
+                    <pattern>
+                        {
+                        "severity": "%level",
+                        "service": "${SERVICE_NAME:-}",
+                        "trace": "%X{X-B3-TraceId:-}",
+                        "span": "%X{X-B3-SpanId:-}",
+                        "exportable": "%X{X-Span-Export:-}",
+                        "pid": "${PID:-}",
+                        "thread": "%thread",
+                        "class": "%logger{40}",
+                        "msg": "%message"
+                        &lt;!&ndash;"idx_pre": "elk-original-third-access",&ndash;&gt;
+                        &lt;!&ndash;"json": "#asJson{%message}"  这个asJson可以把对应的字符串作为json对象取出来,这样es可以对json里面的字段索引了&ndash;&gt;
+                        }
+                    </pattern>
+                </pattern>
+            </providers>
+        </encoder>
+    </appender>-->
+
+
+    <root level="${LOG_LEVEL}">
+        <appender-ref ref="ASYNC_STDOUT"/>
+        <appender-ref ref="ASYNC_FILE_ERROR"/>
+        <appender-ref ref="ASYNC_FILE_INFO"/>
+        <appender-ref ref="ASYNC_FILE_WARN"/>
+        <appender-ref ref="ASYNC_FILE_DEBUG"/>
+        <appender-ref ref="ASYNC_FILE_ALL"/>
+        <!--<appender-ref ref="LOGSTASH"/>-->
+    </root>
+
+
+</configuration>

+ 42 - 0
jnpf-datareport-univer-admin/target/classes/META-INF/spring-configuration-metadata.json

@@ -0,0 +1,42 @@
+{
+  "groups": [
+    {
+      "name": "gateway",
+      "type": "jnpf.properties.GatewayWhite",
+      "sourceType": "jnpf.config.ReportAutoConfiguration",
+      "sourceMethod": "getGateWhite()"
+    },
+    {
+      "name": "report",
+      "type": "jnpf.properties.ReportProperties",
+      "sourceType": "jnpf.config.ReportAutoConfiguration",
+      "sourceMethod": "getReportProperties()"
+    }
+  ],
+  "properties": [
+    {
+      "name": "gateway.block-url",
+      "type": "java.util.List<java.lang.String>",
+      "sourceType": "jnpf.properties.GatewayWhite"
+    },
+    {
+      "name": "gateway.exclude-url",
+      "type": "java.util.List<java.lang.String>",
+      "sourceType": "jnpf.properties.GatewayWhite"
+    },
+    {
+      "name": "gateway.white-ip",
+      "type": "java.util.List<java.lang.String>",
+      "sourceType": "jnpf.properties.GatewayWhite"
+    },
+    {
+      "name": "gateway.white-url",
+      "type": "java.util.List<java.lang.String>",
+      "sourceType": "jnpf.properties.GatewayWhite"
+    }
+  ],
+  "hints": [],
+  "ignored": {
+    "properties": []
+  }
+}

+ 167 - 0
jnpf-datareport-univer-admin/target/classes/application-dev.yml

@@ -0,0 +1,167 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: usky-cloud-mysql
+    port: 3306
+    username: root
+    password: yt123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  data:
+    redis:
+      database: 1
+      host: usky-cloud-redis
+      port: 6379
+      password: 123456
+      timeout: 3000
+      lettuce: #Lettuce为Redis的Java驱动包
+        pool:
+          max-active: 8 # 连接池最大连接数
+          max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+          min-idle: 0 # 连接池中的最小空闲连接
+          max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /home/uskycloud_c01/software/nginx/html/static/  # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 166 - 0
jnpf-datareport-univer-admin/target/classes/application-preview.yml

@@ -0,0 +1,166 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: 127.0.0.1
+    port: 3306
+    username: root
+    password: 123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /data/wwwroot/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 166 - 0
jnpf-datareport-univer-admin/target/classes/application-prod.yml

@@ -0,0 +1,166 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: 127.0.0.1
+    port: 3306
+    username: root
+    password: 123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /data/wwwroot/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 166 - 0
jnpf-datareport-univer-admin/target/classes/application-test.yml

@@ -0,0 +1,166 @@
+# 应用服务器
+server:
+  tomcat:
+    uri-encoding: UTF-8 #tomcat编码
+  port: 32000 #tomcat端口
+
+spring:
+  devtools: #spring开发者工具模块
+    restart:
+      enabled: true #热部署开关
+    freemarker:
+      cache: false #spring内置freemarker缓存
+  thymeleaf:
+    cache: false #spring内置thymeleaf缓存
+
+  # ===================== 数据源配置 =====================
+  exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure #排除自动配置,手动配置druid
+  datasource:
+    db-type: MySQL #数据库类型(可选值 MySQL、SQLServer、Oracle、DM、KingbaseES、PostgreSQL,请严格按可选值填写)
+    host: 127.0.0.1
+    port: 3306
+    username: root
+    password: 123456
+    db-name: jnpf_init
+    db-schema: #金仓达梦选填
+    prepare-url: #自定义url
+
+    # ===================== 动态多数据源 =====================
+    dynamic:
+      primary: master #设置默认的数据源或者数据源组,默认值即为master
+      strict: true #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
+      druid:
+        # 空闲时执行连接测试
+        test-while-idle: true
+        # 连接测试最小间隔
+        time-between-eviction-runs-millis: 60000
+        # 获取连接等待3秒 根据网络情况设定
+        max-wait: 3000
+        # 初始化4个连接
+        initial-size: 4
+        # 最大20个连接
+        max-active: 20
+        # 最少保持4个空闲连接
+        min-idle: 4
+        # 空闲连接保活, 超过配置的空闲时间会进行连接检查完成保活操作(数据库自身会断开达到空闲时间的连接, 程序使用断开的连接会报错)
+        keep-alive: true
+        # 解除注释后Druid连接池打印SQL语句 忽略日志等级配置
+        #filters: slf4j
+        slf4j:
+          statementLogEnabled: true
+          resultSetLogEnabled: false
+          connectionLogEnabled: false
+          dataSourceLogEnabled: false
+          statementCreateAfterLogEnabled: false
+          statementCloseAfterLogEnabled: false
+          statementExecuteAfterLogEnabled: false
+          #打印SQL替换参数
+          statementExecutableSqlLogEnable: true
+          statementPrepareAfterLogEnabled: false
+          statementPrepareCallAfterLogEnabled: false
+          statementParameterSetLogEnabled: false
+  #      datasource:
+  #        master:
+  #          url: jdbc:mysql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.dbname}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
+  #          username: ${spring.datasource.username}
+  #          password: ${spring.datasource.password}
+  #          driver-class-name: com.mysql.cj.jdbc.Driver
+
+  # ===================== Redis配置 =====================
+  # redis单机模式
+  redis:
+    database: 1 #缓存库编号
+    host: 127.0.0.1
+    port: 6379
+    password: 123456  # 密码为空时,请将本行注释
+    timeout: 3000 #超时时间(单位:秒)
+    lettuce: #Lettuce为Redis的Java驱动包
+      pool:
+        max-active: 8 # 连接池最大连接数
+        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        min-idle: 0 # 连接池中的最小空闲连接
+        max-idle: 8 # 连接池中的最大空闲连接
+
+# redis集群模式
+#  redis:
+#    cluster:
+#      nodes:
+#        - 192.168.0.225:6380
+#        - 192.168.0.225:6381
+#        - 192.168.0.225:6382
+#        - 192.168.0.225:6383
+#        - 192.168.0.225:6384
+#        - 192.168.0.225:6385
+#    password: 123456 # 密码为空时,请将本行注释
+#    timeout: 3000 # 超时时间(单位:秒)
+#    lettuce: #Lettuce为Redis的Java驱动包
+#      pool:
+#        max-active: 8 # 连接池最大连接数
+#        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
+#        min-idle: 0 # 连接池中的最小空闲连接
+#        max-idle: 8 # 连接池中的最大空闲连接
+
+# SpringDoc接口文档 访问地址:http://127.0.0.1:30000/doc.html
+springdoc:
+  default-flat-param-object: true
+  api-docs:
+    enabled: true
+#SpringDoc增强
+#knife4j:
+#  basic: #接口文档访问鉴权
+#    enable: true
+#    username: jnpf
+#    password: 123456
+
+config:
+  # ===================== 是否开启测试环境 =====================
+  TestVersion: false
+  # ===================== ApacheShardingSphere 配置开关 =====================
+  sharding-sphere-enabled: false
+  # ===================== 文件存储配置 =====================
+  file-storage: #文件存储配置,不使用的情况下可以不写
+    default-platform: local-plus-1 #默认使用的存储平台
+    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
+    local-plus: # 本地存储升级版
+      - platform: local-plus-1 # 存储平台标识
+        enable-storage: true  #启用存储
+        enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高)
+        domain: "" # 访问域名,例如:“http://127.0.0.1:8030/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名
+        base-path: /data/wwwroot/jnpf-resources/ # 基础路径
+        path-patterns: /** # 访问路径
+        storage-path:  # 存储路径
+    aliyun-oss: # 阿里云 OSS ,不使用的情况下可以不写
+      - platform: aliyun-oss-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        end-point: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
+        base-path: hy/ # 基础路径
+    qiniu-kodo: # 七牛云 kodo ,不使用的情况下可以不写
+      - platform: qiniu-kodo-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        access-key: ??
+        secret-key: ??
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
+        base-path: base/ # 基础路径
+    tencent-cos: # 腾讯云 COS
+      - platform: tencent-cos-1 # 存储平台标识
+        enable-storage: false  # 启用存储
+        secret-id: ??
+        secret-key: ??
+        region: ?? #存仓库所在地域
+        bucket-name: ??
+        domain: ?? # 访问域名,注意“/”结尾,例如:https://abc.cos.ap-nanjing.myqcloud.com/
+        base-path: hy/ # 基础路径
+    minio: # MinIO,由于 MinIO SDK 支持 AWS S3,其它兼容 AWS S3 协议的存储平台也都可配置在这里
+      - platform: minio-1 # 存储平台标识
+        enable-storage: true  # 启用存储
+        access-key: Q9jJs2b6Tv
+        secret-key: Thj2WkpLu9DhmJyJ
+        end-point: http://192.168.0.207:9000/
+        bucket-name: jnpfsoftoss
+        domain:  # 访问域名,注意“/”结尾,例如:http://minio.abc.com/abc/
+        base-path:  # 基础路径

+ 84 - 0
jnpf-datareport-univer-admin/target/classes/application.yml

@@ -0,0 +1,84 @@
+spring:
+  application:
+    name: jnpf-datareport
+  profiles:
+    # 指定环境配置 dev(开发环境-默认)、test(测试环境)、preview(预生产环境)、prod(生产环境)
+    active: dev
+  servlet:
+    multipart: #文件传输配置
+      max-file-size: 100MB #单个数据大小限制
+      max-request-size: 100MB #请求总数据大小限制
+      enabled: true  #是否启用分段上传支持
+  mvc:
+    hiddenmethod: #隐式方法过滤器
+      filter:
+        enabled: true #默认开启。开启以支持:PUT,DELETE表单提交方法
+  jackson: #序列化和反序列化json框架
+    serialization:
+      write-dates-as-timestamps: true #是否写入日期时间时间戳格式
+    time-zone: GMT+8 #指定日期格式化时区
+  main:
+    allow-bean-definition-overriding: true #允许同名bean后者覆盖,默认:true
+    allow-circular-references: true #允许Bean相互引用,默认:false
+
+config:
+  #===================== 访问域名 =====================
+  WebAnnexFilePath: WebAnnexFile
+  DataBackupFilePath: DataBackupFile
+  TemporaryFilePath: TemporaryFile
+  SystemFilePath: SystemFile
+  TemplateFilePath: TemplateFile
+  EmailFilePath: EmailFile
+  DocumentFilePath: DocumentFile
+  DocumentPreviewPath: DocumentPreview
+  UserAvatarFilePath: UserAvatar
+  IMContentFilePath: IMContentFile
+  MPMaterialFilePath: MPMaterial
+  TemplateCodePath: TemplateCode
+  BiVisualPath: BiVisualPath
+
+  ApiDomain: http://192.168.10.196:30000 #主项目后端域名(文档预览中使用)
+  FrontDomain: http://192.168.10.196:3100 #前端域名(文档预览中使用)
+  AppDomain: http://192.168.10.196:8080 #app/h5端域名配置(文档预览中使用)
+
+  #===================== 多租户 =====================
+  MultiTenancy: false #是否开启
+  MultiTenancyUrl: http://192.168.10.196:30006/api/tenant/DbName/ #多租户项目地址
+
+# 接口放行地址 与GatewayWhite中的默认URL合并
+gateway:
+  # 禁止访问接口
+  block-url:
+  ## 配置示例
+  #- /api/message/Notice
+  #- /api/permission/Users/*
+  # 不验证Token, 放行接口(默认记录日志)
+  white-url:
+  #  # 配置示例
+  #- /api/message/Notice
+  #- /api/permission/Users/*
+  # 放行接口(不记录日志)
+  exclude-url:
+  #  # 配置示例
+  #- /api/message/Notice
+  #- /api/permission/Users/*
+  # 入站IP(禁止配置以外的IP访问block-url配置的接口)
+  white-ip:
+  #- 192.168.0.10
+  #- 192.168.0.20
+
+# 日志配置
+logging:
+  config: classpath:logback-spring.xml
+  level:
+    #自定义第三方包名日志等级
+    # 解除注释后Druid连接池打印SQL语句
+    druid.sql.Statement: debug
+#    druid.sql.DataSource: debug
+#    druid.sql.Connection: debug
+#    druid.sql.ResultSet: debug
+log:
+  level:
+    # 等级 TRACE,DEBUG,INFO,WARN,ERROR(不区分大小写)
+    root: info
+  path: log/${spring.application.name}

二進制
jnpf-datareport-univer-admin/target/classes/jnpf/ReportUniverApplication.class


+ 22 - 0
jnpf-datareport-univer-admin/target/classes/jnpf/ReportUniverApplication.java

@@ -0,0 +1,22 @@
+package jnpf;
+
+import com.fasterxml.jackson.core.StreamReadConstraints;
+import org.dromara.x.file.storage.spring.EnableFileStorage;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+
+@SpringBootApplication
+@EnableFileStorage
+public class ReportUniverApplication {
+
+    public static void main(String[] args) {
+        StreamReadConstraints.overrideDefaultStreamReadConstraints(
+                StreamReadConstraints.builder().maxStringLength(100000000).build()
+        );
+        SpringApplication springApplication = new SpringApplication(ReportUniverApplication.class);
+        springApplication.run(args);
+        System.out.println("报表启动完成");
+    }
+
+}

二進制
jnpf-datareport-univer-admin/target/classes/jnpf/aop/DataSourceBindAspect.class


+ 79 - 0
jnpf-datareport-univer-admin/target/classes/jnpf/aop/DataSourceBindAspect.java

@@ -0,0 +1,79 @@
+package jnpf.aop;
+
+import cn.dev33.satoken.context.SaHolder;
+import jnpf.base.UserInfo;
+import jnpf.config.ConfigValueUtil;
+import jnpf.database.util.NotTenantPluginHolder;
+import jnpf.database.util.TenantDataSourceUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.TenantHolder;
+import jnpf.util.UserProvider;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2021/3/15 17:12
+ */
+@Slf4j
+@Aspect
+@Component
+@Order(1)
+public class DataSourceBindAspect {
+
+    @Autowired
+    private ConfigValueUtil configValueUtil;
+
+    @Pointcut("(execution(* jnpf.*.controller.*.*(..)) || execution(* jnpf.controller.*.*(..))))")
+    public void bindDataSource() {
+
+    }
+
+    /**
+     * NoDataSourceBind 不需要绑定数据库的注解
+     *
+     * @param pjp
+     * @return
+     * @throws Throwable
+     */
+    @Around("bindDataSource() && !@annotation(jnpf.util.NoDataSourceBind)")
+    public Object doAroundService(ProceedingJoinPoint pjp) throws Throwable {
+        if (configValueUtil.isMultiTenancy()) {
+            if(StringUtil.isEmpty(TenantHolder.getDatasourceId())){
+                UserInfo userInfo = UserProvider.getUser();
+                String url = null;
+                try{
+                    url = SaHolder.getRequest().getRequestPath();
+                }catch (Exception ee){ }
+                log.error("租户" + userInfo.getTenantId() + "数据库不存在, URL: {}, TOKEN: {}", url, userInfo.getToken());
+                return null;
+            }
+            return pjp.proceed();
+        }
+        Object obj = pjp.proceed();
+        return obj;
+    }
+
+
+
+    @Around("bindDataSource() && @annotation(jnpf.util.NoDataSourceBind)")
+    public Object doAroundService2(ProceedingJoinPoint pjp) throws Throwable {
+        try{
+            NotTenantPluginHolder.setNotSwitchAlwaysFlag();
+            //Filter中提前设置租户信息, 不需要切库的方法进行清除切库
+            TenantDataSourceUtil.clearLocalTenantInfo();
+            return pjp.proceed();
+        }finally {
+            NotTenantPluginHolder.clearNotSwitchAlwaysFlag();
+        }
+    }
+}

二進制
jnpf-datareport-univer-admin/target/classes/jnpf/config/AuthFilter.class


+ 121 - 0
jnpf-datareport-univer-admin/target/classes/jnpf/config/AuthFilter.java

@@ -0,0 +1,121 @@
+package jnpf.config;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.filter.SaServletFilter;
+import cn.dev33.satoken.router.SaHttpMethod;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaResult;
+import jnpf.base.ActionResultCode;
+import jnpf.constant.MsgCode;
+import jnpf.consts.AuthConsts;
+import jnpf.properties.GatewayWhite;
+import jnpf.util.IpUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.UserProvider;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+
+
+/**
+ * 网关验证token
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司(https://www.jnpfsoft.com)
+ * @date 2021-03-24
+ */
+@Slf4j
+@Configuration
+public class AuthFilter {
+
+    private static final String ALL = "*";
+    private static final String MAX_AGE = "18000L";
+
+    // 注册 Sa-Token全局过滤器
+    @Bean
+    public SaServletFilter getSaReactorFilter(GatewayWhite gatewayWhite) {
+        return new SaServletFilter()
+                // 拦截地址
+                .addInclude("/**")
+                .setExcludeList(gatewayWhite.excludeUrl)
+                // 鉴权方法:每次访问进入
+                .setAuth(obj -> {
+                    if(log.isInfoEnabled()){
+                        log.info("请求路径: {}", SaHolder.getRequest().getRequestPath());
+                    }
+                    //拦截路径
+                    SaRouter.match(gatewayWhite.blockUrl).match(o -> {
+                        //禁止访问URL 排除白名单
+                        String ip = getIpAddr();
+                        for (String o1 : gatewayWhite.whiteIp) {
+                            if(ip.startsWith(o1)){
+                                return false;
+                            }
+                        }
+                        log.info("非白名单IP访问限制接口:{}, {}", SaHolder.getRequest().getRequestPath(), ip);
+                        return true;
+                    }).back(MsgCode.AD101.get());
+                    //测试不验证 鉴权服务重启测试模式不清除Token就够了
+                    //SaRouter.match((r)->"true".equals(configValueUtil.getTestVersion())).stop();
+                    //白名单不拦截
+                    SaRouter.match(gatewayWhite.whiteUrl).stop();
+                    //内部请求不拦截
+                    SaRouter.match(t->{
+                        String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
+                        return UserProvider.isValidInnerToken(innerToken);
+                    }).stop();
+                    // 登录校验 -- 拦截所有路由
+                    SaRouter.match("/**", r -> {
+                        //兼容Net、Java大小写不一致问题
+                        String token = StpUtil.getTokenValueNotCut();
+                        if(!StringUtil.isEmpty(token)){
+                            String[] tokenArr = token.split(" ");
+                            if(StpUtil.getLoginIdByToken(tokenArr[tokenArr.length-1]) != null){
+                                return;
+                            }
+                        }
+                        throw NotLoginException.newInstance(StpUtil.getLoginType(), NotLoginException.INVALID_TOKEN, NotLoginException.INVALID_TOKEN_MESSAGE, token);
+                    }).stop();
+                }).setError(e -> {
+                    SaHolder.getResponse().addHeader("Content-Type","application/json; charset=utf-8");
+                    if(e instanceof NotLoginException){
+                        return SaResult.error(ActionResultCode.SessionOverdue.getMessage()).setCode(ActionResultCode.SessionOverdue.getCode());
+                    }
+                    log.error(e.getMessage(), e);
+                    return SaResult.error(MsgCode.AD102.get()).setCode(ActionResultCode.Exception.getCode());
+                })
+                // 前置函数:在每次认证函数之前执行
+                .setBeforeAuth(obj -> {
+                    HttpServletRequest request = (HttpServletRequest) SaHolder.getRequest().getSource();
+                    // ---------- 设置跨域响应头 ----------
+                    SaHolder.getResponse()
+                            // 允许指定域访问跨域资源
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, request.getHeader(HttpHeaders.ORIGIN))
+                            // 允许的header参数
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, ALL)
+                            // 允许所有请求方式
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, ALL)
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL)
+                            // 有效时间
+                            .setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
+
+                    // 如果是预检请求,则立即返回到前端
+                    SaRouter.match(SaHttpMethod.OPTIONS)
+                            .back();
+                });
+    }
+
+    public static String getIpAddr() {
+        return IpUtil.getIpAddr();
+    }
+
+
+}

二進制
jnpf-datareport-univer-admin/target/classes/jnpf/config/ReportAutoConfiguration.class


+ 41 - 0
jnpf-datareport-univer-admin/target/classes/jnpf/config/ReportAutoConfiguration.java

@@ -0,0 +1,41 @@
+package jnpf.config;
+
+import jnpf.consts.ApiConst;
+import jnpf.properties.GatewayWhite;
+import jnpf.properties.GatewayWhiteProperties;
+import jnpf.properties.ReportProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration(proxyBeanMethods = false)
+public class ReportAutoConfiguration {
+
+
+    @Bean
+    @ConfigurationProperties(prefix = GatewayWhite.PREFIX)
+    public GatewayWhite getGateWhite(){
+        return new GatewayWhiteProperties();
+    }
+
+
+    @Bean
+    @ConfigurationProperties(prefix = ReportProperties.PREFIX)
+    public ReportProperties getReportProperties(){
+        return new ReportProperties();
+    }
+
+
+    @Bean
+    public ApiConst initReportApiConst(JnpfOauthConfig jnpfOauthConfig){
+        ApiConst.ME = jnpfOauthConfig.getJnpfDomain() + "/api/oauth/me";
+        ApiConst.DATASET_LIST = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/getList";
+        ApiConst.DATASET_SAVE = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/save";
+        ApiConst.DATASET_DATA = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/Data";
+        ApiConst.SAVE_MENU = jnpfOauthConfig.getJnpfDomain() + "/api/system/Menu/saveReportMenu";
+        ApiConst.GET_MENU = jnpfOauthConfig.getJnpfDomain() + "/api/system/Menu/getReportMenu";
+        ApiConst.PARAMETER_DATA = jnpfOauthConfig.getJnpfDomain() + "/api/system/DataSet/parameterData";
+        return new ApiConst();
+    }
+
+}

二進制
jnpf-datareport-univer-admin/target/classes/jnpf/properties/GatewayWhiteProperties.class


+ 8 - 0
jnpf-datareport-univer-admin/target/classes/jnpf/properties/GatewayWhiteProperties.java

@@ -0,0 +1,8 @@
+package jnpf.properties;
+
+/**
+ * 根据需求重写网关URL
+ */
+public class GatewayWhiteProperties extends GatewayWhite {
+
+}

+ 327 - 0
jnpf-datareport-univer-admin/target/classes/logback-spring.xml

@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+    <!--日志格式应用spring boot默认的格式,也可以自己更改-->
+    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+    <property name="FILE_LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] [%logger{50}] [%M] [%line] - %msg%n" />
+    <springProperty scope="context" name="SERVICE_NAME" source="spring.application.name" defaultValue="jnpf"/>
+
+    <!--定义日志存放的位置,默认存放在项目启动的相对路径的目录-->
+    <springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="log/${SERVICE_NAME}"/>
+    <!-- 全局日志等级 -->
+    <springProperty scope="context" name="LOG_LEVEL_ROOT" source="log.level.root" defaultValue="INFO"/>
+    <!-- 服务自定义等级 如需自定义服务日志等级 修改下方的【自定义服务名】与nacos上的log.level.自定义服务名=等级 -->
+    <springProperty scope="context" name="LOG_LEVEL" source="log.level.jnpf-boot" defaultValue="${LOG_LEVEL_ROOT}"/>
+
+    <!-- 日志记录器,日期滚动记录,level为 ERROR 日志 -->
+    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_error.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd,aux}/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录error级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>error</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,level为 INFO 日志 -->
+    <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_info.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd,aux}/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,level为 WARN 日志 -->
+    <appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_warn.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>warn</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 日志记录器,日期滚动记录,level为 DEBUG 日志 -->
+    <appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_debug.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd,aux}/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>debug</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,所有日志 -->
+    <appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_total.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/total/%d{yyyy-MM-dd,aux}/log-total-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+
+    <!-- 日志记录器,日期滚动记录,level 根据配置动态输出日志 -->
+    <appender name="FILE_RELEASE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_release.log</file>
+
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+
+            <!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
+            <fileNamePattern>${LOG_PATH}/release/%d{yyyy-MM-dd,aux}/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--日志最大的历史7天-->
+            <maxHistory>7</maxHistory>
+
+            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
+            命名日志文件,例如log-error-2013-12-21.0.log -->
+            <maxFileSize>10MB</maxFileSize>
+        </rollingPolicy>
+
+        <!-- 追加方式记录日志 -->
+        <append>true</append>
+
+        <!-- 日志文件的格式 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${FILE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>${LOG_LEVEL}</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+    <!-- 异步输出 DEBUG -->
+    <appender name="ASYNC_FILE_DEBUG" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_DEBUG"/>
+    </appender>
+    <!-- 异步输出 INFO -->
+    <appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_INFO"/>
+    </appender>
+    <!-- 异步输出 WARN -->
+    <appender name="ASYNC_FILE_WARN" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_WARN"/>
+    </appender>
+    <!-- 异步输出 ERROR -->
+    <appender name="ASYNC_FILE_ERROR" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_ERROR"/>
+    </appender>
+    <!-- 异步输出 ALL -->
+    <appender name="ASYNC_FILE_ALL" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="FILE_ALL"/>
+    </appender>
+
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+            <charset>utf-8</charset>
+        </encoder>
+    </appender>
+
+
+    <!-- 异步输出 控制台 -->
+    <appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <appender-ref ref="STDOUT"/>
+    </appender>
+
+
+    <!--<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        &lt;!&ndash; 必填:目标:LogStash的 IP:Port &ndash;&gt;
+        <destination>192.168.0.50:50000</destination>
+        &lt;!&ndash; 可选:保持程序存活时间 &ndash;&gt;
+        <keepAliveDuration>5 minutes</keepAliveDuration>
+        &lt;!&ndash; 可选:重连延迟时长 &ndash;&gt;
+        <reconnectionDelay>10 second</reconnectionDelay>
+        &lt;!&ndash; 可选:等待策略 &ndash;&gt;
+        <waitStrategyType>sleeping</waitStrategyType>
+        &lt;!&ndash;  ============ encoder必须配置,有多种可选 ============= &ndash;&gt;
+        &lt;!&ndash; 编码器二:LoggingEventCompositeJsonEncoder &ndash;&gt;
+        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
+            <providers>
+                &lt;!&ndash; 时间戳:时区 &ndash;&gt;
+                <timestamp>
+                    <timeZone>UTC</timeZone>
+                </timestamp>
+                &lt;!&ndash; 模式 &ndash;&gt;
+                <pattern>
+                    <pattern>
+                        {
+                        "severity": "%level",
+                        "service": "${SERVICE_NAME:-}",
+                        "trace": "%X{X-B3-TraceId:-}",
+                        "span": "%X{X-B3-SpanId:-}",
+                        "exportable": "%X{X-Span-Export:-}",
+                        "pid": "${PID:-}",
+                        "thread": "%thread",
+                        "class": "%logger{40}",
+                        "msg": "%message"
+                        &lt;!&ndash;"idx_pre": "elk-original-third-access",&ndash;&gt;
+                        &lt;!&ndash;"json": "#asJson{%message}"  这个asJson可以把对应的字符串作为json对象取出来,这样es可以对json里面的字段索引了&ndash;&gt;
+                        }
+                    </pattern>
+                </pattern>
+            </providers>
+        </encoder>
+    </appender>-->
+
+
+    <root level="${LOG_LEVEL}">
+        <appender-ref ref="ASYNC_STDOUT"/>
+        <appender-ref ref="ASYNC_FILE_ERROR"/>
+        <appender-ref ref="ASYNC_FILE_INFO"/>
+        <appender-ref ref="ASYNC_FILE_WARN"/>
+        <appender-ref ref="ASYNC_FILE_DEBUG"/>
+        <appender-ref ref="ASYNC_FILE_ALL"/>
+        <!--<appender-ref ref="LOGSTASH"/>-->
+    </root>
+
+
+</configuration>

二進制
jnpf-datareport-univer-admin/target/jnpf-datareport-univer-admin-6.0.0-RELEASE.jar


二進制
jnpf-datareport-univer-admin/target/jnpf-datareport-univer-admin-6.0.0-RELEASE.jar.original


+ 3 - 0
jnpf-datareport-univer-admin/target/maven-archiver/pom.properties

@@ -0,0 +1,3 @@
+artifactId=jnpf-datareport-univer-admin
+groupId=com.jnpf
+version=6.0.0-RELEASE

+ 6 - 0
jnpf-datareport-univer-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

@@ -0,0 +1,6 @@
+jnpf\aop\DataSourceBindAspect.class
+jnpf\ReportUniverApplication.class
+jnpf\config\AuthFilter.class
+META-INF\spring-configuration-metadata.json
+jnpf\config\ReportAutoConfiguration.class
+jnpf\properties\GatewayWhiteProperties.class

+ 5 - 0
jnpf-datareport-univer-admin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@@ -0,0 +1,5 @@
+C:\Users\zhaojinyu\Desktop\USKY\jnpf6.0\jnpf-java-datareport-univer-v6x\jnpf-datareport-univer-admin\src\main\java\jnpf\aop\DataSourceBindAspect.java
+C:\Users\zhaojinyu\Desktop\USKY\jnpf6.0\jnpf-java-datareport-univer-v6x\jnpf-datareport-univer-admin\src\main\java\jnpf\config\AuthFilter.java
+C:\Users\zhaojinyu\Desktop\USKY\jnpf6.0\jnpf-java-datareport-univer-v6x\jnpf-datareport-univer-admin\src\main\java\jnpf\config\ReportAutoConfiguration.java
+C:\Users\zhaojinyu\Desktop\USKY\jnpf6.0\jnpf-java-datareport-univer-v6x\jnpf-datareport-univer-admin\src\main\java\jnpf\properties\GatewayWhiteProperties.java
+C:\Users\zhaojinyu\Desktop\USKY\jnpf6.0\jnpf-java-datareport-univer-v6x\jnpf-datareport-univer-admin\src\main\java\jnpf\ReportUniverApplication.java

+ 21 - 0
jnpf-datareport-univer-biz/pom.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.jnpf</groupId>
+        <artifactId>jnpf-datareport-univer</artifactId>
+        <version>6.0.0-RELEASE</version>
+    </parent>
+
+    <artifactId>jnpf-datareport-univer-biz</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.jnpf</groupId>
+            <artifactId>jnpf-datareport-univer-entity</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 17 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/CodeNumMapper.java

@@ -0,0 +1,17 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.CodeNumEntity;
+
+
+/**
+ * 编码序号
+ *
+ * @author JNPF开发平台组
+ * @version v6.0.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2025/2/28 11:13:44
+ */
+public interface CodeNumMapper extends SuperMapper<CodeNumEntity> {
+
+}

+ 18 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/DictionaryDataMapper.java

@@ -0,0 +1,18 @@
+
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.DictionaryDataEntity;
+
+
+/**
+ * 字典数据
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface DictionaryDataMapper extends SuperMapper<DictionaryDataEntity> {
+
+}

+ 14 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/ReportMapper.java

@@ -0,0 +1,14 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.ReportEntity;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportMapper extends SuperMapper<ReportEntity> {
+
+}

+ 14 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/ReportVersionMapper.java

@@ -0,0 +1,14 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.ReportVersionEntity;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportVersionMapper extends SuperMapper<ReportVersionEntity> {
+
+}

+ 18 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/SystemMapper.java

@@ -0,0 +1,18 @@
+package jnpf.mapper;
+
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.SystemEntity;
+
+
+/**
+ * 系统
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface SystemMapper extends SuperMapper<SystemEntity> {
+
+}

+ 14 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/mapper/UserMapper.java

@@ -0,0 +1,14 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.UserEntity;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface UserMapper extends SuperMapper<UserEntity> {
+
+}

+ 45 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/CodeNumService.java

@@ -0,0 +1,45 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.CodeNumEntity;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * 编码序号
+ *
+ * @author JNPF开发平台组
+ * @version v6.0.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2025/2/28 11:14:52
+ */
+public interface CodeNumService extends SuperService<CodeNumEntity> {
+
+    /**
+     * 根据类型获取数据
+     *
+     * @param type
+     * @return
+     */
+    Integer getNumByType(String type, Integer times);
+
+    /**
+     * 获取多次编码
+     *
+     * @param type
+     * @param num
+     * @return
+     */
+    List<String> getCode(String type, Integer num);
+
+    /**
+     * 获取一次编码
+     *
+     * @param type
+     * @return
+     */
+    String getCodeOnce(String type);
+    String getCodeFunction(Supplier<String> getCode, Predicate<String> existCode);
+}

+ 20 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/DictionaryDataService.java

@@ -0,0 +1,20 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.DictionaryDataEntity;
+
+import java.util.List;
+
+
+/**
+ * 字典数据
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface DictionaryDataService extends SuperService<DictionaryDataEntity> {
+
+    List<DictionaryDataEntity> getDictionName(List<String> id);
+}

+ 74 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/ReportService.java

@@ -0,0 +1,74 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.ReportEntity;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportInfoVO;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.ReportUpForm;
+
+import java.util.List;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportService extends SuperService<ReportEntity> {
+
+    /**
+     * 列表
+     *
+     * @return 实体类
+     */
+    List<ReportEntity> getList(ReportPagination pagination);
+
+    /**
+     * 创建
+     */
+    void create(ReportCrForm form);
+
+    /**
+     * 更新
+     */
+    void update(String id,ReportEntity entity);
+
+    /**
+     * 获取详情
+     *
+     * @return ReportInfoVO
+     */
+    ReportInfoVO getVersionInfo(String versionId);
+
+    /**
+     * 保存或者发布 通过type:0-保存,1-发布
+     *
+     * @param form
+     */
+    void saveOrRelease(ReportUpForm form);
+
+    /**
+     * 下拉选择
+     *
+     */
+    List<ReportEntity> getTreeList();
+
+    /**
+     * 删除
+     * @param id
+     */
+    void delete(String id);
+
+    /**
+     * 导入模板
+     * @param infoVO
+     * @param type
+     * @return
+     */
+    String importData(ReportInfoVO infoVO,Integer type,Boolean idCheck);
+
+    Boolean isEncodeExist(String encode);
+
+
+}

+ 88 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/ReportVersionService.java

@@ -0,0 +1,88 @@
+package jnpf.service;
+
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import jnpf.base.Pagination;
+import jnpf.base.service.SuperService;
+import jnpf.entity.ReportVersionEntity;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.UploaderVO;
+import jnpf.univer.model.UniverPreview;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportVersionService extends SuperService<ReportVersionEntity> {
+
+    /**
+     * 创建版本
+     *
+     * @param form
+     */
+    void create(ReportCrForm form);
+
+    /**
+     * 获取版本列表
+     *
+     * @param templateId
+     * @return
+     */
+    List<ReportVersionEntity> getList(String templateId, SFunction<ReportVersionEntity, ?>... columns);
+
+    /**
+     * 复制版本(点击新增版本)
+     *
+     * @param versionId
+     */
+    String copyVersion(String versionId);
+
+    /**
+     * 根据id删除版本
+     *
+     * @param templateId
+     * @return
+     */
+    void removeByTemplateId(String templateId);
+
+    /**
+     * 预览数据
+     *
+     * @return
+     */
+    UniverPreview preview(String id, ReportPagination pagination, Map<String, Object> params);
+
+    /**
+     * 预览数据
+     *
+     * @return
+     */
+    UniverPreview previewTemplate(String id, ReportPagination pagination, Map<String, Object> params);
+
+    /**
+     * 导入excel
+     *
+     * @param multipartFile
+     */
+    UniverPreview importExcel(MultipartFile multipartFile) throws IOException;
+
+    /**
+     * 导出excel
+     *
+     */
+    UploaderVO downExcel(ReportPagination pagination, Map<String, Object> params);
+
+    /**
+     * 导出excel
+     *
+     * @param pagination
+     */
+    UploaderVO downExcel(ReportPagination pagination);
+}

+ 115 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/SystemService.java

@@ -0,0 +1,115 @@
+package jnpf.service;
+
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.SystemEntity;
+
+import java.util.List;
+
+/**
+ * 系统
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface SystemService extends SuperService<SystemEntity> {
+
+    /**
+     * 获取列表
+     *
+     * @return
+     */
+    List<SystemEntity> getList();
+
+    /**
+     * 获取系统列表
+     *
+     * @param keyword
+     * @param filterMain
+     * @param isList
+     * @param moduleAuthorize
+     * @return
+     */
+    List<SystemEntity> getList(String keyword, Boolean filterEnableMark, boolean verifyAuth, Boolean filterMain, boolean isList, List<String> moduleAuthorize);
+
+    /**
+     * 获取列表
+     *
+     * @return
+     */
+    List<SystemEntity> getListByIdsKey(List<String> ids, String keyword);
+
+    /**
+     * 获取详情
+     *
+     * @param id
+     * @return
+     */
+    SystemEntity getInfo(String id);
+
+    /**
+     * 判断系统名称是否重复
+     *
+     * @param id
+     * @param fullName
+     * @return
+     */
+    Boolean isExistFullName(String id, String fullName);
+
+    /**
+     * 判断系统编码是否重复
+     *
+     * @param id
+     * @param enCode
+     * @return
+     */
+    Boolean isExistEnCode(String id, String enCode);
+
+
+
+
+
+    /**
+     * 通过id获取系统列表
+     *
+     * @param list
+     * @param moduleAuthorize
+     * @return
+     */
+    List<SystemEntity> getListByIds(List<String> list, List<String> moduleAuthorize);
+
+    /**
+     * 通过编码获取系统信息
+     *
+     * @param enCode
+     * @return
+     */
+    SystemEntity getInfoByEnCode(String enCode);
+
+    /**
+     * 获取
+     *
+     * @param moduleAuthorize
+     * @return
+     */
+    List<SystemEntity> findSystemAdmin(List<String> moduleAuthorize);
+
+    /**
+     * 获取
+     *
+     * @param mark
+     * @param mainSystemCode
+     * @return
+     */
+    List<SystemEntity> findSystemAdmin(int mark, String mainSystemCode);
+
+
+    /**
+     * 获取当前用户有编辑权限的应用
+     *
+     * @return
+     */
+    List<SystemEntity> getAuthListByUser();
+}

+ 23 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/UserService.java

@@ -0,0 +1,23 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.UserEntity;
+
+import java.util.List;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface UserService extends SuperService<UserEntity> {
+
+    /**
+     *
+     * @param idList
+     * @return
+     */
+    List<UserEntity> getUserName(List<String> idList);
+
+}

+ 88 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/CodeNumServiceImpl.java

@@ -0,0 +1,88 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.entity.CodeNumEntity;
+import jnpf.mapper.CodeNumMapper;
+import jnpf.service.CodeNumService;
+import jnpf.util.DateUtil;
+import jnpf.util.RandomUtil;
+import lombok.Synchronized;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+/**
+ * 编码获取服务
+ *
+ * @author JNPF开发平台组
+ * @version v6.0.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2025/2/28 11:16:06
+ */
+@Service
+public class CodeNumServiceImpl extends SuperServiceImpl<CodeNumMapper, CodeNumEntity> implements CodeNumService {
+
+    @Synchronized
+    @Override
+    public Integer getNumByType(String type, Integer times) {
+        CodeNumEntity codeNumEntity;
+        Integer num = 1;
+        Integer dateValue = Integer.parseInt(DateUtil.nowDateTime().substring(0, 8));
+
+        QueryWrapper<CodeNumEntity> wrapper = new QueryWrapper();
+        wrapper.lambda().eq(CodeNumEntity::getType, type);
+        List<CodeNumEntity> list = this.list(wrapper);
+        if (list.size() > 0) {
+            codeNumEntity = list.get(0);
+            if (Objects.equals(dateValue, codeNumEntity.getDateValue())) {
+                num = codeNumEntity.getNum();
+            }
+        } else {
+            codeNumEntity = new CodeNumEntity();
+            codeNumEntity.setId(RandomUtil.uuId());
+
+
+        }
+        codeNumEntity.setType(type);
+        codeNumEntity.setDateValue(dateValue);
+        codeNumEntity.setNum(num + times);
+        this.saveOrUpdate(codeNumEntity);
+        return num;
+    }
+
+    @Override
+    public List<String> getCode(String type, Integer num) {
+        Integer value = this.getNumByType(type, num);
+        List<String> list = new ArrayList<>();
+        for (int n = 0; n < num; n++) {
+            String numStr = String.format("%06d", value + n);
+            StringBuilder sb = new StringBuilder();
+            sb.append(type);
+            sb.append(DateUtil.nowDateTime().substring(0, 8));
+            sb.append(numStr);
+            list.add(sb.toString());
+        }
+        return list;
+    }
+
+
+    @Override
+    public String getCodeOnce(String type) {
+        return this.getCode(type, 1).get(0);
+    }
+
+    @Override
+    @Synchronized
+    public String getCodeFunction(Supplier<String> getCode, Predicate<String> existCode) {
+        return Stream.generate(getCode)
+                .filter(code -> !existCode.test(code))
+                .findFirst()
+                .orElseThrow(() -> new RuntimeException("无法获取唯一编码"));
+    }
+}

+ 36 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/DictionaryDataServiceImpl.java

@@ -0,0 +1,36 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.entity.DictionaryDataEntity;
+import jnpf.mapper.DictionaryDataMapper;
+import jnpf.service.DictionaryDataService;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 字典数据
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+@Service
+public class DictionaryDataServiceImpl extends SuperServiceImpl<DictionaryDataMapper, DictionaryDataEntity> implements DictionaryDataService {
+
+    @Override
+    public List<DictionaryDataEntity> getDictionName(List<String> id) {
+        List<DictionaryDataEntity> dictionList = new ArrayList<>();
+        if (id.size() > 0) {
+            QueryWrapper<DictionaryDataEntity> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().and(
+                    t -> t.in(DictionaryDataEntity::getId, id)
+            );
+            dictionList = this.list(queryWrapper);
+        }
+        return dictionList;
+    }
+
+}

+ 306 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/ReportServiceImpl.java

@@ -0,0 +1,306 @@
+package jnpf.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.Method;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jnpf.base.ActionResult;
+import jnpf.base.UserInfo;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.constant.CodeConst;
+import jnpf.constant.MsgCode;
+import jnpf.consts.ApiConst;
+import jnpf.emnus.DataSetTypeEnum;
+import jnpf.entity.ReportEntity;
+import jnpf.entity.ReportVersionEntity;
+import jnpf.entity.SystemEntity;
+import jnpf.exception.DataException;
+import jnpf.mapper.ReportMapper;
+import jnpf.model.data.DataForm;
+import jnpf.model.data.DataSetInfo;
+import jnpf.model.data.DataSetPagination;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportInfoVO;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.ReportUpForm;
+import jnpf.service.CodeNumService;
+import jnpf.service.ReportService;
+import jnpf.service.ReportVersionService;
+import jnpf.service.SystemService;
+import jnpf.util.*;
+import jnpf.util.context.RequestContext;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+@Service
+public class ReportServiceImpl extends SuperServiceImpl<ReportMapper, ReportEntity> implements ReportService {
+
+    @Autowired
+    private CodeNumService codeNumService;
+    @Autowired
+    private SystemService systemService;
+
+
+    @Autowired
+    private ReportVersionService versionService;
+
+    @Override
+    public List<ReportEntity> getList(ReportPagination pagination) {
+        QueryWrapper<ReportEntity> queryWrapper = new QueryWrapper<>();
+        String keyword = pagination.getKeyword();
+        if (ObjectUtil.isNotEmpty(keyword)) {
+            queryWrapper.lambda().and(t -> t.like(ReportEntity::getEnCode, keyword).or().like(ReportEntity::getFullName, keyword));
+        }
+        if (ObjectUtil.isNotEmpty(pagination.getCategory())) {
+            queryWrapper.lambda().eq(ReportEntity::getCategory, pagination.getCategory());
+        }
+        if (ObjectUtil.isNotEmpty(pagination.getState())) {
+            queryWrapper.lambda().eq(ReportEntity::getEnabledMark, pagination.getState());
+        }
+        if (ObjectUtil.isNotEmpty(pagination.getSystemId())) {
+            queryWrapper.lambda().eq(ReportEntity::getSystemId, pagination.getSystemId());
+        }
+        queryWrapper.lambda().orderByAsc(ReportEntity::getSortCode).orderByDesc(ReportEntity::getCreatorTime);
+        Page<ReportEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
+        IPage<ReportEntity> userPage = this.page(page, queryWrapper);
+        return pagination.setData(userPage.getRecords(), page.getTotal());
+    }
+
+    @Override
+    public void create(ReportCrForm form) {
+
+        if (StringUtil.isEmpty(form.getEnCode())) {
+            form.setEnCode(codeNumService.getCodeOnce(CodeConst.BB));
+        }
+        ReportEntity entity = JsonUtil.getJsonToBean(form, ReportEntity.class);
+        UserInfo userInfo = UserProvider.getUser();
+        this.creUpdateCheck(entity, true, true);
+        String id = StringUtil.isNotEmpty(entity.getId()) ? entity.getId() : RandomUtil.uuId();
+        entity.setId(id);
+        entity.setEnabledMark(0);
+        entity.setCreatorUserId(userInfo.getUserId());
+        entity.setCreatorTime(new Date());
+        entity.setLastModifyUserId(null);
+        entity.setLastModifyTime(null);
+        this.setIgnoreLogicDelete().removeById(entity.getId());
+        this.setIgnoreLogicDelete().saveOrUpdate(entity);
+        this.clearIgnoreLogicDelete();
+        form.setId(id);
+        List<ReportVersionEntity> list = versionService.getList(id, ReportVersionEntity::getId);
+        if (CollectionUtils.isEmpty(list)) {
+            versionService.create(form);
+        }
+    }
+
+    @Override
+    public void update(String id, ReportEntity entity) {
+        ReportEntity report = getById(id);
+        if (StringUtil.isEmpty(entity.getEnCode())) {
+            entity.setEnCode(codeNumService.getCodeOnce(CodeConst.BB));
+        }
+
+        this.creUpdateCheck(entity, !report.getFullName().equals(entity.getFullName()), !report.getEnCode().equals(entity.getEnCode()));
+        entity.setId(id);
+        updateById(entity);
+    }
+
+    @Override
+    public ReportInfoVO getVersionInfo(String versionId) {
+        ReportVersionEntity versionEntity = versionService.getById(versionId);
+        ReportEntity entity = this.getById(versionEntity.getTemplateId());
+        ReportInfoVO vo = JsonUtil.getJsonToBean(versionEntity, ReportInfoVO.class);
+        vo.setVersionId(versionId);
+        vo.setId(entity.getId());
+        vo.setFullName(entity.getFullName());
+        vo.setAllowExport(entity.getAllowExport());
+        vo.setAllowWatermark(entity.getAllowWatermark());
+        vo.setWatermarkConfig(entity.getWatermarkConfig());
+        vo.setAllowPrint(entity.getAllowPrint());
+        vo.setCategory(entity.getCategory());
+        vo.setEnCode(entity.getEnCode());
+        vo.setSortCode(entity.getSortCode());
+        DataSetPagination pagination = new DataSetPagination();
+        pagination.setObjectId(versionId);
+        pagination.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+        String json = ReportUtil.http(ApiConst.DATASET_LIST, Method.GET, JsonUtil.entityToMap(pagination));
+        ActionResult result = JsonUtil.getJsonToBean(json, ActionResult.class);
+        List<DataSetInfo> dataSetList = new ArrayList<>();
+        if (ObjectUtil.isNotEmpty(result.getData())) {
+            dataSetList = JsonUtil.getJsonToList(result.getData(), DataSetInfo.class);
+        }
+        vo.setDataSetList(dataSetList);
+        return vo;
+    }
+
+    @Override
+    public void saveOrRelease(ReportUpForm form) {
+        ReportVersionEntity versionEntity = versionService.getById(form.getVersionId());
+        ReportVersionEntity versionNew = JsonUtil.getJsonToBean(form, ReportVersionEntity.class);
+        versionNew.setFenceList(form.getColumnList());
+        versionNew.setId(versionEntity.getId());
+        versionNew.setState(versionEntity.getState());
+        ReportEntity entity = this.getById(form.getId());
+        //发布流程
+        if (Objects.equals(form.getType(), 1)) {
+            //改流程版本
+            if (StringUtil.isNotEmpty(form.getVersionId())) {
+                boolean isRelease = Objects.equals(versionNew.getState(), 2);
+                ReportVersionEntity info = versionService.getList(form.getId(), ReportVersionEntity::getId, ReportVersionEntity::getState).stream().filter(t -> Objects.equals(t.getState(), 1)).findFirst().orElse(null);
+                if (info != null) {
+                    // 变更归档状态,排序码
+                    info.setSortCode(0L);
+                    info.setState(2);
+                    versionService.updateById(info);
+                }
+                versionNew.setState(1);
+                versionNew.setSortCode(1L);
+                entity.setEnabledMark(1);
+                if (isRelease) {
+                    versionService.updateById(versionNew);
+                    return;
+                }
+            }
+        }
+        versionService.updateById(versionNew);
+        //数据集创建
+        String versionId = versionNew.getId();
+        List<DataSetInfo> dataSetList = form.getDataSetList() != null ? form.getDataSetList() : new ArrayList<>();
+        DataForm dataForm = new DataForm();
+        dataForm.setObjectId(versionId);
+        dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+        dataForm.setList(dataSetList);
+        ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        entity.setAllowExport(form.getAllowExport());
+        entity.setAllowPrint(form.getAllowPrint());
+        entity.setAllowWatermark(form.getAllowWatermark());
+        entity.setWatermarkConfig(form.getWatermarkConfig());
+        entity.setLastModifyTime(new Date());
+        entity.setLastModifyUserId(UserProvider.getLoginUserId());
+        this.updateById(entity);
+    }
+
+    @Override
+    public List<ReportEntity> getTreeList() {
+        SystemEntity infoByEnCode = systemService.getInfoByEnCode(RequestContext.getAppCode());
+        if (infoByEnCode == null) {
+            return new ArrayList<>();
+        }
+        QueryWrapper<ReportEntity> query = new QueryWrapper<>();
+        query.lambda().eq(ReportEntity::getEnabledMark, 1);
+        query.lambda().eq(ReportEntity::getSystemId, infoByEnCode.getId());
+        query.lambda().orderByAsc(ReportEntity::getSortCode).orderByDesc(ReportEntity::getCreatorTime);
+        return this.list(query);
+    }
+
+    @Override
+    public void delete(String id) {
+        removeById(id);
+        versionService.removeByTemplateId(id);
+    }
+
+    @Override
+    public String importData(ReportInfoVO infoVO, Integer type, Boolean idCheck) {
+        ReportEntity entity = JsonUtil.getJsonToBean(infoVO, ReportEntity.class);
+        StringJoiner stringJoiner = new StringJoiner("、");
+        //id为空切名称不存在时
+        QueryWrapper<ReportEntity> queryWrapper = new QueryWrapper<>();
+        if (idCheck) {
+            queryWrapper.lambda().eq(ReportEntity::getId, entity.getId());
+            if (this.getById(infoVO.getId()) != null) {
+                if (Objects.equals(type, 1)) {
+                    entity.setId(RandomUtil.uuId());
+                } else {
+                    stringJoiner.add("ID");
+                }
+            }
+        }
+        if (ObjectUtil.equal(type, 1)) {
+            String copyNum = UUID.randomUUID().toString().substring(0, 5);
+            entity.setFullName(entity.getFullName() + ".副本" + copyNum);
+            entity.setEnCode(entity.getEnCode() + copyNum);
+        } else if (ObjectUtil.equal(type, 0) && stringJoiner.length() > 0) {
+            return stringJoiner + MsgCode.IMP007.get();
+        }
+        entity.setEnabledMark(0);
+        entity.setCreatorTime(new Date());
+        entity.setCreatorUserId(UserProvider.getLoginUserId());
+        entity.setLastModifyTime(null);
+        entity.setLastModifyUserId(null);
+        if (type != 1) {
+            this.creUpdateCheck(entity, true, true);
+        }
+        this.setIgnoreLogicDelete().removeById(entity);
+        this.setIgnoreLogicDelete().saveOrUpdate(entity);
+        this.clearIgnoreLogicDelete();
+        //版本添加
+        ReportVersionEntity versionEntity = JsonUtil.getJsonToBean(infoVO, ReportVersionEntity.class);
+        String versionId = RandomUtil.uuId();
+        versionEntity.setId(versionId);
+        versionEntity.setTemplateId(entity.getId());
+        versionEntity.setCreatorUserId(UserProvider.getLoginUserId());
+        versionEntity.setCreatorTime(new Date());
+        versionEntity.setVersion(1);
+        versionEntity.setState(0);
+        versionEntity.setSortCode(0L);
+        versionService.save(versionEntity);
+        //数据集创建
+        List<DataSetInfo> dataSetList = infoVO.getDataSetList() != null ? infoVO.getDataSetList() : new ArrayList<>();
+        if (!dataSetList.isEmpty()) {
+            DataForm dataForm = new DataForm();
+            dataForm.setObjectId(versionId);
+            dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+            dataForm.setList(dataSetList);
+            ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        }
+        return "";
+    }
+
+    @Override
+    public Boolean isEncodeExist(String encode) {
+        QueryWrapper<ReportEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(ReportEntity::getEnCode, encode);
+        if (!this.list(queryWrapper).isEmpty()) {
+            return true;
+        }
+        return false;
+    }
+
+
+    public void creUpdateCheck(ReportEntity entity, Boolean fullNameCheck, Boolean encodeCheck) {
+        String fullName = entity.getFullName();
+        String encode = entity.getEnCode();
+        String systemId = entity.getSystemId();
+        // 名称长度验证
+        if (fullName.length() > 80) {
+            throw new DataException(MsgCode.EXIST005.get());
+        }
+        QueryWrapper<ReportEntity> query = new QueryWrapper<>();
+        //重名验证
+        if (fullNameCheck) {
+            query.lambda().eq(ReportEntity::getFullName, fullName);
+            query.lambda().eq(ReportEntity::getSystemId, systemId);
+            if (!this.list(query).isEmpty()) {
+                throw new DataException(MsgCode.EXIST003.get());
+            }
+        }
+        //编码验证
+        if (encodeCheck) {
+            query.clear();
+            query.lambda().eq(ReportEntity::getEnCode, encode);
+            if (!this.list(query).isEmpty()) {
+                throw new DataException(MsgCode.EXIST002.get());
+            }
+        }
+    }
+
+}

+ 282 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/ReportVersionServiceImpl.java

@@ -0,0 +1,282 @@
+package jnpf.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.Method;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.google.common.collect.ImmutableList;
+import jnpf.base.ActionResult;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.constant.FileTypeConstant;
+import jnpf.constant.MsgCode;
+import jnpf.consts.ApiConst;
+import jnpf.emnus.DataSetTypeEnum;
+import jnpf.entity.FileParameter;
+import jnpf.entity.ReportEntity;
+import jnpf.entity.ReportVersionEntity;
+import jnpf.exception.DataException;
+import jnpf.mapper.ReportVersionMapper;
+import jnpf.model.DataQuery;
+import jnpf.model.data.*;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.UploaderVO;
+import jnpf.service.ReportService;
+import jnpf.service.ReportVersionService;
+import jnpf.univer.chart.UniverChartModel;
+import jnpf.univer.data.custom.UniverCustom;
+import jnpf.univer.model.UniverPreview;
+import jnpf.univer.model.UniverWorkBook;
+import jnpf.util.*;
+import lombok.Cleanup;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+@Service
+public class ReportVersionServiceImpl extends SuperServiceImpl<ReportVersionMapper, ReportVersionEntity> implements ReportVersionService {
+
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private ReportService reportService;
+
+    @Override
+    @DSTransactional
+    public void create(ReportCrForm form) {
+        String versionId = RandomUtil.uuId();
+        ReportVersionEntity entity = JsonUtil.getJsonToBean(form, ReportVersionEntity.class);
+        entity.setId(versionId);
+        entity.setTemplateId(form.getId());
+        entity.setCreatorUserId(UserProvider.getLoginUserId());
+        entity.setCreatorTime(new Date());
+        List<ReportVersionEntity> verList = getList(entity.getId(), ReportVersionEntity::getVersion);
+        int version = verList.stream().map(ReportVersionEntity::getVersion).max(Comparator.naturalOrder()).orElse(0) + 1;
+        entity.setVersion(version);
+        entity.setState(0);
+        entity.setSortCode(0l);
+        this.setIgnoreLogicDelete().removeById(entity.getId());
+        this.setIgnoreLogicDelete().saveOrUpdate(entity);
+        this.clearIgnoreLogicDelete();
+        List<DataSetInfo> dataSetList = form.getDataSetList() != null ? form.getDataSetList() : new ArrayList<>();
+        if (dataSetList.size() > 0) {
+            //数据集创建
+            DataForm dataForm = new DataForm();
+            dataForm.setObjectId(versionId);
+            dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+            dataForm.setList(dataSetList);
+            ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        }
+    }
+
+    @Override
+    public List<ReportVersionEntity> getList(String templateId, SFunction<ReportVersionEntity, ?>... columns) {
+        QueryWrapper<ReportVersionEntity> queryWrapper = new QueryWrapper<>();
+        if (columns != null && columns.length > 0) {
+            queryWrapper.lambda().select(columns);
+        }
+        queryWrapper.lambda().eq(ReportVersionEntity::getTemplateId, templateId);
+        queryWrapper.lambda().orderByDesc(ReportVersionEntity::getSortCode).orderByAsc(ReportVersionEntity::getState);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public String copyVersion(String versionId) {
+        ReportVersionEntity entity = this.getById(versionId);
+        ReportVersionEntity versionEntity = JsonUtil.getJsonToBean(entity, ReportVersionEntity.class);
+        String newVersionId = RandomUtil.uuId();
+        versionEntity.setId(newVersionId);
+        List<ReportVersionEntity> verList = getList(entity.getTemplateId(), ReportVersionEntity::getVersion);
+        int version = verList.stream().map(ReportVersionEntity::getVersion).max(Comparator.naturalOrder()).orElse(0) + 1;
+        versionEntity.setVersion(version);
+        versionEntity.setState(0);
+        versionEntity.setSortCode(0l);
+        versionEntity.setCreatorTime(new Date());
+        versionEntity.setCreatorUserId(UserProvider.getLoginUserId());
+        versionEntity.setLastModifyTime(null);
+        versionEntity.setLastModifyUserId(null);
+        DataSetPagination pagination = new DataSetPagination();
+        pagination.setObjectId(versionId);
+        pagination.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+        String json = ReportUtil.http(ApiConst.DATASET_LIST, Method.GET, JsonUtil.entityToMap(pagination));
+        ActionResult result = JsonUtil.getJsonToBean(json, ActionResult.class);
+        List<DataSetInfo> dataSetList = new ArrayList<>();
+        if (ObjectUtil.isNotEmpty(result.getData())) {
+            dataSetList.addAll(JsonUtil.getJsonToList(result.getData(), DataSetInfo.class));
+        }
+        if (dataSetList.size() > 0) {
+            for (DataSetInfo item : dataSetList) {
+                item.setId(null);
+                item.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+                item.setObjectId(newVersionId);
+            }
+            DataForm dataForm = new DataForm();
+            dataForm.setObjectId(newVersionId);
+            dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+            dataForm.setList(dataSetList);
+            ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        }
+        this.save(versionEntity);
+        return newVersionId;
+    }
+
+    @Override
+    public void removeByTemplateId(String templateId) {
+        QueryWrapper<ReportVersionEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(ReportVersionEntity::getTemplateId, templateId);
+        this.remove(queryWrapper);
+    }
+
+    @Override
+    public UniverPreview preview(String id, ReportPagination pagination, Map<String, Object> params) {
+        ReportVersionEntity entity = getById(id);
+        if (ObjectUtil.isEmpty(entity)) {
+            throw new DataException(MsgCode.FA015.get());
+        }
+        if (ObjectUtil.isEmpty(entity.getSnapshot())) {
+            throw new DataException(MsgCode.FA105.get());
+        }
+        //获取当前
+        UniverWorkBook univerWorkBook = JsonUtil.getJsonToBean(entity.getSnapshot(), UniverWorkBook.class);
+        List<String> sheetOrder = univerWorkBook.getSheetOrder();
+        ReportEntity report = reportService.getById(entity.getTemplateId());
+        Map<String, Map<String, List<Map<String, Object>>>> sheetData = new HashMap<>();
+        Map<String, Map<String, Map<String, Object>>> parameterData = new HashMap<>();
+        //当前数据
+        String sheet = StringUtil.isNotEmpty(pagination.getSheetId()) ? pagination.getSheetId() : !sheetOrder.isEmpty() ? sheetOrder.get(0) : null;
+        for (String sheetId : sheetOrder) {
+            DataSetQuery query = new DataSetQuery();
+            query.setModuleId(entity.getTemplateId());
+            query.setId(id);
+            Map<String, Object> dataMap = new HashMap<>(params);
+            query.setMap(dataMap);
+            query.setType(DataSetTypeEnum.REPORT_VER.getCode());
+            query.setSnowFlakeId(RandomUtil.uuId());
+            query.setConvertConfig(entity.getConvertConfig());
+            List<DataQuery> dataQueryList = StringUtil.isNotEmpty(entity.getQueryList()) ? JsonUtil.getJsonToList(entity.getQueryList(), DataQuery.class) : new ArrayList<>();
+            Map<String, List<DataQuery>> queryMap = dataQueryList.stream().collect(Collectors.groupingBy(DataQuery::getSheet));
+            List<DataQuery> queryListAll = queryMap.get(sheetId) != null ? queryMap.get(sheetId) : new ArrayList<>();
+            List<Object> queryList = new ArrayList<>();
+            if (Objects.equals(sheetId, sheet)) {
+                for (DataQuery dataQuery : queryListAll) {
+                    queryList.addAll(dataQuery.getQueryList());
+                }
+            }
+            query.setQueryList(JSONUtil.toJsonStr(queryList));
+            String sheetJson = ReportUtil.http(ApiConst.DATASET_DATA, Method.POST, JsonUtil.entityToMap(query));
+            if (StringUtil.isNotEmpty(sheetJson)) {
+                Map<String, List<Map<String, Object>>> dataList = new HashMap<>();
+                try {
+                    ActionResult result = JsonUtil.getJsonToBean(sheetJson, ActionResult.class);
+                    if (ObjectUtil.isNotEmpty(result) && result.getData() instanceof Map) {
+                        Map<String, List<Map<String, Object>>> data = JsonUtil.getJsonToBean(result.getData(), Map.class);
+                        dataList.putAll(data);
+                    }
+                } catch (Exception e) {}
+                sheetData.put(sheetId, dataList);
+            }
+
+            //参数数据
+            String parameterJson = ReportUtil.http(ApiConst.PARAMETER_DATA, Method.POST, JsonUtil.entityToMap(query));
+            if (StringUtil.isNotEmpty(parameterJson)) {
+                Map<String, Map<String, Object>> dataList = new HashMap<>();
+                try {
+                    ActionResult result = JsonUtil.getJsonToBean(parameterJson, ActionResult.class);
+                    if (ObjectUtil.isNotEmpty(result) && result.getData() instanceof Map) {
+                        Map data = JsonUtil.getJsonToBean(result.getData(), Map.class);
+                        dataList.putAll(data);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage());
+                }
+                parameterData.put(sheetId, dataList);
+            }
+        }
+        UniverConvert convert = new UniverConvert();
+        UniverPreview vo = convert.transform(entity.getSnapshot(), entity.getCells(), entity.getSortList(), entity.getFenceList(),sheetData, parameterData);
+        vo.setVersionId(id);
+        vo.setQueryList(entity.getQueryList());
+        vo.setAllowWatermark(report.getAllowWatermark());
+        vo.setWatermarkConfig(report.getWatermarkConfig());
+        vo.setFullName(report.getFullName());
+        vo.setAllowExport(report.getAllowExport());
+        vo.setAllowPrint(report.getAllowPrint());
+        return vo;
+    }
+
+    @Override
+    public UniverPreview previewTemplate(String id, ReportPagination pagination, Map<String, Object> params) {
+        ReportVersionEntity entity = getList(id, ReportVersionEntity::getId, ReportVersionEntity::getState).stream().filter(t -> Objects.equals(t.getState(), 1)).findFirst().orElse(null);
+        if (ObjectUtil.isEmpty(entity)) {
+            throw new DataException(MsgCode.FA015.get());
+        }
+        return preview(entity.getId(), pagination, params);
+    }
+
+    @Override
+    public UniverPreview importExcel(MultipartFile multipartFile) throws IOException {
+        UniverCustom cellData = new UniverCustom();
+        UniverWorkBook univerWorkBook = UniverExcel.formFile(multipartFile);
+        UniverPreview vo = new UniverPreview();
+        vo.setSnapshot(JSONUtil.toJsonStr(univerWorkBook));
+        vo.setCells(JSONUtil.toJsonStr(cellData));
+        return vo;
+    }
+
+    @Override
+    public UploaderVO downExcel(ReportPagination pagination, Map<String, Object> params) {
+        String id = pagination.getId();
+        UploaderVO vo = new UploaderVO();
+        ReportVersionEntity versionEntity = getById(id);
+        if (ObjectUtil.isEmpty(versionEntity)) {
+            return vo;
+        }
+        ReportEntity entity = reportService.getById(versionEntity.getTemplateId());
+        UniverPreview preview = preview(id, pagination, params);
+        pagination.setSnapshot(preview.getSnapshot());
+        pagination.setFullName(entity.getFullName());
+        vo = downExcel(pagination);
+        return vo;
+    }
+
+    @Override
+    public UploaderVO downExcel(ReportPagination pagination) {
+        UploaderVO vo = new UploaderVO();
+        if (StringUtil.isNotEmpty(pagination.getSnapshot())) {
+            try {
+                List<UniverChartModel> chartList = new ArrayList<>();
+                @Cleanup XSSFWorkbook workbook = new XSSFWorkbook();
+                List<String> sheetList = Arrays.asList(pagination.getSheetId().split(","));
+                UniverExcel.downExcel(pagination.getSnapshot(), chartList, workbook, sheetList);
+                String fileName = pagination.getFullName() + ".xlsx";
+                @Cleanup ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                workbook.write(outputStream);
+                String url = "/api/Report/data/Download?name=" + fileName + "&encryption=";
+                FileInfo fileInfo = FileUploadUtils.uploadFile(new FileParameter(FileTypeConstant.TEMPORARY, fileName), outputStream.toByteArray());
+                vo.setName(fileInfo.getFilename());
+                vo.setUrl(UploaderUtil.uploaderFile(url, fileInfo.getFilename() + "#" + FileTypeConstant.TEMPORARY));
+            } catch (Exception e) {
+                log.error("报表导出excel异常:" + e.getMessage());
+                throw new DataException(MsgCode.FA107.get());
+            }
+        }
+        return vo;
+    }
+
+}

+ 213 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/SystemServiceImpl.java

@@ -0,0 +1,213 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.UserInfo;
+
+
+import jnpf.base.service.SuperServiceImpl;
+
+import jnpf.constant.CodeConst;
+import jnpf.constant.PermissionConst;
+
+import jnpf.entity.SystemEntity;
+import jnpf.mapper.SystemMapper;
+import jnpf.service.SystemService;
+import jnpf.util.RandomUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.UserProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 系统
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+@Service
+public class SystemServiceImpl extends SuperServiceImpl<SystemMapper, SystemEntity> implements SystemService {
+
+
+
+
+    @Override
+    public List<SystemEntity> getList() {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 1);
+        queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode)
+                .orderByDesc(SystemEntity::getCreatorTime);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> getList(String keyword, Boolean filterEnableMark, boolean verifyAuth, Boolean filterMain, boolean isList, List<String> moduleAuthorize) {
+        UserInfo user = UserProvider.getUser();
+
+        boolean flag = false;
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        if (StringUtil.isNotEmpty(keyword)) {
+            flag = true;
+            queryWrapper.lambda().and(t ->
+                    t.like(SystemEntity::getFullName, keyword).or().like(SystemEntity::getEnCode, keyword)
+                            .or().like(SystemEntity::getDescription, keyword)
+            );
+        }
+        if (filterEnableMark == null) {
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 0);
+        } else if (filterEnableMark) {
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 1);
+        }
+
+        // 过滤掉系统应用
+        if (filterMain != null && filterMain) {
+            queryWrapper.lambda().ne(SystemEntity::getIsMain, 1);
+        }
+        //判断权限列表
+        if (!user.getIsAdministrator() && verifyAuth) {
+            if (user.getIsDevRole()) {
+                queryWrapper.lambda().and(t -> t
+                        .eq(SystemEntity::getUserId, user.getUserId()).or()
+                        .like(SystemEntity::getAuthorizeId, user.getUserId()).or()
+                        .eq(SystemEntity::getAuthorizeId, PermissionConst.ALL_DEV_USER));
+            }
+        }
+
+        //过滤租户分配黑名单
+        if (moduleAuthorize.size() > 0) {
+            queryWrapper.lambda().notIn(SystemEntity::getId, moduleAuthorize);
+        }
+        if (flag) {
+            queryWrapper.lambda().orderByDesc(SystemEntity::getLastModifyTime);
+        } else {
+            queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        }
+
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> getListByIdsKey(List<String> ids, String keyword) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().in(SystemEntity::getId, ids);
+        boolean flag = false;
+        if (StringUtil.isNotEmpty(keyword)) {
+            flag = true;
+            queryWrapper.lambda().and(t ->
+                    t.like(SystemEntity::getFullName, keyword).or().like(SystemEntity::getEnCode, keyword)
+                            .or().like(SystemEntity::getDescription, keyword)
+            );
+        }
+        if (flag) {
+            queryWrapper.lambda().orderByDesc(SystemEntity::getLastModifyTime);
+        } else {
+            queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        }
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public SystemEntity getInfo(String id) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getId, id);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public Boolean isExistFullName(String id, String fullName) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getFullName, fullName);
+        if (StringUtil.isNotEmpty(id)) {
+            queryWrapper.lambda().ne(SystemEntity::getId, id);
+        }
+        return this.count(queryWrapper) > 0;
+    }
+
+    @Override
+    public Boolean isExistEnCode(String id, String enCode) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getEnCode, enCode);
+        if (StringUtil.isNotEmpty(id)) {
+            queryWrapper.lambda().ne(SystemEntity::getId, id);
+        }
+        return this.count(queryWrapper) > 0;
+    }
+
+
+
+
+
+    @Override
+    public List<SystemEntity> getListByIds(List<String> list, List<String> moduleAuthorize) {
+        List<SystemEntity> systemList = new ArrayList<>(16);
+        if (list.size() > 0) {
+            QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+            if (moduleAuthorize != null && moduleAuthorize.size() > 0) {
+                queryWrapper.lambda().notIn(SystemEntity::getId, moduleAuthorize);
+            }
+            queryWrapper.lambda().in(SystemEntity::getId, list);
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 1);
+            queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+            return this.list(queryWrapper);
+        }
+        return systemList;
+    }
+
+    @Override
+    public SystemEntity getInfoByEnCode(String enCode) {
+        if (StringUtil.isEmpty(enCode)) {
+            return null;
+        }
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getEnCode, enCode);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> findSystemAdmin(List<String> moduleAuthorize) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        if (moduleAuthorize != null && moduleAuthorize.size() > 0) {
+            queryWrapper.lambda().notIn(SystemEntity::getId, moduleAuthorize);
+        }
+        queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> findSystemAdmin(int mark, String mainSystemCode) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        if (mark == 1) {
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, mark)
+                    .ne(SystemEntity::getEnCode, mainSystemCode);
+        }
+        queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        return this.list(queryWrapper);
+    }
+
+
+
+    @Override
+    public List<SystemEntity> getAuthListByUser() {
+        UserInfo user = UserProvider.getUser();
+        //开发人员才有编辑权限
+        if (user.getIsDevRole() || user.getIsAdministrator()) {
+            QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+            //判断权限列表
+            if (!user.getIsAdministrator()) {
+                queryWrapper.lambda().eq(SystemEntity::getUserId, user.getUserId()).or();
+                queryWrapper.lambda().like(SystemEntity::getAuthorizeId, user.getUserId()).or();
+                queryWrapper.lambda().eq(SystemEntity::getAuthorizeId, PermissionConst.ALL_DEV_USER);
+            }
+            return list(queryWrapper);
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+}

+ 33 - 0
jnpf-datareport-univer-biz/src/main/java/jnpf/service/impl/UserServiceImpl.java

@@ -0,0 +1,33 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.entity.UserEntity;
+import jnpf.mapper.UserMapper;
+import jnpf.service.UserService;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+@Service
+public class UserServiceImpl extends SuperServiceImpl<UserMapper, UserEntity> implements UserService {
+
+    @Override
+    public List<UserEntity> getUserName(List<String> idList) {
+        List<UserEntity> list = new ArrayList<>();
+        if(idList.size()>0){
+            QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().in(UserEntity::getId, idList);
+            list = this.list(queryWrapper);
+        }
+        return list;
+    }
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/CodeNumMapper.class


+ 17 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/CodeNumMapper.java

@@ -0,0 +1,17 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.CodeNumEntity;
+
+
+/**
+ * 编码序号
+ *
+ * @author JNPF开发平台组
+ * @version v6.0.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2025/2/28 11:13:44
+ */
+public interface CodeNumMapper extends SuperMapper<CodeNumEntity> {
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/DictionaryDataMapper.class


+ 18 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/DictionaryDataMapper.java

@@ -0,0 +1,18 @@
+
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.DictionaryDataEntity;
+
+
+/**
+ * 字典数据
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface DictionaryDataMapper extends SuperMapper<DictionaryDataEntity> {
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportMapper.class


+ 14 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportMapper.java

@@ -0,0 +1,14 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.ReportEntity;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportMapper extends SuperMapper<ReportEntity> {
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportVersionMapper.class


+ 14 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/ReportVersionMapper.java

@@ -0,0 +1,14 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.ReportVersionEntity;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportVersionMapper extends SuperMapper<ReportVersionEntity> {
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/SystemMapper.class


+ 18 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/SystemMapper.java

@@ -0,0 +1,18 @@
+package jnpf.mapper;
+
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.SystemEntity;
+
+
+/**
+ * 系统
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface SystemMapper extends SuperMapper<SystemEntity> {
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/UserMapper.class


+ 14 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/mapper/UserMapper.java

@@ -0,0 +1,14 @@
+package jnpf.mapper;
+
+import jnpf.base.mapper.SuperMapper;
+import jnpf.entity.UserEntity;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface UserMapper extends SuperMapper<UserEntity> {
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/CodeNumService.class


+ 45 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/CodeNumService.java

@@ -0,0 +1,45 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.CodeNumEntity;
+
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+/**
+ * 编码序号
+ *
+ * @author JNPF开发平台组
+ * @version v6.0.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2025/2/28 11:14:52
+ */
+public interface CodeNumService extends SuperService<CodeNumEntity> {
+
+    /**
+     * 根据类型获取数据
+     *
+     * @param type
+     * @return
+     */
+    Integer getNumByType(String type, Integer times);
+
+    /**
+     * 获取多次编码
+     *
+     * @param type
+     * @param num
+     * @return
+     */
+    List<String> getCode(String type, Integer num);
+
+    /**
+     * 获取一次编码
+     *
+     * @param type
+     * @return
+     */
+    String getCodeOnce(String type);
+    String getCodeFunction(Supplier<String> getCode, Predicate<String> existCode);
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/DictionaryDataService.class


+ 20 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/DictionaryDataService.java

@@ -0,0 +1,20 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.DictionaryDataEntity;
+
+import java.util.List;
+
+
+/**
+ * 字典数据
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface DictionaryDataService extends SuperService<DictionaryDataEntity> {
+
+    List<DictionaryDataEntity> getDictionName(List<String> id);
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportService.class


+ 74 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportService.java

@@ -0,0 +1,74 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.ReportEntity;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportInfoVO;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.ReportUpForm;
+
+import java.util.List;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportService extends SuperService<ReportEntity> {
+
+    /**
+     * 列表
+     *
+     * @return 实体类
+     */
+    List<ReportEntity> getList(ReportPagination pagination);
+
+    /**
+     * 创建
+     */
+    void create(ReportCrForm form);
+
+    /**
+     * 更新
+     */
+    void update(String id,ReportEntity entity);
+
+    /**
+     * 获取详情
+     *
+     * @return ReportInfoVO
+     */
+    ReportInfoVO getVersionInfo(String versionId);
+
+    /**
+     * 保存或者发布 通过type:0-保存,1-发布
+     *
+     * @param form
+     */
+    void saveOrRelease(ReportUpForm form);
+
+    /**
+     * 下拉选择
+     *
+     */
+    List<ReportEntity> getTreeList();
+
+    /**
+     * 删除
+     * @param id
+     */
+    void delete(String id);
+
+    /**
+     * 导入模板
+     * @param infoVO
+     * @param type
+     * @return
+     */
+    String importData(ReportInfoVO infoVO,Integer type,Boolean idCheck);
+
+    Boolean isEncodeExist(String encode);
+
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportVersionService.class


+ 88 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/ReportVersionService.java

@@ -0,0 +1,88 @@
+package jnpf.service;
+
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import jnpf.base.Pagination;
+import jnpf.base.service.SuperService;
+import jnpf.entity.ReportVersionEntity;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.UploaderVO;
+import jnpf.univer.model.UniverPreview;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface ReportVersionService extends SuperService<ReportVersionEntity> {
+
+    /**
+     * 创建版本
+     *
+     * @param form
+     */
+    void create(ReportCrForm form);
+
+    /**
+     * 获取版本列表
+     *
+     * @param templateId
+     * @return
+     */
+    List<ReportVersionEntity> getList(String templateId, SFunction<ReportVersionEntity, ?>... columns);
+
+    /**
+     * 复制版本(点击新增版本)
+     *
+     * @param versionId
+     */
+    String copyVersion(String versionId);
+
+    /**
+     * 根据id删除版本
+     *
+     * @param templateId
+     * @return
+     */
+    void removeByTemplateId(String templateId);
+
+    /**
+     * 预览数据
+     *
+     * @return
+     */
+    UniverPreview preview(String id, ReportPagination pagination, Map<String, Object> params);
+
+    /**
+     * 预览数据
+     *
+     * @return
+     */
+    UniverPreview previewTemplate(String id, ReportPagination pagination, Map<String, Object> params);
+
+    /**
+     * 导入excel
+     *
+     * @param multipartFile
+     */
+    UniverPreview importExcel(MultipartFile multipartFile) throws IOException;
+
+    /**
+     * 导出excel
+     *
+     */
+    UploaderVO downExcel(ReportPagination pagination, Map<String, Object> params);
+
+    /**
+     * 导出excel
+     *
+     * @param pagination
+     */
+    UploaderVO downExcel(ReportPagination pagination);
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/SystemService.class


+ 115 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/SystemService.java

@@ -0,0 +1,115 @@
+package jnpf.service;
+
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.SystemEntity;
+
+import java.util.List;
+
+/**
+ * 系统
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+public interface SystemService extends SuperService<SystemEntity> {
+
+    /**
+     * 获取列表
+     *
+     * @return
+     */
+    List<SystemEntity> getList();
+
+    /**
+     * 获取系统列表
+     *
+     * @param keyword
+     * @param filterMain
+     * @param isList
+     * @param moduleAuthorize
+     * @return
+     */
+    List<SystemEntity> getList(String keyword, Boolean filterEnableMark, boolean verifyAuth, Boolean filterMain, boolean isList, List<String> moduleAuthorize);
+
+    /**
+     * 获取列表
+     *
+     * @return
+     */
+    List<SystemEntity> getListByIdsKey(List<String> ids, String keyword);
+
+    /**
+     * 获取详情
+     *
+     * @param id
+     * @return
+     */
+    SystemEntity getInfo(String id);
+
+    /**
+     * 判断系统名称是否重复
+     *
+     * @param id
+     * @param fullName
+     * @return
+     */
+    Boolean isExistFullName(String id, String fullName);
+
+    /**
+     * 判断系统编码是否重复
+     *
+     * @param id
+     * @param enCode
+     * @return
+     */
+    Boolean isExistEnCode(String id, String enCode);
+
+
+
+
+
+    /**
+     * 通过id获取系统列表
+     *
+     * @param list
+     * @param moduleAuthorize
+     * @return
+     */
+    List<SystemEntity> getListByIds(List<String> list, List<String> moduleAuthorize);
+
+    /**
+     * 通过编码获取系统信息
+     *
+     * @param enCode
+     * @return
+     */
+    SystemEntity getInfoByEnCode(String enCode);
+
+    /**
+     * 获取
+     *
+     * @param moduleAuthorize
+     * @return
+     */
+    List<SystemEntity> findSystemAdmin(List<String> moduleAuthorize);
+
+    /**
+     * 获取
+     *
+     * @param mark
+     * @param mainSystemCode
+     * @return
+     */
+    List<SystemEntity> findSystemAdmin(int mark, String mainSystemCode);
+
+
+    /**
+     * 获取当前用户有编辑权限的应用
+     *
+     * @return
+     */
+    List<SystemEntity> getAuthListByUser();
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/UserService.class


+ 23 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/UserService.java

@@ -0,0 +1,23 @@
+package jnpf.service;
+
+import jnpf.base.service.SuperService;
+import jnpf.entity.UserEntity;
+
+import java.util.List;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+public interface UserService extends SuperService<UserEntity> {
+
+    /**
+     *
+     * @param idList
+     * @return
+     */
+    List<UserEntity> getUserName(List<String> idList);
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/CodeNumServiceImpl.class


+ 88 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/CodeNumServiceImpl.java

@@ -0,0 +1,88 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.entity.CodeNumEntity;
+import jnpf.mapper.CodeNumMapper;
+import jnpf.service.CodeNumService;
+import jnpf.util.DateUtil;
+import jnpf.util.RandomUtil;
+import lombok.Synchronized;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+/**
+ * 编码获取服务
+ *
+ * @author JNPF开发平台组
+ * @version v6.0.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2025/2/28 11:16:06
+ */
+@Service
+public class CodeNumServiceImpl extends SuperServiceImpl<CodeNumMapper, CodeNumEntity> implements CodeNumService {
+
+    @Synchronized
+    @Override
+    public Integer getNumByType(String type, Integer times) {
+        CodeNumEntity codeNumEntity;
+        Integer num = 1;
+        Integer dateValue = Integer.parseInt(DateUtil.nowDateTime().substring(0, 8));
+
+        QueryWrapper<CodeNumEntity> wrapper = new QueryWrapper();
+        wrapper.lambda().eq(CodeNumEntity::getType, type);
+        List<CodeNumEntity> list = this.list(wrapper);
+        if (list.size() > 0) {
+            codeNumEntity = list.get(0);
+            if (Objects.equals(dateValue, codeNumEntity.getDateValue())) {
+                num = codeNumEntity.getNum();
+            }
+        } else {
+            codeNumEntity = new CodeNumEntity();
+            codeNumEntity.setId(RandomUtil.uuId());
+
+
+        }
+        codeNumEntity.setType(type);
+        codeNumEntity.setDateValue(dateValue);
+        codeNumEntity.setNum(num + times);
+        this.saveOrUpdate(codeNumEntity);
+        return num;
+    }
+
+    @Override
+    public List<String> getCode(String type, Integer num) {
+        Integer value = this.getNumByType(type, num);
+        List<String> list = new ArrayList<>();
+        for (int n = 0; n < num; n++) {
+            String numStr = String.format("%06d", value + n);
+            StringBuilder sb = new StringBuilder();
+            sb.append(type);
+            sb.append(DateUtil.nowDateTime().substring(0, 8));
+            sb.append(numStr);
+            list.add(sb.toString());
+        }
+        return list;
+    }
+
+
+    @Override
+    public String getCodeOnce(String type) {
+        return this.getCode(type, 1).get(0);
+    }
+
+    @Override
+    @Synchronized
+    public String getCodeFunction(Supplier<String> getCode, Predicate<String> existCode) {
+        return Stream.generate(getCode)
+                .filter(code -> !existCode.test(code))
+                .findFirst()
+                .orElseThrow(() -> new RuntimeException("无法获取唯一编码"));
+    }
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/DictionaryDataServiceImpl.class


+ 36 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/DictionaryDataServiceImpl.java

@@ -0,0 +1,36 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.entity.DictionaryDataEntity;
+import jnpf.mapper.DictionaryDataMapper;
+import jnpf.service.DictionaryDataService;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 字典数据
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+@Service
+public class DictionaryDataServiceImpl extends SuperServiceImpl<DictionaryDataMapper, DictionaryDataEntity> implements DictionaryDataService {
+
+    @Override
+    public List<DictionaryDataEntity> getDictionName(List<String> id) {
+        List<DictionaryDataEntity> dictionList = new ArrayList<>();
+        if (id.size() > 0) {
+            QueryWrapper<DictionaryDataEntity> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().and(
+                    t -> t.in(DictionaryDataEntity::getId, id)
+            );
+            dictionList = this.list(queryWrapper);
+        }
+        return dictionList;
+    }
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportServiceImpl.class


+ 306 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportServiceImpl.java

@@ -0,0 +1,306 @@
+package jnpf.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.Method;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jnpf.base.ActionResult;
+import jnpf.base.UserInfo;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.constant.CodeConst;
+import jnpf.constant.MsgCode;
+import jnpf.consts.ApiConst;
+import jnpf.emnus.DataSetTypeEnum;
+import jnpf.entity.ReportEntity;
+import jnpf.entity.ReportVersionEntity;
+import jnpf.entity.SystemEntity;
+import jnpf.exception.DataException;
+import jnpf.mapper.ReportMapper;
+import jnpf.model.data.DataForm;
+import jnpf.model.data.DataSetInfo;
+import jnpf.model.data.DataSetPagination;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportInfoVO;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.ReportUpForm;
+import jnpf.service.CodeNumService;
+import jnpf.service.ReportService;
+import jnpf.service.ReportVersionService;
+import jnpf.service.SystemService;
+import jnpf.util.*;
+import jnpf.util.context.RequestContext;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+@Service
+public class ReportServiceImpl extends SuperServiceImpl<ReportMapper, ReportEntity> implements ReportService {
+
+    @Autowired
+    private CodeNumService codeNumService;
+    @Autowired
+    private SystemService systemService;
+
+
+    @Autowired
+    private ReportVersionService versionService;
+
+    @Override
+    public List<ReportEntity> getList(ReportPagination pagination) {
+        QueryWrapper<ReportEntity> queryWrapper = new QueryWrapper<>();
+        String keyword = pagination.getKeyword();
+        if (ObjectUtil.isNotEmpty(keyword)) {
+            queryWrapper.lambda().and(t -> t.like(ReportEntity::getEnCode, keyword).or().like(ReportEntity::getFullName, keyword));
+        }
+        if (ObjectUtil.isNotEmpty(pagination.getCategory())) {
+            queryWrapper.lambda().eq(ReportEntity::getCategory, pagination.getCategory());
+        }
+        if (ObjectUtil.isNotEmpty(pagination.getState())) {
+            queryWrapper.lambda().eq(ReportEntity::getEnabledMark, pagination.getState());
+        }
+        if (ObjectUtil.isNotEmpty(pagination.getSystemId())) {
+            queryWrapper.lambda().eq(ReportEntity::getSystemId, pagination.getSystemId());
+        }
+        queryWrapper.lambda().orderByAsc(ReportEntity::getSortCode).orderByDesc(ReportEntity::getCreatorTime);
+        Page<ReportEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
+        IPage<ReportEntity> userPage = this.page(page, queryWrapper);
+        return pagination.setData(userPage.getRecords(), page.getTotal());
+    }
+
+    @Override
+    public void create(ReportCrForm form) {
+
+        if (StringUtil.isEmpty(form.getEnCode())) {
+            form.setEnCode(codeNumService.getCodeOnce(CodeConst.BB));
+        }
+        ReportEntity entity = JsonUtil.getJsonToBean(form, ReportEntity.class);
+        UserInfo userInfo = UserProvider.getUser();
+        this.creUpdateCheck(entity, true, true);
+        String id = StringUtil.isNotEmpty(entity.getId()) ? entity.getId() : RandomUtil.uuId();
+        entity.setId(id);
+        entity.setEnabledMark(0);
+        entity.setCreatorUserId(userInfo.getUserId());
+        entity.setCreatorTime(new Date());
+        entity.setLastModifyUserId(null);
+        entity.setLastModifyTime(null);
+        this.setIgnoreLogicDelete().removeById(entity.getId());
+        this.setIgnoreLogicDelete().saveOrUpdate(entity);
+        this.clearIgnoreLogicDelete();
+        form.setId(id);
+        List<ReportVersionEntity> list = versionService.getList(id, ReportVersionEntity::getId);
+        if (CollectionUtils.isEmpty(list)) {
+            versionService.create(form);
+        }
+    }
+
+    @Override
+    public void update(String id, ReportEntity entity) {
+        ReportEntity report = getById(id);
+        if (StringUtil.isEmpty(entity.getEnCode())) {
+            entity.setEnCode(codeNumService.getCodeOnce(CodeConst.BB));
+        }
+
+        this.creUpdateCheck(entity, !report.getFullName().equals(entity.getFullName()), !report.getEnCode().equals(entity.getEnCode()));
+        entity.setId(id);
+        updateById(entity);
+    }
+
+    @Override
+    public ReportInfoVO getVersionInfo(String versionId) {
+        ReportVersionEntity versionEntity = versionService.getById(versionId);
+        ReportEntity entity = this.getById(versionEntity.getTemplateId());
+        ReportInfoVO vo = JsonUtil.getJsonToBean(versionEntity, ReportInfoVO.class);
+        vo.setVersionId(versionId);
+        vo.setId(entity.getId());
+        vo.setFullName(entity.getFullName());
+        vo.setAllowExport(entity.getAllowExport());
+        vo.setAllowWatermark(entity.getAllowWatermark());
+        vo.setWatermarkConfig(entity.getWatermarkConfig());
+        vo.setAllowPrint(entity.getAllowPrint());
+        vo.setCategory(entity.getCategory());
+        vo.setEnCode(entity.getEnCode());
+        vo.setSortCode(entity.getSortCode());
+        DataSetPagination pagination = new DataSetPagination();
+        pagination.setObjectId(versionId);
+        pagination.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+        String json = ReportUtil.http(ApiConst.DATASET_LIST, Method.GET, JsonUtil.entityToMap(pagination));
+        ActionResult result = JsonUtil.getJsonToBean(json, ActionResult.class);
+        List<DataSetInfo> dataSetList = new ArrayList<>();
+        if (ObjectUtil.isNotEmpty(result.getData())) {
+            dataSetList = JsonUtil.getJsonToList(result.getData(), DataSetInfo.class);
+        }
+        vo.setDataSetList(dataSetList);
+        return vo;
+    }
+
+    @Override
+    public void saveOrRelease(ReportUpForm form) {
+        ReportVersionEntity versionEntity = versionService.getById(form.getVersionId());
+        ReportVersionEntity versionNew = JsonUtil.getJsonToBean(form, ReportVersionEntity.class);
+        versionNew.setFenceList(form.getColumnList());
+        versionNew.setId(versionEntity.getId());
+        versionNew.setState(versionEntity.getState());
+        ReportEntity entity = this.getById(form.getId());
+        //发布流程
+        if (Objects.equals(form.getType(), 1)) {
+            //改流程版本
+            if (StringUtil.isNotEmpty(form.getVersionId())) {
+                boolean isRelease = Objects.equals(versionNew.getState(), 2);
+                ReportVersionEntity info = versionService.getList(form.getId(), ReportVersionEntity::getId, ReportVersionEntity::getState).stream().filter(t -> Objects.equals(t.getState(), 1)).findFirst().orElse(null);
+                if (info != null) {
+                    // 变更归档状态,排序码
+                    info.setSortCode(0L);
+                    info.setState(2);
+                    versionService.updateById(info);
+                }
+                versionNew.setState(1);
+                versionNew.setSortCode(1L);
+                entity.setEnabledMark(1);
+                if (isRelease) {
+                    versionService.updateById(versionNew);
+                    return;
+                }
+            }
+        }
+        versionService.updateById(versionNew);
+        //数据集创建
+        String versionId = versionNew.getId();
+        List<DataSetInfo> dataSetList = form.getDataSetList() != null ? form.getDataSetList() : new ArrayList<>();
+        DataForm dataForm = new DataForm();
+        dataForm.setObjectId(versionId);
+        dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+        dataForm.setList(dataSetList);
+        ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        entity.setAllowExport(form.getAllowExport());
+        entity.setAllowPrint(form.getAllowPrint());
+        entity.setAllowWatermark(form.getAllowWatermark());
+        entity.setWatermarkConfig(form.getWatermarkConfig());
+        entity.setLastModifyTime(new Date());
+        entity.setLastModifyUserId(UserProvider.getLoginUserId());
+        this.updateById(entity);
+    }
+
+    @Override
+    public List<ReportEntity> getTreeList() {
+        SystemEntity infoByEnCode = systemService.getInfoByEnCode(RequestContext.getAppCode());
+        if (infoByEnCode == null) {
+            return new ArrayList<>();
+        }
+        QueryWrapper<ReportEntity> query = new QueryWrapper<>();
+        query.lambda().eq(ReportEntity::getEnabledMark, 1);
+        query.lambda().eq(ReportEntity::getSystemId, infoByEnCode.getId());
+        query.lambda().orderByAsc(ReportEntity::getSortCode).orderByDesc(ReportEntity::getCreatorTime);
+        return this.list(query);
+    }
+
+    @Override
+    public void delete(String id) {
+        removeById(id);
+        versionService.removeByTemplateId(id);
+    }
+
+    @Override
+    public String importData(ReportInfoVO infoVO, Integer type, Boolean idCheck) {
+        ReportEntity entity = JsonUtil.getJsonToBean(infoVO, ReportEntity.class);
+        StringJoiner stringJoiner = new StringJoiner("、");
+        //id为空切名称不存在时
+        QueryWrapper<ReportEntity> queryWrapper = new QueryWrapper<>();
+        if (idCheck) {
+            queryWrapper.lambda().eq(ReportEntity::getId, entity.getId());
+            if (this.getById(infoVO.getId()) != null) {
+                if (Objects.equals(type, 1)) {
+                    entity.setId(RandomUtil.uuId());
+                } else {
+                    stringJoiner.add("ID");
+                }
+            }
+        }
+        if (ObjectUtil.equal(type, 1)) {
+            String copyNum = UUID.randomUUID().toString().substring(0, 5);
+            entity.setFullName(entity.getFullName() + ".副本" + copyNum);
+            entity.setEnCode(entity.getEnCode() + copyNum);
+        } else if (ObjectUtil.equal(type, 0) && stringJoiner.length() > 0) {
+            return stringJoiner + MsgCode.IMP007.get();
+        }
+        entity.setEnabledMark(0);
+        entity.setCreatorTime(new Date());
+        entity.setCreatorUserId(UserProvider.getLoginUserId());
+        entity.setLastModifyTime(null);
+        entity.setLastModifyUserId(null);
+        if (type != 1) {
+            this.creUpdateCheck(entity, true, true);
+        }
+        this.setIgnoreLogicDelete().removeById(entity);
+        this.setIgnoreLogicDelete().saveOrUpdate(entity);
+        this.clearIgnoreLogicDelete();
+        //版本添加
+        ReportVersionEntity versionEntity = JsonUtil.getJsonToBean(infoVO, ReportVersionEntity.class);
+        String versionId = RandomUtil.uuId();
+        versionEntity.setId(versionId);
+        versionEntity.setTemplateId(entity.getId());
+        versionEntity.setCreatorUserId(UserProvider.getLoginUserId());
+        versionEntity.setCreatorTime(new Date());
+        versionEntity.setVersion(1);
+        versionEntity.setState(0);
+        versionEntity.setSortCode(0L);
+        versionService.save(versionEntity);
+        //数据集创建
+        List<DataSetInfo> dataSetList = infoVO.getDataSetList() != null ? infoVO.getDataSetList() : new ArrayList<>();
+        if (!dataSetList.isEmpty()) {
+            DataForm dataForm = new DataForm();
+            dataForm.setObjectId(versionId);
+            dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+            dataForm.setList(dataSetList);
+            ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        }
+        return "";
+    }
+
+    @Override
+    public Boolean isEncodeExist(String encode) {
+        QueryWrapper<ReportEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(ReportEntity::getEnCode, encode);
+        if (!this.list(queryWrapper).isEmpty()) {
+            return true;
+        }
+        return false;
+    }
+
+
+    public void creUpdateCheck(ReportEntity entity, Boolean fullNameCheck, Boolean encodeCheck) {
+        String fullName = entity.getFullName();
+        String encode = entity.getEnCode();
+        String systemId = entity.getSystemId();
+        // 名称长度验证
+        if (fullName.length() > 80) {
+            throw new DataException(MsgCode.EXIST005.get());
+        }
+        QueryWrapper<ReportEntity> query = new QueryWrapper<>();
+        //重名验证
+        if (fullNameCheck) {
+            query.lambda().eq(ReportEntity::getFullName, fullName);
+            query.lambda().eq(ReportEntity::getSystemId, systemId);
+            if (!this.list(query).isEmpty()) {
+                throw new DataException(MsgCode.EXIST003.get());
+            }
+        }
+        //编码验证
+        if (encodeCheck) {
+            query.clear();
+            query.lambda().eq(ReportEntity::getEnCode, encode);
+            if (!this.list(query).isEmpty()) {
+                throw new DataException(MsgCode.EXIST002.get());
+            }
+        }
+    }
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportVersionServiceImpl.class


+ 282 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/ReportVersionServiceImpl.java

@@ -0,0 +1,282 @@
+package jnpf.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.Method;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.google.common.collect.ImmutableList;
+import jnpf.base.ActionResult;
+import jnpf.base.service.SuperServiceImpl;
+import jnpf.constant.FileTypeConstant;
+import jnpf.constant.MsgCode;
+import jnpf.consts.ApiConst;
+import jnpf.emnus.DataSetTypeEnum;
+import jnpf.entity.FileParameter;
+import jnpf.entity.ReportEntity;
+import jnpf.entity.ReportVersionEntity;
+import jnpf.exception.DataException;
+import jnpf.mapper.ReportVersionMapper;
+import jnpf.model.DataQuery;
+import jnpf.model.data.*;
+import jnpf.model.report.ReportCrForm;
+import jnpf.model.report.ReportPagination;
+import jnpf.model.report.UploaderVO;
+import jnpf.service.ReportService;
+import jnpf.service.ReportVersionService;
+import jnpf.univer.chart.UniverChartModel;
+import jnpf.univer.data.custom.UniverCustom;
+import jnpf.univer.model.UniverPreview;
+import jnpf.univer.model.UniverWorkBook;
+import jnpf.util.*;
+import lombok.Cleanup;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.dromara.x.file.storage.core.FileInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author :JNPF开发平台组
+ * @version: V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date :2024/5/11 下午4:35
+ */
+@Service
+public class ReportVersionServiceImpl extends SuperServiceImpl<ReportVersionMapper, ReportVersionEntity> implements ReportVersionService {
+
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private ReportService reportService;
+
+    @Override
+    @DSTransactional
+    public void create(ReportCrForm form) {
+        String versionId = RandomUtil.uuId();
+        ReportVersionEntity entity = JsonUtil.getJsonToBean(form, ReportVersionEntity.class);
+        entity.setId(versionId);
+        entity.setTemplateId(form.getId());
+        entity.setCreatorUserId(UserProvider.getLoginUserId());
+        entity.setCreatorTime(new Date());
+        List<ReportVersionEntity> verList = getList(entity.getId(), ReportVersionEntity::getVersion);
+        int version = verList.stream().map(ReportVersionEntity::getVersion).max(Comparator.naturalOrder()).orElse(0) + 1;
+        entity.setVersion(version);
+        entity.setState(0);
+        entity.setSortCode(0l);
+        this.setIgnoreLogicDelete().removeById(entity.getId());
+        this.setIgnoreLogicDelete().saveOrUpdate(entity);
+        this.clearIgnoreLogicDelete();
+        List<DataSetInfo> dataSetList = form.getDataSetList() != null ? form.getDataSetList() : new ArrayList<>();
+        if (dataSetList.size() > 0) {
+            //数据集创建
+            DataForm dataForm = new DataForm();
+            dataForm.setObjectId(versionId);
+            dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+            dataForm.setList(dataSetList);
+            ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        }
+    }
+
+    @Override
+    public List<ReportVersionEntity> getList(String templateId, SFunction<ReportVersionEntity, ?>... columns) {
+        QueryWrapper<ReportVersionEntity> queryWrapper = new QueryWrapper<>();
+        if (columns != null && columns.length > 0) {
+            queryWrapper.lambda().select(columns);
+        }
+        queryWrapper.lambda().eq(ReportVersionEntity::getTemplateId, templateId);
+        queryWrapper.lambda().orderByDesc(ReportVersionEntity::getSortCode).orderByAsc(ReportVersionEntity::getState);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public String copyVersion(String versionId) {
+        ReportVersionEntity entity = this.getById(versionId);
+        ReportVersionEntity versionEntity = JsonUtil.getJsonToBean(entity, ReportVersionEntity.class);
+        String newVersionId = RandomUtil.uuId();
+        versionEntity.setId(newVersionId);
+        List<ReportVersionEntity> verList = getList(entity.getTemplateId(), ReportVersionEntity::getVersion);
+        int version = verList.stream().map(ReportVersionEntity::getVersion).max(Comparator.naturalOrder()).orElse(0) + 1;
+        versionEntity.setVersion(version);
+        versionEntity.setState(0);
+        versionEntity.setSortCode(0l);
+        versionEntity.setCreatorTime(new Date());
+        versionEntity.setCreatorUserId(UserProvider.getLoginUserId());
+        versionEntity.setLastModifyTime(null);
+        versionEntity.setLastModifyUserId(null);
+        DataSetPagination pagination = new DataSetPagination();
+        pagination.setObjectId(versionId);
+        pagination.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+        String json = ReportUtil.http(ApiConst.DATASET_LIST, Method.GET, JsonUtil.entityToMap(pagination));
+        ActionResult result = JsonUtil.getJsonToBean(json, ActionResult.class);
+        List<DataSetInfo> dataSetList = new ArrayList<>();
+        if (ObjectUtil.isNotEmpty(result.getData())) {
+            dataSetList.addAll(JsonUtil.getJsonToList(result.getData(), DataSetInfo.class));
+        }
+        if (dataSetList.size() > 0) {
+            for (DataSetInfo item : dataSetList) {
+                item.setId(null);
+                item.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+                item.setObjectId(newVersionId);
+            }
+            DataForm dataForm = new DataForm();
+            dataForm.setObjectId(newVersionId);
+            dataForm.setObjectType(DataSetTypeEnum.REPORT_VER.getCode());
+            dataForm.setList(dataSetList);
+            ReportUtil.http(ApiConst.DATASET_SAVE, Method.POST, JsonUtil.entityToMap(dataForm));
+        }
+        this.save(versionEntity);
+        return newVersionId;
+    }
+
+    @Override
+    public void removeByTemplateId(String templateId) {
+        QueryWrapper<ReportVersionEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(ReportVersionEntity::getTemplateId, templateId);
+        this.remove(queryWrapper);
+    }
+
+    @Override
+    public UniverPreview preview(String id, ReportPagination pagination, Map<String, Object> params) {
+        ReportVersionEntity entity = getById(id);
+        if (ObjectUtil.isEmpty(entity)) {
+            throw new DataException(MsgCode.FA015.get());
+        }
+        if (ObjectUtil.isEmpty(entity.getSnapshot())) {
+            throw new DataException(MsgCode.FA105.get());
+        }
+        //获取当前
+        UniverWorkBook univerWorkBook = JsonUtil.getJsonToBean(entity.getSnapshot(), UniverWorkBook.class);
+        List<String> sheetOrder = univerWorkBook.getSheetOrder();
+        ReportEntity report = reportService.getById(entity.getTemplateId());
+        Map<String, Map<String, List<Map<String, Object>>>> sheetData = new HashMap<>();
+        Map<String, Map<String, Map<String, Object>>> parameterData = new HashMap<>();
+        //当前数据
+        String sheet = StringUtil.isNotEmpty(pagination.getSheetId()) ? pagination.getSheetId() : !sheetOrder.isEmpty() ? sheetOrder.get(0) : null;
+        for (String sheetId : sheetOrder) {
+            DataSetQuery query = new DataSetQuery();
+            query.setModuleId(entity.getTemplateId());
+            query.setId(id);
+            Map<String, Object> dataMap = new HashMap<>(params);
+            query.setMap(dataMap);
+            query.setType(DataSetTypeEnum.REPORT_VER.getCode());
+            query.setSnowFlakeId(RandomUtil.uuId());
+            query.setConvertConfig(entity.getConvertConfig());
+            List<DataQuery> dataQueryList = StringUtil.isNotEmpty(entity.getQueryList()) ? JsonUtil.getJsonToList(entity.getQueryList(), DataQuery.class) : new ArrayList<>();
+            Map<String, List<DataQuery>> queryMap = dataQueryList.stream().collect(Collectors.groupingBy(DataQuery::getSheet));
+            List<DataQuery> queryListAll = queryMap.get(sheetId) != null ? queryMap.get(sheetId) : new ArrayList<>();
+            List<Object> queryList = new ArrayList<>();
+            if (Objects.equals(sheetId, sheet)) {
+                for (DataQuery dataQuery : queryListAll) {
+                    queryList.addAll(dataQuery.getQueryList());
+                }
+            }
+            query.setQueryList(JSONUtil.toJsonStr(queryList));
+            String sheetJson = ReportUtil.http(ApiConst.DATASET_DATA, Method.POST, JsonUtil.entityToMap(query));
+            if (StringUtil.isNotEmpty(sheetJson)) {
+                Map<String, List<Map<String, Object>>> dataList = new HashMap<>();
+                try {
+                    ActionResult result = JsonUtil.getJsonToBean(sheetJson, ActionResult.class);
+                    if (ObjectUtil.isNotEmpty(result) && result.getData() instanceof Map) {
+                        Map<String, List<Map<String, Object>>> data = JsonUtil.getJsonToBean(result.getData(), Map.class);
+                        dataList.putAll(data);
+                    }
+                } catch (Exception e) {}
+                sheetData.put(sheetId, dataList);
+            }
+
+            //参数数据
+            String parameterJson = ReportUtil.http(ApiConst.PARAMETER_DATA, Method.POST, JsonUtil.entityToMap(query));
+            if (StringUtil.isNotEmpty(parameterJson)) {
+                Map<String, Map<String, Object>> dataList = new HashMap<>();
+                try {
+                    ActionResult result = JsonUtil.getJsonToBean(parameterJson, ActionResult.class);
+                    if (ObjectUtil.isNotEmpty(result) && result.getData() instanceof Map) {
+                        Map data = JsonUtil.getJsonToBean(result.getData(), Map.class);
+                        dataList.putAll(data);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage());
+                }
+                parameterData.put(sheetId, dataList);
+            }
+        }
+        UniverConvert convert = new UniverConvert();
+        UniverPreview vo = convert.transform(entity.getSnapshot(), entity.getCells(), entity.getSortList(), entity.getFenceList(),sheetData, parameterData);
+        vo.setVersionId(id);
+        vo.setQueryList(entity.getQueryList());
+        vo.setAllowWatermark(report.getAllowWatermark());
+        vo.setWatermarkConfig(report.getWatermarkConfig());
+        vo.setFullName(report.getFullName());
+        vo.setAllowExport(report.getAllowExport());
+        vo.setAllowPrint(report.getAllowPrint());
+        return vo;
+    }
+
+    @Override
+    public UniverPreview previewTemplate(String id, ReportPagination pagination, Map<String, Object> params) {
+        ReportVersionEntity entity = getList(id, ReportVersionEntity::getId, ReportVersionEntity::getState).stream().filter(t -> Objects.equals(t.getState(), 1)).findFirst().orElse(null);
+        if (ObjectUtil.isEmpty(entity)) {
+            throw new DataException(MsgCode.FA015.get());
+        }
+        return preview(entity.getId(), pagination, params);
+    }
+
+    @Override
+    public UniverPreview importExcel(MultipartFile multipartFile) throws IOException {
+        UniverCustom cellData = new UniverCustom();
+        UniverWorkBook univerWorkBook = UniverExcel.formFile(multipartFile);
+        UniverPreview vo = new UniverPreview();
+        vo.setSnapshot(JSONUtil.toJsonStr(univerWorkBook));
+        vo.setCells(JSONUtil.toJsonStr(cellData));
+        return vo;
+    }
+
+    @Override
+    public UploaderVO downExcel(ReportPagination pagination, Map<String, Object> params) {
+        String id = pagination.getId();
+        UploaderVO vo = new UploaderVO();
+        ReportVersionEntity versionEntity = getById(id);
+        if (ObjectUtil.isEmpty(versionEntity)) {
+            return vo;
+        }
+        ReportEntity entity = reportService.getById(versionEntity.getTemplateId());
+        UniverPreview preview = preview(id, pagination, params);
+        pagination.setSnapshot(preview.getSnapshot());
+        pagination.setFullName(entity.getFullName());
+        vo = downExcel(pagination);
+        return vo;
+    }
+
+    @Override
+    public UploaderVO downExcel(ReportPagination pagination) {
+        UploaderVO vo = new UploaderVO();
+        if (StringUtil.isNotEmpty(pagination.getSnapshot())) {
+            try {
+                List<UniverChartModel> chartList = new ArrayList<>();
+                @Cleanup XSSFWorkbook workbook = new XSSFWorkbook();
+                List<String> sheetList = Arrays.asList(pagination.getSheetId().split(","));
+                UniverExcel.downExcel(pagination.getSnapshot(), chartList, workbook, sheetList);
+                String fileName = pagination.getFullName() + ".xlsx";
+                @Cleanup ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                workbook.write(outputStream);
+                String url = "/api/Report/data/Download?name=" + fileName + "&encryption=";
+                FileInfo fileInfo = FileUploadUtils.uploadFile(new FileParameter(FileTypeConstant.TEMPORARY, fileName), outputStream.toByteArray());
+                vo.setName(fileInfo.getFilename());
+                vo.setUrl(UploaderUtil.uploaderFile(url, fileInfo.getFilename() + "#" + FileTypeConstant.TEMPORARY));
+            } catch (Exception e) {
+                log.error("报表导出excel异常:" + e.getMessage());
+                throw new DataException(MsgCode.FA107.get());
+            }
+        }
+        return vo;
+    }
+
+}

二進制
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/SystemServiceImpl.class


+ 213 - 0
jnpf-datareport-univer-biz/target/classes/jnpf/service/impl/SystemServiceImpl.java

@@ -0,0 +1,213 @@
+package jnpf.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jnpf.base.UserInfo;
+
+
+import jnpf.base.service.SuperServiceImpl;
+
+import jnpf.constant.CodeConst;
+import jnpf.constant.PermissionConst;
+
+import jnpf.entity.SystemEntity;
+import jnpf.mapper.SystemMapper;
+import jnpf.service.SystemService;
+import jnpf.util.RandomUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.UserProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 系统
+ *
+ * @author JNPF开发平台组
+ * @version V3.1.0
+ * @copyright 引迈信息技术有限公司
+ * @date 2019年9月27日 上午9:18
+ */
+@Service
+public class SystemServiceImpl extends SuperServiceImpl<SystemMapper, SystemEntity> implements SystemService {
+
+
+
+
+    @Override
+    public List<SystemEntity> getList() {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 1);
+        queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode)
+                .orderByDesc(SystemEntity::getCreatorTime);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> getList(String keyword, Boolean filterEnableMark, boolean verifyAuth, Boolean filterMain, boolean isList, List<String> moduleAuthorize) {
+        UserInfo user = UserProvider.getUser();
+
+        boolean flag = false;
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        if (StringUtil.isNotEmpty(keyword)) {
+            flag = true;
+            queryWrapper.lambda().and(t ->
+                    t.like(SystemEntity::getFullName, keyword).or().like(SystemEntity::getEnCode, keyword)
+                            .or().like(SystemEntity::getDescription, keyword)
+            );
+        }
+        if (filterEnableMark == null) {
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 0);
+        } else if (filterEnableMark) {
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 1);
+        }
+
+        // 过滤掉系统应用
+        if (filterMain != null && filterMain) {
+            queryWrapper.lambda().ne(SystemEntity::getIsMain, 1);
+        }
+        //判断权限列表
+        if (!user.getIsAdministrator() && verifyAuth) {
+            if (user.getIsDevRole()) {
+                queryWrapper.lambda().and(t -> t
+                        .eq(SystemEntity::getUserId, user.getUserId()).or()
+                        .like(SystemEntity::getAuthorizeId, user.getUserId()).or()
+                        .eq(SystemEntity::getAuthorizeId, PermissionConst.ALL_DEV_USER));
+            }
+        }
+
+        //过滤租户分配黑名单
+        if (moduleAuthorize.size() > 0) {
+            queryWrapper.lambda().notIn(SystemEntity::getId, moduleAuthorize);
+        }
+        if (flag) {
+            queryWrapper.lambda().orderByDesc(SystemEntity::getLastModifyTime);
+        } else {
+            queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        }
+
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> getListByIdsKey(List<String> ids, String keyword) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().in(SystemEntity::getId, ids);
+        boolean flag = false;
+        if (StringUtil.isNotEmpty(keyword)) {
+            flag = true;
+            queryWrapper.lambda().and(t ->
+                    t.like(SystemEntity::getFullName, keyword).or().like(SystemEntity::getEnCode, keyword)
+                            .or().like(SystemEntity::getDescription, keyword)
+            );
+        }
+        if (flag) {
+            queryWrapper.lambda().orderByDesc(SystemEntity::getLastModifyTime);
+        } else {
+            queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        }
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public SystemEntity getInfo(String id) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getId, id);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public Boolean isExistFullName(String id, String fullName) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getFullName, fullName);
+        if (StringUtil.isNotEmpty(id)) {
+            queryWrapper.lambda().ne(SystemEntity::getId, id);
+        }
+        return this.count(queryWrapper) > 0;
+    }
+
+    @Override
+    public Boolean isExistEnCode(String id, String enCode) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getEnCode, enCode);
+        if (StringUtil.isNotEmpty(id)) {
+            queryWrapper.lambda().ne(SystemEntity::getId, id);
+        }
+        return this.count(queryWrapper) > 0;
+    }
+
+
+
+
+
+    @Override
+    public List<SystemEntity> getListByIds(List<String> list, List<String> moduleAuthorize) {
+        List<SystemEntity> systemList = new ArrayList<>(16);
+        if (list.size() > 0) {
+            QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+            if (moduleAuthorize != null && moduleAuthorize.size() > 0) {
+                queryWrapper.lambda().notIn(SystemEntity::getId, moduleAuthorize);
+            }
+            queryWrapper.lambda().in(SystemEntity::getId, list);
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, 1);
+            queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+            return this.list(queryWrapper);
+        }
+        return systemList;
+    }
+
+    @Override
+    public SystemEntity getInfoByEnCode(String enCode) {
+        if (StringUtil.isEmpty(enCode)) {
+            return null;
+        }
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(SystemEntity::getEnCode, enCode);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> findSystemAdmin(List<String> moduleAuthorize) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        if (moduleAuthorize != null && moduleAuthorize.size() > 0) {
+            queryWrapper.lambda().notIn(SystemEntity::getId, moduleAuthorize);
+        }
+        queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public List<SystemEntity> findSystemAdmin(int mark, String mainSystemCode) {
+        QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+        if (mark == 1) {
+            queryWrapper.lambda().eq(SystemEntity::getEnabledMark, mark)
+                    .ne(SystemEntity::getEnCode, mainSystemCode);
+        }
+        queryWrapper.lambda().orderByAsc(SystemEntity::getSortCode).orderByDesc(SystemEntity::getCreatorTime);
+        return this.list(queryWrapper);
+    }
+
+
+
+    @Override
+    public List<SystemEntity> getAuthListByUser() {
+        UserInfo user = UserProvider.getUser();
+        //开发人员才有编辑权限
+        if (user.getIsDevRole() || user.getIsAdministrator()) {
+            QueryWrapper<SystemEntity> queryWrapper = new QueryWrapper<>();
+            //判断权限列表
+            if (!user.getIsAdministrator()) {
+                queryWrapper.lambda().eq(SystemEntity::getUserId, user.getUserId()).or();
+                queryWrapper.lambda().like(SystemEntity::getAuthorizeId, user.getUserId()).or();
+                queryWrapper.lambda().eq(SystemEntity::getAuthorizeId, PermissionConst.ALL_DEV_USER);
+            }
+            return list(queryWrapper);
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+}

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