Browse Source

初始化提交

zsy 1 month ago
commit
16dc3d39e4
56 changed files with 4548 additions and 0 deletions
  1. 20 0
      .gitignore
  2. 3 0
      README.md
  3. 120 0
      build.gradle
  4. 234 0
      gradlew
  5. 89 0
      gradlew.bat
  6. 1 0
      settings.gradle
  7. 57 0
      src/main/java/com/rf/AIquantum/AIquantumApplication.java
  8. 45 0
      src/main/java/com/rf/AIquantum/base/model/BaseEntity.java
  9. 18 0
      src/main/java/com/rf/AIquantum/base/repository/BaseRepository.java
  10. 76 0
      src/main/java/com/rf/AIquantum/base/rest/BaseController.java
  11. 30 0
      src/main/java/com/rf/AIquantum/config/CorsConfig.java
  12. 22 0
      src/main/java/com/rf/AIquantum/config/Properties.java
  13. 51 0
      src/main/java/com/rf/AIquantum/config/Swagger2Config.java
  14. 18 0
      src/main/java/com/rf/AIquantum/dao/dto/JpaDto.java
  15. 21 0
      src/main/java/com/rf/AIquantum/dao/dto/ProgressDto.java
  16. 2 0
      src/main/java/com/rf/AIquantum/dao/lombok.config
  17. 41 0
      src/main/java/com/rf/AIquantum/dialogue/dao/model/ChatHistoryEntity.java
  18. 33 0
      src/main/java/com/rf/AIquantum/dialogue/dao/model/DialogueEntity.java
  19. 31 0
      src/main/java/com/rf/AIquantum/dialogue/dao/repository/ChatHistoryRepository.java
  20. 31 0
      src/main/java/com/rf/AIquantum/dialogue/dao/repository/DialogueRepository.java
  21. 48 0
      src/main/java/com/rf/AIquantum/dialogue/rest/ChatHistoryController.java
  22. 203 0
      src/main/java/com/rf/AIquantum/dialogue/rest/DialogueController.java
  23. 21 0
      src/main/java/com/rf/AIquantum/dialogue/service/ChatHistoryService.java
  24. 19 0
      src/main/java/com/rf/AIquantum/dialogue/service/DialogueService.java
  25. 45 0
      src/main/java/com/rf/AIquantum/dialogue/service/impl/ChatHistoryServiceImpl.java
  26. 39 0
      src/main/java/com/rf/AIquantum/dialogue/service/impl/DialogueServiceImpl.java
  27. 93 0
      src/main/java/com/rf/AIquantum/filter/AuthenticationInterceptor.java
  28. 62 0
      src/main/java/com/rf/AIquantum/filter/JWTInterceptor.java
  29. 53 0
      src/main/java/com/rf/AIquantum/filter/JWTInterceptorConfig.java
  30. 12 0
      src/main/java/com/rf/AIquantum/filter/JwtIgnore.java
  31. 33 0
      src/main/java/com/rf/AIquantum/filter/UserCheckInterceptor.java
  32. 67 0
      src/main/java/com/rf/AIquantum/security/SSLConfig.java
  33. 37 0
      src/main/java/com/rf/AIquantum/user/dao/model/UserEntity.java
  34. 25 0
      src/main/java/com/rf/AIquantum/user/dao/repository/UserRepository.java
  35. 151 0
      src/main/java/com/rf/AIquantum/user/rest/UserController.java
  36. 19 0
      src/main/java/com/rf/AIquantum/user/service/UserService.java
  37. 41 0
      src/main/java/com/rf/AIquantum/user/service/impl/UserServiceImpl.java
  38. 40 0
      src/main/java/com/rf/AIquantum/utils/Constant.java
  39. 1228 0
      src/main/java/com/rf/AIquantum/utils/DateUtil.java
  40. 29 0
      src/main/java/com/rf/AIquantum/utils/EmailUtil.java
  41. 19 0
      src/main/java/com/rf/AIquantum/utils/HttpStatus.java
  42. 32 0
      src/main/java/com/rf/AIquantum/utils/IPUtiles.java
  43. 71 0
      src/main/java/com/rf/AIquantum/utils/JWTUtil.java
  44. 35 0
      src/main/java/com/rf/AIquantum/utils/LocalAssert.java
  45. 17 0
      src/main/java/com/rf/AIquantum/utils/PageRequestUtil.java
  46. 431 0
      src/main/java/com/rf/AIquantum/utils/RandomUtil.java
  47. 62 0
      src/main/java/com/rf/AIquantum/utils/Result.java
  48. 112 0
      src/main/java/com/rf/AIquantum/utils/SendEmail.java
  49. 44 0
      src/main/java/com/rf/AIquantum/utils/WebContextUtil.java
  50. 80 0
      src/main/java/com/rf/AIquantum/utils/XMLUtil.java
  51. 140 0
      src/main/java/com/rf/AIquantum/utils/ZipUtils.java
  52. 48 0
      src/main/resources/config/application-prod.yml
  53. 51 0
      src/main/resources/config/application-test.yml
  54. 26 0
      src/main/resources/config/application.yml
  55. 144 0
      src/main/resources/logback.xml
  56. 28 0
      src/main/resources/proguard.conf

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+# ---> Java
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+/.gradle/
+/build/
+/src/main/resources/static/
+/logs/
+/gradle/
+/.idea/

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# AIquantum
+
+review code

+ 120 - 0
build.gradle

@@ -0,0 +1,120 @@
+buildscript {
+	ext {
+		queryDslVersion = '4.2.1'
+		lombokVersion = '1.18.12'
+	}
+}
+plugins {
+	id 'org.springframework.boot' version '2.4.2'
+	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
+	id 'java'
+}
+
+group = 'com.rf'
+version = 'v1.1-'+getNewVersion()
+sourceCompatibility = '8'
+
+configurations {
+	compileOnly {
+		extendsFrom annotationProcessor
+	}
+}
+
+repositories {
+	maven {
+		url 'https://maven.aliyun.com/repository/public'
+	}
+	maven {
+		credentials {
+			username '0p07qf'
+			password 'z1XwdFEf4M'
+		}
+		url 'https://repo.rdc.aliyun.com/repository/107260-release-GqdtcU/'
+	}
+	maven {
+		credentials {
+			username '0p07qf'
+			password 'z1XwdFEf4M'
+		}
+		url 'https://repo.rdc.aliyun.com/repository/107260-snapshot-C6ziam/'
+	}
+	maven {
+		url "https://plugins.gradle.org/m2/"
+	}
+	mavenLocal()
+}
+
+dependencies {
+	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+	implementation 'org.springframework.boot:spring-boot-starter-web'
+	compileOnly 'org.projectlombok:lombok'
+	annotationProcessor 'org.projectlombok:lombok'
+	implementation 'org.springframework.boot:spring-boot-starter-validation:2.6.3'
+
+	implementation 'mysql:mysql-connector-java:8.0.21'
+
+	implementation("com.querydsl:querydsl-core:${queryDslVersion}")
+	implementation("com.querydsl:querydsl-jpa:${queryDslVersion}")
+	annotationProcessor("com.querydsl:querydsl-apt:${queryDslVersion}:jpa",
+			"org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final",
+			"javax.annotation:javax.annotation-api:1.3.2",
+			"org.projectlombok:lombok")
+
+	compileOnly "org.projectlombok:lombok:${lombokVersion}"
+	annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
+	implementation("org.projectlombok:lombok:${lombokVersion}")
+	testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.3'
+
+	implementation 'com.alibaba:fastjson:1.2.83'
+	implementation 'org.apache.poi:poi-ooxml:3.17'
+
+	implementation 'commons-lang:commons-lang:2.6'
+
+	implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
+	implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
+	implementation group: 'io.swagger', name: 'swagger-annotations', version: '1.5.22'
+	implementation group: 'io.swagger', name: 'swagger-models', version: '1.5.22'
+	implementation group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.1'
+	implementation group: 'com.github.qcloudsms', name: 'qcloudsms', version: '1.0.6'
+	implementation group: 'cn.keking.project', name: 'kk-anti-reptile', version: '1.0.0-RELEASE'
+	implementation group: 'com.belerweb', name: 'pinyin4j', version: '2.5.1'
+	implementation 'org.springframework.boot:spring-boot-starter-websocket:2.5.5'
+	implementation 'org.java-websocket:Java-WebSocket:1.5.1'
+	implementation 'com.auth0:java-jwt:3.18.2'
+	implementation group: 'com.alibaba', name: 'druid-spring-boot-starter', version: '1.2.9'
+	testImplementation group: 'junit', name: 'junit', version: '4.13.2'
+	implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.4.7'
+
+	implementation group: 'org.springframework.boot', name: 'spring-boot-configuration-processor', version: '2.6.8'
+
+	implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
+
+	implementation group: 'cn.hutool', name: 'hutool-all', version: '5.7.18'
+
+	implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '2.6.3'
+
+	implementation group: 'org.dom4j', name: 'dom4j', version: '2.1.1'
+
+	implementation group: 'commons-net', name: 'commons-net', version: '3.6'
+
+	implementation group: 'dnsjava', name: 'dnsjava', version: '2.1.1'
+
+	implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
+
+	implementation "io.github.fanyong920:jvppeteer:1.1.5"
+
+
+
+
+
+
+
+}
+
+test {
+	useJUnitPlatform()
+}
+
+def getNewVersion(){
+	return new Date().format("yyyyMMddHHmmss",TimeZone.getTimeZone("GMT+08:00"))
+}

+ 234 - 0
gradlew

@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"

+ 89 - 0
gradlew.bat

@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
settings.gradle

@@ -0,0 +1 @@
+rootProject.name = 'AIquantum'

+ 57 - 0
src/main/java/com/rf/AIquantum/AIquantumApplication.java

@@ -0,0 +1,57 @@
+package com.rf.AIquantum;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author zzf
+ */
+@EnableJpaRepositories(basePackages = {"com.rf.AIquantum"})
+@SpringBootApplication(scanBasePackages = {"com.rf.AIquantum"})
+@EnableJpaAuditing
+@EnableTransactionManagement
+@EnableScheduling
+@Slf4j
+public class AIquantumApplication {
+
+    static Logger logger = LoggerFactory.getLogger(AIquantumApplication.class);
+    @Autowired
+    static Environment environment;
+    @Value("${spring.profiles.active}")
+    static String profile;
+
+
+    public static void main(String[] args) {
+
+        SpringApplication.run(AIquantumApplication.class, args);
+
+    }
+
+
+    /**
+     * 让Spring管理JPAQueryFactory
+     *
+     * @param entityManager
+     * @return
+     */
+    @Bean
+    public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+        return new JPAQueryFactory(entityManager);
+    }
+
+
+}

+ 45 - 0
src/main/java/com/rf/AIquantum/base/model/BaseEntity.java

@@ -0,0 +1,45 @@
+package com.rf.AIquantum.base.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.hibernate.annotations.GenericGenerator;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:13
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@EntityListeners({AuditingEntityListener.class})
+@MappedSuperclass
+public class BaseEntity implements Serializable {
+    @Getter
+    @Id
+    @GenericGenerator(name = "jpa-uuid", strategy = "uuid")
+    @GeneratedValue(generator = "jpa-uuid")
+    @Column(name = "id", columnDefinition = "varchar(36) COMMENT '数据ID'")
+    @NotNull(groups = Update.class)
+    private String id;
+
+    @Column(name = "create_time", columnDefinition = "varchar(36) COMMENT '创建时间'")
+    private String createTime;
+
+
+    @Column(name = "update_time", columnDefinition = "varchar(36) COMMENT '更新时间'")
+    private String updateTime;
+
+
+
+    public @interface Update {
+    }
+}

+ 18 - 0
src/main/java/com/rf/AIquantum/base/repository/BaseRepository.java

@@ -0,0 +1,18 @@
+package com.rf.AIquantum.base.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+import org.springframework.data.repository.NoRepositoryBean;
+
+import java.io.Serializable;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:17
+ */
+@NoRepositoryBean
+public interface BaseRepository<T, PK extends Serializable> extends JpaRepository<T, PK>, JpaSpecificationExecutor, QuerydslPredicateExecutor<T> {
+
+}

+ 76 - 0
src/main/java/com/rf/AIquantum/base/rest/BaseController.java

@@ -0,0 +1,76 @@
+package com.rf.AIquantum.base.rest;
+
+import com.rf.AIquantum.utils.HttpStatus;
+import com.rf.AIquantum.utils.Result;
+
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:20
+ */
+public class BaseController {
+    protected static final String PAGE_NUM = "pageNum";
+
+    protected static final String PAGE_SIZE = "pageSize";
+
+    protected Result success() {
+        return success(null, "成功");
+    }
+
+    protected static <T> Result<T> success(T data) {
+        return success(data, "成功");
+    }
+
+    protected static <T> Result<T> success(T data, String message) {
+        if (null == data) {
+            return new Result<>(HttpStatus.SUCCESS, message);
+        }
+        return new Result<>(HttpStatus.SUCCESS, message, data);
+    }
+
+    protected static <T> Result<T> success(String code,T data, String message) {
+        if (null == data) {
+            return new Result<>(code, message);
+        }
+        return new Result<>(code, message, data);
+    }
+
+    protected Result fail() {
+        return fail(null, "失败");
+    }
+
+    protected static <T> Result<T> fail(T data) {
+        return fail(data, "失败");
+    }
+
+    protected static <T> Result<T> fail(String message) {
+        return new Result<>(HttpStatus.RUNTIME_EXCEPTION, message);
+    }
+
+    protected static <T> Result<T> fail(String code ,T data ,String message){
+        if(data == null)
+            return new Result<>(code,message);
+        else
+            return new Result<>(code,message,data);
+    }
+
+    protected static <T> Result<T> fail(T data, String message) {
+        if (null == data) {
+            return new Result<>(HttpStatus.RUNTIME_EXCEPTION, message);
+        }
+        return new Result<>(HttpStatus.RUNTIME_EXCEPTION, message, data);
+    }
+
+    protected Result failBadRequest() {
+        return failBadRequest(null, "参数异常");
+    }
+
+    protected static <T> Result<T> failBadRequest(T data) {
+        return failBadRequest(null, "参数异常");
+    }
+
+    protected static <T> Result<T> failBadRequest(T data, String message) {
+        return new Result<>(org.springframework.http.HttpStatus.BAD_REQUEST.value() + "", message, data);
+    }
+}

