wangliang 2 years ago
commit
a58de9bde6
77 changed files with 5127 additions and 0 deletions
  1. 33 0
      .gitignore
  2. 16 0
      README.md
  3. 283 0
      pom.xml
  4. 33 0
      teachcloud-exchange-business/.gitignore
  5. 49 0
      teachcloud-exchange-business/pom.xml
  6. 13 0
      teachcloud-exchange-business/src/test/java/com/qmth/teachcloud/exchange/business/TeachcloudExchangeBusinessApplicationTests.java
  7. 33 0
      teachcloud-exchange-common-api/.gitignore
  8. 23 0
      teachcloud-exchange-common-api/pom.xml
  9. 104 0
      teachcloud-exchange-common-api/src/main/java/com/qmth/teachcloud/exchange/common/api/CommonOpenApiController.java
  10. 13 0
      teachcloud-exchange-common-api/src/test/java/com/qmth/teachcloud/exchange/common/api/TeachcloudExchangeCommonApiApplicationTests.java
  11. 33 0
      teachcloud-exchange-common/.gitignore
  12. 119 0
      teachcloud-exchange-common/pom.xml
  13. 22 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/annotation/ApiJsonObject.java
  14. 28 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/annotation/ApiJsonProperty.java
  15. 100 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/BaseEntity.java
  16. 64 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/BaseListPage.java
  17. 54 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/BasePage.java
  18. 44 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/CustomBaseMapper.java
  19. 32 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/CustomizedSqlInjector.java
  20. 63 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/method/InsertBatch.java
  21. 85 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/method/InsertOrUpdateBath.java
  22. 30 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/method/UpdateBatch.java
  23. 37 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/bean/dto/AuthOrgInfoDto.java
  24. 48 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/bean/params/OpenParams.java
  25. 63 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/config/DictionaryConfig.java
  26. 69 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/contant/SpringContextHolder.java
  27. 141 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/contant/SystemConstant.java
  28. 28 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssLocalFileDomain.java
  29. 28 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssLocalPdfDomain.java
  30. 34 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssPrivateDomain.java
  31. 34 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssPublicDomain.java
  32. 23 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/PrefixUrlDomain.java
  33. 65 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/SysDomain.java
  34. 143 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/entity/BasicSchool.java
  35. 132 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/entity/TSAuth.java
  36. 44 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/AppSourceEnum.java
  37. 42 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/AuthEnum.java
  38. 101 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/ExceptionResultEnum.java
  39. 27 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/LocalCatalogEnum.java
  40. 76 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/UploadFileEnum.java
  41. 18 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/mapper/BasicSchoolMapper.java
  42. 16 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/mapper/TSAuthMapper.java
  43. 52 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/AuthInfoService.java
  44. 16 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/BasicSchoolService.java
  45. 93 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/CommonCacheService.java
  46. 16 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/TSAuthService.java
  47. 244 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/AuthInfoServiceImpl.java
  48. 20 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/BasicSchoolServiceImpl.java
  49. 166 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/CommonCacheServiceImpl.java
  50. 20 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/TSAuthServiceImpl.java
  51. 16 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/Base64Util.java
  52. 245 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/FileStoreUtil.java
  53. 30 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/GsonUtil.java
  54. 108 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/JacksonUtil.java
  55. 266 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/RedisUtil.java
  56. 70 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/Result.java
  57. 111 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/ResultUtil.java
  58. 273 0
      teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/ServletUtil.java
  59. 5 0
      teachcloud-exchange-common/src/main/resources/mapper/BasicSchoolMapper.xml
  60. 5 0
      teachcloud-exchange-common/src/main/resources/mapper/TSAuthMapper.xml
  61. 13 0
      teachcloud-exchange-common/src/test/java/com/qmth/teachcloud/exchange/common/TeachcloudExchangeCommonApplicationTests.java
  62. 33 0
      xjtu-exchange/.gitignore
  63. 72 0
      xjtu-exchange/pom.xml
  64. 46 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/XjtuExchangeApplication.java
  65. 72 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/api/OpenApiController.java
  66. 88 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/aspect/ApiControllerAspect.java
  67. 125 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/auth/XjtuAuthenticationService.java
  68. 53 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/auth/XjuSession.java
  69. 120 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/config/MapApiReader.java
  70. 27 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/config/MetaHandler.java
  71. 33 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/config/MultipartConfig.java
  72. 77 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/config/SwaggerConfig.java
  73. 45 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/interceptor/AuthInterceptor.java
  74. 31 0
      xjtu-exchange/src/main/java/com/qmth/xjtu/start/StartRunning.java
  75. 78 0
      xjtu-exchange/src/main/resources/application-dev.properties
  76. 2 0
      xjtu-exchange/src/main/resources/application.properties
  77. 13 0
      xjtu-exchange/src/test/java/com/qmth/xjtu/XjtuExchangeApplicationTests.java

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 16 - 0
README.md

@@ -0,0 +1,16 @@
+逸教云平台-快捷登录系统
+
+1.teachcloud-exchange-common 
+公共模块
+
+项目框架:
+java11,spring boot2.6.12
+
+数据库:
+mysql5.7or8.0
+
+部署:
+docker
+
+附件:
+本地或oss存储

+ 283 - 0
pom.xml