+ 30 - 0
src/main/java/com/rf/AIquantum/config/CorsConfig.java

@@ -0,0 +1,30 @@
+package com.rf.AIquantum.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+@Configuration
+public class CorsConfig {
+
+    private CorsConfiguration buildConfig() {
+
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.setAllowCredentials(true);
+        corsConfiguration.addAllowedOriginPattern("*");
+        corsConfiguration.addAllowedHeader("*");
+        corsConfiguration.addAllowedMethod("*");
+        return corsConfiguration;
+
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", buildConfig());
+        return new CorsFilter(source);
+    }
+
+}

+ 22 - 0
src/main/java/com/rf/AIquantum/config/Properties.java

@@ -0,0 +1,22 @@
+package com.rf.AIquantum.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author:zzf
+ * @Date:2022/7/5:18:15
+ * @Description:
+ */
+
+public class Properties {
+    private final Map<String, Duration> initCaches = new HashMap<>();
+    public Map<String ,Duration> getInitCache(){
+
+        return initCaches;
+    }
+}

+ 51 - 0
src/main/java/com/rf/AIquantum/config/Swagger2Config.java

@@ -0,0 +1,51 @@
+package com.rf.AIquantum.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import springfox.documentation.builders.ApiInfoBuilder;
+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;
+
+/**
+ * @author lpf
+ * @description:swagger 配置
+ * @date 2022/3/14 19:25
+ */
+@Configuration
+@EnableSwagger2
+@Profile({"test","lan"})
+public class Swagger2Config {
+
+    @Bean
+    public Docket createRestApi() {
+        ParameterBuilder tokenPar = new ParameterBuilder();
+        List<Parameter> pars = new ArrayList<>();
+        tokenPar.name("Authorization").description("token令牌,格式为Bearer Token(可从/test/token接口处获取临时测试token)").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+        pars.add(tokenPar.build());
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.rf.AIquantum"))
+                .paths(PathSelectors.any())
+                .build()
+                .globalOperationParameters(pars);
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("量子AI智能体")
+                .version("v1.0")
+                .build();
+    }
+}

+ 18 - 0
src/main/java/com/rf/AIquantum/dao/dto/JpaDto.java

@@ -0,0 +1,18 @@
+package com.rf.AIquantum.dao.dto;
+
+import org.springframework.stereotype.Component;
+
+import java.lang.annotation.*;
+
+/**
+ * @author lpf
+ * @description: 自定义注解类,加载dto上表示这是个JpaDto类,解决jpa原生不能返回dto的问题
+ * @date 2022/4/6 21:08
+ */
+
+@Documented
+@Component
+@Target(value = {ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JpaDto {
+}

+ 21 - 0
src/main/java/com/rf/AIquantum/dao/dto/ProgressDto.java

@@ -0,0 +1,21 @@
+package com.rf.AIquantum.dao.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2022/5/5 18:02
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProgressDto {
+
+    private long maxNum;
+
+    private long havingDoNum;
+
+}

+ 2 - 0
src/main/java/com/rf/AIquantum/dao/lombok.config

@@ -0,0 +1,2 @@
+config.stopbubbling=true
+lombok.equalsandhashcode.callsuper=call

+ 41 - 0
src/main/java/com/rf/AIquantum/dialogue/dao/model/ChatHistoryEntity.java

@@ -0,0 +1,41 @@
+package com.rf.AIquantum.dialogue.dao.model;
+
+import com.rf.AIquantum.base.model.BaseEntity;
+import lombok.*;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author zsy
+ * @description:聊天记录表
+ * @date 2021/6/17 15:55
+ */
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "t_chat_history")
+@EqualsAndHashCode(callSuper=true)
+@org.hibernate.annotations.Table(appliesTo = "t_chat_history", comment = "聊天记录表")
+public class ChatHistoryEntity extends BaseEntity {
+
+    @Column(name = "dialogue_id", columnDefinition = "varchar(36) not null comment '关联对话ID'")
+    private String dialogueId;
+
+    @Column(name = "role", columnDefinition = "varchar(50) not null comment  '消息角色(取值范围为 system、user 或 assistant)'")
+    private String role;
+
+    @Column(name = "content", columnDefinition = "text not null comment '消息内容'")
+    private String content;
+
+    @Column(name = "image", columnDefinition = "longtext comment '图片(Base64编码的字符串表示)'")
+    private String image;
+
+    @Column(name = "status", columnDefinition = "int(2) not null comment  '状态(0:删除;1:正常)'")
+    private int status;
+
+}

+ 33 - 0
src/main/java/com/rf/AIquantum/dialogue/dao/model/DialogueEntity.java

@@ -0,0 +1,33 @@
+package com.rf.AIquantum.dialogue.dao.model;
+
+import com.rf.AIquantum.base.model.BaseEntity;
+import lombok.*;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+/**
+ * @author zsy
+ * @description:对话信息表
+ * @date 2021/6/17 15:55
+ */
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "t_dialogue_info")
+@EqualsAndHashCode(callSuper=true)
+@org.hibernate.annotations.Table(appliesTo = "t_dialogue_info", comment = "对话信息表")
+public class DialogueEntity extends BaseEntity {
+
+    @Column(name = "dialogue_name", columnDefinition = "varchar(60) not null comment '对话名称'")
+    private String dialogueName;
+
+    @Column(name = "phone", columnDefinition = "varchar(36) not null comment '所属用户手机号'")
+    private String phone;
+
+    @Column(name = "status", columnDefinition = "int(2) not null comment  '状态(0:删除;1:正常)'")
+    private int status;
+
+}

+ 31 - 0
src/main/java/com/rf/AIquantum/dialogue/dao/repository/ChatHistoryRepository.java

@@ -0,0 +1,31 @@
+package com.rf.AIquantum.dialogue.dao.repository;
+
+import com.rf.AIquantum.base.repository.BaseRepository;
+import com.rf.AIquantum.dialogue.dao.model.ChatHistoryEntity;
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import org.apache.catalina.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @Description: 聊天记录相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface ChatHistoryRepository extends BaseRepository<ChatHistoryEntity, String> {
+
+
+    List<ChatHistoryEntity> findChatHistoryByDialogueIdAndStatus(String dialogueId,int status);
+
+    @Query(value = "select * from t_chat_history where dialogue_id = ?1 AND status = ?2 order by create_time desc",nativeQuery = true)
+    Page<ChatHistoryEntity> findByDialogueIdAndStatus(String dialogueId, int status, PageRequest of);
+}

+ 31 - 0
src/main/java/com/rf/AIquantum/dialogue/dao/repository/DialogueRepository.java

@@ -0,0 +1,31 @@
+package com.rf.AIquantum.dialogue.dao.repository;
+
+import com.rf.AIquantum.base.repository.BaseRepository;
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import org.apache.catalina.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @Description: 对话相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface DialogueRepository extends BaseRepository<DialogueEntity, String> {
+
+
+    UserEntity findUserByPhone(String phone);
+
+    @Query(value = "select * from t_dialogue_info where phone = ?1 " +
+            " AND status = ?2 AND if( ?3 is not null and  ?3 != '', (dialogue_name like CONCAT('%',  ?3, '%')), 1 = 1) order by create_time desc",nativeQuery = true)
+    Page<DialogueEntity> findByPhoneAndStatusAndSearch(String phone, int status, String search, PageRequest of);
+}

+ 48 - 0
src/main/java/com/rf/AIquantum/dialogue/rest/ChatHistoryController.java

@@ -0,0 +1,48 @@
+package com.rf.AIquantum.dialogue.rest;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.rf.AIquantum.base.rest.BaseController;
+import com.rf.AIquantum.dialogue.dao.model.ChatHistoryEntity;
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.dialogue.service.ChatHistoryService;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import com.rf.AIquantum.user.service.UserService;
+import com.rf.AIquantum.utils.Constant;
+import com.rf.AIquantum.utils.JWTUtil;
+import com.rf.AIquantum.utils.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.util.DigestUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 聊天记录相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@RestController
+@RequestMapping("/chat")
+@Api(tags = "聊天记录相关接口")
+public class ChatHistoryController extends BaseController {
+
+    @Autowired
+    private ChatHistoryService chatHistoryService;
+
+    @GetMapping("/findChats")
+    @ApiOperation(value = "查询聊天记录",notes = "参数包括:pageNum:页码, pageSize:数量, dialogueId:对话id")
+    public Result findDialogues(@RequestParam int pageNum, @RequestParam int pageSize, @RequestParam String dialogueId){
+        Page<ChatHistoryEntity> chatHistoryEntities = chatHistoryService.findByDialogueIdAndStatus(pageNum,pageSize,dialogueId,1);
+        return success(chatHistoryEntities);
+    }
+
+}

+ 203 - 0
src/main/java/com/rf/AIquantum/dialogue/rest/DialogueController.java

@@ -0,0 +1,203 @@
+package com.rf.AIquantum.dialogue.rest;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.rf.AIquantum.base.rest.BaseController;
+import com.rf.AIquantum.dialogue.dao.model.ChatHistoryEntity;
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.dialogue.service.ChatHistoryService;
+import com.rf.AIquantum.dialogue.service.DialogueService;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import com.rf.AIquantum.user.service.UserService;
+import com.rf.AIquantum.utils.Constant;
+import com.rf.AIquantum.utils.JWTUtil;
+import com.rf.AIquantum.utils.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 对话相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@RestController
+@RequestMapping("/dialogue")
+@Api(tags = "对话相关接口")
+public class DialogueController extends BaseController {
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private DialogueService dialogueService;
+
+    @Autowired
+    private ChatHistoryService chatHistoryService;
+
+    @PostMapping("/saveChat")
+    @ApiOperation(value = "保存对话",notes = "参数包括:phone:手机号, dialogueId:对话id(为空时是新建对话), content:消息内容,image:图片(Base64格式,可以为空)")
+    public Result saveChat(@RequestBody String jsonParam) throws UnsupportedEncodingException {
+        JSONObject jsonObject =JSONObject.parseObject(jsonParam);
+        if (!jsonObject.containsKey("phone")) {
+            return fail("", "缺少参数:phone");
+        }
+        if (!jsonObject.containsKey("dialogueId")) {
+            return fail("", "缺少参数:dialogueId");
+        }
+        if (!jsonObject.containsKey("content")) {
+            return fail("", "缺少参数:content");
+        }
+        if (!jsonObject.containsKey("image")) {
+            return fail("", "缺少参数:image");
+        }
+        String phone = jsonObject.getString("phone");
+        UserEntity user = this.userService.findUserByPhone(phone);
+        if (user == null){
+            return fail(null,"用户不存在");
+        }
+        String content = jsonObject.getString("content");
+        String image = jsonObject.getString("image");
+        String dialogueId = jsonObject.getString("dialogueId");
+        if (dialogueId.equals("") || dialogueId == null){
+            if (content.length() > 50){
+                content = content.substring(0,50);
+            }
+            //新建对话
+            DialogueEntity dialogueEntity = new DialogueEntity();
+            dialogueEntity.setDialogueName(content);
+            dialogueEntity.setPhone(phone);
+            dialogueEntity.setStatus(1);
+            dialogueEntity.setCreateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+            dialogueEntity.setUpdateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+            dialogueEntity = this.dialogueService.save(dialogueEntity);
+            dialogueId = dialogueEntity.getId();
+        }
+        ChatHistoryEntity chatHistoryEntity = new ChatHistoryEntity();
+        chatHistoryEntity.setDialogueId(dialogueId);
+        chatHistoryEntity.setRole("user");
+        chatHistoryEntity.setContent(content);
+        chatHistoryEntity.setImage(image);
+        chatHistoryEntity.setStatus(1);
+        chatHistoryEntity.setCreateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+        chatHistoryEntity.setUpdateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+        this.chatHistoryService.save(chatHistoryEntity);
+        //调用模型相关操作
+        List<ChatHistoryEntity> chatHistoryEntities = this.chatHistoryService.findChatHistoryByDialogueIdAndStatus(dialogueId);
+        JSONArray messages = new JSONArray();
+        for (ChatHistoryEntity chatHistory : chatHistoryEntities) {
+            JSONArray contents = new JSONArray();
+            JSONObject jsonText = new JSONObject();
+            jsonText.put("type","text");
+            jsonText.put("text",chatHistory.getContent());
+            if (chatHistory.getImage() != null && !chatHistory.getImage().equals("")) {
+                JSONObject jsonImage = new JSONObject();
+                jsonImage.put("type","image_url");
+                JSONObject jsonUrl = new JSONObject();
+                jsonUrl.put("url",chatHistory.getImage());
+                jsonImage.put("image_url",jsonUrl);
+                contents.add(jsonImage);
+            }
+            contents.add(jsonText);
+            JSONObject jsonRole = new JSONObject();
+            jsonRole.put("role",chatHistory.getRole());
+            jsonRole.put("content",contents);
+            messages.add(jsonRole);
+        }
+        JSONObject jsonChat = new JSONObject();
+        jsonChat.put("messages",messages);
+
+        String url = Constant.INVOKE_IP_PROT + Constant.CHAT_PATH;
+        String data = HttpClientChat(jsonChat,url);
+        JSONObject jsonSystem = JSONObject.parseObject(data);
+        if (jsonSystem == null || !jsonSystem.containsKey("response")) {
+            return fail("", "模型服务内部错误");
+        }
+        content = jsonSystem.getString("response");
+        chatHistoryEntity = new ChatHistoryEntity();
+        chatHistoryEntity.setDialogueId(dialogueId);
+        chatHistoryEntity.setRole("system");
+        chatHistoryEntity.setContent(content);
+        chatHistoryEntity.setStatus(1);
+        chatHistoryEntity.setCreateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+        chatHistoryEntity.setUpdateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+        chatHistoryEntity = this.chatHistoryService.save(chatHistoryEntity);
+
+        return success(chatHistoryEntity);
+    }
+
+    @GetMapping("/findDialogues")
+    @ApiOperation(value = "查询对话列表",notes = "参数包括:pageNum:页码, pageSize:数量, search:搜索内容")
+    public Result findDialogues(@RequestParam int pageNum, @RequestParam int pageSize, @RequestParam String search, HttpServletRequest request){
+        String token = request.getHeader("Authorization");
+        String[] tokens = token.split(" ");
+        if (tokens.length != 2) {
+            token = tokens[0];
+        }else {
+            token = tokens[1];
+        }
+        JWTUtil.verify(token);
+        DecodedJWT verify = JWTUtil.verify(token);
+        String phone = verify.getClaim("phone").asString();
+        Page<DialogueEntity> dialogueEntities = dialogueService.findByPhoneAndStatusAndSearch(pageNum,pageSize,phone,1,search);
+        return success(dialogueEntities);
+    }
+
+    @PostMapping("/updateDialogues")
+    @ApiOperation(value = "修改对话信息(重命名和删除)",notes = "Dialogues对象,修改对话名称时只需将修改后的名称放入dialogueName中;删除对话名称时只需将status的值改为0")
+    public Result updateDialogues(@RequestBody String json) {
+        DialogueEntity dialogueEntity = JSONObject.parseObject(json,DialogueEntity.class);
+        dialogueEntity.setUpdateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS"));
+        this.dialogueService.save(dialogueEntity);
+        return success("修改成功");
+    }
+
+    public static String HttpClientChat(JSONObject jsonChat, String url) throws UnsupportedEncodingException {
+        System.out.println("11:"+jsonChat);
+        CloseableHttpClient httpclient = HttpClients.createDefault();
+        HttpPost httpPost = new HttpPost(url);
+        StringEntity entity = new StringEntity(jsonChat.toString(),"UTF-8");
+        entity.setContentEncoding("UTF-8");
+        entity.setContentType("application/json");
+        httpPost.setEntity(entity);
+        HttpResponse response = null;
+        String responseData = null;
+        try {
+            response = httpclient.execute(httpPost);
+            if (response.getStatusLine().getStatusCode() == 200){
+                responseData =  EntityUtils.toString(response.getEntity());
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                httpclient.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return responseData;
+    }
+
+}

+ 21 - 0
src/main/java/com/rf/AIquantum/dialogue/service/ChatHistoryService.java

@@ -0,0 +1,21 @@
+package com.rf.AIquantum.dialogue.service;
+
+import com.rf.AIquantum.dialogue.dao.model.ChatHistoryEntity;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import org.springframework.data.domain.Page;
+
+import java.util.List;
+
+/**
+ * @Description: 聊天记录相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface ChatHistoryService {
+
+    ChatHistoryEntity save(ChatHistoryEntity chatHistoryEntity);
+
+    List<ChatHistoryEntity> findChatHistoryByDialogueIdAndStatus(String dialogueId);
+
+    Page<ChatHistoryEntity> findByDialogueIdAndStatus(int pageNum, int pageSize, String dialogueId, int status);
+}

+ 19 - 0
src/main/java/com/rf/AIquantum/dialogue/service/DialogueService.java

@@ -0,0 +1,19 @@
+package com.rf.AIquantum.dialogue.service;
+
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import org.springframework.data.domain.Page;
+
+import java.util.List;
+
+/**
+ * @Description: 对话相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface DialogueService {
+
+    DialogueEntity save(DialogueEntity dialogueEntity);
+
+    Page<DialogueEntity> findByPhoneAndStatusAndSearch(int pageNum, int pageSize, String phone, int status, String search);
+}

+ 45 - 0
src/main/java/com/rf/AIquantum/dialogue/service/impl/ChatHistoryServiceImpl.java

@@ -0,0 +1,45 @@
+package com.rf.AIquantum.dialogue.service.impl;
+
+import com.rf.AIquantum.dialogue.dao.model.ChatHistoryEntity;
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.dialogue.dao.repository.ChatHistoryRepository;
+import com.rf.AIquantum.dialogue.service.ChatHistoryService;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import com.rf.AIquantum.user.dao.repository.UserRepository;
+import com.rf.AIquantum.user.service.UserService;
+import com.rf.AIquantum.utils.Constant;
+import com.rf.AIquantum.utils.PageRequestUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 聊天记录相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@Service
+public class ChatHistoryServiceImpl implements ChatHistoryService {
+
+    @Autowired
+    private ChatHistoryRepository chatHistoryRepository;
+
+    @Override
+    public ChatHistoryEntity save(ChatHistoryEntity chatHistoryEntity) {
+        return this.chatHistoryRepository.save(chatHistoryEntity);
+    }
+
+    @Override
+    public List<ChatHistoryEntity> findChatHistoryByDialogueIdAndStatus(String dialogueId) {
+        return this.chatHistoryRepository.findChatHistoryByDialogueIdAndStatus(dialogueId,1);
+    }
+
+    @Override
+    public Page<ChatHistoryEntity> findByDialogueIdAndStatus(int pageNum, int pageSize, String dialogueId, int status) {
+        Page<ChatHistoryEntity> page = this.chatHistoryRepository.findByDialogueIdAndStatus(dialogueId,status,PageRequestUtil.of(pageNum, pageSize));
+        return page;
+    }
+}

+ 39 - 0
src/main/java/com/rf/AIquantum/dialogue/service/impl/DialogueServiceImpl.java

@@ -0,0 +1,39 @@
+package com.rf.AIquantum.dialogue.service.impl;
+
+import com.rf.AIquantum.dialogue.dao.model.DialogueEntity;
+import com.rf.AIquantum.dialogue.dao.repository.DialogueRepository;
+import com.rf.AIquantum.dialogue.service.DialogueService;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import com.rf.AIquantum.user.dao.repository.UserRepository;
+import com.rf.AIquantum.user.service.UserService;
+import com.rf.AIquantum.utils.Constant;
+import com.rf.AIquantum.utils.PageRequestUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 对话相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@Service
+public class DialogueServiceImpl implements DialogueService {
+
+    @Autowired
+    private DialogueRepository dialogueRepository;
+
+    @Override
+    public DialogueEntity save(DialogueEntity dialogueEntity) {
+        return this.dialogueRepository.save(dialogueEntity);
+    }
+
+    @Override
+    public Page<DialogueEntity> findByPhoneAndStatusAndSearch(int pageNum, int pageSize, String phone, int status, String search) {
+        Page<DialogueEntity> page = this.dialogueRepository.findByPhoneAndStatusAndSearch(phone,status,search, PageRequestUtil.of(pageNum, pageSize));
+        return page;
+    }
+}

+ 93 - 0
src/main/java/com/rf/AIquantum/filter/AuthenticationInterceptor.java

@@ -0,0 +1,93 @@
+package com.rf.AIquantum.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.auth0.jwt.exceptions.AlgorithmMismatchException;
+import com.auth0.jwt.exceptions.SignatureVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.rf.AIquantum.filter.JwtIgnore;
+import com.rf.AIquantum.utils.JWTUtil;
+import com.rf.AIquantum.utils.LocalAssert;
+import com.rf.AIquantum.utils.WebContextUtil;
+import io.swagger.models.HttpMethod;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+/**
+ * @Description:使用AuthenticationInterceptor拦截器对接口参数进行验证
+ * @Author: mimang
+ * @Date: 2024/9/6
+ */
+@Slf4j
+@Component
+public class AuthenticationInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        HashMap<String, Object> resultJson = new HashMap<>();
+        final String url = request.getRequestURI();
+        log.info("url-------------------"+url);
+        // 从http请求头中取出token
+        final String token = request.getHeader(JWTUtil.AUTH_HEADER_KEY);
+        //如果不是映射到方法,直接通过
+        if(!(handler instanceof HandlerMethod)){
+            return true;
+        }
+        //如果是方法探测,直接通过
+        if (HttpMethod.OPTIONS.equals(request.getMethod())) {
+            response.setStatus(HttpServletResponse.SC_OK);
+            return true;
+        }
+        //如果方法有JwtIgnore注解,直接通过
+        HandlerMethod handlerMethod = (HandlerMethod) handler;
+        Method method=handlerMethod.getMethod();
+        if (method.isAnnotationPresent(JwtIgnore.class)) {
+            JwtIgnore jwtIgnore = method.getAnnotation(JwtIgnore.class);
+            if(jwtIgnore.value()){
+                return true;
+            }
+        }
+
+        try {
+            LocalAssert.isStringEmpty(token, "token为空,鉴权失败!");
+            //验证,并获取token内部信息
+            String userToken = JWTUtil.verifyToken(token);
+            //将token放入本地缓存
+            WebContextUtil.setUserToken(userToken);
+            return true;
+        }catch (SignatureVerificationException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "无效签名信息");
+        } catch (AlgorithmMismatchException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "token算法不一致");
+        }catch (TokenExpiredException e){
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "token已过期,请重新获取");
+        } catch (Exception e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "登录状态失效,请重新登录");
+        }
+        String s = JSON.toJSONString(resultJson);
+        response.setContentType("application/json;charset=UTF-8");
+        response.getWriter().println(s);
+        return false;
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        //方法结束后,移除缓存的token
+        WebContextUtil.removeUserToken();
+    }
+}
+

+ 62 - 0
src/main/java/com/rf/AIquantum/filter/JWTInterceptor.java

@@ -0,0 +1,62 @@
+package com.rf.AIquantum.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.auth0.jwt.exceptions.AlgorithmMismatchException;
+import com.auth0.jwt.exceptions.SignatureVerificationException;
+import com.rf.AIquantum.utils.JWTUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2821:48
+ */
+@Slf4j
+public class JWTInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        HashMap<String, Object> resultJson = new HashMap<>();
+        String uri = request.getRequestURI();
+        try {
+            String token = request.getHeader("Authorization");
+            if(StringUtils.isEmpty(token)) {
+                resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+                resultJson.put("msg", "无效签名信息");
+            }
+            String[] len = token.split(" ");
+            if (len.length >=1){
+                token = len[1];
+                JWTUtil.verify(token);
+                return true;
+            }else {
+                resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+                resultJson.put("msg", "无效签名信息");
+            }
+
+        } catch (SignatureVerificationException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "无效签名信息");
+        } catch (AlgorithmMismatchException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "token算法不一致");
+        } catch (Exception e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "登录状态失效,请重新登录");
+        }
+        String s = JSON.toJSONString(resultJson);
+        response.setContentType("application/json;charset=UTF-8");
+        response.getWriter().println(s);
+        return false;
+    }
+}

+ 53 - 0
src/main/java/com/rf/AIquantum/filter/JWTInterceptorConfig.java

@@ -0,0 +1,53 @@
+package com.rf.AIquantum.filter;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2822:06
+ */
+@Configuration
+public class JWTInterceptorConfig implements WebMvcConfigurer {
+
+    /*@Autowired
+    private UserCheckInterceptor userCheckInterceptor;
+
+    @Autowired
+    private JWTInterceptor jwtInterceptor;*/
+
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        String[] swaggerExcludes = new String[]{"/swagger-ui.html", "/swagger-resources/**", "/csrf", "/webjars/**"};
+        String[] systemApi = new String[]{"/user/addUser","/user/login"};
+        registry.addInterceptor(new AuthenticationInterceptor())
+                .addPathPatterns("/**")
+                .excludePathPatterns("/", "/index**", "/error")
+                .excludePathPatterns(systemApi)
+                .excludePathPatterns(swaggerExcludes)
+                .excludePathPatterns("/favicon.ico")
+                .excludePathPatterns("/druid/**")
+                .excludePathPatterns("/static/**");
+        registry.addInterceptor(new AuthenticationInterceptor())
+                .addPathPatterns("/**")
+                .excludePathPatterns("/", "/index.html", "/error")
+                .excludePathPatterns(systemApi)
+                .excludePathPatterns(swaggerExcludes)
+                .excludePathPatterns("/favicon.ico")
+                .excludePathPatterns("/druid/**")
+                .excludePathPatterns("/static/**");
+
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/static/**")
+                .addResourceLocations("classpath:/static/");
+    }
+}

+ 12 - 0
src/main/java/com/rf/AIquantum/filter/JwtIgnore.java

@@ -0,0 +1,12 @@
+package com.rf.AIquantum.filter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JwtIgnore {
+    boolean value() default true;
+}

+ 33 - 0
src/main/java/com/rf/AIquantum/filter/UserCheckInterceptor.java

@@ -0,0 +1,33 @@
+package com.rf.AIquantum.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.rf.AIquantum.utils.JWTUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/01/20 16:54
+ */
+public class UserCheckInterceptor implements HandlerInterceptor {
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        HashMap<String, Object> resultJson = new HashMap<>();
+        String uri = request.getRequestURI();
+        String token = request.getHeader("Authorization");
+        token = token.split(" ")[1];
+        JWTUtil.verify(token);
+        DecodedJWT verify = JWTUtil.verify(token);
+        String userId = verify.getClaim("userId").asString();
+        String type = verify.getClaim("type").asString();
+        return true;
+    }
+}

+ 67 - 0
src/main/java/com/rf/AIquantum/security/SSLConfig.java

@@ -0,0 +1,67 @@
+package com.rf.AIquantum.security;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/9/15 14:32
+ */
+@Configuration
+@Profile({"prod", "public"})
+public class SSLConfig {
+
+    @Value("${spring.profiles.active}")
+    private String profile;
+
+    @Bean
+    public TomcatServletWebServerFactory servletContainer() {
+
+        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
+
+            @Override
+            protected void postProcessContext(Context context) {
+
+                SecurityConstraint securityConstraint = new SecurityConstraint();
+                securityConstraint.setUserConstraint("CONFIDENTIAL");
+                SecurityCollection collection = new SecurityCollection();
+                collection.addPattern("/*");
+                securityConstraint.addCollection(collection);
+                context.addConstraint(securityConstraint);
+            }
+        };
+        tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
+        return tomcat;
+    }
+
+
+    private Connector initiateHttpConnector() {
+        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+        connector.setScheme("http");
+        connector.setSecure(false);
+        if ("prod".equals(profile)) {
+            connector.setPort(8082);
+            connector.setRedirectPort(8848);
+        } else if ("public".equals(profile)) {
+            connector.setPort(8081);
+            connector.setRedirectPort(8443);
+        } else {
+            //TODO 待定
+            connector.setPort(9528);
+            connector.setRedirectPort(8849);
+        }
+
+
+        return connector;
+    }
+
+}

+ 37 - 0
src/main/java/com/rf/AIquantum/user/dao/model/UserEntity.java