@@ -0,0 +1,283 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.qmth.teachcloud.exchange.service</groupId>
+    <artifactId>teachcloud-exchange-service</artifactId>
+    <version>1.0.0</version>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>teachcloud-exchange-common</module>
+        <module>teachcloud-exchange-common-api</module>
+        <module>teachcloud-exchange-business</module>
+        <module>xjtu-exchange</module>
+    </modules>
+
+    <properties>
+        <java.version>11</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <qmth.boot.version>1.0.3</qmth.boot.version>
+        <java.version>1.8</java.version>
+        <swagger2.version>2.9.2</swagger2.version>
+        <fastjson.version>1.2.68</fastjson.version>
+        <fileupload.version>1.4</fileupload.version>
+        <poi.version>3.17</poi.version>
+        <aliyun.version>3.8.1</aliyun.version>
+        <guava.version>27.1-jre</guava.version>
+        <hutool.version>5.0.6</hutool.version>
+        <bcprov.version>1.52</bcprov.version>
+        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
+        <gson.version>2.8.6</gson.version>
+        <commons.version>3.10</commons.version>
+        <commons.codec.version>1.15</commons.codec.version>
+        <commons-io.version>2.6</commons-io.version>
+        <jackson.version>2.11.0</jackson.version>
+        <swagger2-bootstrap.version>1.9.6</swagger2-bootstrap.version>
+        <jetbrains.version>13.0</jetbrains.version>
+        <httpclient.version>4.5.12</httpclient.version>
+        <version-plugin.version>2.8.1</version-plugin.version>
+        <netty-all.version>4.1.49.Final</netty-all.version>
+        <itextpdf.version>5.5.13</itextpdf.version>
+        <itextasian.version>5.2.0</itextasian.version>
+        <googleBar.version>3.4.0</googleBar.version>
+        <freemarker.version>2.3.30</freemarker.version>
+        <commons-text.version>1.9</commons-text.version>
+        <junit.version>4.13</junit.version>
+        <activiti.version>6.0.0</activiti.version>
+        <activiti-modeler.version>5.22.0</activiti-modeler.version>
+        <zip4j.version>1.3.3</zip4j.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.qmth.teachcloud.exchange.business</groupId>
+                <artifactId>teachcloud-exchange-business</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.teachcloud.exchange.common</groupId>
+                <artifactId>teachcloud-exchange-common</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.xjtu.exchange</groupId>
+                <artifactId>xjtu-exchange</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.teachcloud.exchange.common.api</groupId>
+                <artifactId>teachcloud-exchange-common-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>starter-api</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-uid</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-cache</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-concurrent</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-fss</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>data-redis</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>data-mybatis-plus</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>tools-device</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-solar</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-logging</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-models</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-retrofit</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-swagger-ui</artifactId>
+                <version>${swagger2.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-swagger2</artifactId>
+                <version>${swagger2.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-lang3</artifactId>
+                <version>${commons.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-codec</groupId>
+                <artifactId>commons-codec</artifactId>
+                <version>${commons.codec.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-text</artifactId>
+                <version>${commons-text.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>${gson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-fileupload</groupId>
+                <artifactId>commons-fileupload</artifactId>
+                <version>${fileupload.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-core</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-annotations</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-databind</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-all</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+            <!-- aes PKCS7 -->
+            <dependency>
+                <groupId>org.bouncycastle</groupId>
+                <artifactId>bcprov-jdk15on</artifactId>
+                <version>${bcprov.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.jetbrains</groupId>
+                <artifactId>annotations</artifactId>
+                <version>${jetbrains.version}</version>
+                <scope>compile</scope>
+            </dependency>
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>${commons-io.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpclient</artifactId>
+                <version>${httpclient.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.netty</groupId>
+                <artifactId>netty-all</artifactId>
+                <version>${netty-all.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>junit</groupId>
+                <artifactId>junit</artifactId>
+                <version>${junit.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <!-- 默认依赖测试JAR -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <version>${spring-boot.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>versions-maven-plugin</artifactId>
+                <version>${version-plugin.version}</version>
+                <configuration>
+                    <generateBackupPoms>false</generateBackupPoms>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>3.2.0</version>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                    <useDefaultDelimiters>false</useDefaultDelimiters>
+                    <delimiters>
+                        <delimiter>$[*]</delimiter>
+                    </delimiters>
+                    <!-- 过滤后缀不需要转码的文件后缀名pdf -->
+                    <nonFilteredFileExtensions>
+                        <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
+                    </nonFilteredFileExtensions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 33 - 0
teachcloud-exchange-business/.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 49 - 0
teachcloud-exchange-business/pom.xml

@@ -0,0 +1,49 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.qmth.teachcloud.exchange.business</groupId>
+    <artifactId>teachcloud-exchange-business</artifactId>
+    <version>1.0.0</version>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>11</source>
+                    <target>11</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <packaging>jar</packaging>
+
+    <parent>
+        <groupId>com.qmth.teachcloud.exchange.service</groupId>
+        <artifactId>teachcloud-exchange-service</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.teachcloud.exchange.common</groupId>
+            <artifactId>teachcloud-exchange-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>5.2.12.RELEASE</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 13 - 0
teachcloud-exchange-business/src/test/java/com/qmth/teachcloud/exchange/business/TeachcloudExchangeBusinessApplicationTests.java

@@ -0,0 +1,13 @@
+package com.qmth.teachcloud.exchange.business;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TeachcloudExchangeBusinessApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}

+ 33 - 0
teachcloud-exchange-common-api/.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 23 - 0
teachcloud-exchange-common-api/pom.xml

@@ -0,0 +1,23 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.qmth.teachcloud.exchange.common.api</groupId>
+    <artifactId>teachcloud-exchange-common-api</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+
+    <parent>
+        <groupId>com.qmth.teachcloud.exchange.service</groupId>
+        <artifactId>teachcloud-exchange-service</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.qmth.teachcloud.exchange.common</groupId>
+            <artifactId>teachcloud-exchange-common</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 104 - 0
teachcloud-exchange-common-api/src/main/java/com/qmth/teachcloud/exchange/common/api/CommonOpenApiController.java

@@ -0,0 +1,104 @@
+package com.qmth.teachcloud.exchange.common.api;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.boot.api.annotation.Aac;
+import com.qmth.boot.api.annotation.BOOL;
+import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.boot.tools.signature.SignatureEntity;
+import com.qmth.boot.tools.signature.SignatureType;
+import com.qmth.teachcloud.exchange.common.bean.params.OpenParams;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.exchange.common.service.BasicSchoolService;
+import com.qmth.teachcloud.exchange.common.util.JacksonUtil;
+import com.qmth.teachcloud.exchange.common.util.Result;
+import com.qmth.teachcloud.exchange.common.util.ServletUtil;
+import io.swagger.annotations.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+/**
+ * <p>
+ * 知学知考开放接口前端控制器
+ * </p>
+ *
+ * @author wangliang
+ * @since 2022-04-26
+ */
+@Api(tags = "公用开放跳转接口Controller")
+@RestController
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.open}/common")
+@Validated
+public class CommonOpenApiController {
+    private static final Logger log = LoggerFactory.getLogger(CommonOpenApiController.class);
+
+    @Resource
+    private BasicSchoolService basicSchoolService;
+
+    @Value("${teachcloud.print.loginUrl}")
+    String teachcloudLoginUrl;
+
+    @ApiOperation(value = "公用跳转接口")
+    @ApiResponses({@ApiResponse(code = 200, message = "返回消息", response = Result.class)})
+    @RequestMapping(value = "/authentication/teachcloud", method = RequestMethod.GET)
+    @Aac(auth = BOOL.FALSE)
+    public void authenticationTeachcloud(@ApiParam(value = "工号", required = true) @RequestParam String account,
+                                         @ApiParam(value = "学校code", required = true) @RequestParam String schoolCode,
+                                         @ApiParam(value = "返回url") @RequestParam(required = false) String returnUrl,
+                                         @ApiParam(value = "其它参数") @RequestParam(required = false) String params) throws IOException {
+        log.info("公用跳转接口进来了,account:{},schoolCode:{}", account, schoolCode);
+        Optional.ofNullable(teachcloudLoginUrl).orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("知学登录跳转地址不存在"));
+        Optional.ofNullable(account).orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("工号不存在"));
+        Optional.ofNullable(schoolCode).orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("学校code不存在"));
+
+        QueryWrapper<BasicSchool> basicSchoolQueryWrapper = new QueryWrapper<>();
+        basicSchoolQueryWrapper.lambda().eq(BasicSchool::getCode, schoolCode);
+        BasicSchool basicSchool = basicSchoolService.getOne(basicSchoolQueryWrapper);
+        Optional.ofNullable(basicSchool).orElseThrow(() -> ExceptionResultEnum.PARAMS_ERROR.exception("学校信息不存在"));
+
+        if (teachcloudLoginUrl.contains(SystemConstant.PATH_MATCH)) {
+            teachcloudLoginUrl = teachcloudLoginUrl.replace(SystemConstant.PATH_MATCH, basicSchool.getCode());
+        }
+
+        long timestamp = System.currentTimeMillis();
+        String path = teachcloudLoginUrl.substring(teachcloudLoginUrl.indexOf(SystemConstant.PATH_SUBSTR), teachcloudLoginUrl.length());
+        String signature = SignatureEntity.build(SignatureType.SECRET, SystemConstant.GET, path, timestamp, basicSchool.getAccessKey(), basicSchool.getAccessSecret());
+
+        StringJoiner stringJoiner = new StringJoiner("")
+                .add(teachcloudLoginUrl)
+                .add(SystemConstant.GET_UNKNOWN).add(SystemConstant.HEADER_TIME).add(SystemConstant.GET_EQUAL).add(String.valueOf(timestamp))
+                .add(SystemConstant.GET_SYMBOL).add(SystemConstant.SIGNATURE).add(SystemConstant.GET_EQUAL).add(signature)
+                .add(SystemConstant.GET_SYMBOL).add(SystemConstant.USER).add(SystemConstant.GET_EQUAL).add(account);
+
+        if (Objects.nonNull(returnUrl) && !Objects.equals(returnUrl, "")) {
+            stringJoiner = stringJoiner.add(SystemConstant.GET_SYMBOL).add(SystemConstant.RETURN_URL).add(SystemConstant.GET_EQUAL).add(returnUrl);
+        }
+        if (Objects.nonNull(params) && !Objects.equals(params, "")) {
+            String decodeJson = URLDecoder.decode(params, SystemConstant.CHARSET_NAME);
+            OpenParams openParams = JacksonUtil.readJson(decodeJson, OpenParams.class);
+            stringJoiner = stringJoiner.add(SystemConstant.GET_SYMBOL).add(SystemConstant.PARAMS).add(SystemConstant.GET_EQUAL).add(JacksonUtil.parseJson(openParams));
+        }
+        String redirectUrl = URLEncoder.encode(stringJoiner.toString(), SystemConstant.CHARSET);
+        log.info("path:{},timestamp:{},account:{},signature:{},redirectUrl:{},redirectUrl_urlencode:{}", path, timestamp, account, signature, stringJoiner.toString(), redirectUrl);
+
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setHeader("Access-Control-Allow-Origin", "*");
+        response.sendRedirect(redirectUrl);
+    }
+}

+ 13 - 0
teachcloud-exchange-common-api/src/test/java/com/qmth/teachcloud/exchange/common/api/TeachcloudExchangeCommonApiApplicationTests.java

@@ -0,0 +1,13 @@
+package com.qmth.teachcloud.exchange.common.api;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TeachcloudExchangeCommonApiApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}

+ 33 - 0
teachcloud-exchange-common/.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 119 - 0
teachcloud-exchange-common/pom.xml

@@ -0,0 +1,119 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.qmth.teachcloud.exchange.common</groupId>
+    <artifactId>teachcloud-exchange-common</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+
+    <parent>
+        <groupId>com.qmth.teachcloud.exchange.service</groupId>
+        <artifactId>teachcloud-exchange-service</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>starter-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>core-fss</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>tools-device</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>core-solar</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>core-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>core-models</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>core-retrofit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-text</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>data-mybatis-plus</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 22 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/annotation/ApiJsonObject.java

@@ -0,0 +1,22 @@
+package com.qmth.teachcloud.exchange.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @Description: swagger2 map参数说明注解
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/23
+ */
+@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ApiJsonObject {
+
+    ApiJsonProperty[] value(); //对象属性值
+
+    String name();  //对象名称
+}

+ 28 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/annotation/ApiJsonProperty.java

@@ -0,0 +1,28 @@
+package com.qmth.teachcloud.exchange.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @Description: swagger2 map参数说明属性注解
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/23
+ */
+@Target(ElementType.ANNOTATION_TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ApiJsonProperty {
+
+    String key();  //key
+
+    String example() default "";
+
+    String type() default "string";
+
+    String description() default "";
+
+    boolean required() default false;
+}

+ 100 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/BaseEntity.java

@@ -0,0 +1,100 @@
+package com.qmth.teachcloud.exchange.common.base;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 基础entity
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/12/6
+ */
+public class BaseEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id")
+    private Long id;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("create_id")
+    @ApiModelProperty(value = "创建人")
+    private Long createId;
+
+    @TableField(value = "create_time", fill = FieldFill.INSERT)//新增执行
+    @ApiModelProperty(value = "创建时间")
+    private Long createTime;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField("update_id")
+    @ApiModelProperty(value = "修改人")
+    private Long updateId;
+
+    @TableField(value = "update_Time", fill = FieldFill.INSERT_UPDATE) // 新增和更新执行
+    @ApiModelProperty(value = "修改时间")
+    private Long updateTime;
+
+    public void insertInfo(Long userId) {
+        this.id = SystemConstant.getDbUuid();
+        this.createId = userId;
+        this.createTime = System.currentTimeMillis();
+    }
+
+    public void updateInfo(Long userId) {
+        this.updateId = userId;
+        this.updateTime = System.currentTimeMillis();
+    }
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getCreateId() {
+        return createId;
+    }
+
+    public void setCreateId(Long createId) {
+        this.createId = createId;
+    }
+
+    public Long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Long createTime) {
+        this.createTime = createTime;
+    }
+
+    public Long getUpdateId() {
+        return updateId;
+    }
+
+    public void setUpdateId(Long updateId) {
+        this.updateId = updateId;
+    }
+
+    public Long getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Long updateTime) {
+        this.updateTime = updateTime;
+    }
+}

+ 64 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/BaseListPage.java

@@ -0,0 +1,64 @@
+package com.qmth.teachcloud.exchange.common.base;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @Description: 分页封装
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/7
+ */
+public class BaseListPage<T> implements Serializable {
+    @ApiModelProperty(value = "当前第几页(从1开始)")
+    private int current;
+
+    @ApiModelProperty(value = "每页条数")
+    private int size;
+
+    @ApiModelProperty(value = "总条数")
+    private int total;
+
+    @ApiModelProperty(value = "内容列表")
+    private List<T> records;
+
+    public BaseListPage(List<T> records, long current, long size, long total) {
+        this.current = (int) current;
+        this.size = (int) size;
+        this.total = (int) total;
+        this.records = records;
+    }
+
+    public int getCurrent() {
+        return current;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public int getTotal() {
+        return total;
+    }
+
+    public List<T> getRecords() {
+        return records;
+    }
+
+    /**
+     * 总页数
+     */
+    public int getPages() {
+        if (getSize() == 0) {
+            return 0;
+        }
+        int pages = getTotal() / getSize();
+        if (getTotal() % getSize() != 0) {
+            pages++;
+        }
+        return pages;
+    }
+}

+ 54 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/BasePage.java

@@ -0,0 +1,54 @@
+package com.qmth.teachcloud.exchange.common.base;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description: 分页封装
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/8/7
+ */
+public class BasePage {
+
+    private Long schoolId;
+
+    @ApiModelProperty(value = "分页页码")
+    private Integer pageNumber;
+
+    @ApiModelProperty(value = "分页数")
+    private Integer pageSize;
+
+    public BasePage(Integer pageNumber, Integer pageSize) {
+        this.pageNumber = (int) pageNumber;
+        this.pageSize = pageSize;
+    }
+
+    public BasePage() {
+
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public Integer getPageNumber() {
+        return pageNumber;
+    }
+
+    public void setPageNumber(Integer pageNumber) {
+        this.pageNumber = pageNumber;
+    }
+
+    public Integer getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize) {
+        this.pageSize = pageSize;
+    }
+}

+ 44 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/CustomBaseMapper.java

@@ -0,0 +1,44 @@
+package com.qmth.teachcloud.exchange.common.base;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * @Description: 自定义mapper
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public interface CustomBaseMapper<T> extends BaseMapper<T> {
+
+    /**
+     * 自定义批量插入
+     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
+     *
+     * @param list
+     * @return
+     */
+    int insertBatch(@Param("collection") Collection<? extends Serializable> list);
+
+    /**
+     * 自定义批量更新
+     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
+     *
+     * @param list
+     * @return
+     */
+    int updateBatch(@Param("collection") Collection<? extends Serializable> list);
+
+    /**
+     * 自定义批量新增或更新
+     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
+     *
+     * @param list
+     * @return
+     */
+    int insertOrUpdateBath(@Param("collection") Collection<? extends Serializable> list);
+}

+ 32 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/CustomizedSqlInjector.java

@@ -0,0 +1,32 @@
+package com.qmth.teachcloud.exchange.common.base;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
+import com.qmth.teachcloud.exchange.common.base.method.InsertBatch;
+import com.qmth.teachcloud.exchange.common.base.method.InsertOrUpdateBath;
+import com.qmth.teachcloud.exchange.common.base.method.UpdateBatch;
+
+import java.util.List;
+
+/**
+ * @Description: 自定义批量sql插入、更新
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class CustomizedSqlInjector extends DefaultSqlInjector {
+
+    /**
+     * 如果只需增加方法,保留mybatis plus自带方法,
+     * 可以先获取super.getMethodList(),再添加add
+     */
+    @Override
+    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
+        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
+        methodList.add(new InsertBatch());
+        methodList.add(new UpdateBatch());
+        methodList.add(new InsertOrUpdateBath());
+        return methodList;
+    }
+}

+ 63 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/method/InsertBatch.java

@@ -0,0 +1,63 @@
+package com.qmth.teachcloud.exchange.common.base.method;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @Description: 自定义批量插入
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class InsertBatch extends AbstractMethod {
+    private final static Logger log = LoggerFactory.getLogger(InsertBatch.class);
+
+    /**
+     * insert into user(id, name, age) values (1, "a", 17), (2, "b", 18);
+     * <script>
+     * insert into user(id, name, age) values
+     * <foreach collection="collection" item="item" index="index" open="(" separator="),(" close=")">
+     * #{item.id}, #{item.name}, #{item.age}
+     * </foreach>
+     * </script>
+     */
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        final String sql = "<script>insert into %s %s values %s</script>";
+        final String fieldSql = prepareFieldSql(tableInfo);
+        final String valueSql = prepareValuesSql(tableInfo);
+        final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
+        log.debug("sqlResult----->{}", sqlResult);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
+        // 第三个参数必须和RootMapper的自定义方法名一致
+        return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
+    }
+
+    private String prepareFieldSql(TableInfo tableInfo) {
+        StringBuilder fieldSql = new StringBuilder();
+        fieldSql.append(tableInfo.getKeyColumn()).append(",");
+        tableInfo.getFieldList().forEach(x -> {
+            fieldSql.append(x.getColumn()).append(",");
+        });
+        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
+        fieldSql.insert(0, "(");
+        fieldSql.append(")");
+        return fieldSql.toString();
+    }
+
+    private String prepareValuesSql(TableInfo tableInfo) {
+        final StringBuilder valueSql = new StringBuilder();
+        valueSql.append("<foreach collection=\"collection\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
+        valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
+        tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
+        valueSql.delete(valueSql.length() - 1, valueSql.length());
+        valueSql.append("</foreach>");
+        return valueSql.toString();
+    }
+}

+ 85 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/method/InsertOrUpdateBath.java

@@ -0,0 +1,85 @@
+package com.qmth.teachcloud.exchange.common.base.method;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+/**
+ * @Description: 自定义插入或更新
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class InsertOrUpdateBath extends AbstractMethod {
+    private final static Logger log = LoggerFactory.getLogger(InsertOrUpdateBath.class);
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        final String sql = "<script>insert into %s %s values %s ON DUPLICATE KEY UPDATE %s</script>";
+        final String tableName = tableInfo.getTableName();
+        final String filedSql = prepareFieldSql(tableInfo);
+        final String modelValuesSql = prepareModelValuesSql(tableInfo);
+        final String duplicateKeySql = prepareDuplicateKeySql(tableInfo);
+        final String sqlResult = String.format(sql, tableName, filedSql, modelValuesSql, duplicateKeySql);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
+        return this.addInsertMappedStatement(mapperClass, modelClass, "insertOrUpdateBath", sqlSource, new NoKeyGenerator(), null, null);
+    }
+
+    /**
+     * 准备ON DUPLICATE KEY UPDATE sql
+     *
+     * @param tableInfo
+     * @return
+     */
+    private String prepareDuplicateKeySql(TableInfo tableInfo) {
+        final StringBuilder duplicateKeySql = new StringBuilder();
+        if (!StringUtils.isEmpty(tableInfo.getKeyColumn())) {
+            duplicateKeySql.append(tableInfo.getKeyColumn()).append("=values(").append(tableInfo.getKeyColumn()).append("),");
+        }
+
+        tableInfo.getFieldList().forEach(x -> {
+            duplicateKeySql.append(x.getColumn())
+                    .append("=values(")
+                    .append(x.getColumn())
+                    .append("),");
+        });
+        duplicateKeySql.delete(duplicateKeySql.length() - 1, duplicateKeySql.length());
+        return duplicateKeySql.toString();
+    }
+
+    /**
+     * 准备属性名
+     *
+     * @param tableInfo
+     * @return
+     */
+    private String prepareFieldSql(TableInfo tableInfo) {
+        StringBuilder fieldSql = new StringBuilder();
+        fieldSql.append(tableInfo.getKeyColumn()).append(",");
+        tableInfo.getFieldList().forEach(x -> {
+            fieldSql.append(x.getColumn()).append(",");
+        });
+        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
+        fieldSql.insert(0, "(");
+        fieldSql.append(")");
+        return fieldSql.toString();
+    }
+
+    private String prepareModelValuesSql(TableInfo tableInfo) {
+        final StringBuilder valueSql = new StringBuilder();
+        valueSql.append("<foreach collection=\"collection\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
+        if (!StringUtils.isEmpty(tableInfo.getKeyProperty())) {
+            valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
+        }
+        tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
+        valueSql.delete(valueSql.length() - 1, valueSql.length());
+        valueSql.append("</foreach>");
+        return valueSql.toString();
+    }
+}

+ 30 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/base/method/UpdateBatch.java

@@ -0,0 +1,30 @@
+package com.qmth.teachcloud.exchange.common.base.method;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @Description: 自定义更新
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/11
+ */
+public class UpdateBatch extends AbstractMethod {
+    private final static Logger log = LoggerFactory.getLogger(UpdateBatch.class);
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        String sql = "<script>\n<foreach collection=\"collection\" item=\"item\" separator=\";\">\nupdate %s %s where %s=#{%s} %s\n</foreach>\n</script>";
+        String additional = tableInfo.isWithVersion() ? tableInfo.getVersionFieldInfo().getVersionOli("item", "item.") : "" + tableInfo.getLogicDeleteSql(true, true);
+        String setSql = sqlSet(tableInfo.isWithLogicDelete(), false, tableInfo, false, "item", "item.");
+        String sqlResult = String.format(sql, tableInfo.getTableName(), setSql, tableInfo.getKeyColumn(), "item." + tableInfo.getKeyProperty(), additional);
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
+        // 第三个参数必须和RootMapper的自定义方法名一致
+        return this.addUpdateMappedStatement(mapperClass, modelClass, "updateBatch", sqlSource);
+    }
+}

+ 37 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/bean/dto/AuthOrgInfoDto.java

@@ -0,0 +1,37 @@
+package com.qmth.teachcloud.exchange.common.bean.dto;
+
+import com.qmth.boot.core.solar.model.AppControl;
+import com.qmth.boot.core.solar.model.OrgInfo;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 鉴权org dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/9/2
+ */
+public class AuthOrgInfoDto implements Serializable {
+
+    OrgInfo orgInfo;
+
+    AppControl control;
+
+    public AuthOrgInfoDto() {
+
+    }
+
+    public AuthOrgInfoDto(OrgInfo orgInfo, AppControl control) {
+        this.orgInfo = orgInfo;
+        this.control = control;
+    }
+
+    public AppControl getControl() {
+        return control;
+    }
+
+    public void setControl(AppControl control) {
+        this.control = control;
+    }
+}

+ 48 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/bean/params/OpenParams.java

@@ -0,0 +1,48 @@
+package com.qmth.teachcloud.exchange.common.bean.params;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 开放接口参数
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/10/20
+ */
+public class OpenParams implements Serializable {
+
+    @ApiModelProperty("姓名")
+    private String name;
+
+    @ApiModelProperty("角色名")
+    private String roleName;
+
+    @ApiModelProperty("机构名")
+    private String orgName;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public String getOrgName() {
+        return orgName;
+    }
+
+    public void setOrgName(String orgName) {
+        this.orgName = orgName;
+    }
+}

+ 63 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/config/DictionaryConfig.java

@@ -0,0 +1,63 @@
+package com.qmth.teachcloud.exchange.common.config;
+
+import com.qmth.teachcloud.exchange.common.domain.*;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description: 数据字典
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/10
+ */
+@Configuration
+public class DictionaryConfig {
+
+    /**
+     * 模块前缀
+     *
+     * @return
+     */
+    @Bean
+    @ConfigurationProperties(prefix = "prefix.url")
+    public PrefixUrlDomain prefixUrlDomain() {
+        return new PrefixUrlDomain();
+    }
+
+    /**
+     * 系统配置
+     *
+     * @return
+     */
+    @Bean
+    @ConfigurationProperties(prefix = "sys.config")
+    public SysDomain sysDomain() {
+        return new SysDomain();
+    }
+
+    @Bean
+    @ConfigurationProperties(prefix = "com.qmth.fss.public", ignoreUnknownFields = false)
+    public FssPublicDomain fssPublicDomain() {
+        return new FssPublicDomain();
+    }
+
+    @Bean
+    @ConfigurationProperties(prefix = "com.qmth.fss.private", ignoreUnknownFields = false)
+    public FssPrivateDomain fssPrivateDomain() {
+        return new FssPrivateDomain();
+    }
+
+    @Bean
+    @ConfigurationProperties(prefix = "com.qmth.fss.localpdf", ignoreUnknownFields = false)
+    public FssLocalPdfDomain fssLocalPdfDomain() {
+        return new FssLocalPdfDomain();
+    }
+
+    @Bean
+    @ConfigurationProperties(prefix = "com.qmth.fss.localfile", ignoreUnknownFields = false)
+    public FssLocalFileDomain fssLocalFileDomain() {
+        return new FssLocalFileDomain();
+    }
+}

+ 69 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/contant/SpringContextHolder.java

@@ -0,0 +1,69 @@
+package com.qmth.teachcloud.exchange.common.contant;
+
+import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description: spring上下文获取工具
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/10/11
+ */
+@Component
+public class SpringContextHolder implements ApplicationContextAware {
+    /**
+     * 上下文对象实例
+     */
+    private volatile static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringContextHolder.applicationContext = applicationContext;
+    }
+
+    /**
+     * 获取application上下文对象
+     *
+     * @return
+     */
+    public static ApplicationContext getApplicationContext() {
+        assertApplicationContext();
+        return applicationContext;
+    }
+
+    /**
+     * 通过name获取bean
+     *
+     * @param beanName
+     * @return
+     */
+//    @SuppressWarnings("unchecked")//忽略警告
+    public static <T> T getBean(String beanName) {
+        assertApplicationContext();
+        return (T) applicationContext.getBean(beanName);
+    }
+
+    /**
+     * 通过class获取bean
+     *
+     * @param requiredType
+     * @return
+     */
+    public static <T> T getBean(Class<T> requiredType) {
+        assertApplicationContext();
+        return (T) applicationContext.getBean(requiredType);
+    }
+
+    /**
+     * 获取实例
+     */
+    private static void assertApplicationContext() {
+        if (SpringContextHolder.applicationContext == null) {
+            throw ExceptionResultEnum.ERROR.exception("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");
+        }
+    }
+}

+ 141 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/contant/SystemConstant.java

@@ -0,0 +1,141 @@
+package com.qmth.teachcloud.exchange.common.contant;
+
+import com.qmth.boot.core.uid.service.UidService;
+import com.qmth.teachcloud.exchange.common.util.Base64Util;
+import org.apache.commons.io.IOUtils;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * @Description: 系统常量
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/10/11
+ */
+public class SystemConstant {
+
+    /**
+     * 系统常量
+     */
+    public static final String SYS_CONFIG_KEY_CHARSETS = "sys.txt.charset";
+    public static final String CHARSET_NAME = "UTF-8";
+    //    public static final String CHARSET_GB2312 = "gb2312";
+    public static final String CHARSET_GBK = "gbk";
+    public static final Charset CHARSET = Charset.forName(CHARSET_NAME);
+    public static final String SUCCESS = "success";
+    public static final String UPDATE_TIME = "updateTime";
+    public static final String SESSION = "session:";
+    public static final String USER = "account";
+    public static final String SCHOOL_ID = "schoolId";
+    public static final String SCHOOL = "school";
+    public static final String SCHOOL_CODE = "schoolCode";
+    public static final String RETURN_URL = "returnUrl";
+    public static final String PARAMS = "params";
+    public static final String ORG = "org";
+    public static final String MD5 = "MD5";
+    public static final String ID = "id";
+    public static final String SIGNATURE = "signature";
+    public static final String GET = "get";
+    public static final String GET_UNKNOWN = "?";
+    public static final String GET_SYMBOL = "&";
+    public static final String GET_EQUAL = "=";
+    public static final String PATH_MATCH = "*";
+    public static final String PATH_SUBSTR = "/#";
+    public static final String JUMP_API_URL = "/api/admin/open/common/authentication/teachcloud";
+
+    /**
+     * 缓存配置
+     */
+    public static final String SCHOOL_CACHE = "school:cache";
+    public static final String SCHOOL_CODE_CACHE = "school:code:cache";
+    public static final String AUTH_INFO_CACHE = "auth:info:cache";
+
+    /**
+     * 鉴权
+     */
+    public static final String HEADER_AUTHORIZATION = "Authorization";
+    public static final String HEADER_TIME = "time";
+    public static final String HEADER_PLATFORM = "platform";
+    public static final String HEADER_DEVICE_ID = "deviceId";
+    public static final String TOKEN = "token";
+    public static final String SIGN = "sign";
+
+    /**
+     * redis
+     */
+    public static final int DEFAULT_SESSION_EXPIRE = 1;//过期时间1天
+//    public static final long REDIS_DEFAULT_EXPIRE_TIME = 24 * 60L * 60L;//过期时间24小时
+
+    /**
+     * aes相关
+     */
+    public static final String AES = "AES";
+    public static final String AES_MODE_PKCS5 = "AES/CBC/PKCS5Padding";//用这个模式,规则必须为16位
+    public static final String AES_MODE_PKCS7 = "AES/CBC/PKCS7Padding";//用这个模式,规则必须为16位
+    public static final String AES_RULE = "1234567890123456";//aes密钥
+
+    /**
+     * 线程池配置
+     */
+    public static final String THREAD_POOL_NAME = "taskThreadPool";
+    //    public static final int THREAD_POOL_CORE_POOL_SIZE = 5;
+//    public static final int THREAD_POOL_MAX_POOL_SIZE = 100;
+    public static final int THREAD_POOL_KEEP_ALIVE_SECONDS = 10;
+    public static final int THREAD_POOL_QUEUE_CAPACITY = 500;
+
+    public static final String LOG_ERROR = "请求出错:{}";
+
+    /**
+     * http设置
+     */
+    public static final int CONNECT_TIME_OUT = 1000 * 60 * 2;//请求超时
+    public static final int SOCKET_CONNECT_TIME_OUT = 1000 * 60 * 30;//读取数据超时
+
+    /**
+     * 获取数据库uuid
+     *
+     * @return
+     */
+    public static Long getDbUuid() {
+        UidService uidservice = SpringContextHolder.getBean(UidService.class);
+        return uidservice.getId();
+    }
+
+    /**
+     * 获取全局uuid
+     *
+     * @return
+     */
+    public static String getUuid() {
+        return String.valueOf(UUID.randomUUID()).replaceAll("-", "");
+    }
+
+    /**
+     * 图片转换
+     *
+     * @param imgBase64
+     * @param filePath
+     * @throws IOException
+     */
+    public static void base64ToImage(String imgBase64, String filePath) throws IOException {
+        OutputStream out = null;
+        try {
+            byte[] b = Base64Util.decode(imgBase64);
+            out = new FileOutputStream(filePath);
+            IOUtils.write(b, out);
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (Objects.nonNull(out)) {
+                out.flush();
+                out.close();
+            }
+        }
+    }
+}

+ 28 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssLocalFileDomain.java

@@ -0,0 +1,28 @@
+package com.qmth.teachcloud.exchange.common.domain;
+
+/**
+ * @Description:
+ * @Author: CaoZixuan
+ * @Date:
+ */
+public class FssLocalFileDomain {
+    private String config;
+
+    private String server;
+
+    public String getConfig() {
+        return config;
+    }
+
+    public void setConfig(String config) {
+        this.config = config;
+    }
+
+    public String getServer() {
+        return server;
+    }
+
+    public void setServer(String server) {
+        this.server = server;
+    }
+}

+ 28 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssLocalPdfDomain.java

@@ -0,0 +1,28 @@
+package com.qmth.teachcloud.exchange.common.domain;
+
+/**
+ * @Description:
+ * @Author: CaoZixuan
+ * @Date:
+ */
+public class FssLocalPdfDomain {
+    private String config;
+
+    private String server;
+
+    public String getConfig() {
+        return config;
+    }
+
+    public void setConfig(String config) {
+        this.config = config;
+    }
+
+    public String getServer() {
+        return server;
+    }
+
+    public void setServer(String server) {
+        this.server = server;
+    }
+}

+ 34 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssPrivateDomain.java

@@ -0,0 +1,34 @@
+package com.qmth.teachcloud.exchange.common.domain;
+
+/**
+ * @Description: 文件存储中心配置-私有
+ * @Author: CaoZixuan
+ * @Date: 2021-08-18
+ */
+public class FssPrivateDomain {
+    private static final long serialVersionUID = 7510626406622200443L;
+
+    private String config;
+
+    private String server;
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public String getConfig() {
+        return config;
+    }
+
+    public void setConfig(String config) {
+        this.config = config;
+    }
+
+    public String getServer() {
+        return server;
+    }
+
+    public void setServer(String server) {
+        this.server = server;
+    }
+}

+ 34 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/FssPublicDomain.java

@@ -0,0 +1,34 @@
+package com.qmth.teachcloud.exchange.common.domain;
+
+/**
+ * @Description: 文件存储中心配置-公有
+ * @Author: CaoZixuan
+ * @Date: 2021-08-18
+ */
+public class FssPublicDomain {
+    private static final long serialVersionUID = 7510626406622200443L;
+
+    private String config;
+
+    private String server;
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public String getConfig() {
+        return config;
+    }
+
+    public void setConfig(String config) {
+        this.config = config;
+    }
+
+    public String getServer() {
+        return server;
+    }
+
+    public void setServer(String server) {
+        this.server = server;
+    }
+}

+ 23 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/PrefixUrlDomain.java

@@ -0,0 +1,23 @@
+package com.qmth.teachcloud.exchange.common.domain;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 模块前缀
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/10
+ */
+public class PrefixUrlDomain implements Serializable {
+
+    String open;
+
+    public String getOpen() {
+        return open;
+    }
+
+    public void setOpen(String open) {
+        this.open = open;
+    }
+}

+ 65 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/domain/SysDomain.java

@@ -0,0 +1,65 @@
+package com.qmth.teachcloud.exchange.common.domain;
+
+import java.io.Serializable;
+import java.time.Duration;
+import java.util.List;
+
+/**
+ * @Description: 系统配置
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/10
+ */
+public class SysDomain implements Serializable {
+
+    boolean oss;
+
+    List attachmentType;
+
+    Integer attachmentLength;
+
+    Double attachmentSize;
+
+    String serverUpload;
+
+    public boolean isOss() {
+        return oss;
+    }
+
+    public void setOss(boolean oss) {
+        this.oss = oss;
+    }
+
+    public List getAttachmentType() {
+        return attachmentType;
+    }
+
+    public void setAttachmentType(List attachmentType) {
+        this.attachmentType = attachmentType;
+    }
+
+    public Integer getAttachmentLength() {
+        return attachmentLength;
+    }
+
+    public void setAttachmentLength(Integer attachmentLength) {
+        this.attachmentLength = attachmentLength;
+    }
+
+    public Double getAttachmentSize() {
+        return attachmentSize;
+    }
+
+    public void setAttachmentSize(Double attachmentSize) {
+        this.attachmentSize = attachmentSize;
+    }
+
+    public String getServerUpload() {
+        return serverUpload;
+    }
+
+    public void setServerUpload(String serverUpload) {
+        this.serverUpload = serverUpload;
+    }
+}

+ 143 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/entity/BasicSchool.java

@@ -0,0 +1,143 @@
+package com.qmth.teachcloud.exchange.common.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.qmth.teachcloud.exchange.common.base.BaseEntity;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * <p>
+ * 学校表
+ * </p>
+ *
+ * @author xf
+ * @since 2021-03-23
+ */
+@TableName("basic_school")
+public class BasicSchool extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String code;
+
+    private String name;
+
+    @ApiModelProperty(value = "是否启用,0:停用,1:启用")
+    private Boolean enable = true;
+
+    @TableField("access_key")
+    private String accessKey;
+
+    @TableField("access_secret")
+    private String accessSecret;
+
+    private String remark;
+
+    @ApiModelProperty(value = "学校logo")
+    @TableField(value = "logo")
+    private String logo;
+
+    public BasicSchool() {
+
+    }
+
+    public BasicSchool(Long id, String code, String name, String accessKey, String accessSecret) {
+        this.code = code;
+        this.name = name;
+        this.accessKey = accessKey;
+        this.accessSecret = accessSecret;
+        setId(id);
+        this.enable = true;
+    }
+
+    public BasicSchool(String code, String name, String accessKey, String accessSecret, String logo) {
+        this.code = code;
+        this.name = name;
+        this.accessKey = accessKey;
+        this.accessSecret = accessSecret;
+        this.logo = logo;
+        setId(SystemConstant.getDbUuid());
+        this.enable = true;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        BasicSchool that = (BasicSchool) o;
+        return code.equals(that.code) && name.equals(that.name) && enable.equals(that.enable) && accessKey.equals(that.accessKey) && accessSecret.equals(that.accessSecret) && remark.equals(that.remark) && logo.equals(that.logo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(code, name, enable, accessKey, accessSecret, remark, logo);
+    }
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public String getLogo() {
+        return logo;
+    }
+
+    public void setLogo(String logo) {
+        this.logo = logo;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Boolean getEnable() {
+        return enable;
+    }
+
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
+
+    public String getAccessSecret() {
+        return accessSecret;
+    }
+
+    public void setAccessSecret(String accessSecret) {
+        this.accessSecret = accessSecret;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}

+ 132 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/entity/TSAuth.java

@@ -0,0 +1,132 @@
+package com.qmth.teachcloud.exchange.common.entity;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.exchange.common.base.BaseEntity;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.enums.AuthEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 激活授权配置表
+ * </p>
+ *
+ * @author wangliang
+ * @since 2022-04-26
+ */
+@ApiModel(value = "TSAuth对象", description = "激活授权配置表")
+public class TSAuth extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "学校id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long schoolId;
+
+    @ApiModelProperty(value = "accessKey")
+    private String accessKey;
+
+    @ApiModelProperty(value = "accessSecret")
+    private String accessSecret;
+
+    @ApiModelProperty(value = "离线授权证书")
+    private String description;
+
+    @ApiModelProperty(value = "授权类型")
+    private AuthEnum type;
+
+    @ApiModelProperty(value = "过期时间")
+    private Long expireTime;
+
+    @ApiModelProperty(value = "文件数据")
+    private byte[] file;
+
+    public TSAuth() {
+
+    }
+
+    public TSAuth(Long schoolId, String accessKey, String accessSecret, AuthEnum type, Long expireTime) {
+        setId(SystemConstant.getDbUuid());
+        this.schoolId = schoolId;
+        this.accessKey = accessKey;
+        this.accessSecret = accessSecret;
+        this.type = type;
+        this.expireTime = expireTime;
+    }
+
+    public TSAuth(Long schoolId, String description, AuthEnum type, Long expireTime) {
+        setId(SystemConstant.getDbUuid());
+        this.schoolId = schoolId;
+        this.description = description;
+        this.type = type;
+        this.expireTime = expireTime;
+    }
+
+    public TSAuth(Long schoolId, byte[] file, AuthEnum type, Long expireTime) {
+        setId(SystemConstant.getDbUuid());
+        this.schoolId = schoolId;
+        this.file = file;
+        this.type = type;
+        this.expireTime = expireTime;
+    }
+
+    public byte[] getFile() {
+        return file;
+    }
+
+    public void setFile(byte[] file) {
+        this.file = file;
+    }
+
+    public Long getExpireTime() {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime) {
+        this.expireTime = expireTime;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
+
+    public String getAccessSecret() {
+        return accessSecret;
+    }
+
+    public void setAccessSecret(String accessSecret) {
+        this.accessSecret = accessSecret;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public AuthEnum getType() {
+        return type;
+    }
+
+    public void setType(AuthEnum type) {
+        this.type = type;
+    }
+}

+ 44 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/AppSourceEnum.java

@@ -0,0 +1,44 @@
+package com.qmth.teachcloud.exchange.common.enums;
+
+import java.util.Objects;
+
+/**
+ * @Description: app应用来源
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/6/29
+ */
+public enum AppSourceEnum {
+
+    SYSTEM("自身应用系统"),
+
+    XJTU_THIRD("西安交通大学"),
+
+    PRINT_THIRD("知学知考-分布式印刷");
+
+    private String title;
+
+    private AppSourceEnum(String title) {
+        this.title = title;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param title
+     * @return
+     */
+    public static String convertToName(String title) {
+        for (AppSourceEnum e : AppSourceEnum.values()) {
+            if (Objects.equals(title, e.getTitle())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+}

+ 42 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/AuthEnum.java

@@ -0,0 +1,42 @@
+package com.qmth.teachcloud.exchange.common.enums;
+
+import java.util.Objects;
+
+/**
+ * @Description: 授权配置类型
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/4/26
+ */
+public enum AuthEnum {
+
+    ON_LINE("在线激活"),
+
+    OFF_LINE("离线激活");
+
+    AuthEnum(String title) {
+        this.title = title;
+    }
+
+    private String title;
+
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param value
+     * @return
+     */
+    public static String convertToName(String value) {
+        for (AuthEnum e : AuthEnum.values()) {
+            if (Objects.equals(value.trim(), e.getTitle())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+}

+ 101 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/ExceptionResultEnum.java

@@ -0,0 +1,101 @@
+package com.qmth.teachcloud.exchange.common.enums;
+
+import com.qmth.boot.api.exception.ApiException;
+import org.springframework.http.HttpStatus;
+
+/**
+ * @Description: 自定义异常消息枚举
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/10/11
+ */
+public enum ExceptionResultEnum {
+    /**
+     * 系统预置
+     */
+    SUCCESS(HttpStatus.OK, 200, "成功"),
+
+    ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000001, "失败"),
+
+    PARAMS_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000002, "参数错误"),
+
+    SQL_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000003, "sql异常:"),
+
+    INVOCATIONTARGET_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000004, "反射异常:"),
+
+    SERVICE_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR, 5000005, "服务器错误"),
+
+    UNKONW_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000006, "未知错误:请联系管理员"),
+
+    EXCEPTION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000007, "系统异常:请联系管理员"),
+
+    /**
+     * 500
+     */
+    NOT_LOGIN(HttpStatus.INTERNAL_SERVER_ERROR, 5000012, "请先登录"),
+
+    MD5_EMPTY(HttpStatus.INTERNAL_SERVER_ERROR, 5000015, "md5为空"),
+
+    /**
+     * 401
+     */
+    PLATFORM_INVALID(HttpStatus.UNAUTHORIZED, 4010001, "platform无效"),
+
+    DEVICE_ID_INVALID(HttpStatus.UNAUTHORIZED, 4010002, "deviceId无效"),
+
+    TOKEN_INVALID(HttpStatus.UNAUTHORIZED, 4010003, "token无效"),
+
+    TIME_INVALID(HttpStatus.UNAUTHORIZED, 4010004, "time无效"),
+
+    AUTHORIZATION_INVALID(HttpStatus.UNAUTHORIZED, 4010005, "authorization无效"),
+
+    AUTHORIZATION_ERROR(HttpStatus.UNAUTHORIZED, 4010006, "签名验证失败"),
+
+    UN_AUTHORIZATION(HttpStatus.UNAUTHORIZED, 4010007, "没有权限"),
+
+    ROLE_ENABLE_AUTHORIZATION(HttpStatus.UNAUTHORIZED, 4010008, "角色被禁用或没有权限"),
+
+    AUTH_INFO_ERROR(HttpStatus.UNAUTHORIZED, 4010009, "系统授权信息已过期,请联系系统管理员激活!"),
+
+    SIGN_INVALID(HttpStatus.UNAUTHORIZED, 4010010, "签名无效"),
+
+    /**
+     * 404
+     */
+    NOT_FOUND(HttpStatus.NOT_FOUND, 4040003, "请求地址错误");
+
+    private HttpStatus status;
+    private int code;
+    private String message;
+
+    private ExceptionResultEnum(HttpStatus status, int code, String message) {
+        this.status = status;
+        this.code = code;
+        this.message = message;
+    }
+
+    public HttpStatus getStatus() {
+        return status;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public ApiException exception() {
+        return new ApiException(status, code, message, message);
+    }
+
+    public ApiException exception(int code, String message) {
+        return new ApiException(status, code, message, message);
+    }
+
+    public ApiException exception(String message) {
+        return new ApiException(status, code, message, message);
+    }
+}

+ 27 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/LocalCatalogEnum.java

@@ -0,0 +1,27 @@
+package com.qmth.teachcloud.exchange.common.enums;
+
+/**
+ * @Description: 本地文件目录枚举
+ * @Author: CaoZixuan
+ * @Date: 2022-08-11
+ */
+public enum LocalCatalogEnum {
+    LOCAL_FILE("localfile","本地文件"),
+    LOCAL_PDF("localpdf","本地pdf")
+    ;
+    private final String type;
+    private final String desc;
+
+    LocalCatalogEnum(String type, String desc) {
+        this.type = type;
+        this.desc = desc;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 76 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/enums/UploadFileEnum.java

@@ -0,0 +1,76 @@
+package com.qmth.teachcloud.exchange.common.enums;
+
+import java.util.Objects;
+
+/**
+ * @Description: 上传文件类型
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/15
+ */
+public enum UploadFileEnum {
+    /**
+     * 客户端
+     */
+    PAPER("paper","private"),
+    /**
+     * 系统相关
+     */
+    UPLOAD("upload","private"),
+    /**
+     * 导入导出
+     */
+    FILE("file","public"),
+
+    PDF("pdf","private"),
+
+    HTML("html","private");
+
+    private String title;
+    private String fssType;
+
+    UploadFileEnum(String title, String fssType) {
+        this.title = title;
+        this.fssType = fssType;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String getFssType() {
+        return fssType;
+    }
+
+
+    /**
+     * 状态转换 toName
+     *
+     * @param title
+     * @return
+     */
+    public static String convertToName(String title) {
+        for (UploadFileEnum e : UploadFileEnum.values()) {
+            if (Objects.equals(title, e.getTitle())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param title
+     * @return
+     */
+    public static String convertToFssType(String title) {
+        for (UploadFileEnum e : UploadFileEnum.values()) {
+            if (Objects.equals(title.toLowerCase(), e.getTitle())) {
+                return e.getFssType();
+            }
+        }
+        return null;
+    }
+}

+ 18 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/mapper/BasicSchoolMapper.java

@@ -0,0 +1,18 @@
+package com.qmth.teachcloud.exchange.common.mapper;
+
+import com.qmth.teachcloud.exchange.common.base.CustomBaseMapper;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 学校表 Mapper 接口
+ * </p>
+ *
+ * @author xf
+ * @since 2021-03-23
+ */
+public interface BasicSchoolMapper extends CustomBaseMapper<BasicSchool> {
+
+}

+ 16 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/mapper/TSAuthMapper.java

@@ -0,0 +1,16 @@
+package com.qmth.teachcloud.exchange.common.mapper;
+
+import com.qmth.teachcloud.exchange.common.base.CustomBaseMapper;
+import com.qmth.teachcloud.exchange.common.entity.TSAuth;
+
+/**
+ * <p>
+ * 激活授权配置表 Mapper 接口
+ * </p>
+ *
+ * @author wangliang
+ * @since 2022-04-26
+ */
+public interface TSAuthMapper extends CustomBaseMapper<TSAuth> {
+
+}

+ 52 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/AuthInfoService.java

@@ -0,0 +1,52 @@
+package com.qmth.teachcloud.exchange.common.service;
+
+import com.qmth.boot.core.solar.model.AppInfo;
+import com.qmth.teachcloud.exchange.common.enums.AuthEnum;
+
+/**
+ * @Description: 授权信息service
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/17
+ */
+public interface AuthInfoService {
+
+    /**
+     * 授权信息初始化
+     *
+     * @return
+     */
+    AppInfo appInfoInit();
+
+    /**
+     * app是否过期
+     *
+     * @param code
+     */
+    void appHasExpired(String code);
+
+    /**
+     * 离线激活
+     *
+     * @param licenseData
+     */
+    void updateLicense(byte[] licenseData) throws Exception;
+
+    /**
+     * 查询授权信息
+     *
+     * @return
+     */
+    Long selectAuthInfo();
+
+    /**
+     * 保存授权信息
+     *
+     * @param appInfo
+     * @param authEnum
+     * @param file
+     * @throws Exception
+     */
+    public void saveAuthInfo(AppInfo appInfo, AuthEnum authEnum, byte[] file) throws Exception;
+}

+ 16 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/BasicSchoolService.java

@@ -0,0 +1,16 @@
+package com.qmth.teachcloud.exchange.common.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+
+/**
+ * <p>
+ * 学校表 服务类
+ * </p>
+ *
+ * @author xf
+ * @since 2021-03-23
+ */
+public interface BasicSchoolService extends IService<BasicSchool> {
+
+}

+ 93 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/CommonCacheService.java

@@ -0,0 +1,93 @@
+package com.qmth.teachcloud.exchange.common.service;
+
+import com.qmth.teachcloud.exchange.common.bean.dto.AuthOrgInfoDto;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+
+/**
+ * @Description: 缓存操作service
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/3/25
+ */
+public interface CommonCacheService {
+
+    /**
+     * 添加学校缓存
+     *
+     * @param schoolId
+     * @return
+     */
+    public BasicSchool schoolCache(Long schoolId);
+
+    /**
+     * 添加学校缓存
+     *
+     * @param code
+     * @return
+     */
+    public BasicSchool schoolCache(String code);
+
+    /**
+     * 更新学校缓存
+     *
+     * @param schoolId
+     * @return
+     */
+    public BasicSchool updateSchoolCache(Long schoolId);
+
+    /**
+     * 更新学校缓存
+     *
+     * @param code
+     * @return
+     */
+    public BasicSchool updateSchoolCache(String code);
+
+    /**
+     * 删除学校缓存
+     *
+     * @param schoolId
+     */
+    public void removeSchoolCache(Long schoolId);
+
+    /**
+     * 删除学校缓存
+     */
+    public void removeSchoolIdCache();
+
+    /**
+     * 删除学校缓存
+     *
+     * @param code
+     */
+    public void removeSchoolCache(String code);
+
+    /**
+     * 删除学校缓存
+     */
+    public void removeSchoolCodeCache();
+
+    /**
+     * 添加鉴权缓存
+     *
+     * @param code
+     * @return
+     */
+    public AuthOrgInfoDto authInfoCache(String code);
+
+    /**
+     * 修改鉴权缓存
+     *
+     * @param code
+     * @return
+     */
+    public AuthOrgInfoDto updateAuthInfoCache(String code);
+
+    /**
+     * 删除鉴权缓存
+     *
+     * @param code
+     */
+    public void removeAuthInfoCache(String code);
+}

+ 16 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/TSAuthService.java

@@ -0,0 +1,16 @@
+package com.qmth.teachcloud.exchange.common.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.exchange.common.entity.TSAuth;
+
+/**
+ * <p>
+ * 激活授权配置表 服务类
+ * </p>
+ *
+ * @author wangliang
+ * @since 2022-04-26
+ */
+public interface TSAuthService extends IService<TSAuth> {
+
+}

+ 244 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/AuthInfoServiceImpl.java

@@ -0,0 +1,244 @@
+package com.qmth.teachcloud.exchange.common.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.boot.core.solar.config.SolarProperties;
+import com.qmth.boot.core.solar.model.AppInfo;
+import com.qmth.boot.core.solar.model.OrgInfo;
+import com.qmth.boot.core.solar.service.SolarService;
+import com.qmth.teachcloud.exchange.common.bean.dto.AuthOrgInfoDto;
+import com.qmth.teachcloud.exchange.common.config.DictionaryConfig;
+import com.qmth.teachcloud.exchange.common.contant.SpringContextHolder;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+import com.qmth.teachcloud.exchange.common.entity.TSAuth;
+import com.qmth.teachcloud.exchange.common.enums.AuthEnum;
+import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.exchange.common.enums.UploadFileEnum;
+import com.qmth.teachcloud.exchange.common.mapper.BasicSchoolMapper;
+import com.qmth.teachcloud.exchange.common.mapper.TSAuthMapper;
+import com.qmth.teachcloud.exchange.common.service.AuthInfoService;
+import com.qmth.teachcloud.exchange.common.service.BasicSchoolService;
+import com.qmth.teachcloud.exchange.common.service.CommonCacheService;
+import com.qmth.teachcloud.exchange.common.service.TSAuthService;
+import com.qmth.teachcloud.exchange.common.util.FileStoreUtil;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileInputStream;
+import java.time.LocalDateTime;
+import java.util.*;
+
+/**
+ * @Description: 授权信息service
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/5/17
+ */
+@Service
+public class AuthInfoServiceImpl implements AuthInfoService {
+    private final static Logger log = LoggerFactory.getLogger(AuthInfoServiceImpl.class);
+
+    @Resource
+    SolarProperties solarProperties;
+
+    @Resource
+    SolarService solarService;
+
+    @Resource
+    TSAuthService tsAuthService;
+
+    @Resource
+    TSAuthMapper tsAuthMapper;
+
+    @Resource
+    CommonCacheService commonCacheService;
+
+    @Resource
+    BasicSchoolService basicSchoolService;
+
+    @Resource
+    BasicSchoolMapper basicSchoolMapper;
+
+    @Resource
+    FileStoreUtil fileStoreUtil;
+
+    @Resource
+    DictionaryConfig dictionaryConfig;
+
+    /**
+     * 授权信息初始化
+     *
+     * @return
+     */
+    @Override
+    public AppInfo appInfoInit() {
+        AuthInfoService authInfoService = SpringContextHolder.getBean(AuthInfoService.class);
+        AppInfo appInfo = null;
+        try {
+            appInfo = solarService.getAppInfo();
+            if (Objects.nonNull(appInfo) && Objects.nonNull(solarProperties)) {
+                if (Objects.nonNull(solarProperties.getAccessKey())
+                        && !Objects.equals(solarProperties.getAccessKey().trim(), "")
+                        && Objects.nonNull(solarProperties.getAccessSecret())
+                        && !Objects.equals(solarProperties.getAccessSecret().trim(), "")) {//在线激活
+                    authInfoService.saveAuthInfo(appInfo, AuthEnum.ON_LINE, null);
+                } else if (Objects.nonNull(solarProperties.getLicense())
+                        && !Objects.equals(solarProperties.getLicense().trim(), "")) {//离线激活
+                    authInfoService.saveAuthInfo(appInfo, AuthEnum.OFF_LINE, null);
+                }
+            } else {
+                QueryWrapper<TSAuth> tsAuthQueryWrapper = new QueryWrapper<>();
+                tsAuthQueryWrapper.lambda().isNotNull(TSAuth::getFile);
+                List<TSAuth> tsAuthList = tsAuthService.list(tsAuthQueryWrapper);
+                if (!CollectionUtils.isEmpty(tsAuthList)) {
+                    for (TSAuth t : tsAuthList) {
+                        appInfo = solarService.update(t.getFile());
+                        authInfoService.saveAuthInfo(appInfo, AuthEnum.OFF_LINE, t.getFile());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return appInfo;
+    }
+
+    /**
+     * app是否过期
+     *
+     * @param code
+     * @return
+     */
+    @Override
+    public void appHasExpired(String code) {
+        if (Objects.nonNull(code)) {
+            AuthOrgInfoDto authOrgInfoDto = commonCacheService.authInfoCache(code);
+            if (Objects.isNull(authOrgInfoDto) || (Objects.nonNull(authOrgInfoDto) && authOrgInfoDto.getControl().hasExpired())) {
+                throw ExceptionResultEnum.AUTH_INFO_ERROR.exception();
+            }
+        }
+    }
+
+    /**
+     * 离线激活
+     *
+     * @param licenseData
+     */
+    @Override
+    public void updateLicense(byte[] licenseData) throws Exception {
+        AppInfo appInfo = solarService.update(licenseData);
+        if (Objects.isNull(appInfo)) {
+            throw ExceptionResultEnum.ERROR.exception("激活失败");
+        }
+        AuthInfoService authInfoService = SpringContextHolder.getBean(AuthInfoService.class);
+        authInfoService.saveAuthInfo(appInfo, AuthEnum.OFF_LINE, licenseData);
+    }
+
+    /**
+     * 查询授权信息
+     *
+     * @return
+     */
+    @Override
+    public Long selectAuthInfo() {
+        Long expireTime = null;
+        AppInfo appInfo = solarService.getAppInfo();
+        if (Objects.nonNull(appInfo) && Objects.nonNull(appInfo.getControl())) {
+            expireTime = Objects.nonNull(appInfo.getControl().getExpireTime()) ? appInfo.getControl().getExpireTime() : -1;
+        }
+        return expireTime;
+    }
+
+    /**
+     * 保存鉴权信息
+     *
+     * @param appInfo
+     * @param authEnum
+     * @param file
+     * @throws Exception
+     */
+    @Override
+    @Transactional
+    public void saveAuthInfo(AppInfo appInfo, AuthEnum authEnum, byte[] file) throws Exception {
+        List<OrgInfo> orgInfoList = solarService.getOrgList();
+        List<TSAuth> tsAuthList = null;
+        Set<Long> orgIdsSet = null;
+        Set<BasicSchool> basicSchoolSet = null;
+        if (!CollectionUtils.isEmpty(orgInfoList)) {
+            tsAuthList = new ArrayList<>();
+            orgIdsSet = new HashSet<>();
+            basicSchoolSet = new HashSet<>();
+        }
+        boolean oss = dictionaryConfig.sysDomain().isOss();
+        for (OrgInfo o : orgInfoList) {
+            orgIdsSet.add(o.getId());
+            if (authEnum == AuthEnum.OFF_LINE) {
+                if (Objects.isNull(file)) {
+                    tsAuthList.add(new TSAuth(o.getId(), solarProperties.getLicense(), authEnum, appInfo.getControl().getExpireTime()));
+                } else {
+                    tsAuthList.add(new TSAuth(o.getId(), file, authEnum, appInfo.getControl().getExpireTime()));
+                }
+            } else {
+                tsAuthList.add(new TSAuth(o.getId(), solarProperties.getAccessKey(), solarProperties.getAccessSecret(), authEnum, appInfo.getControl().getExpireTime()));
+            }
+            if (Objects.isNull(commonCacheService.updateAuthInfoCache(o.getCode()))) {
+                commonCacheService.removeAuthInfoCache(o.getCode());
+            }
+
+            QueryWrapper<BasicSchool> basicSchoolQueryWrapper = new QueryWrapper<>();
+            basicSchoolQueryWrapper.lambda().eq(BasicSchool::getCode, o.getCode());
+            BasicSchool basicSchool = basicSchoolService.getOne(basicSchoolQueryWrapper);
+            if (Objects.isNull(basicSchool)) {//不存在则创建学校
+                basicSchool = new BasicSchool(o.getId(), o.getCode(), o.getName(), o.getAccessKey(), o.getAccessSecret());
+                if (Objects.nonNull(o.getLogo()) && (!o.getLogo().startsWith("https:") || !o.getLogo().startsWith("http"))) {
+                    String filePath = dictionaryConfig.fssLocalFileDomain().getConfig() + File.separator + SystemConstant.getUuid() + ".jpg";
+                    File logoFile = new File(filePath);
+                    if (!logoFile.getParentFile().exists()) {
+                        // 不存在则创建父目录及子文件
+                        logoFile.getParentFile().mkdirs();
+                        logoFile.createNewFile();
+                    }
+                    SystemConstant.base64ToImage(o.getLogo(), filePath);
+
+                    if (oss) {
+                        LocalDateTime nowTime = LocalDateTime.now();
+                        StringJoiner stringJoiner = new StringJoiner("");
+                        stringJoiner.add(UploadFileEnum.FILE.name().toLowerCase()).add(File.separator)
+                                .add(String.valueOf(nowTime.getYear())).add(File.separator)
+                                .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
+                                .add(String.format("%02d", nowTime.getDayOfMonth())).add(File.separator)
+                                .add(SystemConstant.getUuid()).add(".jpg");
+                        fileStoreUtil.ossUpload(stringJoiner.toString(), logoFile, DigestUtils.md5Hex(new FileInputStream(logoFile)), UploadFileEnum.FILE.getFssType());
+                        logoFile.delete();
+                        basicSchool.setLogo(fileStoreUtil.getPrivateUrl(stringJoiner.toString(), UploadFileEnum.FILE.getFssType()));
+                    } else {
+                        basicSchool.setLogo(filePath);
+                    }
+                } else {
+                    basicSchool.setLogo(o.getLogo());
+                }
+                basicSchoolSet.add(basicSchool);
+            }
+        }
+
+        if (!CollectionUtils.isEmpty(tsAuthList) && !CollectionUtils.isEmpty(orgIdsSet)) {
+            QueryWrapper<TSAuth> tsAuthQueryWrapper = new QueryWrapper<>();
+            tsAuthQueryWrapper.lambda().in(TSAuth::getSchoolId, orgIdsSet);
+            tsAuthService.remove(tsAuthQueryWrapper);
+            tsAuthMapper.insertBatch(tsAuthList);
+
+            if (!CollectionUtils.isEmpty(basicSchoolSet)) {
+                commonCacheService.removeSchoolIdCache();
+                commonCacheService.removeSchoolCodeCache();
+                basicSchoolMapper.insertBatch(basicSchoolSet);
+            }
+        }
+    }
+}

+ 20 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/BasicSchoolServiceImpl.java

@@ -0,0 +1,20 @@
+package com.qmth.teachcloud.exchange.common.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+import com.qmth.teachcloud.exchange.common.mapper.BasicSchoolMapper;
+import com.qmth.teachcloud.exchange.common.service.BasicSchoolService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 学校表 服务实现类
+ * </p>
+ *
+ * @author xf
+ * @since 2021-03-23
+ */
+@Service
+public class BasicSchoolServiceImpl extends ServiceImpl<BasicSchoolMapper, BasicSchool> implements BasicSchoolService {
+
+}

+ 166 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/CommonCacheServiceImpl.java

@@ -0,0 +1,166 @@
+package com.qmth.teachcloud.exchange.common.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.boot.core.solar.model.AppInfo;
+import com.qmth.boot.core.solar.model.OrgInfo;
+import com.qmth.boot.core.solar.service.SolarService;
+import com.qmth.teachcloud.exchange.common.bean.dto.AuthOrgInfoDto;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.entity.BasicSchool;
+import com.qmth.teachcloud.exchange.common.service.BasicSchoolService;
+import com.qmth.teachcloud.exchange.common.service.CommonCacheService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 缓存操作serviceImpl 实现类
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/3/25
+ */
+@Service
+public class CommonCacheServiceImpl implements CommonCacheService {
+    private final static Logger log = LoggerFactory.getLogger(CommonCacheServiceImpl.class);
+
+    @Resource
+    BasicSchoolService basicSchoolService;
+
+    @Resource
+    SolarService solarService;
+
+    /**
+     * 添加学校缓存
+     *
+     * @param schoolId
+     * @return
+     */
+    @Override
+    @Cacheable(value = SystemConstant.SCHOOL_CACHE, key = "#p0", unless = "#result == null")
+    public BasicSchool schoolCache(Long schoolId) {
+        return basicSchoolService.getById(schoolId);
+    }
+
+    /**
+     * 添加学校缓存
+     *
+     * @param code
+     * @return
+     */
+    @Override
+    @Cacheable(value = SystemConstant.SCHOOL_CODE_CACHE, key = "#p0", unless = "#result == null")
+    public BasicSchool schoolCache(String code) {
+        QueryWrapper<BasicSchool> basicSchoolQueryWrapper = new QueryWrapper<>();
+        basicSchoolQueryWrapper.lambda().eq(BasicSchool::getCode, code);
+        return basicSchoolService.getOne(basicSchoolQueryWrapper);
+    }
+
+    /**
+     * 更新学校缓存
+     *
+     * @param schoolId
+     * @return
+     */
+    @Override
+    @CachePut(value = SystemConstant.SCHOOL_CACHE, key = "#p0", condition = "#result != null")
+    public BasicSchool updateSchoolCache(Long schoolId) {
+        return basicSchoolService.getById(schoolId);
+    }
+
+    /**
+     * 更新学校缓存
+     *
+     * @param code
+     * @return
+     */
+    @Override
+    @CachePut(value = SystemConstant.SCHOOL_CODE_CACHE, key = "#p0", condition = "#result != null")
+    public BasicSchool updateSchoolCache(String code) {
+        QueryWrapper<BasicSchool> basicSchoolQueryWrapper = new QueryWrapper<>();
+        basicSchoolQueryWrapper.lambda().eq(BasicSchool::getCode, code);
+        return basicSchoolService.getOne(basicSchoolQueryWrapper);
+    }
+
+    /**
+     * 删除学校缓存
+     *
+     * @param schoolId
+     */
+    @Override
+    @CacheEvict(value = SystemConstant.SCHOOL_CACHE, key = "#p0")
+    public void removeSchoolCache(Long schoolId) {
+
+    }
+
+    /**
+     * 删除学校缓存
+     */
+    @Override
+    @CacheEvict(value = SystemConstant.SCHOOL_CACHE, allEntries = true)
+    public void removeSchoolIdCache() {
+
+    }
+
+    /**
+     * 删除学校缓存
+     *
+     * @param code
+     */
+    @Override
+    @CacheEvict(value = SystemConstant.SCHOOL_CODE_CACHE, key = "#p0")
+    public void removeSchoolCache(String code) {
+
+    }
+
+    /**
+     * 删除学校缓存
+     */
+    @Override
+    @CacheEvict(value = SystemConstant.SCHOOL_CODE_CACHE, allEntries = true)
+    public void removeSchoolCodeCache() {
+
+    }
+
+    @Override
+    @Cacheable(value = SystemConstant.AUTH_INFO_CACHE, key = "#p0", unless = "#result == null")
+    public AuthOrgInfoDto authInfoCache(String code) {
+        AppInfo appInfo = solarService.getAppInfo();
+        AuthOrgInfoDto authOrgInfoDto = null;
+        if (Objects.nonNull(appInfo)) {
+            List<OrgInfo> orgInfoList = solarService.getOrgList().stream().filter(s -> Objects.equals(s.getCode(), code)).collect(Collectors.toList());
+            if (Objects.nonNull(orgInfoList) && orgInfoList.size() > 0) {
+                authOrgInfoDto = new AuthOrgInfoDto(orgInfoList.get(0), appInfo.getControl());
+            }
+        }
+        return authOrgInfoDto;
+    }
+
+    @Override
+    @CachePut(value = SystemConstant.AUTH_INFO_CACHE, key = "#p0", condition = "#result != null")
+    public AuthOrgInfoDto updateAuthInfoCache(String code) {
+        AppInfo appInfo = solarService.getAppInfo();
+        AuthOrgInfoDto authOrgInfoDto = null;
+        if (Objects.nonNull(appInfo)) {
+            List<OrgInfo> orgInfoList = solarService.getOrgList().stream().filter(s -> Objects.equals(s.getCode(), code)).collect(Collectors.toList());
+            if (Objects.nonNull(orgInfoList) && orgInfoList.size() > 0) {
+                authOrgInfoDto = new AuthOrgInfoDto(orgInfoList.get(0), appInfo.getControl());
+            }
+        }
+        return authOrgInfoDto;
+    }
+
+    @Override
+    @CacheEvict(value = SystemConstant.AUTH_INFO_CACHE, key = "#p0")
+    public void removeAuthInfoCache(String code) {
+
+    }
+}

+ 20 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/service/impl/TSAuthServiceImpl.java

@@ -0,0 +1,20 @@
+package com.qmth.teachcloud.exchange.common.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.exchange.common.entity.TSAuth;
+import com.qmth.teachcloud.exchange.common.mapper.TSAuthMapper;
+import com.qmth.teachcloud.exchange.common.service.TSAuthService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 激活授权配置表 服务实现类
+ * </p>
+ *
+ * @author wangliang
+ * @since 2022-04-26
+ */
+@Service
+public class TSAuthServiceImpl extends ServiceImpl<TSAuthMapper, TSAuth> implements TSAuthService {
+
+}

+ 16 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/Base64Util.java

@@ -0,0 +1,16 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+
+import java.util.Base64;
+
+public class Base64Util {
+
+    public static String encode(byte[] input) {
+        return new String(Base64.getEncoder().encode(input), SystemConstant.CHARSET);
+    }
+
+    public static byte[] decode(String input) {
+        return Base64.getDecoder().decode(input.getBytes(SystemConstant.CHARSET));
+    }
+}

+ 245 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/FileStoreUtil.java

@@ -0,0 +1,245 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import com.qmth.boot.core.fss.service.FileService;
+import com.qmth.boot.core.fss.store.FileStore;
+import com.qmth.teachcloud.exchange.common.config.DictionaryConfig;
+import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.exchange.common.enums.LocalCatalogEnum;
+import com.qmth.teachcloud.exchange.common.enums.UploadFileEnum;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.*;
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * @Description: 文件存储工具类
+ * @Author: CaoZixuan
+ * @Date: 2021-08-17
+ */
+@Component
+public class FileStoreUtil {
+    private final static Logger log = LoggerFactory.getLogger(FileStoreUtil.class);
+
+    @Resource
+    private FileService fileService;
+
+    @Resource
+    private DictionaryConfig dictionaryConfig;
+
+    /**
+     * 上传文件
+     *
+     * @param dirName     上传到地址
+     * @param inputStream 流
+     * @param type        fileStore类型
+     */
+    public void ossUpload(String dirName, InputStream inputStream, String md5, String type) throws Exception {
+        log.info("ossUpload is come in");
+        fileService.getFileStore(type).write(dirName, inputStream, md5);
+        log.info("dirName:{}", dirName);
+    }
+
+    /**
+     * 上传文件到本地
+     *
+     * @param dirName     上传到地址
+     * @param inputStream 流
+     * @param catalogType 文件
+     */
+    public void localUpload(String dirName, InputStream inputStream, String md5, LocalCatalogEnum catalogType) throws Exception {
+        log.info("ossUpload is come in");
+        String configPath = "";
+        switch (catalogType) {
+            case LOCAL_FILE:
+                configPath = dictionaryConfig.fssLocalFileDomain().getConfig();
+                break;
+            case LOCAL_PDF:
+                configPath = dictionaryConfig.fssLocalPdfDomain().getConfig();
+                break;
+            default:
+                break;
+        }
+        dirName = dirName.replaceAll(configPath, "");
+        fileService.getFileStore(catalogType.getType()).write(dirName, inputStream, md5);
+        log.info("dirName:{}", dirName);
+    }
+
+    /**
+     * 上传文件到本地
+     *
+     * @param inputStream 流
+     * @param finalFile   最终文件
+     * @param catalogType 文件类型
+     * @throws Exception 异常
+     */
+    public void copyInputStreamToFile(InputStream inputStream, File finalFile, String md5, LocalCatalogEnum catalogType) throws Exception {
+        String dirName = finalFile.getPath().replaceAll("\\\\", "/");
+        this.localUpload(dirName, inputStream, md5, catalogType);
+    }
+
+    /**
+     * 上传文件
+     *
+     * @param dirName 上传到地址
+     * @param file    文件
+     * @param type    fileStore类型
+     */
+    public void ossUpload(String dirName, File file, String md5, String type) throws Exception {
+        log.info("ossUpload is come in");
+        fileService.getFileStore(type).write(dirName, new FileInputStream(file), md5);
+        log.info("dirName:{}", dirName);
+    }
+
+    /**
+     * 上传文件
+     *
+     * @param dirName 上传到地址
+     * @param content 文件
+     * @param type    fileStore类型
+     */
+    public void ossUpload(String dirName, String content, String type) throws Exception {
+        log.info("ossUpload is come in");
+        fileService.getFileStore(type).write(dirName, new ByteArrayInputStream(content.getBytes()), DigestUtils.md5Hex(new ByteArrayInputStream(content.getBytes())));
+        log.info("dirName:{}", dirName);
+    }
+
+    /**
+     * 从文件存储上下载文件到本地
+     *
+     * @param dirName   文件地址
+     * @param localPath 本地路径
+     * @param type      fileStore类型
+     * @throws Exception 异常
+     */
+    public File ossDownload(String dirName, String localPath, String type) throws Exception {
+        log.info("ossDownload is come in");
+        return this.saveLocal(fileService.getFileStore(type).read(dirName), localPath);
+    }
+
+
+    /**
+     * 从文件存储上下载文件到byte[]
+     *
+     * @param objectName 文件地址
+     * @param type       fileStore类型
+     * @throws Exception 异常
+     */
+    public byte[] ossDownload(String objectName, String type) throws Exception {
+        log.info("oss Download is come in");
+        return IOUtils.toByteArray(fileService.getFileStore(type).read(objectName));
+    }
+
+    /**
+     * 从文件存储上下载文件到InputStream
+     *
+     * @param objectName 文件地址
+     * @param type       fileStore类型
+     * @throws Exception 异常
+     */
+    public InputStream ossDownloadIs(String objectName, String type) throws Exception {
+        log.info("oss Download is come in");
+        return fileService.getFileStore(type).read(objectName);
+    }
+
+
+    /**
+     * 获取文件访问url
+     *
+     * @param objectPath 文件路径
+     * @param type       文件上传的类型
+     * @return
+     */
+    public String getPrivateUrl(String objectPath, String type) {
+        String server = null;
+        if ("public".equals(type)) {
+            server = dictionaryConfig.fssPublicDomain().getServer();
+            return server + "/" + objectPath;
+        } else if ("private".equals(type)) {
+            Boolean oss = dictionaryConfig.sysDomain().isOss();
+            if (Objects.nonNull(oss) && oss) {
+                FileStore fileStore = fileService.getFileStore(type);
+                return fileStore.getPresignedUrl(objectPath, Duration.ofMinutes(5L));
+            } else {
+                return dictionaryConfig.fssPrivateDomain().getServer() + "/" + objectPath;
+            }
+        } else {
+            throw ExceptionResultEnum.ERROR.exception("文件存储store类型不存在");
+        }
+    }
+
+    /**
+     * 根据数据库文件路径判断文件上传类型
+     *
+     * @param path 路径
+     * @return 类型
+     */
+    public UploadFileEnum getUploadEnumByPath(String path) {
+        path = path.replaceAll("\\\\", "/");
+        String target = path.substring(0, path.indexOf('/'));
+        return UploadFileEnum.valueOf(target.toUpperCase());
+    }
+
+    /**
+     * 文件存在某本地路径
+     *
+     * @param inputStream 输入流
+     * @param dirPath     本地路径
+     * @return 存好的文件
+     * @throws IOException 异常
+     */
+    public File saveLocal(InputStream inputStream, String dirPath) throws IOException {
+        String fileName = dirPath.substring(dirPath.lastIndexOf(File.separator) + 1);
+        String parentPath = dirPath.substring(0, dirPath.lastIndexOf(File.separator)) + File.separator;
+        String name = fileName.substring(0, fileName.lastIndexOf('.'));
+        String suffix = fileName.substring(fileName.lastIndexOf('.'));
+
+        File desFile = buildSingleFileName(parentPath, name, suffix, 0);
+        if (!desFile.exists()) {
+            desFile.getParentFile().mkdirs(); //目标文件目录不存在的话需要创建目录
+            desFile.createNewFile();
+        }
+//        if (desFile.length() > 0) {
+//            return desFile;
+//        }
+        try {
+            FileUtils.copyInputStreamToFile(inputStream, desFile);
+            return desFile;
+        } finally {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+        }
+    }
+
+    /**
+     * 构建唯一的文件名称
+     *
+     * @param path     文件路径
+     * @param fileName 文件名称
+     * @param suffix   文件后缀
+     * @param index    当前下标,初次为0
+     * @return 唯一的文件名称
+     */
+    public static File buildSingleFileName(String path, String fileName, String suffix, Integer index) {
+        File file;
+        //下标不等于0开始拼后缀
+        if (index != 0) {
+            file = new File(path + fileName + "(" + index + ")" + suffix);
+        } else {
+            file = new File(path + fileName + suffix);
+        }
+        //判断文件是否存在 文件不存在退出递归
+        if (file.isFile()) {
+            //每次递归给下标加1
+            file = buildSingleFileName(path, fileName, suffix, ++index);
+        }
+        return file;
+    }
+}

+ 30 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/GsonUtil.java

@@ -0,0 +1,30 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+
+import java.lang.reflect.Type;
+
+/**
+ * @Description: Json工具类
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/10/12
+ */
+public class GsonUtil {
+    private static Gson gson = new GsonBuilder().create();
+
+    public static String toJson(Object value) {
+        return gson.toJson(value);
+    }
+
+    public static <T> T fromJson(String json, Class<T> classOfT) throws JsonParseException {
+        return gson.fromJson(json, classOfT);
+    }
+
+    public static <T> T fromJson(String json, Type typeOfT) throws JsonParseException {
+        return (T) gson.fromJson(json, typeOfT);
+    }
+}

+ 108 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/JacksonUtil.java

@@ -0,0 +1,108 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * @Description: jackson util
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/6
+ */
+public class JacksonUtil {
+    private final static Logger log = LoggerFactory.getLogger(JacksonUtil.class);
+    private volatile static ObjectMapper objectMapper = null;
+
+    static {
+        getInstance();
+    }
+
+    public static ObjectMapper getInstance() {
+        if (Objects.isNull(objectMapper)) {
+            synchronized (ObjectMapper.class) {
+                if (Objects.isNull(objectMapper)) {
+//                    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);//排除json字符串中实体类没有的字段
+                    objectMapper = new ObjectMapper();
+                }
+            }
+        }
+        return objectMapper;
+    }
+
+    /**
+     * 解析json
+     *
+     * @param o
+     * @return
+     */
+    public static String parseJson(Object o) {
+        try {
+            return objectMapper.writeValueAsString(o);
+        } catch (JsonProcessingException e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+        }
+        return null;
+    }
+
+    /**
+     * 读取json
+     *
+     * @param o
+     * @param valueType
+     * @param <T>
+     * @return
+     */
+    public static <T> T readJson(String o, Class<T> valueType) {
+        try {
+            return objectMapper.readValue(o, valueType);
+        } catch (JsonProcessingException e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+        }
+        return null;
+    }
+
+    /**
+     * 读取json list
+     *
+     * @param o
+     * @param cla
+     * @param <T>
+     * @return
+     */
+    public static <T> T readJsonList(String o, Class<T> cla) {
+        try {
+            JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, cla);
+            return objectMapper.readValue(o, javaType);
+        } catch (JsonProcessingException e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+        }
+        return null;
+    }
+
+    /**
+     * 读取json set
+     *
+     * @param o
+     * @param cla
+     * @param <T>
+     * @return
+     */
+    public static <T> T readJsonSet(String o, Class<T> cla) {
+        try {
+            JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(Set.class, cla);
+            return objectMapper.readValue(o, javaType);
+        } catch (JsonProcessingException e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+        }
+        return null;
+    }
+}

+ 266 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/RedisUtil.java

@@ -0,0 +1,266 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Description: redis util
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/15
+ */
+@Component
+public class RedisUtil {
+
+    @Resource
+    RedisTemplate<String, Object> redisTemplate;
+
+    /**
+     * 获取用户会话信息
+     *
+     * @param sessionId
+     * @return
+     */
+    public Object getUserSession(String sessionId) {
+        return redisTemplate.opsForValue().get(SystemConstant.SESSION + sessionId);
+    }
+
+    /**
+     * 删除用户会话缓存
+     *
+     * @param sessionId
+     */
+    public void deleteUserSession(String sessionId) {
+        redisTemplate.delete(SystemConstant.SESSION + sessionId);
+    }
+
+    /**
+     * 设置用户session信息
+     *
+     * @param sessionId
+     * @param o
+     * @param time
+     */
+    public void setUserSession(String sessionId, Object o, long time) {
+        redisTemplate.opsForValue().set(SystemConstant.SESSION + sessionId, o, time, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 获取过期时间
+     *
+     * @param sessionId
+     * @return
+     */
+    public Long getUserSessionExpire(String sessionId) {
+        return redisTemplate.opsForValue().getOperations().getExpire(SystemConstant.SESSION + sessionId);
+    }
+
+    /**
+     * 批量获取key的value
+     *
+     * @param keys
+     * @return
+     */
+    public List<?> multiGet(Set keys) {
+        return redisTemplate.opsForValue().multiGet(keys);
+    }
+
+    /**
+     * 获取key like
+     *
+     * @param key
+     * @return
+     */
+    public Set<?> getKeyPatterns(String key) {
+        if (Objects.nonNull(key)) {
+            return redisTemplate.keys(key);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 设置hash
+     *
+     * @param key
+     * @param hashKey
+     * @param hashValue
+     */
+    public void set(String key, String hashKey, Object hashValue) {
+        redisTemplate.opsForHash().put(key, hashKey, hashValue);
+    }
+
+    /**
+     * 获取hash
+     *
+     * @param key
+     * @param hashKey
+     * @return
+     */
+    public Object get(String key, String hashKey) {
+        return redisTemplate.opsForHash().get(key, hashKey);
+    }
+
+    /**
+     * hash删除
+     *
+     * @param key
+     * @param hashKey
+     */
+    public void delete(String key, String hashKey) {
+        redisTemplate.opsForHash().delete(key, hashKey);
+    }
+
+    /**
+     * 获取hash大小
+     *
+     * @param key
+     * @return
+     */
+    public Long getHashSize(String key) {
+        return redisTemplate.opsForHash().size(key);
+    }
+
+    /**
+     * 获取hash map
+     *
+     * @param key
+     * @return
+     */
+    public Map getHashEntries(String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 分布式锁
+     *
+     * @param key
+     * @param timeout SECONDS
+     * @return
+     */
+    public boolean lock(String key, long timeout) {
+        long expireAt = System.currentTimeMillis() + (timeout * 1000) + 1;
+        return redisTemplate.opsForValue().setIfAbsent(key, expireAt, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 删除锁
+     *
+     * @param key
+     * @return
+     */
+    public void releaseLock(String key) {
+        redisTemplate.expire(key, 100, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * 设置缓存
+     *
+     * @param key
+     * @param o
+     */
+    public void set(String key, Object o) {
+        redisTemplate.opsForValue().set(key, o);
+    }
+
+    /**
+     * 设置缓存
+     *
+     * @param key
+     * @param o
+     * @param time
+     * @param timeUnit
+     */
+    public void set(String key, Object o, long time, TimeUnit timeUnit) {
+        redisTemplate.opsForValue().set(key, o, time, timeUnit);
+    }
+
+    /**
+     * 设置缓存
+     *
+     * @param key
+     * @param o
+     * @param time SECONDS
+     */
+    public void set(String key, Object o, long time) {
+        set(key, o, time, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 获取缓存
+     *
+     * @param key
+     * @return
+     */
+    public Object get(String key) {
+        return redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * 删除缓存
+     *
+     * @param key
+     * @return
+     */
+    public void delete(String key) {
+        redisTemplate.expire(key, 0, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 保存hash结构
+     *
+     * @param key
+     * @param map
+     */
+    public void setForHash(String key, Map<String, Object> map) {
+        redisTemplate.opsForHash().putAll(key, map);
+    }
+
+    /**
+     * 保存list
+     *
+     * @param key
+     * @param Object
+     */
+    public void setForLeftList(String key, Object Object) {
+        redisTemplate.opsForList().leftPush(key, Object);
+    }
+
+    /**
+     * 获取list
+     *
+     * @param key
+     */
+    public Object getForRightList(String key) {
+        return redisTemplate.opsForList().rightPop(key, 0, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置过期时间(秒)
+     *
+     * @param key
+     * @param timeOutSecond
+     */
+    public void expire(String key, int timeOutSecond) {
+        redisTemplate.expire(key, timeOutSecond, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置过期时间
+     *
+     * @param key
+     * @param timeOut
+     */
+    public void expire(String key, long timeOut, TimeUnit timeUnit) {
+        redisTemplate.expire(key, timeOut, timeUnit);
+    }
+}

+ 70 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/Result.java

@@ -0,0 +1,70 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 自定义处理消息
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/10/11
+ */
+//@JsonInclude(JsonInclude.Include.NON_NULL)
+public class Result implements Serializable {
+    private int code;
+    private String message;
+    private Object data;
+
+    public Result() {
+
+    }
+
+    public Result(int code) {
+        this.code = code;
+    }
+
+    public Result(String message) {
+        this.message = message;
+    }
+
+    public Result(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public Result(int code, String message, Object data) {
+        this.code = code;
+        this.message = message;
+        this.data = data;
+    }
+
+    public Result(int code, Object data, String message) {
+        this.code = code;
+        this.data = data;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+}

+ 111 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/ResultUtil.java

@@ -0,0 +1,111 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import cn.hutool.http.HttpStatus;
+import com.qmth.boot.api.exception.ApiException;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Collections;
+import java.util.StringJoiner;
+
+/**
+ * @Description: 自定义消息工具
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/10/11
+ */
+public class ResultUtil {
+    private final static Logger log = LoggerFactory.getLogger(ResultUtil.class);
+
+    public static Result success(Object object) {
+        return new Result(ExceptionResultEnum.SUCCESS.getStatus().value(), ExceptionResultEnum.SUCCESS.getMessage(), object);
+    }
+
+    public static Result success() {
+        return success(null);
+    }
+
+    public static Result error(int code, String message) {
+        return new Result(code, message);
+    }
+
+    public static Result error() {
+        try {
+            StringJoiner stringJoiner = new StringJoiner("");
+            HttpServletRequest request = ServletUtil.getRequest();
+            stringJoiner.add("[error path]:").add(request.getServletPath()).add("\r\n");
+            stringJoiner.add("[status]:").add(String.valueOf(ExceptionResultEnum.EXCEPTION_ERROR.getStatus().value())).add("\r\n");
+            stringJoiner.add("[code]:").add(String.valueOf(ExceptionResultEnum.EXCEPTION_ERROR.getCode())).add("\r\n");
+            stringJoiner.add("[message]:").add(ExceptionResultEnum.EXCEPTION_ERROR.getMessage());
+            log.error(SystemConstant.LOG_ERROR, stringJoiner.toString());
+        } catch (Exception e) {
+        }
+        throw ExceptionResultEnum.EXCEPTION_ERROR.exception();
+    }
+
+    public static Result error(ApiException e, String message) {
+        try {
+            StringJoiner stringJoiner = new StringJoiner("");
+            HttpServletRequest request = ServletUtil.getRequest();
+            stringJoiner.add("[error path]:").add(request.getServletPath()).add("\r\n");
+            stringJoiner.add("[status]:").add(String.valueOf(e.getStatus().value())).add("\r\n");
+            stringJoiner.add("[code]:").add(String.valueOf(e.getCode())).add("\r\n");
+            stringJoiner.add("[message]:").add(message);
+            log.error(SystemConstant.LOG_ERROR, stringJoiner.toString());
+        } catch (Exception e1) {
+        }
+        throw new ApiException(e.getStatus(), e.getCode(), message, message);
+    }
+
+    public static Result error(ExceptionResultEnum e, int code, String message) {
+        try {
+            StringJoiner stringJoiner = new StringJoiner("");
+            HttpServletRequest request = ServletUtil.getRequest();
+            stringJoiner.add("[error path]:").add(request.getServletPath()).add("\r\n");
+            stringJoiner.add("[status]:").add(String.valueOf(e.getStatus().value())).add("\r\n");
+            stringJoiner.add("[code]:").add(String.valueOf(code)).add("\r\n");
+            stringJoiner.add("[message]:").add(message);
+            log.error(SystemConstant.LOG_ERROR, stringJoiner.toString());
+        } catch (Exception e1) {
+        }
+        throw e.exception(code, message);
+    }
+
+    public static Result error(String message) {
+        try {
+            StringJoiner stringJoiner = new StringJoiner("");
+            HttpServletRequest request = ServletUtil.getRequest();
+            stringJoiner.add("[error path]:").add(request.getServletPath()).add("\r\n");
+            stringJoiner.add("[status]:").add(String.valueOf(ExceptionResultEnum.ERROR.getStatus().value())).add("\r\n");
+            stringJoiner.add("[code]:").add(String.valueOf(ExceptionResultEnum.ERROR.getCode())).add("\r\n");
+            stringJoiner.add("[message]:").add(message);
+            log.error(SystemConstant.LOG_ERROR, stringJoiner.toString());
+        } catch (Exception e) {
+        }
+        throw ExceptionResultEnum.ERROR.exception(message);
+    }
+
+    public static Result ok(String message) {
+        return new Result(ExceptionResultEnum.SUCCESS.getStatus().value(), message);
+    }
+
+    public static Result ok(Object data) {
+        return new Result(ExceptionResultEnum.SUCCESS.getStatus().value(), data, ExceptionResultEnum.SUCCESS.getMessage());
+    }
+
+    public static Result ok(boolean success) {
+        return new Result(ExceptionResultEnum.SUCCESS.getStatus().value(), Collections.singletonMap(SystemConstant.SUCCESS, success), ExceptionResultEnum.SUCCESS.getMessage());
+    }
+
+    public static Result ok(Object data, String message) {
+        return new Result(ExceptionResultEnum.SUCCESS.getStatus().value(), data, message);
+    }
+
+    public static Result ok() {
+        return new Result(HttpStatus.HTTP_OK, Collections.singletonMap(SystemConstant.UPDATE_TIME, System.currentTimeMillis()), ExceptionResultEnum.SUCCESS.getMessage());
+    }
+}

+ 273 - 0
teachcloud-exchange-common/src/main/java/com/qmth/teachcloud/exchange/common/util/ServletUtil.java

@@ -0,0 +1,273 @@
+package com.qmth.teachcloud.exchange.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.qmth.boot.core.enums.Platform;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.enums.ExceptionResultEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @Description: http工具
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/10
+ */
+public class ServletUtil {
+    private final static Logger log = LoggerFactory.getLogger(ServletUtil.class);
+
+    /**
+     * 输出错误
+     *
+     * @param response
+     * @param code
+     * @param message
+     * @throws IOException
+     */
+    public static void responseError(ServletResponse response, int code, String message) throws IOException {
+        HttpServletResponse httpResponse = (HttpServletResponse) response;
+        Result result = ResultUtil.error(code, message);
+        String json = JSONObject.toJSONString(result);
+        httpResponse.getWriter().print(json);
+    }
+
+    /**
+     * 获取请求的sign
+     *
+     * @return
+     */
+    public static String getRequestSign() {
+        try {
+            HttpServletRequest request = getRequest();
+            return Objects.isNull(request.getHeader(SystemConstant.SIGN)) ? request.getParameter(SystemConstant.SIGN) : request.getHeader(SystemConstant.SIGN);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            throw ExceptionResultEnum.SIGN_INVALID.exception();
+        }
+    }
+
+    /**
+     * 获取请求的token
+     *
+     * @return
+     */
+    public static String getRequestToken() {
+        try {
+            HttpServletRequest request = getRequest();
+            return Objects.isNull(request.getHeader(SystemConstant.TOKEN)) ? request.getParameter(SystemConstant.TOKEN) : request.getHeader(SystemConstant.TOKEN);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            throw ExceptionResultEnum.TOKEN_INVALID.exception();
+        }
+    }
+
+    /**
+     * 获取请求的platform
+     *
+     * @return
+     */
+    public static Platform getRequestPlatform() {
+        try {
+            HttpServletRequest request = getRequest();
+            String value = Objects.isNull(request.getHeader(SystemConstant.HEADER_PLATFORM)) ? request.getParameter(SystemConstant.HEADER_PLATFORM) : request.getHeader(SystemConstant.HEADER_PLATFORM);
+            return Platform.valueOf(value);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            throw ExceptionResultEnum.PLATFORM_INVALID.exception();
+        }
+    }
+
+    /**
+     * 获取请求的deviceId
+     *
+     * @return
+     */
+    public static String getRequestDeviceId() {
+        try {
+            HttpServletRequest request = getRequest();
+            return Objects.isNull(request.getHeader(SystemConstant.HEADER_DEVICE_ID)) ? request.getParameter(SystemConstant.HEADER_DEVICE_ID) : request.getHeader(SystemConstant.HEADER_DEVICE_ID);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            throw ExceptionResultEnum.DEVICE_ID_INVALID.exception();
+        }
+    }
+
+    /**
+     * 获取请求的Authorization
+     *
+     * @return
+     */
+    public static String getRequestAuthorization() {
+        try {
+            HttpServletRequest request = getRequest();
+            return Objects.isNull(request.getHeader(SystemConstant.HEADER_AUTHORIZATION)) ? request.getParameter(SystemConstant.HEADER_AUTHORIZATION) : request.getHeader(SystemConstant.HEADER_AUTHORIZATION);
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            throw ExceptionResultEnum.AUTHORIZATION_INVALID.exception();
+        }
+    }
+
+    /**
+     * 获取请求的Authorization
+     *
+     * @return
+     */
+    public static Long getRequestTime() {
+        try {
+            HttpServletRequest request = getRequest();
+            String time = Objects.isNull(request.getHeader(SystemConstant.HEADER_TIME)) ? request.getParameter(SystemConstant.HEADER_TIME) : request.getHeader(SystemConstant.HEADER_TIME);
+            return Objects.nonNull(time) ? Long.parseLong(time) : null;
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            throw ExceptionResultEnum.TIME_INVALID.exception();
+        }
+    }
+
+    /**
+     * 获取请求的Session
+     *
+     * @return
+     */
+    public static Object getRequestSession() {
+        Object object = getRequest().getAttribute(SystemConstant.SESSION);
+        if (Objects.isNull(object)) {
+            throw ExceptionResultEnum.NOT_LOGIN.exception();
+        }
+        return object;
+    }
+
+    /**
+     * 获取请求的用户
+     *
+     * @return
+     */
+    public static Object getRequestUser() {
+        Object object = getRequest().getAttribute(SystemConstant.USER);
+        if (Objects.isNull(object)) {
+            throw ExceptionResultEnum.NOT_LOGIN.exception();
+        }
+        return object;
+    }
+
+    /**
+     * 获取header中schoolId
+     *
+     * @return
+     */
+    public static Object getRequestHeaderSchoolId() {
+//        BasicSchool basicSchool = (BasicSchool) getRequestSchool();
+//        return basicSchool.getId();
+        Object object = getRequest().getHeader(SystemConstant.SCHOOL_ID);
+        if (Objects.isNull(object)) {
+            throw ExceptionResultEnum.NOT_LOGIN.exception();
+        }
+        return object;
+    }
+
+    /**
+     * 获取header中schoolId
+     *
+     * @return
+     */
+    public static Object getRequestHeaderSchoolIdByNotVaild() {
+        return getRequest().getHeader(SystemConstant.SCHOOL_ID);
+    }
+
+    /**
+     * 获取请求的学校
+     *
+     * @return
+     */
+    public static Object getRequestSchool() {
+        Object object = getRequest().getAttribute(SystemConstant.SCHOOL);
+        if (Objects.isNull(object)) {
+            throw ExceptionResultEnum.NOT_LOGIN.exception();
+        }
+        return object;
+    }
+
+    /**
+     * 获取请求的学校
+     *
+     * @return
+     */
+    public static Object getRequestSchoolByNotVaild() {
+        return getRequest().getAttribute(SystemConstant.SCHOOL);
+    }
+
+    /**
+     * 获取请求的机构
+     *
+     * @return
+     */
+    public static Object getRequestOrg() {
+        Object object = getRequest().getAttribute(SystemConstant.ORG);
+        if (Objects.isNull(object)) {
+            throw ExceptionResultEnum.NOT_LOGIN.exception();
+        }
+        return object;
+    }
+
+    /**
+     * 获取请求的md5
+     *
+     * @return
+     */
+    public static String getRequestMd5() {
+        String md5 = getRequest().getHeader(SystemConstant.MD5.toLowerCase());
+        if (Objects.isNull(md5)) {
+            throw ExceptionResultEnum.MD5_EMPTY.exception();
+        }
+        return md5;
+    }
+
+    /**
+     * 设置id
+     *
+     * @param ids
+     * @return
+     */
+    public static void setRequestId(List<Long> ids) {
+        HttpServletRequest request = getRequest();
+        request.setAttribute(SystemConstant.ID, ids);
+    }
+
+    /**
+     * 获取id
+     *
+     * @return
+     */
+    public static List<Long> getRequestId() {
+        return Objects.nonNull(getRequest().getAttribute(SystemConstant.ID)) ? (List<Long>) getRequest().getAttribute(SystemConstant.ID) : null;
+    }
+
+    /**
+     * 获取HttpServletRequest
+     *
+     * @return
+     */
+    public static HttpServletRequest getRequest() {
+        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        return servletRequestAttributes.getRequest();
+    }
+
+    /**
+     * 获取HttpServletResponse
+     *
+     * @return
+     */
+    public static HttpServletResponse getResponse() {
+        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        return servletRequestAttributes.getResponse();
+    }
+}

+ 5 - 0
teachcloud-exchange-common/src/main/resources/mapper/BasicSchoolMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qmth.teachcloud.exchange.common.mapper.BasicSchoolMapper">
+
+</mapper>

+ 5 - 0
teachcloud-exchange-common/src/main/resources/mapper/TSAuthMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qmth.teachcloud.exchange.common.mapper.TSAuthMapper">
+
+</mapper>

+ 13 - 0
teachcloud-exchange-common/src/test/java/com/qmth/teachcloud/exchange/common/TeachcloudExchangeCommonApplicationTests.java

@@ -0,0 +1,13 @@
+package com.qmth.teachcloud.exchange.common;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class TeachcloudExchangeCommonApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}

+ 33 - 0
xjtu-exchange/.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 72 - 0
xjtu-exchange/pom.xml

@@ -0,0 +1,72 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.qmth.xjtu.exchange</groupId>
+    <artifactId>xjtu-exchange</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+
+    <parent>
+        <groupId>com.qmth.teachcloud.exchange.service</groupId>
+        <artifactId>teachcloud-exchange-service</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.qmth.teachcloud.exchange.business</groupId>
+            <artifactId>teachcloud-exchange-business</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-beans</artifactId>
+                    <groupId>org.springframework</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.teachcloud.exchange.common.api</groupId>
+            <artifactId>teachcloud-exchange-common-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>${spring-boot.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>dockerfile-maven-plugin</artifactId>
+                <version>1.4.12</version>
+                <configuration>
+                    <repository>registry.cn-shenzhen.aliyuncs.com/xjtu-exchange</repository>
+                    <tag>${project.version}</tag>
+                    <contextDirectory>${project.baseDir}</contextDirectory>
+                    <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
+                    <pullNewerImage>true</pullNewerImage>
+                    <buildArgs>
+                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
+                    </buildArgs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 46 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/XjtuExchangeApplication.java

@@ -0,0 +1,46 @@
+package com.qmth.xjtu;
+
+import com.qmth.boot.core.security.config.SecurityAutoConfiguration;
+import com.qmth.boot.core.security.service.CustomizeAuthorizationService;
+import com.qmth.teachcloud.exchange.common.base.CustomizedSqlInjector;
+import com.qmth.xjtu.auth.XjtuAuthenticationService;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.annotation.Resource;
+
+@SpringBootApplication(scanBasePackages = "com.qmth.*", exclude = {SecurityAutoConfiguration.class})
+@MapperScan({"com.qmth.teachcloud.exchange.business.mapper", "com.qmth.teachcloud.exchange.common.mapper"})
+//主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中,做过web开发的同学一定都有用过@Controller,@Service,@Repository注解,查看其源码你会发现,他们中有一个共同的注解@Component,没错@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中
+@EntityScan(basePackages = {"com.qmth.teachcloud.exchange.business.entity", "com.qmth.teachcloud.exchange.common.entity"})
+//用来扫描和发现指定包及其子包中的Entity定义
+@EnableTransactionManagement // spring开启事务支持
+@EnableAsync // 开启异步任务
+@EnableCaching // 开启缓存注解
+public class XjtuExchangeApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(XjtuExchangeApplication.class, args);
+    }
+
+    @Resource
+    private XjtuAuthenticationService xjtuAuthenticationService;
+
+    @Bean
+    public CustomizeAuthorizationService customizeAuthorizationService() {
+        return registration -> {
+            registration.setDefault(xjtuAuthenticationService);
+        };
+    }
+
+    @Bean
+    public CustomizedSqlInjector customizedSqlInjector() {
+        return new CustomizedSqlInjector();
+    }
+}

+ 72 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/api/OpenApiController.java

@@ -0,0 +1,72 @@
+package com.qmth.xjtu.api;
+
+import com.qmth.boot.api.annotation.Aac;
+import com.qmth.boot.api.annotation.BOOL;
+import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.teachcloud.exchange.common.bean.params.OpenParams;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.util.JacksonUtil;
+import com.qmth.teachcloud.exchange.common.util.Result;
+import com.qmth.teachcloud.exchange.common.util.ServletUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+/**
+ * <p>
+ * 西安交通大学开放接口前端控制器
+ * </p>
+ *
+ * @author wangliang
+ * @since 2022-04-26
+ */
+@Api(tags = "西安交通大学开放接口Controller")
+@Controller
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.open}")
+@Validated
+public class OpenApiController {
+    private static final Logger log = LoggerFactory.getLogger(OpenApiController.class);
+
+    @ApiResponses({@ApiResponse(code = 200, message = "返回消息", response = Result.class)})
+    @RequestMapping(value = "/authentication", method = RequestMethod.GET)
+    @Aac(auth = BOOL.FALSE)
+    public String authentication(@ApiParam(value = "工号", required = true) @RequestParam String account,
+                                 @ApiParam(value = "返回url") @RequestParam(required = false) String returnUrl) throws IOException {
+        HttpServletRequest request = ServletUtil.getRequest();
+        HttpServletResponse response = ServletUtil.getResponse();
+        String schoolCode = "test-school-2";
+
+        //todo 学校业务逻辑待完善
+
+        StringJoiner stringJoiner = new StringJoiner("")
+                .add(SystemConstant.JUMP_API_URL)
+                .add(SystemConstant.GET_UNKNOWN).add(SystemConstant.USER).add(SystemConstant.GET_EQUAL).add(account)
+                .add(SystemConstant.GET_SYMBOL).add(SystemConstant.SCHOOL_CODE).add(SystemConstant.GET_EQUAL).add(schoolCode);
+
+        if (Objects.nonNull(returnUrl) && !Objects.equals(returnUrl, "")) {
+            stringJoiner = stringJoiner.add(SystemConstant.GET_SYMBOL).add(SystemConstant.RETURN_URL).add(SystemConstant.GET_EQUAL).add(returnUrl);
+        }
+        OpenParams openParams = new OpenParams();
+        openParams.setName("test1");
+
+        if (Objects.nonNull(openParams)) {
+            stringJoiner = stringJoiner.add(SystemConstant.GET_SYMBOL).add(SystemConstant.PARAMS).add(SystemConstant.GET_EQUAL).add(JacksonUtil.parseJson(openParams));
+        }
+        log.info("redirectUrl:{},schoolCode:{}", stringJoiner.toString(), schoolCode);
+        return stringJoiner.toString();
+    }
+}

+ 88 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/aspect/ApiControllerAspect.java

@@ -0,0 +1,88 @@
+package com.qmth.xjtu.aspect;
+
+import com.qmth.boot.api.exception.ApiException;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import com.qmth.teachcloud.exchange.common.util.JacksonUtil;
+import com.qmth.teachcloud.exchange.common.util.ResultUtil;
+import com.qmth.teachcloud.exchange.common.util.ServletUtil;
+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.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BeanPropertyBindingResult;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+/**
+ * @Description: api aspect
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/5/12
+ */
+@Aspect
+@Component
+public class ApiControllerAspect {
+    private final static Logger log = LoggerFactory.getLogger(ApiControllerAspect.class);
+
+    /**
+     * api切入点
+     */
+    @Pointcut("execution(public * com.qmth.xjtu.api.*.*(..))")
+    public void apiAspect() {
+    }
+
+    /**
+     * 后台环绕切入
+     *
+     * @param joinPoint
+     * @return
+     * @throws Throwable
+     */
+    @Around(value = "apiAspect()")
+    public Object aroundApiPoint(ProceedingJoinPoint joinPoint) throws Throwable {
+        long start = System.currentTimeMillis();
+        StringJoiner stringJoiner = new StringJoiner("");
+        try {
+            MethodSignature msig = (MethodSignature) joinPoint.getSignature();
+            String className = msig.getDeclaringTypeName();
+            String methodName = msig.getName();
+            Object[] args = joinPoint.getArgs();
+            String[] paramsName = msig.getParameterNames();
+            HttpServletRequest request = ServletUtil.getRequest();
+            stringJoiner.add("============请求地址============:").add(request.getServletPath()).add("\r\n");
+            stringJoiner.add("============类============:").add(className).add("\r\n");
+            stringJoiner.add("============方法============:").add(methodName).add("\r\n");
+            if (Objects.nonNull(args) && args.length > 0) {
+                for (int i = 0; i < args.length; i++) {
+                    if (Objects.nonNull(args[i]) && (args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse || args[i] instanceof CommonsMultipartFile || args[i] instanceof MultipartFile || args[i] instanceof BeanPropertyBindingResult)) {
+                        continue;
+                    } else {
+                        stringJoiner.add("参数key:").add(JacksonUtil.parseJson(paramsName[i])).add(",参数value:").add(JacksonUtil.parseJson(args[i])).add("\r\n");
+                    }
+                }
+            }
+            return joinPoint.proceed();
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            if (e instanceof ApiException) {
+                return ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                return ResultUtil.error(e.getMessage());
+            }
+        } finally {
+            long end = System.currentTimeMillis();
+            stringJoiner.add("============耗时============:").add((end - start) / 1000 + "").add("秒");
+            log.info("request:{}", stringJoiner.toString());
+        }
+    }
+}

+ 125 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/auth/XjtuAuthenticationService.java

@@ -0,0 +1,125 @@
+package com.qmth.xjtu.auth;
+
+import com.qmth.boot.core.security.model.AccessEntity;
+import com.qmth.boot.core.security.service.AuthorizationService;
+import com.qmth.boot.tools.signature.SignatureType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class XjtuAuthenticationService implements AuthorizationService {
+    private final static Logger log = LoggerFactory.getLogger(XjtuAuthenticationService.class);
+
+//    @Resource
+//    CommonCacheService commonCacheService;
+//
+//    @Resource
+//    RedisUtil redisUtil;
+//
+//    @Resource
+//    DictionaryConfig dictionaryConfig;
+//
+//    @Resource
+//    AuthInfoService authInfoService;
+
+    @Override
+    public AccessEntity findByIdentity(String identity, SignatureType signatureType, String path) {
+        return new XjuSession(identity, SignatureType.TOKEN);
+    }
+
+    @Override
+    public boolean hasPermission(AccessEntity accessEntity, String path) {
+//        if (Objects.nonNull(accessEntity) && Objects.nonNull(accessEntity.getIdentity())) {
+//            TBSession tbSession = (TBSession) redisUtil.getUserSession(accessEntity.getIdentity());
+//            if (Objects.isNull(tbSession)) {
+//                log.warn("Authorization faile: session id not exists: {}", accessEntity.getIdentity());
+//                throw ExceptionResultEnum.NOT_LOGIN.exception();
+//            }
+//            if (tbSession.getExpireTime() <= System.currentTimeMillis()) {
+//                log.warn("Authorization faile: session has expired, expire time={}", tbSession.getExpireTime());
+//                throw ExceptionResultEnum.NOT_LOGIN.exception();
+//            }
+//            Platform platform = ServletUtil.getRequestPlatform();
+//            String deviceId = ServletUtil.getRequestDeviceId();
+//            if (!tbSession.getPlatform().equalsIgnoreCase(platform.name())) {
+//                log.warn("Authorization faile: platform invalid, session platform is {}", tbSession.getPlatform());
+//                throw ExceptionResultEnum.AUTHORIZATION_ERROR.exception();
+//            }
+//            if (!tbSession.getDeviceId().equalsIgnoreCase(deviceId)) {
+//                log.warn("Authorization faile: deviceId invalid, session deviceId is {} ", tbSession.getDeviceId());
+//                throw ExceptionResultEnum.AUTHORIZATION_ERROR.exception();
+//            }
+//            Long userId = Long.parseLong(tbSession.getIdentity());
+//            SysUser sysUser = commonCacheService.userCache(userId);
+//            HttpServletRequest request = ServletUtil.getRequest();
+//            HttpServletResponse response = ServletUtil.getResponse();
+//            request.setAttribute(SystemConstant.SESSION, tbSession);
+//            request.setAttribute(SystemConstant.USER, sysUser);
+//            boolean auth = authFootCommon(userId, SystemConstant.USER_OAUTH_CACHE, path, request, response);
+//            if (auth) {
+//                Long expireTime = redisUtil.getUserSessionExpire(accessEntity.getIdentity());
+//                if (Objects.nonNull(expireTime) && expireTime.longValue() > -1L) {
+//                    if (Objects.nonNull(tbSession.getLastAccessTime()) && (System.currentTimeMillis() - tbSession.getLastAccessTime()) / 1000 > dictionaryConfig.sysDomain().getSessionActive().getSeconds()) {
+//                        log.warn("Authorization faile: session active, session active is {}", dictionaryConfig.sysDomain().getSessionActive().getSeconds());
+//                        throw ExceptionResultEnum.NOT_LOGIN.exception();
+//                    }
+//                    tbSession.setLastInfo();
+//                    redisUtil.setUserSession(accessEntity.getIdentity(), tbSession, expireTime);
+//                }
+//            }
+//            return auth;
+//        }
+        return false;
+    }
+
+    /**
+     * 鉴权尾公用
+     *
+     * @param userId
+     * @param type
+     * @param path
+     * @param request
+     * @param response
+     * @return
+     */
+    public boolean authFootCommon(Long userId,
+                                  String type,
+                                  String path,
+                                  HttpServletRequest request,
+                                  HttpServletResponse response) {
+        //验证权限
+//        AuthBean authBean = type.contains(SystemConstant.USER_OAUTH_CACHE) ? authBean = commonCacheService.userAuthCache(userId) : null;
+//        if (Objects.isNull(authBean)) {
+//            throw ExceptionResultEnum.ROLE_ENABLE_AUTHORIZATION.exception();
+//        }
+//        request.setAttribute(SystemConstant.SCHOOL, authBean.getSchool());
+//        request.setAttribute(SystemConstant.ORG, authBean.getOrg());
+//
+//        //超级系统管理员拥有所有权限
+//        int count = Objects.nonNull(authBean) ? (int) authBean.getRoleList().stream().filter(s -> Objects.equals(s.getName(), RoleTypeEnum.ADMIN.getDesc())).count() : 0;
+//        if (count > 0) {
+//            return true;
+//        }
+//        if (Objects.nonNull(authBean.getSchool())) {
+//            authInfoService.appHasExpired(authBean.getSchool().getCode());
+//        }
+//        //系统公用接口不拦截
+//        Set<String> sysUrls = commonCacheService.privilegeUrlCache(PrivilegePropertyEnum.SYS, SystemConstant.getHeadOrUserSchoolId());
+//        int sysCount = Objects.nonNull(sysUrls) ? (int) sysUrls.stream().filter(s -> s.equalsIgnoreCase(path)).count() : 0;
+//        if (sysCount > 0) {
+//            return true;
+//        }
+//        Set<String> urls = authBean.getUrls();
+//        int privilegeCount = Objects.nonNull(urls) ? (int) urls.stream().filter(s -> s.equalsIgnoreCase(path)).count() : 0;
+//        if (privilegeCount == 0) {
+//            log.warn("Authorization faile: url cannot access");
+//            throw ExceptionResultEnum.UN_AUTHORIZATION.exception();
+//        }
+//        response.setStatus(ExceptionResultEnum.SUCCESS.getCode());
+        return true;
+    }
+}

+ 53 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/auth/XjuSession.java

@@ -0,0 +1,53 @@
+package com.qmth.xjtu.auth;
+
+import com.qmth.boot.core.security.model.AccessEntity;
+import com.qmth.boot.tools.signature.SignatureType;
+
+import java.util.Collection;
+
+public class XjuSession implements AccessEntity {
+
+    private String identity;
+
+    private SignatureType signatureType;
+
+    public XjuSession(String identity, SignatureType signatureType) {
+        this.identity = identity;
+        this.signatureType = signatureType;
+    }
+
+    public void setIdentity(String identity) {
+        this.identity = identity;
+    }
+
+    @Override
+    public String getIdentity() {
+        return identity;
+    }
+
+    @Override
+    public String getSecret() {
+//        RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
+//        TBSession tbSession = (TBSession) redisUtil.getUserSession(identity);
+//        return Objects.nonNull(tbSession) ? tbSession.getAccessToken() : null;
+        return null;
+    }
+
+    @Override
+    public Collection<String> getAllowIP() {
+        return null;
+    }
+
+    @Override
+    public Collection<String> getDenyIP() {
+        return null;
+    }
+
+    public SignatureType getSignatureType() {
+        return signatureType;
+    }
+
+    public void setSignatureType(SignatureType signatureType) {
+        this.signatureType = signatureType;
+    }
+}

+ 120 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/config/MapApiReader.java

@@ -0,0 +1,120 @@
+package com.qmth.xjtu.config;
+
+import com.fasterxml.classmate.TypeResolver;
+import com.google.common.base.Optional;
+import com.qmth.teachcloud.exchange.common.annotation.ApiJsonObject;
+import com.qmth.teachcloud.exchange.common.annotation.ApiJsonProperty;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import org.apache.ibatis.javassist.*;
+import org.apache.ibatis.javassist.bytecode.AnnotationsAttribute;
+import org.apache.ibatis.javassist.bytecode.ConstPool;
+import org.apache.ibatis.javassist.bytecode.annotation.Annotation;
+import org.apache.ibatis.javassist.bytecode.annotation.BooleanMemberValue;
+import org.apache.ibatis.javassist.bytecode.annotation.StringMemberValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ResolvedMethodParameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.ParameterBuilderPlugin;
+import springfox.documentation.spi.service.contexts.ParameterContext;
+
+import java.util.Map;
+
+/**
+ * @Description: swagger2 map参数说明插件
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/23
+ */
+@Component
+@Order   //plugin加载顺序,默认是最后加载
+public class MapApiReader implements ParameterBuilderPlugin {
+    private final static Logger log = LoggerFactory.getLogger(MapApiReader.class);
+
+    @Autowired
+    private TypeResolver typeResolver;
+
+    @Override
+    public void apply(ParameterContext parameterContext) {
+        ResolvedMethodParameter methodParameter = parameterContext.resolvedMethodParameter();
+
+        if (methodParameter.getParameterType().canCreateSubtype(Map.class) || methodParameter.getParameterType().canCreateSubtype(String.class)) { //判断是否需要修改对象ModelRef,这里我判断的是Map类型和String类型需要重新修改ModelRef对象
+            Optional<ApiJsonObject> optional = methodParameter.findAnnotation(ApiJsonObject.class);  //根据参数上的ApiJsonObject注解中的参数动态生成Class
+            if (optional.isPresent()) {
+                String name = optional.get().name();  //model 名称
+                ApiJsonProperty[] properties = optional.get().value();
+                parameterContext.getDocumentationContext().getAdditionalModels().add(typeResolver.resolve(createRefModel(properties, name)));  //像documentContext的Models中添加我们新生成的Class
+                parameterContext.parameterBuilder()  //修改Map参数的ModelRef为我们动态生成的class
+                        .parameterType("body")
+                        .modelRef(new ModelRef(name))
+                        .name(name);
+            }
+        }
+    }
+
+    private final static String basePackage = "com.qmth.teachcloud.entity.";  //动态生成的Class名
+
+    /**
+     * 根据propertys中的值动态生成含有Swagger注解的javaBeen
+     */
+    private Class createRefModel(ApiJsonProperty[] propertys, String name) {
+        ClassPool pool = ClassPool.getDefault();
+        CtClass ctClass = pool.makeClass(basePackage + name);
+        try {
+            for (ApiJsonProperty property : propertys) {
+                ctClass.addField(createField(property, ctClass));
+            }
+            return ctClass.toClass();
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            return null;
+        }
+    }
+
+    /**
+     * 根据property的值生成含有swagger apiModelProperty注解的属性
+     */
+    private CtField createField(ApiJsonProperty property, CtClass ctClass) throws NotFoundException, CannotCompileException {
+        CtField ctField = new CtField(getFieldType(property.type()), property.key(), ctClass);
+        ctField.setModifiers(Modifier.PUBLIC);
+        ConstPool constPool = ctClass.getClassFile().getConstPool();
+        AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+        Annotation ann = new Annotation("io.swagger.annotations.ApiModelProperty", constPool);
+        ann.addMemberValue("value", new StringMemberValue(property.description(), constPool));
+        ann.addMemberValue("required", new BooleanMemberValue(property.required(), constPool));
+        attr.addAnnotation(ann);
+        ctField.getFieldInfo().addAttribute(attr);
+        return ctField;
+    }
+
+    private CtClass getFieldType(String type) throws NotFoundException {
+        CtClass fileType = null;
+        switch (type) {
+            case "string":
+                fileType = ClassPool.getDefault().get(String.class.getName());
+                break;
+            case "int":
+                fileType = ClassPool.getDefault().get(Integer.class.getName());
+                break;
+            case "long":
+                fileType = ClassPool.getDefault().get(Long.class.getName());
+                break;
+            case "boolean":
+                fileType = ClassPool.getDefault().get(Boolean.class.getName());
+                break;
+            default:
+                break;
+        }
+        return fileType;
+    }
+
+    @Override
+    public boolean supports(DocumentationType delimiter) {
+        return true;
+    }
+}

+ 27 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/config/MetaHandler.java

@@ -0,0 +1,27 @@
+package com.qmth.xjtu.config;
+
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description: mybatis 自动插入时间和id
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/4/20
+ */
+@Component
+public class MetaHandler implements MetaObjectHandler {
+
+    @Override
+    public void insertFill(MetaObject metaObject) {
+        this.setFieldValByName("createTime", System.currentTimeMillis(), metaObject);
+        this.setFieldValByName("updateTime", System.currentTimeMillis(), metaObject);
+    }
+
+    @Override
+    public void updateFill(MetaObject metaObject) {
+        this.setFieldValByName("updateTime", System.currentTimeMillis(), metaObject);
+    }
+}

+ 33 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/config/MultipartConfig.java

@@ -0,0 +1,33 @@
+package com.qmth.xjtu.config;
+
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.multipart.MultipartResolver;
+import org.springframework.web.multipart.commons.CommonsMultipartResolver;
+
+/**
+ * @Description: Multipart 附件上传配置
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/29
+ */
+@Configuration
+public class MultipartConfig {
+
+    /**
+     * 附件上传配置
+     *
+     * @return
+     */
+    @Bean
+    public MultipartResolver multipartResolver() {
+        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
+        resolver.setDefaultEncoding(SystemConstant.CHARSET_NAME);
+        resolver.setResolveLazily(true);// resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
+        resolver.setMaxInMemorySize(2);// 低于此值,只保留在内存里,超过此阈值,生成硬盘上的临时文件。
+        resolver.setMaxUploadSize(200 * 1024 * 1024);// 最大200M
+        return resolver;
+    }
+}

+ 77 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/config/SwaggerConfig.java

@@ -0,0 +1,77 @@
+package com.qmth.xjtu.config;
+
+import com.google.common.base.Predicates;
+import com.qmth.teachcloud.exchange.common.contant.SystemConstant;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Description: swagger配置类
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/9/21
+ */
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+    @Bean
+    public Docket createRestApi() {
+        ParameterBuilder tokenPar = new ParameterBuilder();
+        ParameterBuilder tokenPar1 = new ParameterBuilder();
+        ParameterBuilder tokenPar2 = new ParameterBuilder();
+        ParameterBuilder tokenPar3 = new ParameterBuilder();
+        ParameterBuilder tokenPar4 = new ParameterBuilder();
+        ParameterBuilder tokenPar5 = new ParameterBuilder();
+        List<Parameter> pars = new ArrayList<>();
+        tokenPar.name(SystemConstant.HEADER_PLATFORM).description("平台").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+        tokenPar1.name(SystemConstant.HEADER_DEVICE_ID).description("设备id").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+        tokenPar2.name(SystemConstant.HEADER_AUTHORIZATION).description("鉴权token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+        tokenPar3.name(SystemConstant.HEADER_TIME).description("时间戳").modelRef(new ModelRef("long")).parameterType("header").required(false).build();
+        tokenPar4.name(SystemConstant.MD5.toLowerCase()).description("md5").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+        tokenPar5.name(SystemConstant.SCHOOL_ID).description("学校id").modelRef(new ModelRef("long")).parameterType("header").required(false).build();
+        pars.add(tokenPar.build());
+        pars.add(tokenPar1.build());
+        pars.add(tokenPar2.build());
+        pars.add(tokenPar3.build());
+        pars.add(tokenPar4.build());
+        pars.add(tokenPar5.build());
+
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("xjtu-exchange")
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.qmth.xjtu"))
+//                .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any())
+                // 不显示错误的接口地址
+                .paths(Predicates.not(PathSelectors.regex("/error.*")))// 错误路径不监控
+                .build()
+                .globalOperationParameters(pars)
+                .apiInfo(apiInfo());
+    }
+
+    private ApiInfo apiInfo() {
+        ApiInfo apiInfo = new ApiInfo(
+                "西安交通大学-cas单点登录 - api",
+                "Some custom description of API.",
+                "API TOS",
+                "Terms of service",
+                "myeaddress@company.com",
+                "License of API",
+                "API license URL");
+        return apiInfo;
+    }
+}

+ 45 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/interceptor/AuthInterceptor.java

@@ -0,0 +1,45 @@
+package com.qmth.xjtu.interceptor;
+
+import com.qmth.boot.api.interceptor.ExtendInterceptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class AuthInterceptor extends ExtendInterceptor {
+    private final static Logger log = LoggerFactory.getLogger(AuthInterceptor.class);
+
+    @Value("${com.qmth.api.metrics-endpoint}")
+    String endpoint;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        log.info("preHandle is come in");
+//        if (request.getServletPath().contains(endpoint)) {
+        return true;
+//        } else {
+//            return AuthUtil.adminAuthInterceptor(request, response, handler);
+//        }
+    }
+
+    @Override
+    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
+        log.info("postHandle is come in");
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
+        log.info("afterCompletion is come in");
+    }
+
+    @Override
+    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        log.info("afterConcurrentHandlingStarted is come in");
+    }
+}

+ 31 - 0
xjtu-exchange/src/main/java/com/qmth/xjtu/start/StartRunning.java

@@ -0,0 +1,31 @@
+package com.qmth.xjtu.start;
+
+import com.qmth.teachcloud.exchange.common.service.AuthInfoService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @Description: 服务启动时初始化运行,哪个微服务模块需要则拿此模版去用
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/3
+ */
+@Component
+public class StartRunning implements CommandLineRunner {
+    private final static Logger log = LoggerFactory.getLogger(StartRunning.class);
+
+    @Resource
+    AuthInfoService authInfoService;
+
+    @Override
+    public void run(String... args) throws Exception {
+        log.info("服务器启动时执行 start");
+        authInfoService.appInfoInit();
+        log.info("服务器启动时执行 end");
+    }
+}

+ 78 - 0
xjtu-exchange/src/main/resources/application-dev.properties

@@ -0,0 +1,78 @@
+server.port=7111
+#tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200
+server.tomcat.threads.max=2500
+#tomcat\u6700\u5927\u8FDE\u63A5\u6570
+server.tomcat.max-connections=2500
+#tomcat\u7684URI\u7F16\u7801
+server.tomcat.uri-encoding=UTF-8
+
+#\u9879\u76EE\u540D\u79F0
+spring.application.name=xjtu-exchange
+
+#\u6570\u636E\u6E90\u914D\u7F6E
+db.host=localhost
+db.port=3306
+db.name=exchange-v1.0.0
+db.username=root
+db.password=123456789
+
+#redis\u6570\u636E\u6E90\u914D\u7F6E
+com.qmth.redis.host=${db.host}
+com.qmth.redis.port=6379
+com.qmth.redis.db=2
+#com.qmth.redis.password=
+
+#mysql\u914D\u7F6E
+com.qmth.datasource.url=jdbc:mysql://${db.host}:${db.port}/${db.name}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
+com.qmth.datasource.username=${db.username}
+com.qmth.datasource.password=${db.password}
+com.qmth.mybatis.log-level=debug
+
+com.qmth.fss.public.config=oss://key:secret@teachcloud-print-dev-public.oss-api.qmth.com.cn
+com.qmth.fss.public.server=https://oss-file.qmth.com.cn/teachcloud-print-dev-public
+com.qmth.fss.private.config=oss://key:secret@teachcloud-print-dev-private.oss-api.qmth.com.cn
+com.qmth.fss.private.server=https://oss-file.qmth.com.cn/teachcloud-print-dev-private
+com.qmth.fss.localfile.config=/Users/king/Downloads/file-temp
+com.qmth.fss.localfile.server=http://127.0.0.1:7001
+com.qmth.fss.localpdf.config=/Users/king/Downloads/pdf-temp
+com.qmth.fss.localpdf.server=http://127.0.0.1:7001
+
+#\u7CFB\u7EDF\u914D\u7F6E
+sys.config.oss=true
+sys.config.attachmentType=.xlsx,.xls,.doc,.docx,.pdf,.jpg,.jpeg,.png,.html,.zip,.mp3,.wav,.dll,.exe,.ftl,.bpmn,.xml
+sys.config.attachmentLength=100
+sys.config.attachmentSize=200
+sys.config.serverUpload=
+spring.resources.static-locations=file:${sys.config.serverUpload},classpath:/META-INF/resources/,classpath:/resources/
+
+#com.qmth.api.uri-prefix=/aaa
+#\u7EDF\u8BA1\u9875\u9762\u914D\u7F6E
+com.qmth.api.metrics-endpoint=/metrics-count
+com.qmth.api.global-auth=true
+#com.qmth.api.global-strict=false
+#com.qmth.api.global-rate-limit=1/5s
+
+#token\u8D85\u65F6\u914D\u7F6E
+com.qmth.auth.time-max-ahead=1m
+com.qmth.auth.time-max-delay=5m
+
+#\u7F13\u5B58\u65F6\u95F4
+com.qmth.cache.expire-after-write=8h
+
+#api\u524D\u7F00
+prefix.url.open=admin/open
+
+#\u65E5\u671F\u683C\u5F0F\u5316
+spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+spring.jackson.time-zone=GMT+8
+
+#\u65E5\u5FD7\u914D\u7F6E
+com.qmth.logging.root-level=info
+com.qmth.logging.file-path=/Users/king/Downloads/xjtu-exchange.log
+
+com.qmth.solar.access-key=274f823e5f59410f8b3bb6edcd8e2b6e
+com.qmth.solar.access-secret=y7AO6W0TOdTF8HpWBwGHbp3wfIHsmUKr
+#com.qmth.solar.license=/Volumes/extend/\u542F\u660E/\u5206\u5E03\u5F0F\u5370\u5237/\u5206\u5E03\u5F0F\u5370\u5237&\u6559\u7814\u5206\u6790v3.1.0/tc-dev-wl.lic
+
+teachcloud.print.loginUrl=http://*.teach-cloud-test.com/#/login-open
+#teachcloud.print.loginUrl=http://127.0.0.1:7111/#/login-open

+ 2 - 0
xjtu-exchange/src/main/resources/application.properties

@@ -0,0 +1,2 @@
+#\u5207\u6362\u914D\u7F6E\u6587\u4EF6
+spring.profiles.active=dev

+ 13 - 0
xjtu-exchange/src/test/java/com/qmth/xjtu/XjtuExchangeApplicationTests.java

@@ -0,0 +1,13 @@
+package com.qmth.xjtu;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class XjtuExchangeApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}