@@ -0,0 +1,37 @@
+package com.rf.AIquantum.user.dao.model;
+
+import com.rf.AIquantum.base.model.BaseEntity;
+import lombok.*;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+
+/**
+ * @author zsy
+ * @description:用户信息表
+ * @date 2021/6/17 15:55
+ */
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "t_user_info")
+@EqualsAndHashCode(callSuper=true)
+@org.hibernate.annotations.Table(appliesTo = "t_user_info", comment = "用户信息表")
+public class UserEntity extends BaseEntity {
+
+    @Column(name = "user_name", columnDefinition = "varchar(50) not null comment '用户名'")
+    private String userName;
+
+    @Column(name = "phone", columnDefinition = "varchar(36) not null comment '手机号(唯一、登录名)'")
+    private String phone;
+
+    @Column(name = "password", columnDefinition = "varchar(32) not null comment '密码'")
+    private String password;
+
+    @Column(name = "role_type", columnDefinition = "varchar(2) default '1' comment  '角色(默认为1 1普通用户;2 管理员)'")
+    private String roleType;
+
+}

+ 25 - 0
src/main/java/com/rf/AIquantum/user/dao/repository/UserRepository.java

@@ -0,0 +1,25 @@
+package com.rf.AIquantum.user.dao.repository;
+
+import com.rf.AIquantum.base.repository.BaseRepository;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import org.apache.catalina.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface UserRepository extends BaseRepository<UserEntity, String> {
+
+
+    UserEntity findUserByPhone(String phone);
+}

+ 151 - 0
src/main/java/com/rf/AIquantum/user/rest/UserController.java

@@ -0,0 +1,151 @@
+package com.rf.AIquantum.user.rest;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.rf.AIquantum.base.rest.BaseController;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import com.rf.AIquantum.user.service.UserService;
+import com.rf.AIquantum.utils.Constant;
+import com.rf.AIquantum.utils.JWTUtil;
+import com.rf.AIquantum.utils.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.DigestUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@RestController
+@RequestMapping("/user")
+@Api(tags = "用户注册登录等相关接口")
+public class UserController extends BaseController {
+
+    @Autowired
+    private UserService userService;
+
+    @PostMapping("/addUser")
+    @ApiOperation(value = "新增用户",notes = "参数包括:userName:用户名, phone:手机号, password:密码(MD5加密后的字符串)")
+    public Result addOrUpdateUser(@RequestBody String jsonParam){
+        JSONObject jsonObject =JSONObject.parseObject(jsonParam);
+        if (!jsonObject.containsKey("phone") || !jsonObject.containsKey("password") || !jsonObject.containsKey("userName")) {
+            return fail("", "手机号、密码、用户名不能为空");
+        }
+        String phone = jsonObject.getString("phone");
+        UserEntity user = this.userService.findUserByPhone(phone);
+        if (user != null){
+            return fail(null,"手机号已存在");
+        }
+        user = new UserEntity();
+        user.setPhone(phone);
+        user.setPassword(jsonObject.getString("password"));
+        user.setUserName(jsonObject.getString("userName"));
+        user.setRoleType("1");
+        user.setCreateTime(DateUtil.now());
+        user.setUpdateTime(DateUtil.now());
+        userService.save(user);
+        return success("操作成功");
+    }
+
+    @ApiOperation(value = "系统登录接口",notes = "参数包括:phone:账号, password:密码(MD5加密后的字符串)")
+    @PostMapping("/login")
+    public Result login(HttpServletRequest request, @RequestBody String jsonParam){
+        try {
+            JSONObject jsonObject =JSONObject.parseObject(jsonParam);
+            if (!jsonObject.containsKey("phone") || !jsonObject.containsKey("password") ) {
+                return fail("", "账号或密码不能为空");
+            }
+            String password = jsonObject.getString("password");
+            String phone = jsonObject.getString("phone");
+            UserEntity userEntity = this.userService.findUserByPhone(phone);
+            if (userEntity == null) {
+                return fail(null, "用户不存在");
+            }
+            if (userEntity.getPassword().equals(password)) {
+                userEntity.setPassword(null);
+                String token = JWTUtil.getTokenByUserInfo(userEntity);
+                JSONObject resultJson = new JSONObject();
+                resultJson.put("user", userEntity);
+                resultJson.put("token", token);
+                request.getSession().setAttribute("user", userEntity);
+                return success(resultJson);
+            } else {
+                return fail(null, "密码错误");
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            return fail();
+        }
+    }
+
+    /**
+     * 修改密码
+     * @param jsonParam 待修改用户密码参数
+     * @return
+     */
+    @ApiOperation(value = "修改密码",notes = "data参数包括:id:用户id,password:新密码(MD5加密后的字符串),oldPassword:旧密码(MD5加密后的字符串)")
+    @PostMapping("/updatePassword")
+    public Result updatePassword(@RequestBody String jsonParam){
+        try {
+            JSONObject jsonObject =JSONObject.parseObject(jsonParam);
+            if(!jsonObject.containsKey("id")|| StringUtils.isEmpty(jsonObject.getString("id")))
+                return failBadRequest(null,"用户id不能为空!");
+            if(!jsonObject.containsKey("oldPassword")|| StringUtils.isEmpty(jsonObject.getString("oldPassword")))
+                return failBadRequest(null,"旧密码不能为空!");
+            if(!jsonObject.containsKey("password")|| StringUtils.isEmpty(jsonObject.getString("password")))
+                return failBadRequest(null,"新密码不能为空!");
+            String password =  jsonObject.getString("password");
+            String oldPassword = jsonObject.getString("oldPassword");
+            String id = jsonObject.getString("id");
+            UserEntity userEntity = userService.findById(id);
+            if (userEntity == null) {
+                return fail(null, "用户不存在");
+            }
+            if (!userEntity.getPassword().equals(oldPassword)) {
+                return fail("", "旧密码有误");
+            }
+            userEntity.setPassword(password);
+            userEntity.setUpdateTime(DateUtil.now());
+            this.userService.save(userEntity);
+            return success();
+        }catch (Exception e){
+            e.printStackTrace();
+            return fail();
+        }
+    }
+
+    /**
+     * 登出
+     * @param userNo 账号
+     * @desc
+     * @return
+     */
+    /*@ApiOperation(value = "登出",notes = "json字符串形式传参(加密),data参数包括:userNo:账号" )
+    @PostMapping("/logout")
+    public Result logout(@RequestParam String userNo){
+        try {
+            if ( StringUtils.isEmpty( userNo)    ) {
+                return fail("", "账号不能为空");
+            }
+            //首先校验用户是否存在
+            UserEntity userEntity = userService.findUserByUserNo(userNo);
+            if (userEntity == null){
+                return fail(null,"用户不存在");
+            }
+            return success();
+        }catch (Exception e){
+            e.printStackTrace();
+            return fail();
+        }
+    }*/
+
+}

+ 19 - 0
src/main/java/com/rf/AIquantum/user/service/UserService.java

@@ -0,0 +1,19 @@
+package com.rf.AIquantum.user.service;
+
+import com.rf.AIquantum.user.dao.model.UserEntity;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface UserService {
+
+    public String getSystemVersion();
+
+    UserEntity findUserByPhone(String phone);
+
+    void save(UserEntity userEntity);
+
+    UserEntity findById(String id);
+}

+ 41 - 0
src/main/java/com/rf/AIquantum/user/service/impl/UserServiceImpl.java

@@ -0,0 +1,41 @@
+package com.rf.AIquantum.user.service.impl;
+
+import com.rf.AIquantum.user.dao.model.UserEntity;
+import com.rf.AIquantum.user.dao.repository.UserRepository;
+import com.rf.AIquantum.user.service.UserService;
+import com.rf.AIquantum.utils.Constant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@Service
+public class UserServiceImpl implements UserService {
+
+    @Autowired
+    private UserRepository userRepository;
+    @Override
+    public String getSystemVersion() {
+        return Constant.SYSTEM_VERSION;
+    }
+
+    @Override
+    public UserEntity findUserByPhone(String phone) {
+        return this.userRepository.findUserByPhone(phone);
+    }
+
+    @Override
+    public void save(UserEntity userEntity) {
+        this.userRepository.save(userEntity);
+    }
+
+    @Override
+    public UserEntity findById(String id) {
+        return this.userRepository.findById(id).orElse(null);
+    }
+}

+ 40 - 0
src/main/java/com/rf/AIquantum/utils/Constant.java

@@ -0,0 +1,40 @@
+package com.rf.AIquantum.utils;
+
+/**
+ * @author zzf
+ * @description:静态类
+ * @date 2021/1/19 16:45
+ */
+public class Constant {
+
+
+    public static final String SYSTEM_VERSION ="1.0";
+
+
+
+    public static final String DEFAULT_VALUE_ZERO ="0";
+
+    public static String MAGIC_NUM_0 = "0";
+    public static String MAGIC_NUM_1 = "1";
+    public static String MAGIC_NUM_2 = "2";
+
+    public static final String DATE_TRANS_FLAG_START = "start";
+    public static final String DATE_TRANS_FLAG_END = "end";
+
+
+    public static final String DEFAULT_PASSWORD = "123456";
+
+    //调用模型的IP和端口
+    public static final String INVOKE_IP_PROT = "https://u439933-9915-1c8b14ad.bjc1.seetacloud.com:8443";
+    //聊天功能接口路径
+    public static final String CHAT_PATH = "/chat";
+
+
+
+
+
+
+
+
+
+}

+ 1228 - 0
src/main/java/com/rf/AIquantum/utils/DateUtil.java

@@ -0,0 +1,1228 @@
+package com.rf.fileCrack.utils;
+
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+public class DateUtil {
+	/**
+	 * 默认的日期格式组合,用来将字符串转化为日期用
+	 * 
+	 */
+	public static final String[] DATE_PARSE_PATTERNS = { "yyyy/MM/dd",
+			"yyyy-MM-dd", "yyyy年MM月dd日" };
+	/**
+	 * 获取当前系统时间格式
+	 * 
+	 */
+	public static final String DEFAULT_DATE = "yyyy-MM-dd HH:mm:ss";
+	/**
+	 * 特殊日期格式
+	 */
+	public static final String DEFAULT_DATE_T = "yyyy-MM-dd:HH:mm";
+	
+	/**
+	 * 特殊日期格式2
+	 */
+	public static final String DEFAULT_DATE_T2 = "yyyy-MM-dd HH:mm";
+	/**
+	 * 默认的时间格式
+	 */
+	public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";
+
+	/**
+	 * 默认的日期格式
+	 */
+	public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
+	
+	/**
+	 * 获取当前系统时间格式
+	 * 用于生成文件名
+	 */
+	public static final String DEFAULT_FILE_DATE = "yyyyMMddHHmmss";
+	
+
+	/**
+	 * 日期代码,周日
+	 */
+	public static final int SUNDAY = 1;
+
+	/**
+	 * 日期代码,周一
+	 */
+	public static final int MONDAY = 2;
+
+	/**
+	 * 日期代码,周二
+	 */
+	public static final int TUESDAY = 3;
+
+	/**
+	 * 日期代码,周三
+	 */
+	public static final int WEDNESDAY = 4;
+
+	/**
+	 * 日期代码,周四
+	 */
+	public static final int THURSDAY = 5;
+
+	/**
+	 * 日期代码,周五
+	 */
+	public static final int FRIDAY = 6;
+
+	/**
+	 * 日期代码,周六
+	 */
+	public static final int SATURDAY = 7;
+
+	/**
+	 * 日期精度,秒
+	 */
+	public static final int ACCURACY_SECOND = 1;
+
+	/**
+	 * 日期精度,分
+	 */
+	public static final int ACCURACY_MINUTE = 2;
+
+	/**
+	 * 日期精度,小时
+	 */
+	public static final int ACCURACY_HOUR = 3;
+
+	/**
+	 * 日期精度,天
+	 */
+	public static final int ACCURACY_DAY = 4;
+
+	/**
+	 * 日期精度,月
+	 */
+	public static final int ACCURACY_MONTH = 5;
+
+	/**
+	 * 日期精度,年
+	 */
+	public static final int ACCURACY_YEAR = 6;
+
+	/**
+	 * 比较用日期格式,精度为年
+	 */
+	public static final String ACCURACY_PATTERN_YEAR = "yyyy";
+
+	/**
+	 * 比较用日期格式,精度为月
+	 */
+	public static final String ACCURACY_PATTERN_MONTH = "yyyyMM";
+
+	/**
+	 * 比较用日期格式,精度为日
+	 */
+	public static final String ACCURACY_PATTERN_DAY = "yyyyMMdd";
+
+	/**
+	 * 比较用日期格式,精度为时
+	 */
+	public static final String ACCURACY_PATTERN_HOUR = "yyyyMMddHH";
+
+	/**
+	 * 比较用日期格式,精度为分
+	 */
+	public static final String ACCURACY_PATTERN_MINUTE = "yyyyMMddHHmm";
+
+	/**
+	 * 比较用日期格式,精度为秒
+	 */
+	public static final String ACCURACY_PATTERN_SECOND = "yyyyMMddHHmmss";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_YEAR = "yyyy";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_MONTH = "M";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_DAY = "d";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_HOUR = "H";
+
+	/**
+	 * 单一属性格式,分
+	 */
+	public static final String SINGLE_MINUTE = "m";
+
+	/**
+	 * 单一属性格式,秒
+	 */
+	public static final String SINGLE_SECOND = "s";
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_SECOND = 1000;
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_MINUTE = 1000 * 60;
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_HOUR = 1000 * 60 * 60;
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
+
+	/**
+	 * 将给定的日期字符串,按照预定的日期格式,转化为Date型数据
+	 * 
+	 * @param dateStr
+	 *            日期字符字符串
+	 * @return 日期型结果
+	 */
+	public static Date parseDate(String dateStr) {
+		Date date = null;
+		try {
+			date = org.apache.commons.lang.time.DateUtils.parseDate(dateStr,
+					DATE_PARSE_PATTERNS);
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return date;
+	}
+	
+	/**
+	 * 根据指定格式转化String型日期到Date型
+	 * 
+	 * @param dateStr
+	 *            String型日期
+	 * @param parsePattern
+	 *            指定的格式
+	 * @return Date型日期
+	 */
+	public static Date parseDate(String dateStr, String parsePattern) {
+		Date date = null;
+		try {
+			date = org.apache.commons.lang.time.DateUtils.parseDate(dateStr,
+					new String[] { parsePattern.toString() });
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return date;
+	}
+
+	/**
+	 * 返回系统当前时间(Date型)
+	 * 
+	 * @return 系统当前时间
+	 */
+	public static Date getCurrentDate() {
+		return new Date();
+	}
+
+	/**
+	 * 日期计算,日加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            天数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addDays(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addDays(date, amount);
+	}
+
+	/**
+	 * 日期计算,周加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            周数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addWeeks(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addWeeks(date, amount);
+	}
+
+	/**
+	 * 日期计算,月加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            月数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addMonths(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addMonths(date, amount);
+	}
+
+	/**
+	 * 日期计算,年加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            年数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addYears(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addYears(date, amount);
+	}
+
+	/**
+	 * 日期计算,小时加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            小时增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addHours(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addHours(date, amount);
+	}
+
+	/**
+	 * 日期计算,分钟加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            分钟增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addMinutes(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addMinutes(date, amount);
+	}
+
+	/**
+	 * 日期计算,秒加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            秒增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addSeconds(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addSeconds(date, amount);
+	}
+
+	/**
+	 * 根据指定格式,返回日期时间字符串
+	 * 
+	 * @param date
+	 *            日期变量
+	 * @param pattern
+	 *            日期格式
+	 * @return 日期时间字符串
+	 */
+	public static String getDateStr(Date date, String pattern) {
+		DateFormat df = new SimpleDateFormat(pattern);
+		return df.format(date);
+	}
+
+	/**
+	 * 输出时间String(默认格式)
+	 * 
+	 * @param date
+	 *            日期
+	 * @return 默认格式化的日期
+	 */
+	public static String getTimeStr(Date date) {
+		return getDateStr(date, DEFAULT_TIME_PATTERN);
+	}
+
+	/**
+	 * 取指定日期所在月的第一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在月的第一天
+	 */
+	public static Date getFirstDayOfMonth(Date date) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.DATE, 1);
+		return cal.getTime();
+	}
+
+	/**
+	 * 取指定日期所在月的最后一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在月的最后一天
+	 */
+	public static Date getLastDayOfMonth(Date date) {
+		Date nextMonth = addMonths(date, 1);
+		Date firstDayOfNextMonth = getFirstDayOfMonth(nextMonth);
+		return addDays(firstDayOfNextMonth, -1);
+	}
+
+	/**
+	 * 取指定日期所在年的第一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在年的第一天
+	 */
+	public static Date getFirstDayOfYear(Date date) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.DATE, 1);
+		cal.set(Calendar.MONTH, 0);
+		return cal.getTime();
+	}
+
+	/**
+	 * 取指定日期所在年的最后一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在月的最后一天
+	 */
+	public static Date getLastDayOfYear(Date date) {
+		Date nextMonth = addYears(date, 1);
+		Date firstDayOfNextYear = getFirstDayOfYear(nextMonth);
+		return addDays(firstDayOfNextYear, -1);
+	}
+
+	/**
+	 * 取指定日期所在周的指定天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @param day
+	 *            指定的天(星期几)
+	 * @param firstDay
+	 *            一星期的起始天
+	 * @return 指定周星期日的日期
+	 */
+	public static Date getDayInWeek(Date date, int day, int firstDay) {
+		Calendar cal = getCalendar(date);
+		cal.setFirstDayOfWeek(firstDay);
+		cal.set(Calendar.DAY_OF_WEEK, day);
+		return cal.getTime();
+	}
+
+	/**
+	 * 根据Date型的日期,取Calendar型的日期
+	 * 
+	 * @param date
+	 *            Date型的日期
+	 * @return Calendar型的日期
+	 */
+	public static Calendar getCalendar(Date date) {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		return cal;
+	}
+
+	/**
+	 * 日期比较(精确到天),date1晚于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @return date1晚于date2,返回true,否则返回false
+	 */
+	public static boolean later(Date date1, Date date2) {
+		boolean result = false;
+		if (1 == compare(date1, date2, ACCURACY_DAY)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 日期比较(精确到天),date1早于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @return date1早于date2,返回true,否则返回false
+	 */
+	public static boolean earlier(Date date1, Date date2) {
+		boolean result = false;
+		if (-1 == compare(date1, date2, ACCURACY_DAY)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 日期比较(精确到天),date1等于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @return date1等于date2,返回true,否则返回false
+	 */
+	public static boolean equal(Date date1, Date date2) {
+		boolean result = false;
+		if (0 == compare(date1, date2, ACCURACY_DAY)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则比较日期,date1晚于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return date1晚于date2,返回true,否则返回false
+	 */
+	public static boolean later(Date date1, Date date2, int accuracy) {
+		boolean result = false;
+		if (1 == compare(date1, date2, accuracy)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则比较日期,date1早于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return date1早于date2,返回true,否则返回false
+	 */
+	public static boolean earlier(Date date1, Date date2, int accuracy) {
+		boolean result = false;
+		if (-1 == compare(date1, date2, accuracy)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则比较日期,date1等于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return date1等于date2,返回true,否则返回false
+	 */
+	public static boolean equal(Date date1, Date date2, int accuracy) {
+		boolean result = false;
+		if (0 == compare(date1, date2, accuracy)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则,比较日期
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return int型,date1晚,返回1;date1早,返回-1;相等,返回0
+	 */
+	public static int compare(Date date1, Date date2, int accuracy) {
+		String pattern = DEFAULT_DATE_PATTERN;
+		switch (accuracy) {
+		case ACCURACY_YEAR:
+			pattern = ACCURACY_PATTERN_YEAR;
+			break;
+		case ACCURACY_MONTH:
+			pattern = ACCURACY_PATTERN_MONTH;
+			break;
+		case ACCURACY_DAY:
+			pattern = ACCURACY_PATTERN_DAY;
+			break;
+		case ACCURACY_HOUR:
+			pattern = ACCURACY_PATTERN_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			pattern = ACCURACY_PATTERN_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			pattern = ACCURACY_PATTERN_SECOND;
+			break;
+		default:
+			break;
+		}
+		Date formatedDate1 = transDateFormat(date1, pattern);
+		Date formatedDate2 = transDateFormat(date2, pattern);
+		return formatedDate1.compareTo(formatedDate2);
+	}
+	/**
+	 * 根据指定规则,比较日期
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return int型,date1晚,返回1;date1早,返回-1;相等,返回0
+	 * @throws ParseException 
+	 */
+	public static int compare(String date1, String date2, int accuracy) throws ParseException {
+		String pattern = DEFAULT_DATE_PATTERN;
+		switch (accuracy) {
+		case ACCURACY_YEAR:
+			pattern = ACCURACY_PATTERN_YEAR;
+			break;
+		case ACCURACY_MONTH:
+			pattern = ACCURACY_PATTERN_MONTH;
+			break;
+		case ACCURACY_DAY:
+			pattern = ACCURACY_PATTERN_DAY;
+			break;
+		case ACCURACY_HOUR:
+			pattern = ACCURACY_PATTERN_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			pattern = ACCURACY_PATTERN_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			pattern = ACCURACY_PATTERN_SECOND;
+			break;
+		default:
+			break;
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE);
+		Date formatedDate1 = transDateFormat(sdf.parse(date1), pattern);
+		Date formatedDate2 = transDateFormat(sdf.parse(date2), pattern);
+		return formatedDate1.compareTo(formatedDate2);
+	}
+	/**
+	 * 根据指定规则,转化日期,如只取年、取年月等
+	 * 
+	 * @param date
+	 *            待转化日期
+	 * @param pattern
+	 *            日期格式
+	 * @return 转化后的日期
+	 */
+	public static Date transDateFormat(Date date, String pattern) {
+		String dateStr = getDateStr(date, pattern);
+		return parseDate(dateStr, pattern);
+	}
+
+	/**
+	 * 返回时定时间的年
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的年
+	 */
+	public static String getYear(Date date) {
+		return getDateStr(date, SINGLE_YEAR);
+	}
+
+	/**
+	 * 返回时定时间的月
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的月
+	 */
+	public static String getMonth(Date date) {
+		return getDateStr(date, SINGLE_MONTH);
+	}
+
+	/**
+	 * 返回时定时间的日
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的日
+	 */
+	public static String getDay(Date date) {
+		return getDateStr(date, SINGLE_DAY);
+	}
+
+	/**
+	 * 返回时定时间的小时
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的小时
+	 */
+	public static String getHour(Date date) {
+		return getDateStr(date, SINGLE_HOUR);
+	}
+
+	/**
+	 * 返回时定时间的分
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的分
+	 */
+	public static String getMinute(Date date) {
+		return getDateStr(date, SINGLE_MINUTE);
+	}
+
+	/**
+	 * 返回时定时间的秒
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的秒
+	 */
+	public static String getSecond(Date date) {
+		return getDateStr(date, SINGLE_SECOND);
+	}
+
+	/**
+	 * 将时间日期变量的年份变为指定年, 如果日期不存在,则向后一天,如20102月
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定年
+	 * @return 修改后的日期变量
+	 */
+	public static Date setYear(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.YEAR, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的月份变为指定月
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定月
+	 * @return 修改后的日期变量
+	 */
+	public static Date setMonth(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.MONTH, amount - 1);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的年份变为指定日
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定日
+	 * @return 修改后的日期变量
+	 */
+	public static Date setDay(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.DAY_OF_MONTH, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的小时变为指定时
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定时
+	 * @return 修改后的日期变量
+	 */
+	public static Date setHour(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.HOUR_OF_DAY, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的分钟变为指定分
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定分
+	 * @return 修改后的日期变量
+	 */
+	public static Date setMinute(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.MINUTE, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的秒变为指定秒
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定秒
+	 * @return 修改后的日期变量
+	 */
+	public static Date setSecond(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.SECOND, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 根据制定单位,计算两个日期之间的天数差
+	 * 
+	 * @param a
+	 *            时间点1
+	 * @param b
+	 *            时间点2
+	 * @return 时间差
+	 */
+	public static int getDateDistance(Date a, Date b) {
+		return getDateDistance(a, b, ACCURACY_DAY);
+	}
+
+	/**
+	 * 根据制定单位,计算两个日期之间的差
+	 * 
+	 * @param a
+	 *            时间点1
+	 * @param b
+	 *            时间点2
+	 * @param unit
+	 *            时间单位
+	 * @return 时间差
+	 */
+	public static int getDateDistance(Date a, Date b, int unit) {
+		int result = 0;
+		if (null != a && null != b) {
+			String pattern = null;
+			switch (unit) {
+			case ACCURACY_HOUR: // '\003'
+				pattern = "yyyyMMddHH";
+				break;
+			case ACCURACY_MINUTE: // '\002'
+				pattern = "yyyyMMddHHmm";
+				break;
+			case ACCURACY_SECOND: // '\001'
+				pattern = "yyyyMMddHHmmss";
+				break;
+			default:
+				pattern = "yyyyMMdd";
+			}
+			Date startDate = transDateFormat(1 != a.compareTo(b) ? a : b,
+					pattern);
+			Date endDate = transDateFormat(1 != a.compareTo(b) ? b : a, pattern);
+			if (1 <= unit && 4 >= unit) {
+				result = getDistanceByUnit(startDate, endDate, unit);
+				return result;
+			}
+			GregorianCalendar startCalendar = new GregorianCalendar();
+			startCalendar.setTime(startDate);
+			int startYears = startCalendar.get(Calendar.YEAR);
+			int startMonths = startCalendar.get(Calendar.MONTH);
+			int startDays = startCalendar.get(Calendar.DAY_OF_MONTH);
+
+			GregorianCalendar endCalendar = new GregorianCalendar();
+			endCalendar.setTime(endDate);
+			int endYears = endCalendar.get(Calendar.YEAR);
+			int endMonths = endCalendar.get(Calendar.MONTH);
+			int endDays = endCalendar.get(Calendar.DAY_OF_MONTH);
+
+			int yearBetween = endYears - startYears;
+			int monthBetween = endMonths - startMonths;
+			if (endDays < startDays
+					&& endDays != endCalendar.getActualMaximum(Calendar.DATE)) {
+				monthBetween--;
+			}
+			if (ACCURACY_YEAR == unit) {
+				if (monthBetween < 0) {
+					yearBetween--;
+				}
+				result = yearBetween;
+			}
+			if (ACCURACY_MONTH == unit) {
+				result = (yearBetween * 12 + monthBetween);
+			}
+		}
+		return result;
+
+	}
+
+	/**
+	 * 内部方法,计算时间点的差距
+	 * 
+	 * @param startDate
+	 *            起始时间
+	 * @param endDate
+	 *            终止时间
+	 * @param unit
+	 *            时间单位
+	 * @return 时间差
+	 */
+	public static int getDistanceByUnit(Date startDate, Date endDate, int unit) {
+		int result = 0;
+		long millisecondPerUnit = MILLISECONDS_PER_DAY;
+		switch (unit) {
+		case ACCURACY_HOUR:
+			millisecondPerUnit = MILLISECONDS_PER_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			millisecondPerUnit = MILLISECONDS_PER_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			millisecondPerUnit = MILLISECONDS_PER_SECOND;
+			break;
+		default:
+			break;
+		}
+		long start = startDate.getTime();
+		long end = endDate.getTime();
+		long distance = end - start;
+		result = Integer.valueOf((distance / millisecondPerUnit) + "");
+		return result;
+	}
+	
+	/**
+	 * 内部方法,计算时间点的差距toLong
+	 * 
+	 * @param startDate
+	 *            起始时间
+	 * @param endDate
+	 *            终止时间
+	 * @param unit
+	 *            时间单位
+	 * @return 时间差
+	 */
+	public static long getDistanceByUnit_toLong(Date startDate, Date endDate, int unit) {
+		long result = 0;
+		long millisecondPerUnit = MILLISECONDS_PER_DAY;
+		switch (unit) {
+		case ACCURACY_HOUR:
+			millisecondPerUnit = MILLISECONDS_PER_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			millisecondPerUnit = MILLISECONDS_PER_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			millisecondPerUnit = MILLISECONDS_PER_SECOND;
+			break;
+		default:
+			break;
+		}
+		long start = startDate.getTime();
+		long end = endDate.getTime();
+		long distance = end - start;
+		result = distance / millisecondPerUnit;
+		return result;
+	}
+	
+	 
+
+	/**
+	 * 返回指定日期是当年的第几周
+	 * 
+	 * @param date
+	 *            指定日期
+	 * @return 周数(从1开始)
+	 */
+	public static int getWeekOfYear(Date date) {
+		return getCalendar(date).get(Calendar.WEEK_OF_YEAR);
+	}
+
+	/**
+	 * 获取指定日期是星期几
+	 * 
+	 * @param date
+	 *            指定日期
+	 * @return 星期日--1; 星期一--2; 星期二--3; 星期三--4; 星期四--5; 星期五--6; 星期六--7;
+	 */
+	public static int getWeekOfDate(Date date) {
+		return getCalendar(date).get(Calendar.DAY_OF_WEEK);
+	}
+
+	/**
+	 * 判断指定年份日期的年份是否为闰年
+	 * 
+	 * @param date
+	 *            日期
+	 * @return 闰年ture,非闰年false
+	 */
+	public static boolean isLeapYear(Date date) {
+		int year = getCalendar(date).get(Calendar.YEAR);
+		return isLeapYear(year);
+	}
+
+	/**
+	 * 判断指定年份日期的年份是否为闰年
+	 * 
+	 * @param year
+	 *            年份数字
+	 * @return 闰年ture,非闰年false
+	 */
+	public static boolean isLeapYear(int year) {
+		if ((year % 400) == 0) {
+			return true;
+		} else if ((year % 4) == 0) {
+			if ((year % 100) == 0) {
+				return false;
+			} else {
+				return true;
+			}
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * 按照strFormat格式输出当前时间
+	 * 
+	 * @param strFormat
+	 *            格式
+	 * @return 指定格式的当前系统日期
+	 */
+	public static String getCurrentDate(String strFormat) {
+		return getDateStr(getCurrentDate(), strFormat);
+	}
+
+	/**
+	 * 校验日期数据(校验输入值是否为指定的日期格式)
+	 * 
+	 * @param strDate
+	 *            要校验的日期
+	 * @param strFormat
+	 *            日期格式
+	 * @return true/false (符合/不符合)
+	 */
+	public static boolean checkDate(String strDate, String strFormat) {
+		Date date = null;
+		if ((strDate != null) && (strDate.trim().length() != 0)) {
+			DateFormat myDateFmt = new SimpleDateFormat(strFormat);
+			try {
+				date = myDateFmt.parse(strDate);
+
+				if (!strDate.equals(myDateFmt.format(date))) {
+					date = null;
+					return false;
+				}
+			} catch (ParseException e) {
+				date = null;
+				return false;
+			}
+		}
+		return true;
+	}
+	/**
+	 * 
+	 * @Description:获取当期系统日期以特定格式显示
+	 * @param 
+	 * @return 格式为"yyyy-MM-dd HH:mm:ss"的时间
+	 * @throws 
+	 * @author baolf
+	 * @date 2016-7-25
+	 */
+	public static String getNowTime(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE);
+		String date = sd.format(now);
+		return date;
+	}
+	/**
+	 * 
+	 * @Description:获取当期系统两小时后时间   以特定格式显示
+	 * @param 
+	 * @return 格式为"yyyy-MM-dd HH:mm:ss"的时间
+	 * @throws 
+	 * @author wwq
+	 * @date 2018-08-13
+	 */
+	public static String get2HoursLater(){
+		Date twoHours = new Date(System.currentTimeMillis()+120 * 60 * 1000);
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE);
+		String date = sd.format(twoHours);
+		return date;
+	}
+	/**
+	 * 
+	 * @Description:获取当期系统日期以特定格式显示
+	 * @param 
+	 * @return 格式为"yyyy-MM-dd"的时间
+	 * @throws 
+	 * @author
+	 * @date 2016-7-25
+	 */
+	public static String getNowTime1(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
+		String date = sd.format(now);
+		return date;
+	}
+	
+	/**
+	 * 自定义时间格式
+	 * @param strFormat
+	 * @return
+	 */
+	public static String getNowTime(String strFormat){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(strFormat);
+		String date = sd.format(now);
+		return date;
+	}
+	
+    /**
+     * 时间串,没有分割符
+     * 用于自动生成文件名用
+     * @return
+     */
+	public static synchronized String getFileNameNowTime(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_FILE_DATE);
+		String date = sd.format(now);
+		return date;
+	}
+	
+	/**
+	 * 获得几位随机数(正数)
+	 * @param num
+	 * @return
+	 */
+	public static String getRandom(int num)
+	{
+		StringBuffer format = new StringBuffer("0.0");
+		for(int ii=2;ii<=num;ii++)
+		{
+			format.append("0");
+		}
+		DecimalFormat df = new DecimalFormat(format.toString());
+		return df.format(Math.random()).replace("0.","");
+		
+	}
+	public static String getReleaseBatch(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
+		String date = sd.format(now);
+		date = date.replace("-", "");
+		return date;
+	}
+//	public static void main(String[] args) {
+//	}
+	public static String getBeforeNowTime(){
+		long time = 1*60*1000+10000;//1分钟
+		Date now = new Date(new Date().getTime()-time);
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE);
+		String date = sd.format(now);
+		return date;
+	}
+	/**
+	 * 获取秒数  (1970-01-01 08:00:00)
+	 * @Description :
+	 * @param : 
+	 * @throws : 
+	 * @author :
+	 */
+	public static  int getDateInt(String date)
+	{		
+		return getDistanceByUnit( 
+				   parseDate("1970-01-01 08:00:00", DEFAULT_DATE),
+				   parseDate(date, DEFAULT_DATE),1) ;
+	}
+	/**
+	 * 判断字符串是否不为空 空返回false 非空返回true
+	 *
+	 * @param sourceStr
+	 * @return
+	 */
+	public static boolean isNotEmpty(String sourceStr) {
+
+		if (sourceStr == null) {
+			return false;
+		}
+		if (sourceStr.trim().length() > 0) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 统计两个时间的时间差
+	 * 相差几秒几毫秒
+	 */
+	public static String getDistanceTime(String str1, String str2) {
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+		Date one;
+		Date two;
+		long day = 0;//天数差
+		long hour = 0;//小时数差
+		long min = 0;//分钟数差
+		long second=0;//秒数差
+		long diff=0 ;//毫秒差
+		String result = null;
+		try {
+			final Calendar c = Calendar.getInstance();
+			c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
+			one = df.parse(str1);
+			c.setTime(one);
+			two = df.parse(str2);
+			long time1 = one.getTime();
+			long time2 = two.getTime();
+			diff = time2 - time1;
+			day = diff / (24 * 60 * 60 * 1000);
+			hour = (diff / (60 * 60 * 1000) - day * 24);
+			min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
+			second = diff/1000;
+			//System.out.println("day="+day+" hour="+hour+" min="+min+" ss="+second%60+" SSS="+diff%1000);
+			result=second%60+"秒"+diff%1000+"毫秒";
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return String.valueOf(diff);
+	}
+
+	/*public static void main(String[] args) {
+		//开始时间
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+		String beginTime = df.format(new Date());
+		String endTime = df.format(new Date());
+		System.out.println("时间差:"+getDistanceTime(beginTime,endTime));
+	}*/
+
+	/*
+	 * 将yyyyMMddHHmmss格式的数据装换成yyyy-MM-dd:HH:mm格式的数据
+	 * */
+	public static String formatDate(String dateStr) throws NullPointerException {
+		//
+		StringBuffer dateBuffer = new StringBuffer();
+		return dateBuffer.append(dateStr.substring(0, 4)).append("-").append(dateStr.substring(4, 6)).append("-").append(dateStr.substring(6, 8))
+				.append(" ").append(dateStr.substring(8, 10)).append(":").append(dateStr.substring(10, 12)).append(":").append(dateStr.substring(12, 14)).toString();
+	}
+	
+}

+ 29 - 0
src/main/java/com/rf/AIquantum/utils/EmailUtil.java

@@ -0,0 +1,29 @@
+package com.rf.fileCrack.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.net.smtp.SMTPClient;
+
+import org.apache.commons.net.smtp.SMTPReply;
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.Type;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Slf4j
+public class EmailUtil {
+
+    private static final String EMAIL_REGEX = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
+
+    public static boolean checkEmail(String email) {
+        if (email == null || email.isEmpty()) {
+            return false;
+        }
+        Pattern pattern = Pattern.compile(EMAIL_REGEX);
+        Matcher matcher = pattern.matcher(email);
+        return matcher.matches();
+    }
+
+}

+ 19 - 0
src/main/java/com/rf/AIquantum/utils/HttpStatus.java

@@ -0,0 +1,19 @@
+package com.rf.AIquantum.utils;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:37
+ */
+public interface HttpStatus {
+    String SUCCESS = "200";
+    String SUCCESS_PUB = "201";
+
+    String RUNTIME_EXCEPTION = "2001";
+
+    String SERVER_EXCEPTION = "500100";
+
+    String PARAMETER_ISNULL = "500101";
+
+    String USER_NOT_FOUND = "6001";
+}

+ 32 - 0
src/main/java/com/rf/AIquantum/utils/IPUtiles.java

@@ -0,0 +1,32 @@
+package com.rf.fileCrack.utils;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2517:59
+ */
+public class IPUtiles {
+    public static String getRealIp(HttpServletRequest request) {
+        String ip = request.getHeader("X-Real-IP");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Forwarded-For");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        if (ip != null && ip.contains(",")) {
+            String[] ipArray = ip.split(",");
+            ip = ipArray[0];
+        }
+        return ip;
+    }
+
+}

+ 71 - 0
src/main/java/com/rf/AIquantum/utils/JWTUtil.java

@@ -0,0 +1,71 @@
+package com.rf.AIquantum.utils;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTCreator;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.rf.AIquantum.user.dao.model.UserEntity;
+
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2820:18
+ */
+public class JWTUtil {
+
+    private static final String SING = "xVWGEYTPF1hjnFt$HDZ0f^iet^^q@hZv";
+
+    public static final String AUTH_HEADER_KEY = "Authorization";
+
+    //token前缀
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    public static String getToken(Map<String, String> map) {
+
+        Calendar instance = Calendar.getInstance();
+        instance.add(Calendar.DATE, 5);
+        JWTCreator.Builder builder = JWT.create();
+        map.forEach(builder::withClaim);
+        String token = builder.withExpiresAt(instance.getTime())
+                .sign(Algorithm.HMAC256(SING));
+        return token;
+    }
+
+    public static String getTokenByUserInfo(UserEntity userEntity){
+        HashMap<String, String> payload = new HashMap<>();
+        payload.put("userId", userEntity.getId());
+        payload.put("phone",userEntity.getPhone());
+        payload.put("userName",userEntity.getUserName());
+        payload.put("type", userEntity.getRoleType());
+        return  getToken(payload);
+    }
+
+    /**
+     * 验证token
+     * @param token
+     */
+    public static String verifyToken(String token) throws Exception {
+        try {
+            return JWT.require(Algorithm.HMAC256(SING))
+                    .build()
+                    .verify(token.replace(TOKEN_PREFIX, ""))
+                    .getSubject();
+        } catch (TokenExpiredException e){
+            throw new Exception("token已失效,请重新登录",e);
+        } catch (JWTVerificationException e) {
+            throw new Exception("token验证失败!",e);
+        }
+    }
+
+
+    public static DecodedJWT verify(String token) {
+        return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
+    }
+
+}

+ 35 - 0
src/main/java/com/rf/AIquantum/utils/LocalAssert.java

@@ -0,0 +1,35 @@
+package com.rf.AIquantum.utils;
+
+import com.alibaba.druid.util.StringUtils;
+
+import java.util.Collection;
+
+/**
+ * @Description:断言工具类
+ * @Author: mimang
+ * @Date: 2024/9/6
+ */
+public abstract  class LocalAssert {
+    public static void isTrue(boolean expression, String message) throws RuntimeException {
+        if (!expression) {
+            throw new RuntimeException(message);
+        }
+    }
+    public static void isStringEmpty(String param, String message) throws RuntimeException{
+        if(StringUtils.isEmpty(param)) {
+            throw new RuntimeException(message);
+        }
+    }
+
+    public static void isObjectEmpty(Object object, String message) throws RuntimeException {
+        if (object == null) {
+            throw new RuntimeException(message);
+        }
+    }
+
+    public static void isCollectionEmpty(Collection coll, String message) throws RuntimeException {
+        if (coll == null || (coll.size() == 0)) {
+            throw new RuntimeException(message);
+        }
+    }
+}

+ 17 - 0
src/main/java/com/rf/AIquantum/utils/PageRequestUtil.java

@@ -0,0 +1,17 @@
+package com.rf.AIquantum.utils;
+
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+
+/**
+ * @Description:分页工具
+ * @Author: zsf
+ * @Date: 2022/7/5
+ */
+public class PageRequestUtil {
+
+    public static PageRequest of(int page, int size) {
+        if (page <=0){page=0;}else {page = page-1;}
+        return PageRequest.of(page, size, Sort.unsorted());
+    }
+}

+ 431 - 0
src/main/java/com/rf/AIquantum/utils/RandomUtil.java

@@ -0,0 +1,431 @@
+package com.rf.AIquantum.utils;
+
+//import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * 随机数工具类
+ */
+public class RandomUtil {
+
+    /**
+     * 获取两数之间的随机数
+     * @param min 最小数
+     * @param max 最大数
+     * @return
+     */
+    public static int scopeNum(int min,int max){
+        Random random = new Random();
+        return random.nextInt(max)%(max-min+1) + min;
+    }
+
+    /**
+     * 获取两数之间的随机数,排除指定的数据
+     * @param min 最小值
+     * @param max 最大值
+     * @param arr 要排除的集合数据
+     * @return
+     */
+    public static int chooseNum(int min, int max, List arr){
+        //Log.i("集合",arr.toString());
+        if ( arr.size() == 4){
+            return 5;
+        }
+        Random random = new Random();
+        int num = random.nextInt(max)%(max-min+1) + min;
+        if ( arr.contains(num)){
+            return chooseNum(min,max,arr);
+        }else {
+            return num;
+        }
+    }
+
+    /**
+     * 随机生成26位字母
+     * @param size 生成位数
+     * @param flag 大小写
+     * @return
+     */
+    public static String randomChar(int size,char flag){
+        //最终生成的字符串
+        String str = "";
+        for (int i = 0; i < size; i++) {
+            str = str + (char)(Math.random()*26+flag);
+        }
+        return str;
+    }
+
+
+    /**
+     * 获取到记忆量表字符出厂顺序
+     *
+     * @return
+     */
+    public static Map recallChar(){
+        Map map = new HashMap();
+        Map exerciseList = new HashMap();
+        Map examList = new HashMap();
+
+        Map mapChar0 = createBack0();
+        Map mapChar1 = createBack(1);
+        Map mapChar2 = createBack(2);
+        String[] strings0 = new String[18];
+        String[] strings1 = new String[18];
+        String[] strings2 = new String[18];
+        for ( int i = 0 ; i<mapChar0.size() ;i++){
+            Object a = mapChar0.get(i);
+            strings0[i] = a.toString();
+            Object b = mapChar1.get(i);
+            strings1[i] = b.toString();
+            Object c = mapChar2.get(i);
+            strings2[i] = c.toString();
+        }
+        exerciseList.put("back0",strings0);
+        exerciseList.put("back1",strings1);
+        exerciseList.put("back2",strings2);
+
+        String[][] stringsa = new String[6][18];
+        String[][] stringsb = new String[6][18];
+        String[][] stringsc = new String[6][18];
+        for ( int j = 0 ; j<6 ;j++){
+            Map mapChar01 = createBack0();
+            Map mapChar11 = createBack(1);
+            Map mapChar21 = createBack(2);
+            String[] strings01 = new String[18];
+            String[] strings11 = new String[18];
+            String[] strings21 = new String[18];
+            for ( int i = 0 ; i<mapChar01.size() ;i++){
+                Object a = mapChar01.get(i);
+                strings01[i] = a.toString();
+                Object b = mapChar11.get(i);
+                strings11[i] = b.toString();
+                Object c = mapChar21.get(i);
+                strings21[i] = c.toString();
+            }
+            stringsa[j] = strings01;
+            stringsb[j] = strings11;
+            stringsc[j] = strings21;
+        }
+        examList.put("back0",stringsa);
+        examList.put("back1",stringsb);
+        examList.put("back2",stringsc);
+
+        map.put("exerciseList",exerciseList);
+        map.put("examList",examList);
+        return map;
+    }
+
+
+    /**
+     * 制作0back组块数据
+     * @return
+     */
+    public static Map createBack0(){
+        List list = new ArrayList();
+        List indexList = new ArrayList();
+        Map mapChar = new LinkedHashMap();
+        mapChar = getMapChar(mapChar,list);
+        indexList = getRandomNum(1,17,indexList,9);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get(0));
+        }
+        //Log.i("0-back",mapChar.toString());
+        return mapChar;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBack(int type){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        mapChar = getMapChar(mapChar,list);
+        //Log.i(type+"-mapOld",mapChar.toString());
+        List indexList = new ArrayList();
+        indexList = getRandomNum(type,17,indexList,9);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        //Log.i(type+"-Index",indexList.toString());
+        //Log.i(type+"-back",mapChar.toString());
+        return mapChar;
+    }
+
+
+
+    /**
+     * 获取到18位的随机字符
+     * @param map
+     * @param list
+     * @return
+     */
+    public static Map getMapChar(Map map,List list){
+        char strChar = (char)(Math.random()*26+'A');
+        if ( list.isEmpty()){
+            list.add(strChar);
+        }else {
+            if ( !list.contains( strChar)){
+                list.add(strChar);
+            }
+        }
+        if ( list.size() == 18 ){
+            for (int i = 0; i<list.size();i++){
+                map.put(i,list.get(i));
+            }
+            return map;
+        }else {
+            return getMapChar(map,list);
+        }
+    }
+
+    /**
+     * 获取到范围内随机数
+     * @param min
+     * @param max
+     * @param list
+     * @return
+     */
+    public static List getRandomNum(int min,int max,List list,int size){
+        Random random = new Random();
+        int num = random.nextInt(max)%(max-min+1) + min;
+        if ( !list.contains(num)) {
+            list.add(num);
+        }
+        if ( list.size() == size){
+            return list;
+        }else {
+            return getRandomNum(min,max,list,size);
+        }
+    }
+
+    /**
+     * 获取到记忆量表字符出厂顺序2
+     * @return
+     */
+    public static Map recallCharTwo(){
+        Map map = new HashMap();
+        Map exerciseList = new HashMap();
+        Map examList = new HashMap();
+
+        Map back1 = new LinkedHashMap();
+        Map back1Map1 = createBackOne(1);
+        Map back1Map2 = createBackTwo(1,back1Map1);
+        for ( int i = 0 ; i<back1Map1.size() ;i++){
+            back1.put(i,back1Map1.get(i));
+        }
+        for ( int i = 0 ; i<back1Map2.size() ;i++){
+            back1.put(i+9,back1Map2.get(i));
+        }
+        Map back2 = new LinkedHashMap();
+        Map back2Map1 = createBackOne(2);
+        Map back2Map2 = createBackS(2,back2Map1);
+        for ( int i = 0 ; i<back2Map1.size() ;i++){
+            back2.put(i,back2Map1.get(i));
+        }
+        for ( int i = 0 ; i<back2Map2.size() ;i++){
+            back2.put(i+9,back2Map2.get(i));
+        }
+        //System.out.println("mapChar1:"+mapChar1);
+        //System.out.println("mapChar2:"+mapChar2);
+        String[] strings1 = new String[18];
+        String[] strings2 = new String[18];
+        for ( int i = 0 ; i<back1.size() ;i++){
+            Object b = back1.get(i);
+            strings1[i] = b.toString();
+            Object c = back2.get(i);
+            strings2[i] = c.toString();
+        }
+        exerciseList.put("back1",strings1);
+        exerciseList.put("back2",strings2);
+
+        String[][] stringsb = new String[3][18];
+        String[][] stringsc = new String[3][18];
+        for ( int j = 0 ; j<3 ;j++){
+            Map examback1 = new LinkedHashMap();
+            Map examback1Map1 = createBackOne(1);
+            Map examback1Map2 = createBackTwo(1,examback1Map1);
+            for ( int i = 0 ; i<examback1Map1.size() ;i++){
+                examback1.put(i,examback1Map1.get(i));
+            }
+            for ( int i = 0 ; i<examback1Map2.size() ;i++){
+                examback1.put(i+9,examback1Map2.get(i));
+            }
+            Map examback2 = new LinkedHashMap();
+            Map examback2Map1 = createBackOne(2);
+            Map examback2Map2 = createBackS(2,examback2Map1);
+            for ( int i = 0 ; i<examback2Map1.size() ;i++){
+                examback2.put(i,examback2Map1.get(i));
+            }
+            for ( int i = 0 ; i<examback2Map2.size() ;i++){
+                examback2.put(i+9,examback2Map2.get(i));
+            }
+            String[] strings11 = new String[18];
+            String[] strings21 = new String[18];
+            for ( int i = 0 ; i<examback1.size() ;i++){
+                Object b = examback1.get(i);
+                strings11[i] = b.toString();
+                Object c = examback2.get(i);
+                strings21[i] = c.toString();
+            }
+            stringsb[j] = strings11;
+            stringsc[j] = strings21;
+        }
+        examList.put("back1",stringsb);
+        examList.put("back2",stringsc);
+
+        map.put("exerciseList",exerciseList);
+        map.put("examList",examList);
+        return map;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBackOne(int type){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        mapChar = getMapCharTwo(mapChar,list);
+        List indexList = new ArrayList();
+        indexList = getRandomNumTwo(type,8,indexList,4);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        return mapChar;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBackTwo(int type,Map map11){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        list.add(map11.get(8));
+        mapChar = getMapCharTwo(mapChar,list);
+        List indexList = new ArrayList();
+        indexList = getRandomNumTwo(type,8,indexList,4);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        return mapChar;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBackS(int type,Map map11){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        list.add(map11.get(8));
+        mapChar = getMapCharTwo(mapChar,list);
+        List indexList = new ArrayList();
+        indexList = getRandomNumTwo(type,8,indexList,5);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        return mapChar;
+    }
+
+
+
+    /**
+     * 获取到18位的随机字符
+     * @param map
+     * @param list
+     * @return
+     */
+    public static Map getMapCharTwo(Map map,List list){
+        //char strChar = (char)(Math.random()*26+'A');
+        int ran1 = (int) (Math.random()*(10-1)+1);
+        if ( list.isEmpty()){
+            list.add(ran1);
+        }else {
+            if ( !list.contains( ran1)){
+                list.add(ran1);
+            }
+        }
+        if ( list.size() == 9 ){
+            for (int i = 0; i<list.size();i++){
+                map.put(i,list.get(i));
+            }
+            return map;
+        }else {
+            return getMapCharTwo(map,list);
+        }
+    }
+
+    /**
+     * 获取到范围内随机数
+     * @param min
+     * @param max
+     * @param list
+     * @return
+     */
+    public static List getRandomNumTwo(int min,int max,List list,int size){
+        Random random = new Random();
+        int num = random.nextInt(max)%(max-min+1) + min;
+        if ( !list.contains(num)) {
+            list.add(num);
+        }
+        if ( list.size() == size){
+            return list;
+        }else {
+            return getRandomNumTwo(min,max,list,size);
+        }
+    }
+
+
+    /*public static Map recallCharTwo(){
+        Map map = new HashMap();
+        Map exerciseList = new HashMap();
+        Map examList = new HashMap();
+
+        String[] strings1 = new String[20];
+        String[] strings2 = new String[20];
+        for ( int i = 0 ; i<20 ;i++){
+            int ran1 = (int) (Math.random()*(10-1)+1);
+            int ran2 = (int) (Math.random()*(10-1)+1);
+            strings1[i] = String.valueOf(ran1);
+            strings2[i] = String.valueOf(ran2);
+        }
+        exerciseList.put("back1",strings1);
+        exerciseList.put("back2",strings2);
+
+        String[][] stringsb = new String[3][20];
+        String[][] stringsc = new String[3][20];
+        for ( int j = 0 ; j<3 ;j++){
+            String[] strings11 = new String[20];
+            String[] strings21 = new String[20];
+            for ( int i = 0 ; i<20 ;i++){
+                int ran1 = (int) (Math.random()*(10-1)+1);
+                int ran2 = (int) (Math.random()*(10-1)+1);
+                strings11[i] = String.valueOf(ran1);
+                strings21[i] = String.valueOf(ran2);
+            }
+            stringsb[j] = strings11;
+            stringsc[j] = strings21;
+        }
+        examList.put("back1",stringsb);
+        examList.put("back2",stringsc);
+
+        map.put("exerciseList",exerciseList);
+        map.put("examList",examList);
+        return map;
+    }*/
+
+
+}

+ 62 - 0
src/main/java/com/rf/AIquantum/utils/Result.java

@@ -0,0 +1,62 @@
+package com.rf.AIquantum.utils;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:27
+ */
+
+public class Result<T> {
+    /**
+     * 状态码
+     */
+    private String code;
+
+    /**
+     * 信息
+     */
+    private String msg;
+
+    /**
+     * 返回数据
+     */
+    private T data;
+
+    public Result(String code, String msg, T data) {
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+    }
+
+    public Result() {
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public Result(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+}

+ 112 - 0
src/main/java/com/rf/AIquantum/utils/SendEmail.java

@@ -0,0 +1,112 @@
+package com.rf.AIquantum.utils;
+
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import java.util.Date;
+import java.util.Properties;
+
+public class SendEmail {
+
+    //发件人的邮箱和授权码
+    private final String myEmailAccount = "1219951757@qq.com";//发件人的邮箱
+    private final String myEmailPassword = "kjwsfnytpuabhgjc";//发件人的邮箱授权码
+    private String password=null;//破解密码
+    private String receiveMailAccount = null ;//收件人邮箱
+    private String fileName=null;//文件名
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+    public void setReceiveMailAccount(String receiveMailAccount) {
+        this.receiveMailAccount = receiveMailAccount;
+    }
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+    // 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
+    // 网易163邮箱的 SMTP 服务器地址为: smtp.163.com    腾讯: smtp.qq.com
+    private  String myEmailSMTPServer = "smtp.qq.com";
+
+    public  void Send() throws Exception {
+        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
+        Properties props = new Properties();                    // 参数配置
+        props.setProperty("mail.transport.protocol", "smtp");   // 使用的协议(JavaMail规范要求)
+        props.setProperty("mail.smtp.host", myEmailSMTPServer);   // 发件人的邮箱的 SMTP 服务器地址
+        props.setProperty("mail.smtp.auth", "true");            // 需要请求认证
+        // PS: 某些邮箱服务器要求 SMTP 连接需要使用 SSL 安全认证 (为了提高安全性, 邮箱支持SSL连接, 也可以自己开启),
+        //     如果无法连接邮件服务器, 仔细查看控制台打印的 log, 如果有有类似 “连接失败, 要求 SSL 安全连接” 等错误,
+        //     打开下面 /* ... */ 之间的注释代码, 开启 SSL 安全连接。
+
+        // SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接,
+        //                  需要改为对应邮箱的 SMTP 服务器的端口, 具体可查看对应邮箱服务的帮助,
+        //                  QQ邮箱的SMTP(SLL)端口为465或587, 其他邮箱自行去查看)
+        final String smtpPort = "465";
+        props.setProperty("mail.smtp.port", smtpPort);
+        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+        props.setProperty("mail.smtp.socketFactory.fallback", "false");
+        props.setProperty("mail.smtp.socketFactory.port", smtpPort);
+
+
+        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
+        Session session = Session.getDefaultInstance(props);
+        session.setDebug(true);                                 // 设置为debug模式, 可以查看详细的发送 log
+
+        // 3. 创建一封邮件
+        MimeMessage message = createMessage(session, myEmailAccount, receiveMailAccount,fileName,password);
+
+        // 4. 根据 Session 获取邮件传输对象
+        Transport transport = session.getTransport();
+
+        // 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
+        //
+        //    PS_01: 成败的判断关键在此一句, 如果连接服务器失败, 都会在控制台输出相应失败原因的 log,
+        //           仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接, 根据给出的错误
+        //           类型到对应邮件服务器的帮助网站上查看具体失败原因。
+        //
+        //    PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:
+        //           (1) 邮箱没有开启 SMTP 服务;
+        //           (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;
+        //           (3) 邮箱服务器要求必须要使用 SSL 安全连接;
+        //           (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;
+        //           (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。
+        //
+        //    PS_03: 仔细看log, 认真看log, 看懂log, 错误原因都在log已说明。
+        transport.connect(myEmailAccount, myEmailPassword);
+
+        // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
+        transport.sendMessage(message, message.getAllRecipients());
+
+        // 7. 关闭连接
+        transport.close();
+    }
+
+    /**
+     * 创建一封只包含文本的简单邮件
+     *
+     * @param session 和服务器交互的会话
+     * @param sendMail 发件人邮箱
+     * @param receiveMail 收件人邮箱
+     * @return
+     * @throws Exception
+     */
+    public  MimeMessage createMessage(Session session, String sendMail, String receiveMail,String fileName,String password) throws Exception {
+        // 1. 创建一封邮件
+        MimeMessage message = new MimeMessage(session);
+        // 2. From: 发件人(昵称有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改昵称)
+        message.setFrom(new InternetAddress(sendMail, "AI文件破解平台", "UTF-8"));
+        // 3. To: 收件人(可以增加多个收件人、抄送、密送)
+        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail, "xx用户", "UTF-8"));
+        // 4. Subject: 邮件主题(标题有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改标题)
+        message.setSubject("AI文件破解平台通知", "UTF-8");
+        // 5. Content: 邮件正文(可以使用html标签)(内容有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改发送内容)
+        message.setContent("【AI文件破解平台】您上传的文件:"+fileName+";密码为:"+password, "text/html;charset=UTF-8");
+        // 6. 设置发件时间
+        message.setSentDate(new Date());
+        // 7. 保存设置
+        message.saveChanges();
+
+        return message;
+    }
+}

+ 44 - 0
src/main/java/com/rf/AIquantum/utils/WebContextUtil.java

@@ -0,0 +1,44 @@
+package com.rf.AIquantum.utils;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * @Description:线程缓存工具类
+ * @Author: mimang
+ * @Date: 2024/9/6
+ */
+public class WebContextUtil {
+    //本地线程缓存token
+    private static ThreadLocal<String> local = new ThreadLocal<>();
+
+    /**
+     * 设置token信息
+     * @param content
+     */
+    public static void setUserToken(String content){
+        removeUserToken();
+        local.set(content);
+    }
+
+    /**
+     * 获取token信息
+     * @return
+     */
+    /*public static UserEntity getUserToken(){
+        if(local.get() != null){
+            UserEntity userToken = JSONObject.parseObject(local.get() , UserEntity.class);
+            return userToken;
+        }
+        return null;
+    }*/
+
+    /**
+     * 移除token信息
+     * @return
+     */
+    public static void removeUserToken(){
+        if(local.get() != null){
+            local.remove();
+        }
+    }
+}

+ 80 - 0
src/main/java/com/rf/AIquantum/utils/XMLUtil.java

@@ -0,0 +1,80 @@
+package com.rf.AIquantum.utils;
+
+import com.alibaba.fastjson.JSON;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import java.util.*;
+
+/**
+ * @Description:xml工具
+ * @Author: zsf
+ * @Date: 2022/8/12
+ */
+public class XMLUtil {
+
+    /**
+     * 选择需要返回的格式: 1、返回 List<Map>\2、返回 Map
+     * @param xml
+     * @return
+     */
+    @SuppressWarnings("all")
+    public static Map<String, Object> parseXML(String xml) throws DocumentException {
+        // 1、 List<Map>
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        // 2、 Map
+        Map<String, Object> resultMap = new HashMap<>();
+        Document document = null;
+        document = DocumentHelper.parseText(xml);
+        Element root = document.getRootElement();
+        Iterator<Element> rootIter = root.elementIterator();
+        while (rootIter.hasNext()) {
+            Element ele = rootIter.next();
+            Map<String, Object> parenMap = new HashMap<>();
+            chile(ele, null, parenMap, null, null);
+            // 1、list
+            resultList.add(parenMap);
+            // 2、map
+            resultMap.put(ele.getName(), parenMap);
+        }
+        // toJSON
+        String listJSON = JSON.toJSONString(resultList);
+        String mapJSON = JSON.toJSONString(resultMap);
+        //System.out.println(listJSON);
+        //System.out.println(JSON.toJSONString(mapJSON));
+        return resultMap;
+    }
+
+    public static void chile(Element ele, String keyName, Map<String, Object> parenMap, Map<String, Object> childMap,
+                             List<Map<String, Object>> childData) {
+        Iterator<Element> childIter = ele.elementIterator();
+        while (childIter.hasNext()) {
+            Element attr = childIter.next();
+            Iterator<Element> childIter2 = attr.elementIterator();
+            if (childIter2.hasNext()) {
+                Element attr2 = childIter2.next();
+                Map<String, Object> childMap2 = new HashMap<>();
+                List<Map<String, Object>> childData2 = new ArrayList<>();
+
+                chile(attr, attr.getName(), parenMap, childMap2, childData2);
+            } else if (keyName != null) {
+                childMap.put(attr.getName().trim(), attr.getText().trim());
+            } else {
+                //parenMap.put(attr.getName().trim(), attr.getText().trim());
+                parenMap.put(attr.attribute(0).getValue().trim(), attr.getText().trim());
+            }
+        }
+        if (keyName != null && childMap != null && !childMap.isEmpty()) {
+            if (parenMap != null && parenMap.get(keyName) != null) {
+                List<Map<String, Object>> object = (List<Map<String, Object>>) parenMap.get(keyName);
+                object.add(childMap);
+            } else {
+                childData.add(childMap);
+                parenMap.put(keyName, childData);
+            }
+        }
+    }
+
+}

+ 140 - 0
src/main/java/com/rf/AIquantum/utils/ZipUtils.java

@@ -0,0 +1,140 @@
+package com.rf.AIquantum.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class ZipUtils {
+    private static final Logger log = LoggerFactory.getLogger(ZipUtils.class);
+
+    private ZipUtils() {
+    }
+    /**
+     * 创建ZIP文件
+     * @param sourcePath 文件或文件夹路径
+     * @param zipPath 生成的zip文件存在路径(包括文件名)
+     * @param isDrop  是否删除原文件:true删除、false不删除
+     */
+    public static void createZip(String sourcePath, String zipPath,Boolean isDrop) {
+        FileOutputStream fos = null;
+        ZipOutputStream zos = null;
+        try {
+            fos = new FileOutputStream(zipPath);
+            zos = new ZipOutputStream(fos);
+            //zos.setEncoding("utf8");//此处修改字节码方式。
+            //createXmlFile(sourcePath,"293.xml");
+            writeZip(new File(sourcePath), "", zos,isDrop);
+        } catch (FileNotFoundException e) {
+            log.error("创建ZIP文件失败",e);
+        } finally {
+            try {
+                if (zos != null) {
+                    zos.close();
+                }
+            } catch (IOException e) {
+                log.error("创建ZIP文件失败",e);
+            }
+
+        }
+    }
+    /**
+     * 清空文件和文件目录
+     *
+     * @param f
+     */
+    public static void clean(File f) throws Exception {
+        String cs[] = f.list();
+        if (cs == null || cs.length <= 0) {
+            //System.out.println("delFile:[ " + f + " ]");
+            boolean isDelete = f.delete();
+            if (!isDelete) {
+                //System.out.println("delFile:[ " + f.getName() + "文件删除失败!" + " ]");
+                throw new Exception(f.getName() + "文件删除失败!");
+            }
+        } else {
+            for (int i = 0; i < cs.length; i++) {
+                String cn = cs[i];
+                String cp = f.getPath() + File.separator + cn;
+                File f2 = new File(cp);
+                if (f2.exists() && f2.isFile()) {
+                    //System.out.println("delFile:[ " + f2 + " ]");
+                    boolean isDelete = f2.delete();
+                    if (!isDelete) {
+                        //System.out.println("delFile:[ " + f2.getName() + "文件删除失败!" + " ]");
+                        throw new Exception(f2.getName() + "文件删除失败!");
+                    }
+                } else if (f2.exists() && f2.isDirectory()) {
+                    clean(f2);
+                }
+            }
+            //System.out.println("delFile:[ " + f + " ]");
+            boolean isDelete = f.delete();
+            if (!isDelete) {
+                //System.out.println("delFile:[ " + f.getName() + "文件删除失败!" + " ]");
+                throw new Exception(f.getName() + "文件删除失败!");
+            }
+        }
+    }
+    private static void writeZip(File file, String parentPath, ZipOutputStream zos,Boolean isDrop) {
+        if(file.exists()){
+            if(file.isDirectory()){//处理文件夹
+                parentPath+=file.getName()+File.separator;
+                File [] files=file.listFiles();
+                if(files.length != 0)
+                {
+                    for(File f:files){
+                        writeZip(f, parentPath, zos,isDrop);
+                    }
+                }
+                else
+                {       //空目录则创建当前目录
+                    try {
+                        zos.putNextEntry(new ZipEntry(parentPath));
+                    } catch (IOException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+                }
+            }else{
+                FileInputStream fis=null;
+                try {
+                    fis=new FileInputStream(file);
+                    ZipEntry ze = new ZipEntry(parentPath + file.getName());
+                    zos.putNextEntry(ze);
+                    byte [] content=new byte[1024];
+                    int len;
+                    while((len=fis.read(content))!=-1){
+                        zos.write(content,0,len);
+                        zos.flush();
+                    }
+
+                } catch (FileNotFoundException e) {
+                    log.error("创建ZIP文件失败",e);
+                } catch (IOException e) {
+                    log.error("创建ZIP文件失败",e);
+                }finally{
+                    try {
+                        if(fis!=null){
+                            fis.close();
+                        }
+                        if(isDrop){
+                            clean(file);
+                        }
+                    }catch(IOException e){
+                        log.error("创建ZIP文件失败",e);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+}

+ 48 - 0
src/main/resources/config/application-prod.yml

@@ -0,0 +1,48 @@
+server:
+  port: 8060
+  address: 0.0.0.0
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      url: jdbc:mysql://10.11.7.12:3306/post_station1?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8
+      username: root
+      password: Gqt@qnrcyz105
+      initial-size: 5
+      min-idle: 5
+      max-active: 20
+      max-wait: 30000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      validation-query: select '1' from dual
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+      pool-prepared-statements: true
+      max-open-prepared-statements: 20
+      max-pool-prepared-statement-per-connection-size: 20
+      filters: stat,wall
+      filter:
+        stat:
+          enabled: true
+          db-type: mysql
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      stat-view-servlet:
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: testAdmin
+        login-password: asdcjiafh^&912834
+        enabled: true
+        allow:
+      web-stat-filter:
+        url-pattern: /*
+        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
+        enabled: true
+        session-stat-enable: true
+
+
+
+
+

+ 51 - 0
src/main/resources/config/application-test.yml

@@ -0,0 +1,51 @@
+server:
+  port: 8062
+  address: 0.0.0.0
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      url: jdbc:mysql://49.232.26.44:3306/quantum?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8
+      username: root
+      password: Mysql@.2020
+      initial-size: 5
+      min-idle: 5
+      max-active: 20
+      max-wait: 30000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      validation-query: select '1' from dual
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+      pool-prepared-statements: true
+      max-open-prepared-statements: 20
+      max-pool-prepared-statement-per-connection-size: 20
+      filters: stat,wall
+      filter:
+        stat:
+          enabled: true
+          db-type: mysql
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      stat-view-servlet:
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: testAdmin
+        login-password: asdcjiafh^&912834
+        enabled: true
+        allow:
+      web-stat-filter:
+        url-pattern: /*
+        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
+        enabled: true
+        session-stat-enable: true
+#swagger 显示隐藏配置
+swagger:
+  show: true
+
+
+
+
+

+ 26 - 0
src/main/resources/config/application.yml

@@ -0,0 +1,26 @@
+spring:
+  profiles:
+    active: test
+
+  jpa:
+    hibernate:
+      ddl-auto: update
+    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+    show-sql: false
+    open-in-view: false
+  servlet:
+    multipart:
+      enabled: true
+      file-size-threshold: 2KB
+      max-request-size: 1000MB
+      max-file-size: 1000MB
+logging:
+  level:
+    org.springframework.security:
+      - debug
+      - info
+    org.springframework.web: error
+    org.hibernate.SQL: debug
+    org.hibernate.engine.QueryParameters: debug
+    org.hibernate.engine.query.HQLQueryPlan: debug
+    org.hibernate.type.descriptor.sql.BasicBinder: trace

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

@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <property name="LOG_HOME" value="./logs/%d{yyyy-MM-dd}"/>
+    <property name="LOG_NAME" value="AIquantum"/>
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{35}) |  %msg %n</pattern>
+        </layout>
+    </appender>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+    <appender name="POSITION_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-position-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="EVENT_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-event-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="TRACK_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-track-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="FILE_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-file-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="RESTART_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-restart.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="REDIS_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-redis.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <root level="info">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
+    <logger name="com.patrol.mobile.controller" level="info" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+    </logger>
+
+    <logger name="POSITION_LOG" level="info" additivity="false">
+        <appender-ref ref="POSITION_LOG_APPENDER"/>
+    </logger>
+    <logger name="EVENT_LOG" level="info" additivity="false">
+        <appender-ref ref="EVENT_LOG_APPENDER"/>
+    </logger>
+    <logger name="TRACK_LOG" level="info" additivity="false">
+        <appender-ref ref="TRACK_LOG_APPENDER"/>
+    </logger>
+    <logger name="FILE_LOG" level="info" additivity="false">
+        <appender-ref ref="FILE_LOG_APPENDER"/>
+    </logger>
+    <logger name="RESTART_LOG" level="info" additivity="false">
+        <appender-ref ref="RESTART_LOG_APPENDER"/>
+    </logger>
+    <logger name="REDIS_LOG" level="info" additivity="false">
+        <appender-ref ref="REDIS_LOG_APPENDER"/>
+    </logger>
+</configuration>

+ 28 - 0
src/main/resources/proguard.conf

@@ -0,0 +1,28 @@
+-ignorewarnings
+-keepdirectories
+
+-keep interface com.your_package.** { *; }
+-keep class com.your_package.main{ *; }
+-keep class com.your_package.model.** { *; }
+
+-keepparameternames
+-keepclassmembers @org.springframework.** class * {
+    *;
+}
+
+-keepclassmembers @org.springframework.** interface * {
+    *;
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep @org.springframework.** class *
+-keepclassmembers @javax.** class * { *; }
+
+-dontwarn org.springframework.**
+-dontwarn javax.**
+-dontwarn org.yaml.snakeyaml.**
+-dontwarn okhttp3.**