Gogs преди 8 месеца
ревизия
bd9578be96
променени са 100 файла, в които са добавени 5975 реда и са изтрити 0 реда
  1. 23 0
      education-ai/pom.xml
  2. 7 0
      education-ai/src/main/java/com/education/Main.java
  3. 51 0
      education-ai/src/main/java/com/education/workflow/AbstractWorkFlowRunner.java
  4. 16 0
      education-ai/src/main/java/com/education/workflow/DefAIFactory.java
  5. 33 0
      education-ai/src/main/java/com/education/workflow/DefContextCollector.java
  6. 31 0
      education-ai/src/main/java/com/education/workflow/DefPromptOptimizer.java
  7. 8 0
      education-ai/src/main/java/com/education/workflow/iface/IAIFactory.java
  8. 7 0
      education-ai/src/main/java/com/education/workflow/iface/IContext.java
  9. 17 0
      education-ai/src/main/java/com/education/workflow/iface/IContextCollector.java
  10. 15 0
      education-ai/src/main/java/com/education/workflow/iface/IPromptOptimizer.java
  11. 6 0
      education-ai/src/main/java/com/education/workflow/iface/IResult.java
  12. 8 0
      education-ai/src/main/java/com/education/workflow/iface/IStructParser.java
  13. 16 0
      education-ai/src/main/java/com/education/workflow/iface/IWorkFlowRunner.java
  14. 31 0
      education-api/.gitignore
  15. 310 0
      education-api/mvnw
  16. 182 0
      education-api/mvnw.cmd
  17. 64 0
      education-api/pom.xml
  18. 27 0
      education-api/src/main/java/com/education/api/EducationApiApplication.java
  19. 92 0
      education-api/src/main/java/com/education/api/config/auth/AdminLoginRealm.java
  20. 51 0
      education-api/src/main/java/com/education/api/config/auth/AuthBeanConfig.java
  21. 127 0
      education-api/src/main/java/com/education/api/config/auth/StudentLoginRealm.java
  22. 48 0
      education-api/src/main/java/com/education/api/config/interceptor/AdminAuthInterceptor.java
  23. 38 0
      education-api/src/main/java/com/education/api/config/interceptor/StudentAuthInterceptor.java
  24. 92 0
      education-api/src/main/java/com/education/api/config/interceptor/WebAppConfig.java
  25. 147 0
      education-api/src/main/java/com/education/api/config/util/KnowledgePointConverter.java
  26. 117 0
      education-api/src/main/java/com/education/api/controller/LimitController.java
  27. 98 0
      education-api/src/main/java/com/education/api/controller/admin/LoginController.java
  28. 131 0
      education-api/src/main/java/com/education/api/controller/admin/education/CourseInfoController.java
  29. 60 0
      education-api/src/main/java/com/education/api/controller/admin/education/CustomizeModelController.java
  30. 89 0
      education-api/src/main/java/com/education/api/controller/admin/education/ExamInfoController.java
  31. 40 0
      education-api/src/main/java/com/education/api/controller/admin/education/ExamMonitorController.java
  32. 80 0
      education-api/src/main/java/com/education/api/controller/admin/education/ExtKnowledgePointController.java
  33. 73 0
      education-api/src/main/java/com/education/api/controller/admin/education/GoalInfoController.java
  34. 69 0
      education-api/src/main/java/com/education/api/controller/admin/education/GradeInfoController.java
  35. 79 0
      education-api/src/main/java/com/education/api/controller/admin/education/HomeworkGoalInfoController.java
  36. 120 0
      education-api/src/main/java/com/education/api/controller/admin/education/HomeworkInfoController.java
  37. 73 0
      education-api/src/main/java/com/education/api/controller/admin/education/LanguagePointsInfoController.java
  38. 446 0
      education-api/src/main/java/com/education/api/controller/admin/education/QuestionInfoController.java
  39. 71 0
      education-api/src/main/java/com/education/api/controller/admin/education/StepModelController.java
  40. 46 0
      education-api/src/main/java/com/education/api/controller/admin/education/StuGoalInfoController.java
  41. 59 0
      education-api/src/main/java/com/education/api/controller/admin/education/StuHomeworkInfoController.java
  42. 132 0
      education-api/src/main/java/com/education/api/controller/admin/education/StudentInfoController.java
  43. 65 0
      education-api/src/main/java/com/education/api/controller/admin/education/SubjectInfoController.java
  44. 169 0
      education-api/src/main/java/com/education/api/controller/admin/education/TestPaperInfoController.java
  45. 30 0
      education-api/src/main/java/com/education/api/controller/admin/system/HomeController.java
  46. 34 0
      education-api/src/main/java/com/education/api/controller/admin/system/QuartzController.java
  47. 124 0
      education-api/src/main/java/com/education/api/controller/admin/system/SystemAdminController.java
  48. 64 0
      education-api/src/main/java/com/education/api/controller/admin/system/SystemLogController.java
  49. 88 0
      education-api/src/main/java/com/education/api/controller/admin/system/SystemMenuController.java
  50. 18 0
      education-api/src/main/java/com/education/api/controller/admin/system/SystemMessageController.java
  51. 13 0
      education-api/src/main/java/com/education/api/controller/admin/system/SystemRegionController.java
  52. 84 0
      education-api/src/main/java/com/education/api/controller/admin/system/SystemRoleController.java
  53. 33 0
      education-api/src/main/java/com/education/api/controller/admin/system/WebSiteConfigController.java
  54. 56 0
      education-api/src/main/java/com/education/api/controller/student/CourseInfoController.java
  55. 36 0
      education-api/src/main/java/com/education/api/controller/student/CourseValuateController.java
  56. 74 0
      education-api/src/main/java/com/education/api/controller/student/ExamInfoController.java
  57. 15 0
      education-api/src/main/java/com/education/api/controller/student/GradeInfoController.java
  58. 40 0
      education-api/src/main/java/com/education/api/controller/student/MessageInfoController.java
  59. 71 0
      education-api/src/main/java/com/education/api/controller/student/StuGoalInfoController.java
  60. 61 0
      education-api/src/main/java/com/education/api/controller/student/StuHomeworkInfoController.java
  61. 39 0
      education-api/src/main/java/com/education/api/controller/student/StudentCourseCollectController.java
  62. 89 0
      education-api/src/main/java/com/education/api/controller/student/StudentInfoController.java
  63. 45 0
      education-api/src/main/java/com/education/api/controller/student/SubjectInfoController.java
  64. 90 0
      education-api/src/main/java/com/education/api/controller/student/TestPaperInfoController.java
  65. 28 0
      education-api/src/main/java/com/education/api/controller/student/WebSiteConfigController.java
  66. 41 0
      education-api/src/main/java/com/education/api/controller/student/WrongBookController.java
  67. 109 0
      education-api/src/main/resources/application-dev.yml
  68. 108 0
      education-api/src/main/resources/application-dev1.yml
  69. 139 0
      education-api/src/main/resources/application-prod.yml
  70. 114 0
      education-api/src/main/resources/application-test.yml
  71. 14 0
      education-api/src/main/resources/application.yml
  72. 0 0
      education-api/src/main/resources/config-dev.json
  73. 95 0
      education-api/src/main/resources/config-test.json
  74. 95 0
      education-api/src/main/resources/config.json
  75. 24 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.1_system_admin.sql
  76. 46 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.2_system_dict_value.sql
  77. 103 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.3_system_menu.sql
  78. 15 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.4_system_dict.sql
  79. 12 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.5_system_role.sql
  80. 7 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.6_system_role_menu.sql
  81. 171 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.7_system_qrtz.sql
  82. 17 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.8_system_log.sql
  83. 7 0
      education-api/src/main/resources/db/1.0.1/V1.0.1.9_system_admin_role.sql
  84. 20 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.10_school_info.sql
  85. 10 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.11_student_course_collect.sql
  86. 28 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.12_student_info.sql
  87. 15 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.13_student_question_answer.sql
  88. 14 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.14_student_wrong_book.sql
  89. 14 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.15_study_history.sql
  90. 10 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.16_subject_info.sql
  91. 20 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.17_test_paper_info.sql
  92. 15 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.18_test_paper_info_setting.sql
  93. 11 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.19_test_paper_question_info.sql
  94. 11 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.1_message_info.sql
  95. 13 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.2_grade_info.sql
  96. 21 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.3_course_info.sql
  97. 9 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.4_course_question_info.sql
  98. 22 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.5_exam_info.sql
  99. 13 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.6_language_points_info.sql
  100. 16 0
      education-api/src/main/resources/db/1.0.2/V1.0.2.7_message_log.sql

+ 23 - 0
education-ai/pom.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.education</groupId>
+        <artifactId>education</artifactId>
+        <version>1.0.5-RELEASE</version>
+    </parent>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+    </properties>
+
+
+    <groupId>com.education.ai</groupId>
+    <artifactId>education-ai</artifactId>
+    <version>1.0.5-RELEASE</version>
+
+</project>

+ 7 - 0
education-ai/src/main/java/com/education/Main.java

@@ -0,0 +1,7 @@
+package com.education;
+
+public class Main {
+    public static void main(String[] args) {
+        System.out.println("Hello world!");
+    }
+}

+ 51 - 0
education-ai/src/main/java/com/education/workflow/AbstractWorkFlowRunner.java

@@ -0,0 +1,51 @@
+package com.education.workflow;
+
+import com.education.workflow.iface.*;
+import org.springframework.context.annotation.Bean;
+
+import java.util.List;
+
+//工作流执行器
+//能根据不同工作流,走不同的执行器
+//最好采用配置方法
+public abstract class AbstractWorkFlowRunner implements IWorkFlowRunner {
+
+    @Override
+    public IAIFactory getAIFactory() {
+        return aiFactory();
+    }
+
+    @Override
+    public IPromptOptimizer getPromptOptimizer(){
+        return promptOptimizer();
+    }
+
+    @Bean
+    IAIFactory aiFactory() {
+        return new DefAIFactory();
+    }
+
+    @Bean
+    IPromptOptimizer promptOptimizer() {
+        return new DefPromptOptimizer();
+    }
+
+    //执行
+    public IResult run() {
+        //第一步 收集上下文
+       List<IContext> ctxList = this.getCollector().collect();
+
+       //第二步 上下文优化
+        ctxList = this.getPromptOptimizer().optimize(ctxList,this.getPrompt());
+
+        IContext target = this.getPromptOptimizer().flat(ctxList);
+        //第三步 调用AI
+        IResult result = this.getAIFactory().invoke(target);
+
+        //第四步 转换成
+        this.getStructParser().parse(result);
+
+        return result;
+    }
+
+}

+ 16 - 0
education-ai/src/main/java/com/education/workflow/DefAIFactory.java

@@ -0,0 +1,16 @@
+package com.education.workflow;
+
+import com.education.workflow.iface.IAIFactory;
+import com.education.workflow.iface.IContext;
+import com.education.workflow.iface.IResult;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DefAIFactory implements IAIFactory {
+
+    //调用AI的方法
+    @Override
+    public IResult invoke(IContext ctx) {
+        return null;
+    }
+}

+ 33 - 0
education-ai/src/main/java/com/education/workflow/DefContextCollector.java

@@ -0,0 +1,33 @@
+package com.education.workflow;
+
+import com.education.workflow.iface.IContext;
+import com.education.workflow.iface.IContextCollector;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class DefContextCollector implements IContextCollector {
+
+    protected  List<IContext> contexts = Collections.synchronizedList(new ArrayList<IContext>());
+
+    protected String url;
+    @Override
+    public void setUrl(String url) {
+       this.url = url;
+    }
+
+    @Override
+    public List<IContext> collect() {
+        this.contexts.addAll(this.doCollect());
+        return contexts;
+    }
+
+    protected  abstract  List<IContext>  doCollect();
+
+    @Override
+    public void setContext(IContext context) {
+     this.contexts.add(context);
+    }
+}

+ 31 - 0
education-ai/src/main/java/com/education/workflow/DefPromptOptimizer.java

@@ -0,0 +1,31 @@
+package com.education.workflow;
+
+import com.education.workflow.iface.IContext;
+import com.education.workflow.iface.IPromptOptimizer;
+import org.nustaq.serialization.annotations.Serialize;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Component
+public class DefPromptOptimizer implements IPromptOptimizer {
+
+    //优化提示词
+    @Override
+    public List<IContext> optimize(List<IContext> ctx, String prompt) {
+       Serializable s =  prompt;
+        ctx.add((IContext) s);
+        return ctx;
+    }
+
+    @Override
+    public IContext flat(List<IContext> ctx) {
+        StringBuffer sb = new StringBuffer();
+        for (IContext c : ctx) {
+            sb.append(c);
+        }
+        Serializable c = sb.toString();
+        return (IContext) c;
+    }
+}

+ 8 - 0
education-ai/src/main/java/com/education/workflow/iface/IAIFactory.java

@@ -0,0 +1,8 @@
+package com.education.workflow.iface;
+
+import org.nustaq.serialization.annotations.Serialize;
+
+//AI工厂
+public interface IAIFactory {
+    IResult invoke(IContext ctx);
+}

+ 7 - 0
education-ai/src/main/java/com/education/workflow/iface/IContext.java

@@ -0,0 +1,7 @@
+package com.education.workflow.iface;
+
+import java.io.Serializable;
+
+//可序列化的
+public interface IContext extends Serializable {
+}

+ 17 - 0
education-ai/src/main/java/com/education/workflow/iface/IContextCollector.java

@@ -0,0 +1,17 @@
+package com.education.workflow.iface;
+
+import java.util.List;
+
+//上下文收集类
+public interface IContextCollector {
+
+    //返回上下文列表
+    List<IContext> collect();
+
+    //设置上下文源
+    void setUrl(String url);
+
+    //设置上下文
+    void setContext(IContext context);
+
+}

+ 15 - 0
education-ai/src/main/java/com/education/workflow/iface/IPromptOptimizer.java

@@ -0,0 +1,15 @@
+package com.education.workflow.iface;
+
+import org.nustaq.serialization.annotations.Serialize;
+
+import java.util.List;
+
+//提示词优化器
+public interface IPromptOptimizer {
+
+    //优化提示词
+    List<IContext> optimize(List<IContext> ctx , String prompt);
+
+    //把数组拉平
+    IContext flat(List<IContext> ctx);
+}

+ 6 - 0
education-ai/src/main/java/com/education/workflow/iface/IResult.java

@@ -0,0 +1,6 @@
+package com.education.workflow.iface;
+
+import java.io.Serializable;
+
+public interface IResult extends Serializable {
+}

+ 8 - 0
education-ai/src/main/java/com/education/workflow/iface/IStructParser.java

@@ -0,0 +1,8 @@
+package com.education.workflow.iface;
+
+//结构转换器
+public interface IStructParser {
+
+    //把结果转成目标地址
+    void parse(IResult ctx);
+}

+ 16 - 0
education-ai/src/main/java/com/education/workflow/iface/IWorkFlowRunner.java

@@ -0,0 +1,16 @@
+package com.education.workflow.iface;
+
+public interface IWorkFlowRunner {
+    //工作流执行
+    IResult run();
+
+    IContextCollector getCollector();
+
+    IAIFactory getAIFactory();
+
+    IPromptOptimizer getPromptOptimizer();
+
+    IStructParser getStructParser();
+
+    String getPrompt();
+}

+ 31 - 0
education-api/.gitignore

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

+ 310 - 0
education-api/mvnw

@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  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
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    if [ -n "$MVNW_REPOURL" ]; then
+      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    else
+      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    fi
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $jarUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+    if $cygwin; then
+      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+    fi
+
+    if command -v wget > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget "$jarUrl" -O "$wrapperJarPath"
+        else
+            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl -o "$wrapperJarPath" "$jarUrl" -f
+        else
+            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+        fi
+
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaClass=`cygpath --path --windows "$javaClass"`
+        fi
+        if [ -e "$javaClass" ]; then
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaClass")
+            fi
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 182 - 0
education-api/mvnw.cmd

@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  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,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%

+ 64 - 0
education-api/pom.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.education</groupId>
+        <artifactId>education</artifactId>
+        <version>1.0.5-RELEASE</version>
+    </parent>
+
+    <groupId>com.education.api</groupId>
+    <artifactId>education-api</artifactId>
+    <version>1.0.5-RELEASE</version>
+    <name>education-admin-api</name>
+    <description>基于Spring Boot构建的智能教育平台</description>
+
+    <dependencies>
+        <dependency>
+            <artifactId>education-common-api</artifactId>
+            <groupId>com.education.common.api</groupId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <artifactId>education-canal</artifactId>
+            <groupId>com.education.canal</groupId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.xuwei-k</groupId>
+            <artifactId>html2image</artifactId>
+            <version>0.1.0</version>
+        </dependency>
+
+        <dependency>
+            <artifactId>education-ai</artifactId>
+            <groupId>com.education.ai</groupId>
+            <version>1.0.5-RELEASE</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+
+            <!-- 打包跳过单元测试 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.20.1</version>
+                <configuration>
+                    <!-- 不指定单元测试 -->
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 27 - 0
education-api/src/main/java/com/education/api/EducationApiApplication.java

@@ -0,0 +1,27 @@
+package com.education.api;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+
+
+/**
+ * 管理后台启动类
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/3/8 11:11
+ */
+@SpringBootApplication(scanBasePackages =
+   {
+       "com.education"
+   }
+)
+@MapperScan("com.education.business.mapper")
+@EnableCaching
+public class EducationApiApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(EducationApiApplication.class, args);
+    }
+}

+ 92 - 0
education-api/src/main/java/com/education/api/config/auth/AdminLoginRealm.java

@@ -0,0 +1,92 @@
+package com.education.api.config.auth;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.education.auth.AuthConfig;
+import com.education.auth.LoginToken;
+import com.education.auth.realm.LoginAuthRealm;
+import com.education.business.service.system.SystemAdminService;
+import com.education.business.session.AdminUserSession;
+import com.education.business.task.TaskManager;
+import com.education.business.task.param.WebSocketMessageParam;
+import com.education.common.constants.LocalQueueConstants;
+import com.education.common.enums.BooleanEnum;
+import com.education.common.enums.LoginEnum;
+import com.education.common.enums.SocketMessageTypeEnum;
+import com.education.common.exception.BusinessException;
+import com.education.common.utils.IpUtils;
+import com.education.common.utils.PasswordUtil;
+import com.education.common.utils.RequestUtils;
+import com.education.model.entity.SystemAdmin;
+import com.jfinal.kit.HashKit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+
+/**
+ * 管理员登录认证
+ * @author zengjintao
+ * @create_at 2021年11月27日 0027 11:28
+ * @since version 1.0.4
+ */
+@Component
+public class AdminLoginRealm implements LoginAuthRealm<AdminUserSession> {
+
+    private final Logger logger = LoggerFactory.getLogger(AdminLoginRealm.class);
+    @Resource
+    private SystemAdminService systemAdminService;
+    @Resource
+    private TaskManager taskManager;
+    @Resource
+    private AuthConfig authConfig;
+
+    @Override
+    public AdminUserSession doLogin(LoginToken loginToken) {
+        String password = loginToken.getPassword();
+        LambdaQueryWrapper queryWrapper = Wrappers.<SystemAdmin>lambdaQuery()
+                .eq(SystemAdmin::getLoginName, loginToken.getUsername());
+        SystemAdmin systemAdmin = systemAdminService.getOne(queryWrapper);
+        Assert.notNull(systemAdmin, () -> new BusinessException("用户名不存在"));
+        password = PasswordUtil.createPassword(systemAdmin.getEncrypt(), password);
+        if (!password.equals(systemAdmin.getPassword())) {
+            throw new BusinessException("用户名或密码错误");
+        }
+
+        Integer flag = systemAdmin.getDisabledFlag();
+        if (BooleanEnum.YES.getCode().equals(flag)) {
+            throw new BusinessException("账号已被禁用");
+        }
+        AdminUserSession adminUserSession = new AdminUserSession(systemAdmin.getId(), loginToken.getDeviceType());
+        adminUserSession.setSystemAdmin(systemAdmin);
+        adminUserSession.setLoginCount(systemAdmin.getLoginCount());
+        return adminUserSession;
+    }
+
+    @Override
+    public void loadPermission(AdminUserSession userSession) {
+        systemAdminService.loadUserMenuAndPermission(userSession);
+    }
+
+    @Override
+    public void onRejectSession(AdminUserSession userSession) {
+        String hashToken = HashKit.md5(userSession.getToken());
+        logger.warn("用户:{}会话token:{}被挤下线", userSession.getSystemAdmin().getLoginName(),
+                authConfig.getSessionIdPrefix() + StrUtil.COLON + LoginEnum.ADMIN.getValue() +
+                        StrUtil.COLON + hashToken);
+        WebSocketMessageParam taskParam = new WebSocketMessageParam(LocalQueueConstants.SYSTEM_SOCKET_MESSAGE);
+        taskParam.setHashToken(hashToken);
+        taskParam.setSocketMessageTypeEnum(SocketMessageTypeEnum.REJECT_SESSION);
+        taskParam.setIp(IpUtils.getAddressIp(RequestUtils.getRequest()));
+        taskManager.pushTask(taskParam);
+    }
+
+    @Override
+    public String getLoginType() {
+        return LoginEnum.ADMIN.getValue();
+    }
+}

+ 51 - 0
education-api/src/main/java/com/education/api/config/auth/AuthBeanConfig.java

@@ -0,0 +1,51 @@
+package com.education.api.config.auth;
+
+import com.education.auth.AuthConfig;
+import com.education.auth.AuthHandler;
+import com.education.auth.AuthRealmManager;
+import com.education.auth.realm.LoginAuthRealm;
+import com.education.auth.session.RedisSessionStorage;
+import com.education.auth.token.JwtTokenFactory;
+import com.education.common.cache.CacheBean;
+import com.education.common.model.JwtToken;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Resource;
+
+/**
+ * auth 认证配置
+ * @author zengjintao
+ * @create_at 2021年11月27日 0027 11:47
+ * @since version 1.0.4
+ */
+@Configuration
+public class AuthBeanConfig {
+
+    @Resource
+    private AdminLoginRealm adminLoginRealm;
+    @Resource
+    private StudentLoginRealm studentLoginRealm;
+
+    @Bean
+    public AuthRealmManager authRealmManager(JwtToken jwtToken,
+                                             AuthConfig authConfig,
+                                             CacheBean redisCacheBean) {
+        AuthRealmManager authRealmManager = new AuthRealmManager(
+                new RedisSessionStorage(redisCacheBean, authConfig.getSessionIdPrefix()),
+                new JwtTokenFactory(jwtToken), authConfig);
+        authRealmManager.addLoginAuthRealm(adminLoginRealm);
+        authRealmManager.addLoginAuthRealm(studentLoginRealm);
+        return authRealmManager;
+    }
+
+    @Bean
+    public AuthHandler authHandler() {
+        return new AuthHandler();
+    }
+
+   /// @Bean
+  //  public AuthConfig AuthConfig() {
+   //     return new AuthConfig();
+   /// }
+}

+ 127 - 0
education-api/src/main/java/com/education/api/config/auth/StudentLoginRealm.java

@@ -0,0 +1,127 @@
+package com.education.api.config.auth;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.education.auth.AuthConfig;
+import com.education.auth.LoginToken;
+import com.education.auth.realm.LoginAuthRealm;
+import com.education.business.service.education.GradeInfoService;
+import com.education.business.service.education.StudentInfoService;
+import com.education.business.session.StudentSession;
+import com.education.business.task.TaskManager;
+import com.education.business.task.param.WebSocketMessageParam;
+import com.education.common.constants.CacheTime;
+import com.education.common.constants.LocalQueueConstants;
+import com.education.common.enums.LoginEnum;
+import com.education.common.enums.SocketMessageTypeEnum;
+import com.education.common.exception.BusinessException;
+import com.education.common.utils.IpUtils;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.PasswordUtil;
+import com.education.common.utils.RequestUtils;
+import com.education.model.entity.GradeInfo;
+import com.education.model.entity.StudentInfo;
+import com.jfinal.kit.HashKit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author zengjintao
+ * @create_at 2021年11月30日 0030 14:28
+ * @since version 1.0.4
+ */
+@Component
+public class StudentLoginRealm implements LoginAuthRealm<StudentSession> {
+
+    private final Logger logger = LoggerFactory.getLogger(StudentLoginRealm.class);
+    @Resource
+    private StudentInfoService studentInfoService;
+    @Resource
+    private GradeInfoService gradeInfoService;
+    @Resource
+    private TaskManager taskManager;
+    @Resource
+    private AuthConfig authConfig;
+
+    @Override
+    public StudentSession doLogin(LoginToken loginToken) {
+        LambdaQueryWrapper queryWrapper = Wrappers.<StudentInfo>lambdaQuery()
+                .eq(StudentInfo::getLoginName, loginToken.getUsername());
+        StudentInfo studentInfo = studentInfoService.selectFirst(queryWrapper);
+        if (ObjectUtils.isEmpty(studentInfo)) {
+            throw new BusinessException("用户不存在");
+        }
+
+        String dataBasePassword = studentInfo.getPassword();
+        String encrypt = studentInfo.getEncrypt();
+        if (!dataBasePassword.equals(PasswordUtil.createPassword(encrypt, loginToken.getPassword()))) {
+            throw new BusinessException("用户名或密码错误");
+        }
+
+        if (studentInfo.isDisabledFlag()) {
+            throw new BusinessException("账号已被禁用");
+        }
+
+        GradeInfo gradeInfo = gradeInfoService.getById(studentInfo.getGradeInfoId());
+        StudentSession studentSession = new StudentSession(studentInfo.getId(), loginToken.getDeviceType());
+        studentSession.setName(studentInfo.getName());
+        studentSession.setHeadImg(studentInfo.getHeadImg());
+        studentSession.setSex(studentInfo.getSex());
+        studentSession.setAge(studentInfo.getAge());
+        studentSession.setBirthday(studentInfo.getBirthday());
+        studentSession.setAddress(studentInfo.getAddress());
+        studentSession.setSex(studentInfo.getSex());
+        studentSession.setMobile(studentInfo.getMobile());
+        studentSession.setLoginCount(studentInfo.getLoginCount());
+        studentSession.setGradeInfoId(gradeInfo.getId());
+        studentSession.setGradeInfoName(gradeInfo.getName());
+        return studentSession;
+    }
+
+    @Override
+    public String getLoginType() {
+        return LoginEnum.STUDENT.getValue();
+    }
+
+    @Override
+    public void onLoginSuccess(StudentSession userSession) {
+        studentInfoService.updateLoginInfo(userSession.getId(), userSession.getLoginCount());
+    }
+
+    @Override
+    public void onLogoutSuccess(StudentSession userSession) {
+
+    }
+
+    @Override
+    public void onRejectSession(StudentSession userSession) {
+        String hashToken = HashKit.md5(userSession.getToken());
+        logger.warn("学员:{}会话token:{}被挤下线", userSession.getLoginName(),
+                authConfig.getSessionIdPrefix() + StrUtil.COLON + LoginEnum.STUDENT.getValue() +
+                        StrUtil.COLON + hashToken);
+        WebSocketMessageParam taskParam = new WebSocketMessageParam(LocalQueueConstants.SYSTEM_SOCKET_MESSAGE);
+        taskParam.setHashToken(HashKit.md5(userSession.getToken()));
+        taskParam.setSocketMessageTypeEnum(SocketMessageTypeEnum.REJECT_SESSION);
+        taskParam.setIp(IpUtils.getAddressIp(RequestUtils.getRequest()));
+        taskManager.pushTask(taskParam);
+    }
+
+    @Override
+    public long getSessionTimeOut(boolean rememberMe) {
+        if (rememberMe) {
+            // 缓存一周
+            return CacheTime.ONE_WEEK_SECOND;
+        }
+        // 考虑到有点试卷可能考试时间在2个小时,默认将token失效时间先设置为3个小时
+        return CacheTime.THREE_HOUR_SECOND;
+    }
+
+    @Override
+    public void onLoginFail(String username, Exception e) {
+
+    }
+}

+ 48 - 0
education-api/src/main/java/com/education/api/config/interceptor/AdminAuthInterceptor.java

@@ -0,0 +1,48 @@
+/**
+ *
+ */
+package com.education.api.config.interceptor;
+import com.education.auth.AuthUtil;
+import com.education.auth.session.UserSession;
+import com.education.business.interceptor.BaseInterceptor;
+import com.education.common.enums.LoginEnum;
+import com.education.common.exception.BusinessException;
+import com.education.common.utils.RequestUtils;
+import com.education.common.utils.ResultCode;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 用户认证拦截器
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2017年5月18日 下午2:41:05
+ */
+@Component
+public class AdminAuthInterceptor extends BaseInterceptor {
+
+	@Override
+	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object)
+			throws Exception {
+		super.checkHeader(request);
+		String targetUrl = RequestUtils.getRequestUrl(request);
+		if (request.getMethod().equals("OPTIONS")){
+			return true;
+		}
+		if (targetUrl.startsWith("/api/dict")) {
+			return true;
+		}
+		else if (targetUrl.startsWith("/api/upload")) {
+			return true;
+		}
+		else if (targetUrl.startsWith("/uploads")) {
+			return true;
+		}
+		UserSession userSession = AuthUtil.getSession(LoginEnum.ADMIN.getValue());
+		if (userSession == null) {
+			throw new BusinessException(new ResultCode(ResultCode.UN_AUTH_ERROR_CODE, "会话已过期,请重新登录"));
+		}
+		return checkToken(LoginEnum.ADMIN.getValue(), response);
+	}
+}

+ 38 - 0
education-api/src/main/java/com/education/api/config/interceptor/StudentAuthInterceptor.java

@@ -0,0 +1,38 @@
+package com.education.api.config.interceptor;
+
+import cn.hutool.core.util.StrUtil;
+import com.education.auth.AuthUtil;
+import com.education.auth.session.UserSession;
+import com.education.business.interceptor.BaseInterceptor;
+import com.education.common.enums.LoginEnum;
+import com.education.common.exception.BusinessException;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.ResultCode;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 学员端api 拦截器
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/21 21:38
+ */
+@Component
+public class StudentAuthInterceptor extends BaseInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        String method = request.getMethod();
+        // OPTIONS 请求直接放行,解决uni-app 请求跨域问题
+        if (StrUtil.isNotBlank(method) && "OPTIONS".equalsIgnoreCase(method)) {
+            return true;
+        }
+        super.checkHeader(request);
+        UserSession userSession = AuthUtil.getSession(LoginEnum.STUDENT.getValue());
+        if (ObjectUtils.isEmpty(userSession)) {
+            throw new BusinessException(new ResultCode(ResultCode.UN_AUTH_ERROR_CODE, "会话已过期,请重新登录!"));
+        }
+        return checkToken(LoginEnum.STUDENT.getValue(), response);
+    }
+}

+ 92 - 0
education-api/src/main/java/com/education/api/config/interceptor/WebAppConfig.java

@@ -0,0 +1,92 @@
+/**
+ * 
+ */
+package com.education.api.config.interceptor;
+
+
+import com.education.auth.PermissionInterceptor;
+import com.education.common.config.OssProperties;
+import com.education.common.enums.OssPlatformEnum;
+
+import com.education.business.interceptor.FormLimitInterceptor;
+import com.education.business.interceptor.LogInterceptor;
+import com.education.business.interceptor.ParamsValidateInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 系统配置
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2017年9月27日下午8:03:45
+ */
+@Configuration
+public class WebAppConfig implements WebMvcConfigurer {
+
+	@Autowired
+	private LogInterceptor logInterceptor;
+	@Autowired
+	private AdminAuthInterceptor authInterceptor;
+	@Autowired
+	private ParamsValidateInterceptor paramsValidateInterceptor;
+	@Autowired
+	private FormLimitInterceptor formLimitInterceptor;
+	@Autowired
+	private StudentAuthInterceptor studentAuthInterceptor;
+
+	@Resource
+	private OssProperties ossProperties;
+
+
+	//不需要拦截的url
+	private static final List<String> noInterceptorUrl = new ArrayList<String>() {
+		{
+			add("/system/unAuth");
+			add("/system/login");
+			add("/auth/**");
+			add("/api/image");
+		}
+	};
+
+	@Override
+	public void addInterceptors(InterceptorRegistry registry) {
+		registry.addInterceptor(logInterceptor).addPathPatterns("/**");
+		registry.addInterceptor(formLimitInterceptor).addPathPatterns("/**");
+		registry.addInterceptor(paramsValidateInterceptor).addPathPatterns("/**");
+		registry.addInterceptor(authInterceptor)
+				.excludePathPatterns(noInterceptorUrl)
+				.addPathPatterns("/api/**")
+				.addPathPatterns("/system/**");
+		registry.addInterceptor(studentAuthInterceptor)
+				.excludePathPatterns("/student/login")
+				.addPathPatterns("/student/**");
+		registry.addInterceptor(new PermissionInterceptor());
+	}
+
+	@Override
+	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
+		/*ModelBeanConfig modelBeanConfig = new ModelBeanConfig(jdbcTemplate);
+		resolvers.add(new RequestModelBeanBodyMethodArgumentResolver());
+		resolvers.add(new RequestModelBeanMethodArgumentResolver());*/
+	}
+
+	@Override
+	public void addResourceHandlers(ResourceHandlerRegistry registry) {
+		 //配置静态资源路径
+		registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
+		registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+		if (OssPlatformEnum.LOCAL.getValue().equals(ossProperties.getPlatform())) {
+			//配置文件上传虚拟路径
+			registry.addResourceHandler("/uploads/**").addResourceLocations("file:" + ossProperties.getBucketName());
+		}
+	}
+}

+ 147 - 0
education-api/src/main/java/com/education/api/config/util/KnowledgePointConverter.java

@@ -0,0 +1,147 @@
+package com.education.api.config.util;
+import com.alibaba.fastjson.JSON;
+import com.education.model.entity.ExtKnowledgePoint;
+
+import java.util.*;
+
+public class KnowledgePointConverter {
+
+    // 内部类:定义JSON中的节点结构
+    static class Node {
+        private String id;         // 对应ExtKnowledgePoint的id
+        private String name;       // 对应ExtKnowledgePoint的pointName
+        private double symbolSize; // 保持默认值
+        private double x;          // 保持默认值
+        private double y;          // 保持默认值
+        private double value;      // 保持默认值
+        private int category;      // 对应categories的索引
+
+        public Node(String id, String name ,int category) {
+            this.id = id;
+            this.name = name;
+            this.symbolSize = 10.0;  // 默认值
+            this.x = 0.0;            // 默认值
+            this.y = 0.0;            // 默认值
+            this.value = 5.0;        // 默认值
+            this.category = 0;       // 默认归类到第一个分类(可自定义)
+        }
+
+        // getter和setter(FastJSON序列化需要)
+        public String getId() { return id; }
+        public void setId(String id) { this.id = id; }
+        public String getName() { return name; }
+        public void setName(String name) { this.name = name; }
+        public double getSymbolSize() { return symbolSize; }
+        public void setSymbolSize(double symbolSize) { this.symbolSize = symbolSize; }
+        public double getX() { return x; }
+        public void setX(double x) { this.x = x; }
+        public double getY() { return y; }
+        public void setY(double y) { this.y = y; }
+        public double getValue() { return value; }
+        public void setValue(double value) { this.value = value; }
+        public int getCategory() { return category; }
+        public void setCategory(int category) { this.category = category; }
+    }
+
+    // 内部类:定义JSON中的链接结构
+    static class Link {
+        private String source;  // 对应ExtKnowledgePoint的parentId
+        private String target;  // 对应ExtKnowledgePoint的id
+
+        public Link(String source, String target) {
+            this.source = source;
+            this.target = target;
+        }
+
+        // getter和setter
+        public String getSource() { return source; }
+        public void setSource(String source) { this.source = source; }
+        public String getTarget() { return target; }
+        public void setTarget(String target) { this.target = target; }
+    }
+
+    // 新增:定义分类结构(categories)
+    static class Category {
+        private String name; // 分类名称
+
+        public Category(String name) {
+            this.name = name;
+        }
+
+        public String getName() { return name; }
+        public void setName(String name) { this.name = name; }
+    }
+
+    /**
+     * 将List<ExtKnowledgePoint>转换为包含categories的目标JSON结构
+     * @param knowledgePoints 知识点列表
+     * @return 转换后的JSON字符串
+     */
+    public static String convert(List<ExtKnowledgePoint> knowledgePoints) {
+        // 1. 构建节点列表(nodes)
+        List<Node> nodes = new ArrayList<>();
+        for (ExtKnowledgePoint point : knowledgePoints) {
+            Node node = new Node(
+                    point.getId().toString(),
+                    point.getPointName(),
+                    point.getLevel()
+            );
+            // 可选:根据level设置category(与categories索引对应)
+            if (point.getLevel() != null) {
+                // 例如:level=1 → 分类0(A),level=2 → 分类1(B)
+                node.setCategory(point.getLevel() - 1);
+            }
+            nodes.add(node);
+        }
+
+        // 2. 构建链接列表(links)
+        List<Link> links = new ArrayList<>();
+        for (ExtKnowledgePoint point : knowledgePoints) {
+            Integer parentId = point.getParentId();
+            if (parentId != null) {
+                Link link = new Link(
+                        parentId.toString(),
+                        point.getId().toString()
+                );
+                links.add(link);
+            }
+        }
+
+        // 3. 新增:构建分类列表(categories)
+        int max = getMaxLevel(knowledgePoints);
+       List<Category> categories = new ArrayList<>();
+       for (int i = 0 ; i <= max ; i++) {
+           categories.add(new Category(i+ ""));  // 第一个分类
+           //categories.add(new Category("B"));  // 第二个分类
+       }
+
+
+        // 4. 组装为最终JSON结构(包含nodes、links、categories)
+        Map<String, Object> result = new HashMap<>();
+        result.put("nodes", nodes);
+        result.put("links", links);
+        result.put("categories", categories);  // 新增categories节点
+
+        // 5. 转换为JSON字符串并返回
+        return JSON.toJSONString(result, true);
+    }
+
+    /**
+     * 获取知识点列表中level字段的最大值
+     * @param knowledgePoints 知识点列表
+     * @return level的最大值,如果列表为空或所有level为null则返回0
+     */
+    public static int getMaxLevel(List<ExtKnowledgePoint> knowledgePoints) {
+        if (knowledgePoints == null || knowledgePoints.isEmpty()) {
+            return 0;
+        }
+
+        // 使用Java 8 Stream过滤掉null值并获取最大值
+        Optional<Integer> maxLevel = knowledgePoints.stream()
+                .map(ExtKnowledgePoint::getLevel)
+                .filter(level -> level != null)
+                .max(Integer::compareTo);
+
+        return maxLevel.orElse(0);
+    }
+}

+ 117 - 0
education-api/src/main/java/com/education/api/controller/LimitController.java

@@ -0,0 +1,117 @@
+package com.education.api.controller;
+
+import com.education.common.cache.CacheBean;
+import com.education.common.disabled.RateLimitLock;
+import com.education.common.utils.Result;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * 限流测试接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_date 2020/6/12 10:41
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/limit")
+public class LimitController {
+
+    @Resource
+    private JdbcTemplate jdbcTemplate;
+    @Resource
+    private CacheBean redisCacheBean;
+    @Resource
+    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
+    @Resource
+    private RabbitTemplate rabbitTemplate;
+
+    private final Map cache = new HashMap();
+
+    private ReentrantLock reentrantLock = new ReentrantLock();
+
+    @GetMapping
+    @RateLimitLock(limit = 20)
+    public Result limit() {
+        return Result.success("访问接口");
+    }
+    @GetMapping("submit")
+    public Result submit(@RequestParam Map params) {
+
+
+        System.out.println("执行submit方法保存数据" + params);
+        return Result.success("success");
+    }
+
+
+  /*  public static void main(String[] args) {
+        for (int i = 0; i < 100000; i++) {
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    System.out.println(HttpKit.get("http://localhost/limit/jdbcTest"));
+                }
+            }).start();
+        }
+    }*/
+
+    @GetMapping("jdbcTestCache")
+    public Result jdbcTestCache() {
+        List<Map<String, Object>> list = redisCacheBean.get("jdbcTest");
+        if (list == null) {
+            System.err.println("缓存无数据");
+            reentrantLock.lock();
+            try {
+                list = redisCacheBean.get("jdbcTest");
+                if (list == null) {
+                    System.err.println("查询数据库");
+                    list = jdbcTemplate.queryForList("select * from question_info_copy limit 5000, 50");
+                    redisCacheBean.put("jdbcTest", list);
+                }
+            } finally {
+                reentrantLock.unlock();
+            }
+        }
+        return Result.success(list);
+    }
+    @GetMapping("jdbcTest")
+    public Result jdbcTest() {
+        List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from question_info_copy limit 5000, 50");
+        return Result.success(list);
+    }
+
+    /**
+     * 使用mysql乐观锁更新文章阅读量或者点赞量测试接口
+     */
+    @GetMapping("mysql")
+    public void mysql() {
+        jdbcTemplate.update("update exam_info set mark = mark + 1 where id = 1");
+    }
+
+    @GetMapping("syncMysql")
+    public void syncMysql() {
+        synchronized (this) {
+            jdbcTemplate.update("update exam_info set mark = mark + 1 where id = 1");
+        }
+    }
+
+    /**
+     * 使用线程池更新文章阅读量或者点赞量测试接口
+     */
+    @GetMapping("threadPool")
+    public void threadPool() {
+        threadPoolTaskExecutor.execute(() -> {
+            jdbcTemplate.update("update exam_info set mark = mark + 1 where id = 1");
+        });
+    }
+}

+ 98 - 0
education-api/src/main/java/com/education/api/controller/admin/LoginController.java

@@ -0,0 +1,98 @@
+package com.education.api.controller.admin;
+
+import com.education.auth.AuthUtil;
+import com.education.auth.LoginToken;
+import com.education.business.session.AdminUserSession;
+import com.education.business.task.TaskManager;
+import com.education.business.task.param.AdminLoginTaskParam;
+import com.education.common.annotation.FormLimit;
+import com.education.common.annotation.SystemLog;
+import com.education.common.base.BaseController;
+import com.education.common.constants.AuthConstants;
+import com.education.common.constants.LocalQueueConstants;
+import com.education.common.enums.LoginEnum;
+import com.education.common.utils.IpUtils;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.request.UserLoginRequest;
+import com.jfinal.kit.Kv;
+import io.swagger.annotations.Api;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 系统登录
+ *
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2019/3/22 22:12
+ */
+@RestController
+@RequestMapping("/system")
+@Api(value = "管理员登录登出接口", tags = "系统登录登出接口")
+public class LoginController extends BaseController {
+
+    @Resource
+    private TaskManager taskManager;
+    @Resource
+    private HttpServletRequest request;
+
+    /**
+     * 管理员登录接口
+     *
+     * @param userLoginRequest
+     * @return
+     */
+    @PostMapping("/login")
+    @SystemLog(describe = "登录管理系统")
+    @FormLimit
+    public Result<Map> login(@RequestBody @Validated UserLoginRequest userLoginRequest, HttpServletResponse response) {
+        String codeKey = userLoginRequest.getKey();
+        if(!"test".equals(codeKey)){
+            String imageCode = userLoginRequest.getCode();
+            String cacheCode = cacheBean.get(codeKey);
+            if (!imageCode.equalsIgnoreCase(cacheCode)) {
+                return Result.fail(ResultCode.CODE_ERROR, "验证码输入错误");
+            }
+        }
+        LoginToken loginToken = new LoginToken(userLoginRequest.getUserName(), userLoginRequest.getPassword(),
+                LoginEnum.ADMIN.getValue(), userLoginRequest.getDeviceType(), false);
+        AdminUserSession userSession = AuthUtil.login(loginToken);
+        response.addHeader(AuthConstants.AUTHORIZATION, userSession.getToken());
+        Kv userInfo = Kv.create().set("id", userSession.getId())
+                .set("permissionList", userSession.getPermissionList())
+                .set("menuList", userSession.getMenuTreeList())
+                .set("login_name", userLoginRequest.getUserName());
+        Map resultMap = new HashMap<>();
+        resultMap.put("userInfo", userInfo);
+        // 异步更新用户相关信息
+        // 异步更新用户相关信息
+        AdminLoginTaskParam adminLoginTaskParam = new AdminLoginTaskParam(LocalQueueConstants.ADMIN_LOGIN_SUCCESS_QUEUE);
+        adminLoginTaskParam.setSystemAdmin(userSession.getSystemAdmin());
+        adminLoginTaskParam.setNewLoginIp(IpUtils.getAddressIp(request));
+        taskManager.pushTask(adminLoginTaskParam);
+        return Result.success(ResultCode.SUCCESS, "登录成功", resultMap);
+    }
+
+    /**
+     * 系统退出
+     *
+     * @return
+     */
+    @PostMapping("logout")
+    @SystemLog(describe = "退出管理系统")
+    @FormLimit
+    public Result logout() {
+        AuthUtil.logout(LoginEnum.ADMIN.getValue());
+        return Result.success(ResultCode.SUCCESS, "退出成功");
+    }
+}

+ 131 - 0
education-api/src/main/java/com/education/api/controller/admin/education/CourseInfoController.java

@@ -0,0 +1,131 @@
+package com.education.api.controller.admin.education;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.CourseInfoService;
+import com.education.business.service.education.CourseSectionNodeService;
+import com.education.business.service.education.CourseSectionService;
+import com.education.common.annotation.Param;
+import com.education.common.annotation.ParamsType;
+import com.education.common.annotation.ParamsValidate;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.entity.CourseInfo;
+import com.education.model.entity.CourseSection;
+import com.education.model.entity.CourseSectionNode;
+import com.education.model.request.PageParam;
+import com.education.model.vo.CourseSectionVo;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 课程管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/25 15:03
+ */
+@RestController
+@RequestMapping("/system/course")
+public class CourseInfoController extends BaseController {
+    @Resource
+    private CourseSectionService courseSectionService;
+    @Resource
+    private CourseInfoService courseInfoService;
+    @Resource
+    private CourseSectionNodeService courseSectionNodeService;
+
+
+    /**
+     * 课程列表
+     * @param pageParam
+     * @param courseInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:course:list")
+    public Result list(PageParam pageParam, CourseInfo courseInfo) {
+        return Result.success(courseInfoService.selectPageList(pageParam, courseInfo));
+    }
+
+    /**
+     * 添加或修改课程
+     * @param courseInfo
+     * @return
+     */
+    @PostMapping("saveOrUpdate")
+    @ParamsValidate(params = {
+        @Param(name = "name", message = "请输入课程名称"),
+        @Param(name = "headImg", message = "请上传课程封面"),
+        @Param(name = "schoolType", message = "请选择课程阶段"),
+        @Param(name = "gradeInfoId", message = "请选择年级"),
+        @Param(name = "subjectId", message = "请选择所属科目")
+    }, paramsType = ParamsType.JSON_DATA)
+    //@RequiresPermissions(value = {"system:course:save", "system:course:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody CourseInfo courseInfo) {
+        courseInfoService.saveOrUpdateCourse(courseInfo);
+        return Result.success();
+    }
+
+    /**
+     * 删除课程
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:course:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        courseInfoService.deleteById(id);
+        return Result.success();
+    }
+
+    /**
+     * 添加或修改课程章节
+     * @param CourseSection
+     * @return
+     */
+    @PostMapping("/section")
+    @ParamsValidate(params = {
+            @Param(name = "title", message = "请输入章节标题"),
+            @Param(name = "courseId", message = "课程Id为空"),
+    }, paramsType = ParamsType.JSON_DATA)
+    //@RequiresPermissions(value = {"system:section:save", "system:section:update"}, logical = Logical.OR)
+    public Result section(@RequestBody CourseSection section) {
+        courseSectionService.saveOrUpdate(section);
+        return Result.success();
+    }
+
+    @GetMapping("/{courseId}/section")
+    //@RequiresPermissions("system:section:list")
+    public Result section(@PathVariable Integer courseId) {
+        List<CourseSection> list = courseSectionService.list(new LambdaQueryWrapper<CourseSection>().eq(CourseSection::getCourseId, courseId));
+        List<CourseSectionVo> collect = list.stream().map(item -> {
+            CourseSectionVo courseSectionVo = new CourseSectionVo(item);
+            List<CourseSectionNode> nodeList = courseSectionNodeService.list(new LambdaQueryWrapper<CourseSectionNode>().eq(CourseSectionNode::getCourseSectionId, item.getId()));
+            courseSectionVo.setCourseSectionNodeList(nodeList);
+            return courseSectionVo;
+        }).collect(Collectors.toList());
+        return Result.success(collect);
+    }
+    @PostMapping("/section/node")
+    @ParamsValidate(params = {
+            @Param(name = "title", message = "请输入节点标题"),
+            @Param(name = "courseId", message = "请选择所属课程"),
+            @Param(name = "synopsis", message = "请输入节点简介"),
+            @Param(name = "courseSectionId", message = "请选择所属章节"),
+    }, paramsType = ParamsType.JSON_DATA)
+    //@RequiresPermissions(value = {"system:section:node:save", "system:section:node:update"}, logical = Logical.OR)
+    public Result sectionNode(@RequestBody CourseSectionNode sectionNode) {
+        courseSectionNodeService.saveOrUpdate(sectionNode);
+        return Result.success(sectionNode);
+    }
+    @DeleteMapping("/section/node/{id}")
+    //@RequiresPermissions("system:section:node:deleteById")
+    public Result delSectionNode(@PathVariable Integer id) {
+        courseSectionNodeService.removeById(id);
+        return Result.success();
+    }
+}

+ 60 - 0
education-api/src/main/java/com/education/api/controller/admin/education/CustomizeModelController.java

@@ -0,0 +1,60 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.CustomizeModelService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.CustomizeModelDto;
+import com.education.model.entity.CustomizeModel;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+/**
+ * 自定义模版管理
+ */
+@RequestMapping("/system/customizeModel")
+@RestController
+public class CustomizeModelController extends BaseController {
+
+    @Resource
+    private CustomizeModelService customizeModelService;
+
+    /**
+     * 模版分页列表
+     * @param pageParam
+     * @param customizeModel
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:customizeModel:list")
+    public Result selectPage(PageParam pageParam, CustomizeModel customizeModel) {
+        return Result.success(customizeModelService.selectPageList(pageParam, customizeModel));
+    }
+
+    /**
+     * 添加或修改
+     * @param customizeModelDto
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:customizeModel:save","system:customizeModel:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody CustomizeModelDto customizeModelDto) {
+        customizeModelService.saveOrUpdate(customizeModelDto);
+        return Result.success();
+    }
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:customizeModel:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        customizeModelService.removeById(id);
+        return Result.success();
+    }
+
+}

+ 89 - 0
education-api/src/main/java/com/education/api/controller/admin/education/ExamInfoController.java

@@ -0,0 +1,89 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.ExamInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.StudentExamInfoDto;
+import com.education.model.entity.TestPaperInfo;
+import com.education.model.request.PageParam;
+import com.education.model.request.StudentQuestionRequest;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 考试管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/23 19:55
+ */
+@RestController("/system")
+@RequestMapping("/system/exam")
+public class ExamInfoController extends BaseController {
+
+    @Resource
+    private ExamInfoService examInfoService;
+
+    @GetMapping
+    //@RequiresPermissions("system:exam:list")
+    public Result list(PageParam pageParam, StudentExamInfoDto studentExamInfoDto) {
+        return Result.success(examInfoService.selectExamInfoList(pageParam, studentExamInfoDto));
+    }
+
+    /**
+     * 获取学员试卷试题列表
+     * @param studentId
+     * @param examInfoId
+     * @return
+     */
+    @GetMapping("getExamQuestionList/{studentId}/{examInfoId}")
+    public Result getExamQuestionList(@PathVariable Integer studentId, @PathVariable Integer examInfoId) {
+        return Result.success(examInfoService.selectExamQuestionAnswer(studentId, examInfoId));
+    }
+
+    /**
+     * 批改学员试卷
+     * @param studentQuestionRequest
+     * @return
+     */
+    @PostMapping("correctExamQuestion")
+    //@RequiresPermissions("system:exam:correct")
+   // 暂时注释 @CacheEvict(cacheNames = CacheKey.EXAM_CACHE, key = "#studentQuestionRequest.examInfoId")
+    public Result correctExamQuestion(@RequestBody StudentQuestionRequest studentQuestionRequest) {
+        examInfoService.correctStudentExam(studentQuestionRequest);
+        return Result.success(ResultCode.SUCCESS, "批改成功");
+    }
+
+    /**
+     * 考试统计
+     * @param testPaperInfo
+     * @return
+     */
+    @GetMapping("getExamReportList")
+    //@RequiresPermissions("system:exam:examReportList")
+    public Result selectExamReportList(PageParam pageParam, TestPaperInfo testPaperInfo) {
+        return Result.success(examInfoService.selectExamReportList(pageParam, testPaperInfo));
+    }
+
+    /**
+     * 考试成绩分析
+     * @param testPaperInfoId
+     * @return
+     */
+    @GetMapping("getExamDetailReport/{testPaperInfoId}")
+    public Result getExamDetailReport(@PathVariable Integer testPaperInfoId) {
+        return Result.success(examInfoService.examDetailReport(testPaperInfoId));
+    }
+
+    /**
+     * 获取考试排名列表
+     * @param testPaperInfoId
+     * @return
+     */
+    @GetMapping("getExamRankingList/{testPaperInfoId}")
+    public Result getExamRankingList(PageParam pageParam, @PathVariable Integer testPaperInfoId) {
+        return Result.success(examInfoService.getExamRankingList(pageParam, testPaperInfoId));
+    }
+}

+ 40 - 0
education-api/src/main/java/com/education/api/controller/admin/education/ExamMonitorController.java

@@ -0,0 +1,40 @@
+package com.education.api.controller.admin.education;
+
+import com.education.business.service.education.ExamMonitorService;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.Result;
+import com.education.model.dto.ExamMonitor;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 考试监控接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2021/1/29 15:17
+ */
+@RestController
+@RequestMapping("/system/examMonitor")
+public class ExamMonitorController extends BaseController {
+
+    @Resource
+    private ExamMonitorService examMonitorService;
+
+    /**
+     * 获取试卷正在考试学员
+     * @param testPaperInfoId
+     * @return
+     */
+    @GetMapping("/selectByTestPaperInfoId/{testPaperInfoId}")
+    public Result<PageInfo<ExamMonitor>> selectByTestPaperInfoId(PageParam pageParam, @PathVariable Integer testPaperInfoId) {
+        List<ExamMonitor> studentInfoList = examMonitorService.getExamMonitorByTestPaperInfoId(testPaperInfoId);
+        return Result.success(ObjectUtils.selectPageList(pageParam.getPageNumber(), pageParam.getPageSize(), studentInfoList));
+    }
+}

+ 80 - 0
education-api/src/main/java/com/education/api/controller/admin/education/ExtKnowledgePointController.java

@@ -0,0 +1,80 @@
+package com.education.api.controller.admin.education;
+
+import com.alibaba.fastjson.JSON;
+import com.education.api.config.util.KnowledgePointConverter;
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.ExtKnowledgePointService;
+import com.education.common.annotation.SystemLog;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.ExtKnowledgePointDto;
+import com.education.model.entity.ExtKnowledgePoint;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 知识点管理
+ */
+@RequestMapping("/system/extKnowledgePoint")
+@RestController
+public class ExtKnowledgePointController extends BaseController {
+
+    @Resource
+    private ExtKnowledgePointService extKnowledgePointService;
+
+    /**
+     * 知识点分页列表
+     * @param pageParam
+     * @param extKnowledgePoint
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:extKnowledgePoint:list")
+    public Result selectPage(PageParam pageParam, ExtKnowledgePoint extKnowledgePoint) {
+        return Result.success(extKnowledgePointService.selectPageList(pageParam, extKnowledgePoint));
+    }
+
+    /**
+     * 添加或修改
+     * @param extKnowledgePointDto
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:extKnowledgePoint:save","system:extKnowledgePoint:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody ExtKnowledgePointDto extKnowledgePointDto) {
+        extKnowledgePointService.saveOrUpdate(extKnowledgePointDto);
+        return Result.success();
+    }
+
+
+    /**
+     * 根据id查看知识图谱信息
+     * @param id
+     * @return
+     */
+    @GetMapping("selectById")
+    @SystemLog(describe = "根据id查看知识图谱信息")
+    public Result selectById(Integer id) {
+
+        List<ExtKnowledgePoint> list =  extKnowledgePointService.selectById(id);
+        if (list == null && list.isEmpty()) {
+            return Result.fail();
+        }
+        return Result.success( JSON.parseObject(KnowledgePointConverter.convert(list)));
+    }
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:extKnowledgePoint:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        extKnowledgePointService.removeById(id);
+        return Result.success();
+    }
+}

+ 73 - 0
education-api/src/main/java/com/education/api/controller/admin/education/GoalInfoController.java

@@ -0,0 +1,73 @@
+package com.education.api.controller.admin.education;
+
+import com.education.business.service.education.GoalInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.GoalInfoDto;
+import com.education.model.entity.ExtKnowledgePoint;
+import com.education.model.entity.GoalInfo;
+import com.education.model.request.PageParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 导向目标管理
+ */
+@RequestMapping("/system/goalInfo")
+@RestController
+public class GoalInfoController extends BaseController {
+
+    @Autowired
+    private GoalInfoService goalInfoService;
+
+    /**
+     * 添加导向目标
+     * @param goalInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("system:goalInfo:save")
+    public Result add(@RequestBody GoalInfoDto goalInfo) {
+        Integer id = goalInfoService.add(goalInfo);
+        return Result.success(id);
+    }
+
+    /**
+     * 更新导向目标
+     * @param goalInfo
+     * @return
+     */
+    @PutMapping
+    //@RequiresPermissions("system:goalInfo:update")
+    public Result update(@RequestBody @Validated(GoalInfo.Update.class) GoalInfo goalInfo) {
+        goalInfoService.saveOrUpdate(goalInfo);
+        return Result.success();
+    }
+
+    /**
+     * 删除导向目标
+     * @param id
+     * @return
+     */
+    @DeleteMapping("/{id}")
+    //@RequiresPermissions("system:goalInfo:delete")
+    public Result delete(@PathVariable Integer id) {
+        //todo check goal info's relation and status
+        goalInfoService.removeById(id);
+        return Result.success(ResultCode.SUCCESS, "删除成功");
+    }
+
+    /**
+     * 查询导向目标列表
+     * @param pageParam
+     * @param goalInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:extKnowledgePoint:list")
+    public Result selectPage(PageParam pageParam, GoalInfo goalInfo) {
+        return Result.success(goalInfoService.selectPageList(pageParam, goalInfo));
+    }
+}

+ 69 - 0
education-api/src/main/java/com/education/api/controller/admin/education/GradeInfoController.java

@@ -0,0 +1,69 @@
+package com.education.api.controller.admin.education;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.GradeInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.Result;
+import com.education.model.entity.GradeInfo;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+/**
+ * 年级管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/19 12:42
+ */
+@RestController
+@RequestMapping("/system/gradeInfo")
+public class GradeInfoController extends BaseController {
+
+    @Resource
+    private GradeInfoService gradeInfoService;
+
+    /**
+     * 年级列表
+     * @param pageParam
+     * @param gradeInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:grade:list")
+    public Result<PageInfo<GradeInfo>> list(PageParam pageParam, GradeInfo gradeInfo) {
+        LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(GradeInfo.class)
+                .like(ObjectUtils.isNotEmpty(gradeInfo.getName()), GradeInfo::getName, gradeInfo.getName())
+                .eq(ObjectUtils.isNotEmpty(gradeInfo.getSchoolType()),
+                        GradeInfo::getSchoolType, gradeInfo.getSchoolType());
+        return Result.success(gradeInfoService.selectPage(pageParam, queryWrapper));
+    }
+
+    /**
+     * 保存或添加年级
+     * @param gradeInfo
+     * @return
+     */
+    @PostMapping("saveOrUpdate")
+    //@RequiresPermissions(value = {"system:grade:save", "system:grade:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody GradeInfo gradeInfo) {
+        gradeInfoService.saveOrUpdate(gradeInfo);
+        return Result.success();
+    }
+
+    /**
+     * 删除年级
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:grade:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        gradeInfoService.removeById(id);
+        return Result.success();
+    }
+}

+ 79 - 0
education-api/src/main/java/com/education/api/controller/admin/education/HomeworkGoalInfoController.java

@@ -0,0 +1,79 @@
+package com.education.api.controller.admin.education;
+
+import com.education.business.service.education.HomeworkGoalInfoService;
+import com.education.business.service.education.HomeworkInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.HomeworkGoalInfoDto;
+import com.education.model.entity.HomeworkGoalInfo;
+import com.education.model.entity.HomeworkInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 作业与目标导向配置管理
+ */
+@RequestMapping("/system/homeworkGoalInfo")
+@RestController
+public class HomeworkGoalInfoController extends BaseController {
+
+    @Autowired
+    private HomeworkInfoService homeworkInfoService;
+
+    @Autowired
+    private HomeworkGoalInfoService homeworkGoalInfoService;
+
+    /**
+     * 添加作业与导向目标布置
+     * @param homeworkGoalInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("system:homeworkGoalInfo:save")
+    public Result add(@RequestBody HomeworkGoalInfo homeworkGoalInfo) {
+        homeworkGoalInfoService.saveOrUpdate(homeworkGoalInfo);
+        //todo homeworkInfoService update question number
+        return Result.success();
+    }
+
+    /**
+     * 删除作业与导向目标布置
+     * @param homeworkInfoId 作业布置id
+     * @param goalInfoId 导向目标id
+     * @return
+     */
+    @DeleteMapping("/{homeworkInfoId}/{goalInfoId}")
+    //@RequiresPermissions("system:homeworkGoalInfo:delete")
+    public Result delete(@PathVariable Integer homeworkInfoId, @PathVariable Integer goalInfoId) {
+        //todo check homework info's relation and status,delete relative goal infos,update homework info's question number
+        homeworkGoalInfoService.removeHomeworkGoalInfo(homeworkInfoId, goalInfoId);
+        return Result.success(ResultCode.SUCCESS, "删除成功");
+    }
+
+//    /**
+//     * 添加或修改
+//     * @param homeworkGoalInfoDto
+//     * @return
+//     */
+//    @PostMapping
+//    //@RequiresPermissions(value = {"system:homeworkGoalInfo:save","system:homeworkGoalInfo:update"}, logical = Logical.OR)
+//    public Result saveOrUpdate(@RequestBody HomeworkGoalInfoDto homeworkGoalInfoDto) {
+//        homeworkGoalInfoService.saveOrUpdate(homeworkGoalInfoDto);
+//        return Result.success();
+//    }
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:homeworkGoalInfo:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        homeworkGoalInfoService.removeById(id);
+        return Result.success();
+    }
+
+}

+ 120 - 0
education-api/src/main/java/com/education/api/controller/admin/education/HomeworkInfoController.java

@@ -0,0 +1,120 @@
+package com.education.api.controller.admin.education;
+
+import com.education.business.service.education.GoalInfoService;
+import com.education.business.service.education.HomeworkInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.GoalInfoDto;
+import com.education.model.dto.HomeworkInfoReqDto;
+import com.education.model.dto.TestPaperInfoDto;
+import com.education.model.entity.GoalInfo;
+import com.education.model.entity.HomeworkInfo;
+import com.education.model.request.PageParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 作业布置管理
+ */
+@RequestMapping("/system/homeworkInfo")
+@RestController
+public class HomeworkInfoController extends BaseController {
+
+    @Autowired
+    private HomeworkInfoService homeworkInfoService;
+
+    /**
+     * 添加作业布置
+     * @param homeworkInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("system:homeworkInfo:save")
+    public Result add(@RequestBody  HomeworkInfo homeworkInfo) {
+        homeworkInfoService.saveOrUpdate(homeworkInfo);
+        return Result.success();
+    }
+
+    /**
+     * 更新作业布置
+     * @param homeworkInfo
+     * @return
+     */
+    @PutMapping
+    //@RequiresPermissions("system:homeworkInfo:update")
+    public Result update(@RequestBody  HomeworkInfo homeworkInfo) {
+        HomeworkInfo hi = homeworkInfoService.getById(homeworkInfo.getId());
+        if (hi.getPublishFlag() != 0) {  //0为未发布
+            return Result.fail(ResultCode.FAIL,"作业已发布不能修改");
+        }
+        homeworkInfoService.saveOrUpdate(homeworkInfo);
+        return Result.success();
+    }
+
+    /**
+     * 删除作业(含删除导向目标配置)
+     * @param id
+     * @return
+     */
+    @DeleteMapping("/{id}")
+    //@RequiresPermissions("system:homeworkInfo:delete")
+    public Result delete(@PathVariable Integer id) {
+        HomeworkInfo hi = homeworkInfoService.getById(id);
+        if (hi.getPublishFlag() != 0) {  //0为未发布
+            return Result.fail(ResultCode.FAIL,"作业已发布不能修改");
+        }        homeworkInfoService.removeById(id);
+        return Result.success(ResultCode.SUCCESS, "删除成功");
+    }
+
+    /**
+     * 获取作业列表
+     * @param pageParam 分布参数
+     * @param req 请求参数
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:homeworkInfo:list")
+    public Result selectPage(PageParam pageParam,  HomeworkInfoReqDto req) {
+        HomeworkInfo homeworkInfo = new HomeworkInfo();
+        homeworkInfo.setSubjectId(req.getSubjectId());
+        homeworkInfo.setGradeInfoId(req.getGradeInfoId());
+        return Result.success(homeworkInfoService.selectPageList(pageParam, homeworkInfo));
+    }
+
+    /**
+     * 获取作业详情
+     * @param id 作业布置id
+     * @return
+     */
+    @GetMapping("/{id}")
+    public Result get(@PathVariable Integer id) {
+        return Result.success(homeworkInfoService.getById(id));
+    }
+
+    /**
+     * 获取作业关联的导向目标列表
+     * @param id 作业id
+     * @return
+     */
+    @GetMapping("/{id}/goals")
+    public Result<List<GoalInfoDto>> getGoals(@PathVariable Integer id) {
+        List<GoalInfoDto> goals = homeworkInfoService.getGoals(id);
+        return Result.success(goals);
+    }
+
+    /**
+     * 布置作业
+     * @param id 作业id
+     * @return
+     */
+    @PostMapping("/{id}/assign")
+    public Result assign(@PathVariable Integer id) {
+        homeworkInfoService.assign(id);
+        return Result.success();
+    }
+
+}

+ 73 - 0
education-api/src/main/java/com/education/api/controller/admin/education/LanguagePointsInfoController.java

@@ -0,0 +1,73 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.LanguagePointsInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.LanguagePointsInfoDto;
+import com.education.model.entity.LanguagePointsInfo;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 知识点管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/19 14:14
+ */
+@RestController
+@RequestMapping("/system/languagePointsInfo")
+public class LanguagePointsInfoController extends BaseController {
+
+    @Resource
+    private LanguagePointsInfoService languagePointsInfoService;
+
+    /**
+     * 获取一级知识点列表
+     * @param languagePointsInfo
+     * @return
+     */
+    @GetMapping("selectList")
+    //@RequiresPermissions("system:languagePointsInfo:list")
+    public Result<LanguagePointsInfo> selectFirstPoints(LanguagePointsInfo languagePointsInfo) {
+        return Result.success(languagePointsInfoService.selectList(languagePointsInfo));
+    }
+
+    /**
+     * 根据parentId 查找子节点
+     * @param parentId
+     * @return
+     */
+    @GetMapping("selectByParentId")
+    public Result<LanguagePointsInfoDto> selectByParentId(Integer parentId) {
+        LanguagePointsInfo languagePointsInfo = new LanguagePointsInfo();
+        languagePointsInfo.setParentId(parentId);
+        return Result.success(languagePointsInfoService.selectList(languagePointsInfo));
+    }
+
+    /**
+     * 添加或修改知识点
+     * @param languagePointsInfo
+     * @return
+     */
+    @PostMapping("saveOrUpdate")
+    //@RequiresPermissions(value = {"system:languagePointsInfo:save", "system:languagePointsInfo:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody LanguagePointsInfo languagePointsInfo) {
+        languagePointsInfoService.saveOrUpdate(languagePointsInfo);
+        return Result.success();
+    }
+
+    /**
+     * 删除知识点
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:languagePointsInfo:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        return Result.success(languagePointsInfoService.deleteById(id));
+    }
+
+}

+ 446 - 0
education-api/src/main/java/com/education/api/controller/admin/education/QuestionInfoController.java

@@ -0,0 +1,446 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.parser.ExcelQuestionImportResult;
+import com.education.business.parser.QuestionImportResult;
+import com.education.business.parser.TxtQuestionImportResult;
+import com.education.business.service.education.QuestionInfoService;
+import com.education.business.service.education.ai.question.QuestionWorkFlowRunner;
+import com.education.common.annotation.Param;
+import com.education.common.annotation.ParamsType;
+import com.education.common.annotation.ParamsValidate;
+import com.education.common.base.BaseController;
+import com.education.common.config.OssProperties;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.QuestionInfoDto;
+import com.education.model.entity.QuestionInfo;
+import com.education.model.request.PageParam;
+import com.education.model.request.QuestionInfoQuery;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 试题管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/19 10:45
+ */
+@RestController
+@RequestMapping("/system/question")
+public class QuestionInfoController extends BaseController {
+
+    @Resource
+    private QuestionInfoService questionInfoService;
+    private final Logger logger = LoggerFactory.getLogger(QuestionInfoController.class);
+
+    @Resource
+    private OssProperties ossProperties;
+
+    @Resource
+    QuestionWorkFlowRunner questionWorkFlowRunner;
+
+//    public static void main(String[] args) {
+//        String filepath = "D:\\home\\words\\2025\\03\\13\\145804-ae8aec8e6f9747f38122ca25e347e956.pdf";
+//        String question = "根据文件出1道选择题, 请把题干放到title属性,选项插入到options数组属性内,答案放到anwser属性。例如:{title:'题干',options:[{'label':'A', text:'1'}],answer:'B'}这样的格式,输出JSON文本";//requestData.getQuestion();
+//        Map<String, Object> result = null;
+//
+//        // 处理逻辑,例如判断是否为空
+//        if (filepath == null || filepath.isEmpty()) {
+//            filepath = "默认文件路径";
+//        }
+//        if (question == null || question.isEmpty()) {
+//            question = "默认问题";
+//        }
+//
+//        try {
+//            // 1. 指定 Python 脚本路径
+//            String pythonScript = "D:\\home\\test.py";//ossProperties.getBucketName()+"test.py";
+//
+//            // 2. 构造 JSON 数据
+//            Map<String, String> data = new HashMap<>();
+//            data.put("filepath", filepath);
+//            data.put("question", question);
+//
+//            // 3. 使用 Gson 生成 JSON 字符串
+//            Gson gson = new Gson();
+//            String jsonInput = gson.toJson(data);
+//
+//            // 4. 启动 Python 进程
+//            ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScript);
+//            processBuilder.environment().put("PYTHONIOENCODING", "UTF-8");
+//            processBuilder.redirectErrorStream(true);
+//            Process process = processBuilder.start();
+//
+//            // 5. 传递 JSON 参数
+//            OutputStream os = process.getOutputStream();
+//            os.write(jsonInput.getBytes(StandardCharsets.UTF_8));
+//            os.flush();
+//            os.close();
+//
+//            // 6. 读取 Python 输出
+//            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
+//            StringBuilder output = new StringBuilder();
+//            String line;
+//            while ((line = reader.readLine()) != null) {
+//                output.append(line).append("\n");
+//            }
+////            System.out.println("Python 返回1: " + output.toString().trim());
+//            // 7. 解析 Python 返回的 JSON 数据
+//            String jsonOutput = output.toString();
+//            System.out.println("Python 返回1: " + jsonOutput);
+//            String[] split = jsonOutput.split("\n");
+//            String s = split[split.length - 1];
+//            // 8. 让 Gson 解析 JSON,并正确显示中文
+//            result = gson.fromJson(s, Map.class);
+//            System.out.println("解析后的结果: " + result);
+//
+//            // 8. 等待 Python 进程结束
+//            int exitCode = process.waitFor();
+//            System.out.println("Python 进程退出码: " + exitCode);
+//
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+    @PostMapping("/process")
+    public Response processFile(@RequestBody RequestData requestData) {
+
+        // 获取前端传来的数据
+        String filepath = requestData.getFilepath();  //"D:\\home\\words\\2025\\03\\13\\145804-ae8aec8e6f9747f38122ca25e347e956.pdf";
+        String question = requestData.getQuestion(); //"根据文件出1道选择题, 请把题干放到title属性,选项插入到options数组属性内,答案放到anwser属性。例如:{title:'题干',options:[{'label':'A', text:'1'}],answer:'B'}这样的格式,输出JSON文本";//requestData.getQuestion();
+        Map<String, Object> result = null;
+
+        // 处理逻辑,例如判断是否为空
+        if (filepath == null || filepath.isEmpty()) {
+            filepath = "";
+        }
+        if (question == null || question.isEmpty()) {
+            question = "";
+        }
+
+
+        //设置出题提示词
+        questionWorkFlowRunner.setPrompt(question);
+
+        //设置上下文
+        questionWorkFlowRunner.getCollector();
+        questionWorkFlowRunner.run();
+
+        filepath = ossProperties.getBucketName() + filepath;
+
+        try {
+            // 1. 指定 Python 脚本路径
+            String pythonScript = ossProperties.getBucketName()+"question.py";//"D:\\home\\test.py";
+
+            // 2. 构造 JSON 数据
+            Map<String, String> data = new HashMap<>();
+            data.put("filepath", filepath);
+            data.put("question", question);
+
+            // 3. 使用 Gson 生成 JSON 字符串
+            Gson gson = new Gson();
+            String jsonInput = gson.toJson(data);
+
+            // 4. 启动 Python 进程
+            ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScript);
+            processBuilder.environment().put("PYTHONIOENCODING", "UTF-8");
+            processBuilder.redirectErrorStream(true);
+            Process process = processBuilder.start();
+
+            // 5. 传递 JSON 参数
+            OutputStream os = process.getOutputStream();
+            os.write(jsonInput.getBytes(StandardCharsets.UTF_8));
+            os.flush();
+            os.close();
+
+            // 6. 读取 Python 输出
+            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
+            StringBuilder output = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                output.append(line).append("\n");
+            }
+//            System.out.println("Python 返回1: " + output.toString().trim());
+            // 7. 解析 Python 返回的 JSON 数据
+            String jsonOutput = output.toString();
+            System.out.println("Python 返回1: " + jsonOutput);
+            String[] split = jsonOutput.split("\n");
+            String s = split[split.length - 1];
+            // 8. 让 Gson 解析 JSON,并正确显示中文
+            result = gson.fromJson(s, Map.class);
+            System.out.println("解析后的结果: " + result);
+
+            // 8. 等待 Python 进程结束
+            int exitCode = process.waitFor();
+            System.out.println("Python 进程退出码: " + exitCode);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        // 构造返回信息
+        return new Response("接收到的数据", result);
+    }
+
+    // 定义请求数据的 JavaBean
+   static class RequestData {
+        private String filepath;
+        private String question;
+
+        public String getFilepath() {
+            return filepath;
+        }
+
+        public void setFilepath(String filepath) {
+            this.filepath = filepath;
+        }
+
+        public String getQuestion() {
+            return question;
+        }
+
+        public void setQuestion(String question) {
+            this.question = question;
+        }
+    }
+
+    // 定义返回数据的 JavaBean
+  static  class Response {
+        private String message;
+        private Map<String, Object> content;
+
+
+        public Response(String message, Map<String, Object> content) {
+            this.message = message;
+            this.content = content;
+
+        }
+        public String getMessage() {
+            return message;
+        }
+
+        public Map<String, Object> getContent() {
+            return content;
+        }
+
+    }
+
+    /**
+     * 试题列表
+     * @param pageParam
+     * @param questionInfoQuery
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:question:list")
+    public Result list(PageParam pageParam, QuestionInfoQuery questionInfoQuery) {
+        return Result.success(questionInfoService.selectPageList(pageParam, questionInfoQuery));
+    }
+
+    /**
+     * 添加或修改试题
+     * @param questionInfoDto
+     * @return
+     */
+    @PostMapping("saveOrUpdate")
+    //@RequiresPermissions(value = {"system:question:save", "system:question:update"}, logical = Logical.OR)
+    @ParamsValidate(params = {
+        @Param(name = "schoolType", message = "请选择所属阶段"),
+        @Param(name = "gradeInfoId", message = "请选择所属年级"),
+        @Param(name = "subjectId", message = "请选择所属科目"),
+        @Param(name = "questionType", message = "请选择试题类型"),
+        @Param(name = "content", message = "请输入试题内容"),
+        @Param(name = "answer", message = "请输入试题答案")
+    }, paramsType = ParamsType.JSON_DATA)
+    public Result saveOrUpdate(@RequestBody QuestionInfoDto questionInfoDto) {
+        return Result.success(questionInfoService.saveOrUpdateQuestionInfo(questionInfoDto));
+    }
+
+    @PostMapping("saveQuestionInfoDtos")
+    public Result saveQuestionInfoDtos(@RequestBody JsonNode jsonArray) throws JsonProcessingException {
+        List<QuestionInfoDto> questionInfoDtos = new ArrayList<>();
+        if (jsonArray.isArray()) {
+            QuestionInfoDto questionInfoDto = null;
+            for (JsonNode jsonObject : jsonArray) {
+                questionInfoDto = new QuestionInfoDto();
+                // 处理每个 JSON 对象
+                String title = jsonObject.get("title").asText();
+                questionInfoDto.setContent(title);
+                JsonNode optionsNode = jsonObject.get("options");
+                if (optionsNode.isArray()) {
+                   /* for (JsonNode option : optionsNode) {
+                        String label = option.get("label").asText();
+                        String text = option.get("text").asText();
+                        System.out.println("选项标签: " + label + ", 选项文本: " + text);
+                    }*/
+                    ObjectMapper objectMapper = new ObjectMapper();
+                    questionInfoDto.setOptions(objectMapper.writeValueAsString(optionsNode).replace("text","option_name"));
+
+                }
+                String answer = jsonObject.get("answer").asText();
+                int subjectId = jsonObject.get("subjectId").asInt();
+                int gradeId = jsonObject.get("gradeId").asInt();
+                int schoolType = jsonObject.get("schoolType").asInt();
+                JsonNode questionTypeJson = jsonObject.get("questionType");
+                if(questionTypeJson == null || questionTypeJson.isEmpty()) {
+                    questionInfoDto.setQuestionType(1);
+                }else {
+                    questionInfoDto.setQuestionType(questionTypeJson.asInt());
+
+                }
+
+                questionInfoDto.setAnswer(answer);
+                questionInfoDto.setSubjectId(subjectId);
+                questionInfoDto.setGradeInfoId(gradeId);
+                questionInfoDto.setSchoolType(schoolType);
+                questionInfoDtos.add(questionInfoDto);
+            }
+        }else {
+            return Result.success(new ResultCode(ResultCode.FAIL, "数据格式错误"));
+        }
+        List<String> emptyFields = validateQuestionInfoDtos(questionInfoDtos);
+        if (emptyFields.isEmpty()) {
+            // 调用服务层方法处理 QuestionInfoDto 列表
+            return Result.success(questionInfoService.saveQuestionInfoList(questionInfoDtos));
+        } else {
+            return Result.success(new ResultCode(ResultCode.FAIL, emptyFields.get(0)));
+        }
+
+    }
+
+    public  List<String> validateQuestionInfoDtos(List<QuestionInfoDto> questionInfoDtos) {
+        List<String> emptyFields = new ArrayList<>();
+        for (int i = 0; i < questionInfoDtos.size(); i++) {
+            QuestionInfoDto dto = questionInfoDtos.get(i);
+            if (dto.getSchoolType() == null) {
+                emptyFields.add("第 " + (i + 1) + " 个对象的 schoolType 字段为空");
+            }
+            if (dto.getGradeInfoId() == null) {
+                emptyFields.add("第 " + (i + 1) + " 个对象的 gradeInfoId 字段为空");
+            }
+            if (dto.getSubjectId() == null) {
+                emptyFields.add("第 " + (i + 1) + " 个对象的 subjectId 字段为空");
+            }
+//            if (dto.getQuestionType() == null ) {
+//                emptyFields.add("第 " + (i + 1) + " 个对象的 questionType 字段为空");
+//            }
+            if (dto.getContent() == null || dto.getContent().trim().isEmpty()) {
+                emptyFields.add("第 " + (i + 1) + " 个对象的 content 字段为空");
+            }
+            if (dto.getAnswer() == null || dto.getAnswer().trim().isEmpty()) {
+                emptyFields.add("第 " + (i + 1) + " 个对象的 answer 字段为空");
+            }
+        }
+        return emptyFields;
+    }
+
+    /**
+     * 试题详情
+     * @param id
+     * @return
+     */
+    @GetMapping("selectById")
+    public Result selectById(Integer id) {
+        return Result.success(questionInfoService.selectById(id));
+    }
+
+    /**
+     * 根据id 删除试题
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:question:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        return Result.success(questionInfoService.deleteById(id));
+    }
+
+    /**
+     * 导入试题
+     * @param gradeInfoId
+     * @param subjectId
+     * @param file
+     * @return
+     */
+    @PostMapping("importQuestion")
+    @ParamsValidate(params = {
+        @Param(name = "schoolType", message = "请选择导入所属阶段"),
+        @Param(name = "gradeInfoId", message = "请选择导入所属年级"),
+        @Param(name = "subjectId", message = "请选择导入所属科目")
+    })
+    public Result importQuestion(
+                                 HttpServletResponse response,
+                                 @RequestParam Integer schoolType,
+                                 @RequestParam Integer gradeInfoId,
+                                 @RequestParam Integer subjectId,
+                                 @RequestParam MultipartFile file) {
+        String contentType = file.getContentType();
+        if (!excelTypes.contains(contentType) && !textTypes.contains(contentType)) {
+            return Result.fail(ResultCode.FAIL, "只能导入excel或者txt类型文件");
+        }
+        try {
+            QuestionImportResult questionImportResult = null;
+            if (excelTypes.contains(contentType)) {
+                questionImportResult = new ExcelQuestionImportResult(file, response);
+            } else {
+                questionImportResult = new TxtQuestionImportResult(file);
+            }
+
+            questionImportResult.readTemplate();
+
+            if (!questionImportResult.isHasData()) {
+                return Result.success(ResultCode.FAIL, questionImportResult.getErrorMsg());
+            }
+
+            List<QuestionInfo> questionInfoList = questionImportResult.getSuccessImportQuestionList();
+            int successCount = questionInfoService.importQuestion(schoolType, gradeInfoId,
+                    subjectId, questionInfoList);
+
+            int failCount = 0;
+            List<QuestionInfo> failQuestionList = questionImportResult.getFailImportQuestionList();
+
+            if (failQuestionList != null) {
+                failCount = failQuestionList.size();
+            }
+
+            // excel 数据校验失败
+            String msg = successCount + "道试题导入成功";
+            if (ObjectUtils.isNotEmpty(questionImportResult.getErrorMsg())) {
+                if (failCount > 0) {
+                    msg += "," + failCount + "道试题导入失败(分别为)" + questionImportResult.getErrorMsg();
+                }
+                return Result.success(ResultCode.EXCEL_VERIFICATION_FAIL,
+                       msg, questionImportResult.getErrorFileUrl());
+            }
+            return Result.success(ResultCode.SUCCESS, msg);
+        } catch (Exception e) {
+            logger.error("数据导入失败", e);
+        }
+        return Result.fail(ResultCode.FAIL, "数据导入失败");
+    }
+}

+ 71 - 0
education-api/src/main/java/com/education/api/controller/admin/education/StepModelController.java

@@ -0,0 +1,71 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.StepModelService;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.Result;
+import com.education.model.dto.StepModelDto;
+import com.education.model.entity.StepModel;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import java.util.Date;
+
+/**
+ * 模版管理
+ */
+@RequestMapping("/system/stepModel")
+@RestController
+public class StepModelController extends BaseController {
+
+    @Resource
+    private StepModelService stepModelService;
+
+    /**
+     * 模版分页列表
+     * @param pageParam
+     * @param  stepModel
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:stepModel:list")
+    public Result selectPage(PageParam pageParam,  StepModel stepModel) {
+        PageInfo<StepModel> list = stepModelService.selectPageList(pageParam,  stepModel);
+        return Result.success( list);
+    }
+
+    /**
+     * 添加或修改
+     * @param  stepModelDto
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:stepModel:save","system:stepModel:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody StepModelDto stepModelDto) {
+        StepModel model = new StepModel();
+        model.setId(stepModelDto.getId());
+        model.setCreateDate(new Date());
+        model.setUpdateDate(new Date());
+        model.setName(stepModelDto.getName());
+        model.setPrompt(stepModelDto.getPrompt());
+        model.setAgentId(stepModelDto.getAgentId());
+        model.setReserve(stepModelDto.getReserve());
+        stepModelService.saveOrUpdate( model);
+        return Result.success();
+    }
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:stepModel:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+         stepModelService.removeById(id);
+        return Result.success();
+    }
+
+}

+ 46 - 0
education-api/src/main/java/com/education/api/controller/admin/education/StuGoalInfoController.java

@@ -0,0 +1,46 @@
+package com.education.api.controller.admin.education;
+
+import com.education.business.service.education.StuGoalInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.entity.StuGoalInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 学生导向目标批改
+ */
+@RequestMapping("/system/stuGoalInfo")
+@RestController
+public class StuGoalInfoController extends BaseController {
+
+    @Autowired
+    private StuGoalInfoService stuGoalInfoService;
+
+    /**
+     * 答题
+     * @param stuGoalInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("system:stuGoalInfo:update")
+    public Result correct(@RequestBody @Validated StuGoalInfo stuGoalInfo) {
+        Integer id = stuGoalInfo.getId();
+        if (id == null || id == 0 ) {
+            stuGoalInfoService.saveOrUpdate(stuGoalInfo);
+            return Result.success();
+        }
+        StuGoalInfo si = stuGoalInfoService.getById(stuGoalInfo.getGoalInfoId());
+        if (si.getCorrectStatus() == 2 ||  si.getCorrectStatus() == 3 ) { //批改状态,2-待批改 3-已批改
+            return Result.fail(ResultCode.FAIL,"批改状态为待修改或已批改不能修改");
+
+        }
+        stuGoalInfoService.saveOrUpdate(stuGoalInfo);
+        return Result.success();
+    }
+}

+ 59 - 0
education-api/src/main/java/com/education/api/controller/admin/education/StuHomeworkInfoController.java

@@ -0,0 +1,59 @@
+package com.education.api.controller.admin.education;
+
+import com.education.business.service.education.StuHomeworkInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.entity.StuHomeworkInfo;
+import com.education.model.request.PageParam;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 学生作业批改
+ */
+@RequestMapping("/system/stuHomeworkInfo")
+@RestController
+public class StuHomeworkInfoController extends BaseController {
+
+    @Resource
+    private StuHomeworkInfoService stuHomeworkInfoService;
+
+    /**
+     * 提交作业
+     * @param stuHomeworkInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("system:stuHomeworkInfo:update")
+    public Result correct(@RequestBody @Validated StuHomeworkInfo stuHomeworkInfo) {
+        stuHomeworkInfoService.saveOrUpdate(stuHomeworkInfo);
+        return Result.success();
+    }
+
+    /**
+     * 学生作业信息分页列表
+     * @param pageParam
+     * @param stuHomeworkInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:stuHomeworkInfo:list")
+    public Result selectPage(PageParam pageParam, StuHomeworkInfo stuHomeworkInfo) {
+        return Result.success(stuHomeworkInfoService.selectPageList(pageParam, stuHomeworkInfo));
+    }
+
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:stuHomeworkInfo:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        stuHomeworkInfoService.removeById(id);
+        return Result.success();
+    }
+}

+ 132 - 0
education-api/src/main/java/com/education/api/controller/admin/education/StudentInfoController.java

@@ -0,0 +1,132 @@
+package com.education.api.controller.admin.education;
+
+import cn.afterturn.easypoi.excel.entity.ImportParams;
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.StudentInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.config.OssProperties;
+import com.education.common.model.ExcelResult;
+import com.education.common.model.StudentInfoImport;
+import com.education.common.utils.*;
+import com.education.model.dto.StudentInfoDto;
+import com.education.model.entity.StudentInfo;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import javax.annotation.Resource;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * 学员管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/21 18:15
+ */
+@RequestMapping("/system/student")
+@RestController
+public class StudentInfoController extends BaseController {
+
+    @Resource
+    private StudentInfoService studentInfoService;
+    @Resource
+    private OssProperties ossProperties;
+
+    /**
+     * 学员分页列表
+     * @param pageParam
+     * @param studentInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:student:list")
+    public Result selectPage(PageParam pageParam, StudentInfo studentInfo) {
+        return Result.success(studentInfoService.selectPageList(pageParam, studentInfo));
+    }
+
+    /**
+     * 添加或修改学员
+     * @param studentInfoDto
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:student:save", "system:student:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody StudentInfoDto studentInfoDto) {
+        if (ObjectUtils.isEmpty(studentInfoDto.getId()) && !checkPassword(studentInfoDto)) {
+            return Result.fail(ResultCode.FAIL, "密码与确认密码不一致");
+        }
+        studentInfoService.saveOrUpdate(studentInfoDto);
+        return Result.success();
+    }
+
+    private boolean checkPassword(StudentInfoDto studentInfoDto) {
+        String password = studentInfoDto.getPassword();
+        String confirmPassword = studentInfoDto.getConfirmPassword();
+        return password.equals(confirmPassword);
+    }
+
+    /**
+     * 重置学员密码
+     * @param studentInfoDto
+     * @return
+     */
+    @PostMapping("updatePassword")
+    //@RequiresPermissions("system:student:updatePassword")
+    public Result updatePassword(@RequestBody StudentInfoDto studentInfoDto) {
+        if (!checkPassword(studentInfoDto)) {
+            return Result.fail(ResultCode.FAIL, "密码与确认密码不一致");
+        }
+        studentInfoService.updatePassword(studentInfoDto);
+        return Result.success();
+    }
+
+    /**
+     * 删除学员
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:student:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        studentInfoService.removeById(id);
+        return Result.success();
+    }
+
+    /**
+     * excel 导入学员
+     * @param file
+     * @return
+     * @throws Exception
+     */
+    @RequestMapping("importStudent")
+    //@RequiresPermissions("system:student:import")
+    public Result importStudent(@RequestParam MultipartFile file) throws Exception {
+        if (!excelTypes.contains(file.getContentType())) {
+            return Result.fail(ResultCode.FAIL, "只能导入excel文件");
+        }
+
+        InputStream inputStream = file.getInputStream();
+        ImportParams importParams = new ImportParams();
+        importParams.setNeedVerfiy(true);
+        importParams.setSaveUrl(ossProperties.getBucketName() + "image"); // 设置头像上传路径
+
+        ExcelResult excelResult = ExcelUtils.importExcel(inputStream,
+                StudentInfoImport.class, importParams, "/student/importExcelError/");
+        int successCount = studentInfoService.importStudentFromExcel(excelResult.getExcelImportResult().getList());
+
+        List<StudentInfoImport> studentInfoImportList = excelResult.getExcelImportResult().getFailList();
+
+        int failCount = 0;
+        if (studentInfoImportList != null) {
+            failCount = studentInfoImportList.size();
+        }
+
+        String msg = successCount + "名学员数据导入成功";
+        if (failCount > 0) {
+            msg += failCount + "名学员数据导入失败(分别为)" + excelResult.getErrorMsg();
+            return Result.success(ResultCode.EXCEL_VERIFICATION_FAIL, msg, excelResult.getErrorExcelUrl());
+        }
+        return Result.success(ResultCode.SUCCESS, msg);
+    }
+}

+ 65 - 0
education-api/src/main/java/com/education/api/controller/admin/education/SubjectInfoController.java

@@ -0,0 +1,65 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.SubjectInfoService;
+import com.education.common.annotation.Param;
+import com.education.common.annotation.ParamsType;
+import com.education.common.annotation.ParamsValidate;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.entity.SubjectInfo;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 科目管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/19 13:51
+ */
+@RestController
+@RequestMapping("/system/subject")
+public class SubjectInfoController extends BaseController {
+
+    @Resource
+    private SubjectInfoService subjectInfoService;
+
+    /**
+     * 科目列表
+     * @param pageParam
+     * @param subjectInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:subject:list")
+    public Result list(PageParam pageParam, SubjectInfo subjectInfo) {
+        return Result.success(subjectInfoService.selectPageList(pageParam, subjectInfo));
+    }
+
+    /**
+     * 添加或修改科目
+     * @param subjectInfo
+     * @return
+     */
+    @PostMapping
+    @ParamsValidate(params = {
+        @Param(name = "name", message = "请输入科目名称"),
+        @Param(name = "schoolType", message = "请选择科目阶段")
+    }, paramsType = ParamsType.JSON_DATA)
+    //@RequiresPermissions(value = {"system:subject:save", "system:subject:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody SubjectInfo subjectInfo) {
+        subjectInfoService.saveOrUpdate(subjectInfo);
+        return Result.success();
+    }
+
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:subject:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        subjectInfoService.deleteById(id);
+        return Result.success(ResultCode.SUCCESS, "删除成功");
+    }
+}

+ 169 - 0
education-api/src/main/java/com/education/api/controller/admin/education/TestPaperInfoController.java

@@ -0,0 +1,169 @@
+package com.education.api.controller.admin.education;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.TestPaperInfoService;
+import com.education.business.service.education.TestPaperInfoSettingService;
+import com.education.common.base.BaseController;
+import com.education.common.constants.CacheKey;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.TestPaperInfoDto;
+import com.education.model.dto.TestPaperQuestionDto;
+import com.education.model.entity.TestPaperInfo;
+import com.education.model.entity.TestPaperQuestionInfo;
+import com.education.model.request.PageParam;
+import com.education.model.request.TestPaperQuestionRequest;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 试卷管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/20 21:21
+ */
+@RestController
+@RequestMapping("/system/testPaperInfo")
+public class TestPaperInfoController extends BaseController {
+
+    @Resource
+    private TestPaperInfoService testPaperInfoService;
+    @Resource
+    private TestPaperInfoSettingService testPaperInfoSettingService;
+
+    /**
+     * 试卷列表
+     * @param pageParam
+     * @param testPaperInfoDto
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:testPaperInfo:list")
+    public Result list(PageParam pageParam, TestPaperInfoDto testPaperInfoDto) {
+        return Result.success(testPaperInfoService.selectPageList(pageParam, testPaperInfoDto));
+    }
+
+    /**
+     * 添加或修改试卷
+     * @param testPaperInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:testPaperInfo:save", "system:testPaperInfo:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody TestPaperInfo testPaperInfo) {
+        if (testPaperInfo.getId() != null) {
+            TestPaperInfo dataBaseTestPaperInfo = testPaperInfoService.getById(testPaperInfo.getId());
+            if (dataBaseTestPaperInfo.getExamNumber() > 0) {
+                return Result.fail(ResultCode.FAIL, "试卷已被使用, 无法修改");
+            }
+        }
+        testPaperInfoService.saveOrUpdate(testPaperInfo);
+        return Result.success();
+    }
+
+    /**
+     * 获取试卷试题列表
+     * @param testPaperQuestionRequest
+     * @return
+     */
+    @GetMapping("getPaperQuestionList")
+    //@RequiresPermissions("system:testPaperInfo:relevanceQuestion")
+    public Result selectPaperQuestionList(PageParam pageParam, TestPaperQuestionRequest testPaperQuestionRequest) {
+        return Result.success(testPaperInfoService.selectPaperQuestionList(pageParam, testPaperQuestionRequest));
+    }
+
+    /**
+     * 修改试卷试题分数或者排序
+     * @param testPaperQuestionDto
+     * @return
+     */
+    @PostMapping("updatePaperQuestionMarkOrSort")
+    public Result updatePaperQuestionMarkOrSort(@RequestBody TestPaperQuestionDto testPaperQuestionDto) {
+        testPaperInfoService.updatePaperQuestionMarkOrSort(testPaperQuestionDto);
+        return Result.success();
+    }
+
+    /**
+     * 保存试卷试题
+     * @param testPaperQuestionInfoList
+     * @return
+     */
+    @PostMapping("saveTestPaperInfoQuestion")
+  /*  @CacheEvict(
+        cacheNames = CacheKey.TEST_PAPER_INFO_CACHE,
+        key = "#testPaperQuestionInfoList.get(0).testPaperInfoId"
+    )*/
+    public Result saveTestPaperInfoQuestion(@RequestBody List<TestPaperQuestionInfo> testPaperQuestionInfoList) {
+        testPaperInfoService.saveTestPaperInfoQuestion(testPaperQuestionInfoList);
+        return Result.success();
+    }
+
+    /**
+     * 发布试卷
+     * @param testPaperInfoId
+     * @return
+     */
+    @PostMapping("publishTestPaperInfo/{testPaperInfoId}")
+    //@RequiresPermissions("system:testPaperInfo:publish")
+    public Result publishTestPaperInfo(@PathVariable Integer testPaperInfoId) {
+        return Result.success(testPaperInfoService.publishTestPaperInfo(testPaperInfoId));
+    }
+
+    /**
+     * 撤销试卷
+     * @param testPaperInfoId
+     * @return
+     */
+    @PostMapping("cancelTestPaperInfo/{testPaperInfoId}")
+    //@RequiresPermissions("system:testPaperInfo:cancel")
+    public Result cancelTestPaperInfo(@PathVariable Integer testPaperInfoId) {
+        return Result.success(testPaperInfoService.cancelTestPaperInfo(testPaperInfoId));
+    }
+
+
+    /**
+     * 删除试卷
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:testPaperInfo:deleteById")
+    @CacheEvict(cacheNames = CacheKey.TEST_PAPER_INFO_CACHE, key = "#id")
+    public Result deleteById(@PathVariable Integer id) {
+        return Result.success(testPaperInfoService.deleteById(id));
+    }
+
+    /**
+     * 移除试卷试题
+     * @param testPaperQuestionInfo
+     * @return
+     */
+    @DeleteMapping("removePaperQuestion")
+    public Result removePaperQuestion(@RequestBody TestPaperQuestionInfo testPaperQuestionInfo) {
+        return Result.success(testPaperInfoService.removePaperQuestion(testPaperQuestionInfo));
+    }
+
+    /**
+     * 试卷打印
+     * @param testPaperInfoId
+     * @return
+     */
+    @GetMapping("printPaperInfo/{testPaperInfoId}")
+    public Result printPaperInfo(@PathVariable Integer testPaperInfoId) {
+        return Result.success(testPaperInfoService.printPaperInfo(testPaperInfoId));
+    }
+
+    /**
+     * 获取试卷配置信息
+     * @param testPaperInfoId
+     * @return
+     */
+    @GetMapping("getPaperSettingInfo/{testPaperInfoId}")
+    public Result getPaperSettingInfo(@PathVariable Integer testPaperInfoId) {
+        return Result.success(testPaperInfoSettingService.selectByTestPaperInfoId(testPaperInfoId));
+    }
+}

+ 30 - 0
education-api/src/main/java/com/education/api/controller/admin/system/HomeController.java

@@ -0,0 +1,30 @@
+package com.education.api.controller.admin.system;
+
+import com.education.business.service.system.HomeService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 首页数据接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/2/16 16:07
+ */
+@RequestMapping("/system/home")
+@RestController
+@Api(tags = "首页数据接口")
+public class HomeController extends BaseController {
+
+    @Autowired
+    private HomeService homeService;
+
+    @GetMapping("headDataCount")
+    public Result count() {
+        return Result.success(homeService.countData());
+    }
+}

+ 34 - 0
education-api/src/main/java/com/education/api/controller/admin/system/QuartzController.java

@@ -0,0 +1,34 @@
+package com.education.api.controller.admin.system;
+
+import com.education.business.service.system.SystemQuartzJobService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.entity.SystemQuartzJob;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * 定时任务管理
+ */
+@RestController
+@RequestMapping("/system/quartz")
+public class QuartzController extends BaseController {
+
+    @Resource
+    private SystemQuartzJobService systemQuartzJobService;
+
+    /**
+     * 添加定时任务
+     * @param systemQuartzJob
+     * @return
+     */
+    @PostMapping("save")
+    public Result saveQuartz(@RequestBody SystemQuartzJob systemQuartzJob) {
+        systemQuartzJobService.saveQuartzJob(systemQuartzJob);
+        return Result.success();
+    }
+}

+ 124 - 0
education-api/src/main/java/com/education/api/controller/admin/system/SystemAdminController.java

@@ -0,0 +1,124 @@
+package com.education.api.controller.admin.system;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.system.SystemAdminService;
+import com.education.common.annotation.SystemLog;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.AdminRoleDto;
+import com.education.model.entity.SystemAdmin;
+import com.education.model.request.PageParam;
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+
+
+/**
+ * 管理员管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2019/3/21 19:48
+ */
+@RestController
+@Api(tags = "管理员管理")
+@RequestMapping("/system/admin")
+public class SystemAdminController extends BaseController {
+
+    @Resource
+    private SystemAdminService systemAdminService;
+
+    /**
+     * 管理员列表
+     * @param pageParam
+     * @param systemAdmin
+     * @return
+     */
+    @GetMapping
+    @SystemLog(describe = "获取管理员列表")
+    //@RequiresPermissions("system:admin:list")
+    public Result<PageInfo<SystemAdmin>> list(PageParam pageParam, SystemAdmin systemAdmin) {
+        return Result.success(systemAdminService.listPage(pageParam, systemAdmin));
+    }
+
+    /**
+     * 管理员详情
+     * @param id
+     * @return
+     */
+    @GetMapping("selectById")
+    @SystemLog(describe = "查看管理员详情")
+    public Result selectById(Integer id) {
+        return Result.success(systemAdminService.selectById(id));
+    }
+
+    /**
+     * 添加或修改管理员
+     * @param adminRoleDto
+     * @return
+     */
+    @PostMapping
+    @SystemLog(describe = "添加或修改管理员")
+    //@RequiresPermissions(value = {"system:admin:save", "system:admin:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody AdminRoleDto adminRoleDto) {
+        systemAdminService.saveOrUpdate(adminRoleDto);
+        return Result.success();
+    }
+
+    /**
+     * 删除管理员
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    @SystemLog(describe = "删除管理员")
+    //@RequiresPermissions("system:admin:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        systemAdminService.deleteById(id);
+        return Result.success();
+    }
+
+
+    /**
+     * 修改密码
+     * @param adminRoleDto
+     * @return
+     */
+    @PostMapping("updatePassword")
+    @SystemLog(describe = "修改管理员密码")
+    //@RequiresPermissions("system:admin:updatePassword")
+    public Result updatePassword(@RequestBody AdminRoleDto adminRoleDto) {
+        systemAdminService.updatePassword(adminRoleDto);
+        return Result.success(ResultCode.SUCCESS, "修改密码成功");
+    }
+
+    /**
+     * 修改密码
+     * @param adminRoleDto
+     * @return
+     */
+    @PostMapping("resettingPassword")
+    @SystemLog(describe = "管理员重置密码")
+    public Result resettingPassword(@RequestBody AdminRoleDto adminRoleDto) {
+        systemAdminService.resettingPassword(adminRoleDto);
+        return Result.success(ResultCode.SUCCESS, "修改重置成功,退出后请使用新密码进行登录");
+    }
+
+    /**
+     * 获取在线用户
+     * @return
+     */
+    @GetMapping("getOnlineUserList")
+    @SystemLog(describe = "获取在线用户列表")
+    public Result<PageInfo<SystemAdmin>> getOnlineUserList(PageParam pageParam) {
+        return Result.success(systemAdminService.getOnlineUserList(pageParam));
+    }
+}

+ 64 - 0
education-api/src/main/java/com/education/api/controller/admin/system/SystemLogController.java

@@ -0,0 +1,64 @@
+package com.education.api.controller.admin.system;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.system.SystemLogService;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.Result;
+import com.education.model.entity.SystemLog;
+import com.education.model.request.PageParam;
+import com.education.model.request.SystemLogQuery;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+/**
+ * 系统日志管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2019/4/2 19:26
+ */
+@RestController
+@RequestMapping("/system/log")
+public class SystemLogController extends BaseController {
+
+    @Resource
+    private SystemLogService systemLogService;
+
+    /**
+     * 日志列表
+     * @param pageParam
+     * @param systemLogQuery
+     * @return
+     */
+    @GetMapping("list")
+    //@RequiresPermissions("system:log:list")
+    public Result<PageInfo<SystemLog>> list(PageParam pageParam, SystemLogQuery systemLogQuery) {
+        LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(SystemLog.class)
+                .gt(ObjectUtils.isNotEmpty(systemLogQuery.getStartTime()),
+                        SystemLog::getCreateDate, systemLogQuery.getStartTime())
+                .le(ObjectUtils.isNotEmpty(systemLogQuery.getEndTime()),
+        SystemLog::getCreateDate, systemLogQuery.getEndTime())
+                .orderByDesc(SystemLog::getId);
+        return Result.success(systemLogService.selectPage(pageParam, queryWrapper));
+    }
+
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:log:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        systemLogService.removeById(id);
+        return Result.success();
+    }
+
+    /**
+     * 清空所以操作日志
+     * @return
+     */
+    @DeleteMapping
+    public Result delete() {
+        systemLogService.removeAll();
+        return Result.success();
+    }
+}

+ 88 - 0
education-api/src/main/java/com/education/api/controller/admin/system/SystemMenuController.java

@@ -0,0 +1,88 @@
+package com.education.api.controller.admin.system;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.system.SystemMenuService;
+import com.education.common.annotation.SystemLog;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.MenuTree;
+import com.education.model.entity.SystemMenu;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import java.util.List;
+
+
+/**
+ * 菜单管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2019/3/22 21:44
+ */
+@RestController
+@RequestMapping("/system/menu")
+public class SystemMenuController extends BaseController {
+
+    @Autowired
+    private SystemMenuService systemMenuService;
+
+    /**
+     * 菜单列表
+     * @return
+     */
+    @GetMapping("menuTreeList")
+    //@RequiresPermissions("system:menu:list")
+    @SystemLog(describe = "获取菜单列表")
+    public Result<List<MenuTree>> menuTreeList() {
+        return Result.success(systemMenuService.selectMenuTreeList());
+    }
+
+    /**
+     * 菜单详情
+     * @param id
+     * @return
+     */
+    @GetMapping("selectById")
+    public Result<MenuTree> selectById(Integer id) {
+        return Result.success(systemMenuService.selectById(id));
+    }
+
+    /**
+     * 保存或修改菜单
+     * @param systemMenu
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:menu:save", "system:menu:update"}, logical = Logical.OR)
+    public Result saveOrUpdate(@RequestBody SystemMenu systemMenu) {
+        systemMenuService.saveOrUpdate(systemMenu);
+        return Result.success();
+    }
+
+    /**
+     * 根据id 删除菜单
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:menu:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        SystemMenu systemMenu = systemMenuService.getById(id);
+        if (ResultCode.SUCCESS.equals(systemMenu.getCreateType())) {
+            return Result.success(ResultCode.FAIL, "您不能删除系统内置菜单");
+        }
+        systemMenuService.deleteById(id);
+        return Result.success(ResultCode.SUCCESS, "删除成功");
+    }
+
+    /**
+     * 获取角色 选中的 tree 菜单
+     * @param roleId
+     * @return
+     */
+    @GetMapping("selectMenuListByRoleId")
+    public Result<List<Integer>> selectMenuListByRoleId(Integer roleId) {
+        return Result.success(systemMenuService.selectTreeCheckedMenuId(roleId));
+    }
+}

+ 18 - 0
education-api/src/main/java/com/education/api/controller/admin/system/SystemMessageController.java

@@ -0,0 +1,18 @@
+package com.education.api.controller.admin.system;
+
+import com.education.common.base.BaseController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * 系统消息通知接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/3/15 13:59
+ */
+@RestController
+@RequestMapping("/system/message")
+public class SystemMessageController extends BaseController {
+
+}

+ 13 - 0
education-api/src/main/java/com/education/api/controller/admin/system/SystemRegionController.java

@@ -0,0 +1,13 @@
+package com.education.api.controller.admin.system;
+
+import com.education.common.base.BaseController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 地区管理接口
+ */
+@RestController
+@RequestMapping("/system/region")
+public class SystemRegionController extends BaseController {
+}

+ 84 - 0
education-api/src/main/java/com/education/api/controller/admin/system/SystemRoleController.java

@@ -0,0 +1,84 @@
+package com.education.api.controller.admin.system;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.system.SystemRoleService;
+import com.education.common.annotation.Param;
+import com.education.common.annotation.ParamsType;
+import com.education.common.annotation.ParamsValidate;
+import com.education.common.annotation.SystemLog;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.RoleMenuDto;
+import com.education.model.entity.SystemRole;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+
+/**
+ * 角色管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2019/3/22 21:39
+ */
+@RestController
+@RequestMapping("/system/role")
+public class SystemRoleController extends BaseController {
+
+    @Resource
+    private SystemRoleService systemRoleService;
+
+    /**
+     * 管理员列表
+     * @param pageParam
+     * @param systemRole
+     * @return
+     */
+    @GetMapping
+    @SystemLog(describe = "获取管理员列表")
+    //@RequiresPermissions("system:role:list")
+    public Result<PageInfo<SystemRole>> list(PageParam pageParam, SystemRole systemRole) {
+        return Result.success(systemRoleService.listPage(pageParam, systemRole));
+    }
+
+    /**
+     * 修改角色权限
+     * @param roleMenuDto
+     * @return
+     */
+    @PostMapping("saveRolePermission")
+    //@RequiresPermissions("system:role:savePermission")
+    public Result saveRolePermission(@RequestBody RoleMenuDto roleMenuDto) {
+        systemRoleService.saveRolePermission(roleMenuDto);
+        return Result.success(ResultCode.SUCCESS, "权限设置成功");
+    }
+
+    /**
+     * 保存或修改角色
+     * @param systemRole
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions(value = {"system:role:save", "system:role:update"}, logical = Logical.OR)
+    @ParamsValidate(params = {
+       @Param(name = "name", message = "请输入角色名称")
+    }, paramsType = ParamsType.JSON_DATA)
+    public Result saveOrUpdate(@RequestBody SystemRole systemRole) {
+        systemRoleService.saveOrUpdate(systemRole);
+        return Result.success();
+    }
+
+    /**
+     * 删除角色
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:role:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        return Result.success(systemRoleService.deleteById(id));
+    }
+}

+ 33 - 0
education-api/src/main/java/com/education/api/controller/admin/system/WebSiteConfigController.java

@@ -0,0 +1,33 @@
+package com.education.api.controller.admin.system;
+
+import com.education.business.service.system.WebsiteConfigService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.WebsiteConfigDto;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+/**
+ * @author zengjintao
+ * @create_at 2021/11/2 19:24
+ * @since version 1.0.3
+ */
+@RestController
+@RequestMapping("/system/webSite")
+public class WebSiteConfigController extends BaseController {
+
+    @Resource
+    private WebsiteConfigService websiteConfigService;
+
+    @GetMapping
+    public Result getWebSiteConfig() {
+        return Result.success(websiteConfigService.getWebSiteConfig());
+    }
+
+    @PostMapping
+    public Result saveOrUpdate(@RequestBody @Validated WebsiteConfigDto websiteConfigDto) {
+        websiteConfigService.saveOrUpdate(websiteConfigDto);
+        return Result.success();
+    }
+}

+ 56 - 0
education-api/src/main/java/com/education/api/controller/student/CourseInfoController.java

@@ -0,0 +1,56 @@
+package com.education.api.controller.student;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.education.business.service.education.CourseInfoService;
+import com.education.business.service.education.CourseSectionService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.entity.CourseInfo;
+import com.education.model.entity.CourseSection;
+import com.education.model.entity.CourseSectionNode;
+import com.education.model.request.PageParam;
+import com.education.model.vo.CourseSectionVo;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 课程管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/23 18:42
+ */
+@RestController("student-courseInfo")
+@RequestMapping("/student/courseInfo")
+public class CourseInfoController extends BaseController {
+
+    @Resource
+    private CourseInfoService courseInfoService;
+
+    @Resource
+    private CourseSectionService courseSectionService;
+
+    /**
+     * 课程列表
+     * @param pageParam
+     * @param courseInfo
+     * @return
+     */
+    @GetMapping
+    public Result selectPageList(PageParam pageParam, CourseInfo courseInfo) {
+        return Result.success(courseInfoService.selectPageList(pageParam, courseInfo));
+    }
+
+
+    @GetMapping("/{courseId}/section")
+    //@RequiresPermissions("system:section:list")
+    public Result section(@PathVariable Integer courseId) {
+        List<CourseSection> list = courseSectionService.list(new LambdaQueryWrapper<CourseSection>().eq(CourseSection::getCourseId, courseId));
+        return Result.success(list);
+    }
+}

+ 36 - 0
education-api/src/main/java/com/education/api/controller/student/CourseValuateController.java

@@ -0,0 +1,36 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.education.CourseValuateService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.entity.CourseValuate;
+import com.education.model.request.PageParam;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 课程评价接口
+ * @author zengjintao
+ * @create_at 2021/10/17 9:27
+ * @since version 1.0.3
+ */
+@RestController
+@RequestMapping("/student/courseValuate")
+public class CourseValuateController extends BaseController {
+
+    @Resource
+    private CourseValuateService courseValuateService;
+
+    @GetMapping
+    public Result listPage(PageParam pageParam, CourseValuate courseValuate) {
+        return Result.success(courseValuateService.listPage(pageParam, courseValuate));
+    }
+
+    @PostMapping
+    public Result saveOrUpdate(@RequestBody @Validated CourseValuate courseValuate) {
+        courseValuateService.saveOrUpdate(courseValuate);
+        return Result.success();
+    }
+}

+ 74 - 0
education-api/src/main/java/com/education/api/controller/student/ExamInfoController.java

@@ -0,0 +1,74 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.education.ExamInfoService;
+import com.education.business.service.education.ExamMonitorService;
+import com.education.business.session.UserSessionContext;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.ExamMonitor;
+import com.education.model.dto.StudentExamInfoDto;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 学生端考试记录管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/22 16:53
+ */
+@RequestMapping("/student/exam")
+@RestController("student-exam")
+public class ExamInfoController extends BaseController {
+
+    @Resource
+    private ExamInfoService examInfoService;
+    @Resource
+    private ExamMonitorService examMonitorService;
+
+    /**
+     * 考试记录列表
+     * @param pageParam
+     * @param studentExamInfoDto
+     * @return
+     */
+    @GetMapping
+    public Result selectExamInfoList(PageParam pageParam, StudentExamInfoDto studentExamInfoDto) {
+        return Result.success(examInfoService.selectStudentExamInfoList(pageParam, studentExamInfoDto));
+    }
+
+
+    /**
+     * 获取考试试题及答案
+     * @param examInfoId
+     * @return
+     */
+    @GetMapping("selectExamQuestionAnswer/{id}")
+    public Result selectExamQuestionAnswer(@PathVariable("id") Integer examInfoId) {
+        Integer studentId = UserSessionContext.getStudentId();
+        return Result.success(examInfoService.selectExamQuestionAnswer(studentId, examInfoId));
+    }
+
+    /**
+     * 获取考试结果
+     * @param examInfoId
+     * @return
+     */
+    @GetMapping("selectExamInfo/{id}")
+   // 暂时注释 @Cacheable(cacheNames = CacheKey.EXAM_CACHE, key = "#examInfoId")
+    public Result<StudentExamInfoDto> selectExamInfo(@PathVariable("id") Integer examInfoId) {
+        return Result.success(examInfoService.getExamInfoById(examInfoId));
+    }
+
+    /**
+     * 添加监控中心接口
+     * @param examMonitor
+     * @return
+     */
+    @PostMapping("addToExamExamMonitor")
+    public Result addToExamExamMonitor(@RequestBody ExamMonitor examMonitor) {
+        examMonitorService.addStudentToExamMonitor(examMonitor);
+        return Result.success();
+    }
+}

+ 15 - 0
education-api/src/main/java/com/education/api/controller/student/GradeInfoController.java

@@ -0,0 +1,15 @@
+package com.education.api.controller.student;
+
+import com.education.common.base.BaseController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/22 9:45
+ */
+@RestController("student-gradeInfo")
+@RequestMapping("/student/gradeInfo")
+public class GradeInfoController extends BaseController {
+}

+ 40 - 0
education-api/src/main/java/com/education/api/controller/student/MessageInfoController.java

@@ -0,0 +1,40 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.education.MessageInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.Result;
+import com.education.model.entity.MessageInfo;
+import com.education.model.request.PageParam;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+
+/**
+ * 消息通知接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/12/13 14:35
+ */
+@RestController
+@RequestMapping("/student/message")
+public class MessageInfoController extends BaseController {
+
+    @Resource
+    private MessageInfoService messageInfoService;
+
+    @GetMapping
+    public Result<PageInfo<MessageInfo>> list(PageParam pageParam) {
+        return Result.success(messageInfoService.selectList(pageParam));
+    }
+
+    /**
+     * 获取未读消息数量
+     * @return
+     */
+    @GetMapping("getUnReadMessageCount")
+    public Result getUnReadMessageCount() {
+        return Result.success(messageInfoService.getUnReadMessageCount());
+    }
+}

+ 71 - 0
education-api/src/main/java/com/education/api/controller/student/StuGoalInfoController.java

@@ -0,0 +1,71 @@
+package com.education.api.controller.student;
+
+
+import com.education.business.service.education.StuGoalInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.StuGoalInfoDto;
+import com.education.model.entity.StuGoalInfo;
+import com.education.model.request.PageParam;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+/**
+ * 学生导向目标管理
+ */
+@RequestMapping("/student/stuGoalInfo")
+@RestController("student-stuGoalInfo")
+public class StuGoalInfoController extends BaseController {
+
+    @Resource
+    private StuGoalInfoService stuGoalInfoService;
+
+    /**
+     * 答题
+     * @param stuGoalInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("student:stuGoalInfo:update")
+    public Result answer(@RequestBody @Validated StuGoalInfo stuGoalInfo) {
+        stuGoalInfoService.saveOrUpdate(stuGoalInfo);
+        return Result.success();
+    }
+
+    /**
+     * 学生导向目标答题记录分页列表
+     * @param pageParam
+     * @param stuGoalInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:stuGoalInfo:list")
+    public Result selectPage(PageParam pageParam, StuGoalInfo stuGoalInfo) {
+        return Result.success(stuGoalInfoService.selectPageList(pageParam, stuGoalInfo));
+    }
+
+//    /**
+//     * 添加或修改
+//     * @param stuGoalInfoDto
+//     * @return
+//     */
+//    @PostMapping
+//    //@RequiresPermissions(value = {"system:stuGoalInfo:save","system:stuGoalInfo:update"}, logical = Logical.OR)
+//    public Result saveOrUpdate(@RequestBody StuGoalInfoDto stuGoalInfoDto) {
+//        stuGoalInfoService.saveOrUpdate(stuGoalInfoDto);
+//        return Result.success();
+//    }
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:stuGoalInfo:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        stuGoalInfoService.removeById(id);
+        return Result.success();
+    }
+}

+ 61 - 0
education-api/src/main/java/com/education/api/controller/student/StuHomeworkInfoController.java

@@ -0,0 +1,61 @@
+package com.education.api.controller.student;
+
+import com.education.auth.annotation.Logical;
+import com.education.auth.annotation.RequiresPermissions;
+import com.education.business.service.education.StuHomeworkInfoService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.StuHomeworkInfoDto;
+import com.education.model.entity.StuHomeworkInfo;
+import com.education.model.request.PageParam;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+
+/**
+ * 学生作业管理
+ */
+@RequestMapping("/student/stuHomeworkInfo")
+@RestController("student-stuHomeworkInfo")
+public class StuHomeworkInfoController extends BaseController {
+
+    @Resource
+    private StuHomeworkInfoService stuHomeworkInfoService;
+
+    /**
+     * 提交作业
+     * @param stuHomeworkInfo
+     * @return
+     */
+    @PostMapping
+    //@RequiresPermissions("student:stuHomeworkInfo:update")
+    public Result submit(@RequestBody @Validated StuHomeworkInfo stuHomeworkInfo) {
+        stuHomeworkInfoService.saveOrUpdate(stuHomeworkInfo);
+        return Result.success();
+    }
+
+    /**
+     * 学生作业信息分页列表
+     * @param pageParam
+     * @param stuHomeworkInfo
+     * @return
+     */
+    @GetMapping
+    //@RequiresPermissions("system:stuHomeworkInfo:list")
+    public Result selectPage(PageParam pageParam, StuHomeworkInfo stuHomeworkInfo) {
+        return Result.success(stuHomeworkInfoService.selectPageList(pageParam, stuHomeworkInfo));
+    }
+
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    @DeleteMapping("{id}")
+    //@RequiresPermissions("system:stuHomeworkInfo:deleteById")
+    public Result deleteById(@PathVariable Integer id) {
+        stuHomeworkInfoService.removeById(id);
+        return Result.success();
+    }
+}

+ 39 - 0
education-api/src/main/java/com/education/api/controller/student/StudentCourseCollectController.java

@@ -0,0 +1,39 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.education.StudentCourseCollectService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.model.dto.StudentCourseCollectDto;
+import com.education.model.entity.StudentCourseCollect;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * 课程收藏
+ * @author zengjintao
+ * @create_at 2021/12/26 11:01
+ * @since version 1.0.3
+ */
+@RestController
+@RequestMapping("/student/course/collect")
+public class StudentCourseCollectController extends BaseController {
+
+    @Resource
+    private StudentCourseCollectService studentCourseCollectService;
+
+    /**
+     * 课程收藏或取消收藏
+     * @param studentCourseCollectDto
+     * @return
+     */
+    @PostMapping
+    public Result collect(@RequestBody StudentCourseCollectDto studentCourseCollectDto) {
+        studentCourseCollectService.collect(studentCourseCollectDto);
+        return Result.success();
+    }
+
+}

+ 89 - 0
education-api/src/main/java/com/education/api/controller/student/StudentInfoController.java

@@ -0,0 +1,89 @@
+package com.education.api.controller.student;
+
+import com.education.auth.AuthUtil;
+import com.education.auth.LoginToken;
+import com.education.business.service.education.StudentInfoService;
+import com.education.business.session.StudentSession;
+import com.education.common.annotation.Param;
+import com.education.common.annotation.ParamsType;
+import com.education.common.annotation.ParamsValidate;
+import com.education.common.base.BaseController;
+import com.education.common.constants.AuthConstants;
+import com.education.common.enums.LoginEnum;
+import com.education.common.utils.RegexUtils;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.StudentInfoDto;
+import com.education.model.entity.StudentInfo;
+import com.education.model.request.UserLoginRequest;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 学员登录接口
+ *
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/21 20:58
+ */
+@RequestMapping("/student")
+@RestController("student-controller")
+public class StudentInfoController extends BaseController {
+
+    @Resource
+    private StudentInfoService studentInfoService;
+
+    /**
+     * 学员登录接口
+     *
+     * @param userLoginRequest
+     * @return
+     */
+    @PostMapping("login")
+    public Result login(@RequestBody UserLoginRequest userLoginRequest, HttpServletResponse response) {
+        LoginToken loginToken = new LoginToken(userLoginRequest.getUserName(), userLoginRequest.getPassword(), LoginEnum.STUDENT.getValue(), userLoginRequest.getDeviceType(),
+                userLoginRequest.isChecked());
+        loginToken.setDeviceType(userLoginRequest.getDeviceType());
+        StudentSession session = AuthUtil.login(loginToken);
+        response.addHeader(AuthConstants.AUTHORIZATION, session.getToken());
+        return Result.success(ResultCode.SUCCESS, "登录成功", session);
+    }
+
+    @PostMapping("logout")
+    public Result logout() {
+        AuthUtil.logout(LoginEnum.STUDENT.getValue());
+        return Result.success(ResultCode.SUCCESS, "退出成功");
+    }
+
+    /**
+     * 修改新密码
+     *
+     * @param studentInfoDto
+     * @return
+     */
+    @PostMapping("updatePassword")
+    public Result updatePassword(@RequestBody StudentInfoDto studentInfoDto) {
+        return Result.success(studentInfoService.updatePassword(studentInfoDto.getPassword(),
+                studentInfoDto.getNewPassword(), studentInfoDto.getConfirmPassword()));
+    }
+
+    /**
+     * 修改个人资料
+     *
+     * @param studentInfo
+     * @return
+     */
+    @PostMapping("updateStudentInfo")
+    @ParamsValidate(params = {
+            @Param(name = "name", message = "请输入姓名"),
+            @Param(name = "sex", message = "请选择性别"),
+            @Param(name = "mobile", message = "请输入手机号", regexp = RegexUtils.MOBILE_REGEX, regexpMessage = "非法手机号")
+    }, paramsType = ParamsType.JSON_DATA)
+    public Result updateInfo(@RequestBody StudentInfo studentInfo) {
+        return Result.success(studentInfoService.updateInfo(studentInfo));
+    }
+}

+ 45 - 0
education-api/src/main/java/com/education/api/controller/student/SubjectInfoController.java

@@ -0,0 +1,45 @@
+package com.education.api.controller.student;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.education.business.service.education.SubjectInfoService;
+import com.education.business.session.UserSessionContext;
+import com.education.common.base.BaseController;
+import com.education.common.utils.ObjectUtils;
+import com.education.common.utils.Result;
+import com.education.model.entity.SubjectInfo;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * 学生端 科目管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/22 9:41
+ */
+@RestController("student-subjectInfo")
+@RequestMapping("/student/subjectInfo")
+public class SubjectInfoController extends BaseController {
+
+    @Resource
+    private SubjectInfoService subjectInfoService;
+
+    /**
+     * 根据年级获取科目列表
+     * @param gradeInfoId
+     * @return
+     */
+    @GetMapping("selectByGradeInfoId")
+    public Result selectByGradeInfoId(Integer gradeInfoId) {
+        if (ObjectUtils.isEmpty(gradeInfoId)) {
+            gradeInfoId = UserSessionContext.getStudentUserSession().getGradeInfoId();
+        }
+        LambdaQueryWrapper queryWrapper = Wrappers.<SubjectInfo>lambdaQuery()
+                .eq(SubjectInfo::getGradeInfoId, gradeInfoId);
+        return Result.success(subjectInfoService.list(queryWrapper));
+    }
+
+}

+ 90 - 0
education-api/src/main/java/com/education/api/controller/student/TestPaperInfoController.java

@@ -0,0 +1,90 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.education.ExamInfoService;
+import com.education.business.service.education.ExamMonitorService;
+import com.education.business.service.education.TestPaperInfoService;
+import com.education.business.session.UserSessionContext;
+import com.education.common.annotation.FormLimit;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import com.education.common.utils.ResultCode;
+import com.education.model.dto.ExamMonitor;
+import com.education.model.dto.TestPaperInfoDto;
+import com.education.model.request.PageParam;
+import com.education.model.request.StudentQuestionRequest;
+import com.education.model.request.TestPaperQuestionRequest;
+import com.education.model.response.StudentExamRate;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 学生端试卷管理
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/11/22 10:26
+ */
+@RestController("student-testPaperInfo")
+@RequestMapping("/student/testPaperInfo")
+public class TestPaperInfoController extends BaseController {
+
+    @Resource
+    private TestPaperInfoService testPaperInfoService;
+    @Resource
+    private ExamInfoService examInfoService;
+    @Resource
+    private ExamMonitorService examMonitorService;
+
+    /**
+     * 试卷列表
+     * @param pageParam
+     * @param testPaperInfoDto
+     * @return
+     */
+    @GetMapping("list")
+    public Result list(PageParam pageParam, TestPaperInfoDto testPaperInfoDto) {
+        testPaperInfoDto.setPublishFlag(true);
+        return Result.success(testPaperInfoService.selectPageList(pageParam, testPaperInfoDto));
+    }
+
+    /**
+     * 获取试卷试题
+     * @param id
+     * @return sync = true 目前貌似只针对本地缓存有效 (该方式主要用户高并发下的同步操作,从而减少对数据库的请求)
+     */
+    @GetMapping("selectPaperQuestionById")
+    public Result selectPaperQuestionById(Integer id) {
+        PageParam pageParam = new PageParam(); // 设置不分页
+        TestPaperQuestionRequest testPaperQuestionRequest = new TestPaperQuestionRequest();
+        testPaperQuestionRequest.setTestPaperInfoId(id);
+        return Result.success(testPaperInfoService.selectPaperQuestionListByCache(pageParam, testPaperQuestionRequest));
+    }
+
+    /**
+     * 提交试卷试题
+     * @param studentQuestionRequest
+     * @return
+     */
+    @PostMapping("commitPaper")
+    @FormLimit(message = "请勿重复提交考试")
+    public Result commitPaper(@RequestBody StudentQuestionRequest studentQuestionRequest) {
+        return Result.success(ResultCode.SUCCESS,
+                "提交成功",
+                examInfoService.commitTestPaperInfoQuestion(studentQuestionRequest));
+    }
+
+    /**
+     * 更新学员考试答题进度
+     * @param studentExamRate
+     * @return
+     */
+    @PostMapping("updateStudentExamRate")
+    public Result updateStudentExamRate(@RequestBody StudentExamRate studentExamRate) {
+        ExamMonitor examMonitor = examMonitorService.getExamMonitorStudent(studentExamRate.getTestPaperInfoId(),
+                UserSessionContext.getStudentId());
+        examMonitor.setAnswerQuestionCount(studentExamRate.getAnswerQuestionCount());
+        examMonitor.setTestPaperInfoId(studentExamRate.getTestPaperInfoId());
+        examMonitorService.addStudentToExamMonitor(examMonitor);
+        return Result.success();
+    }
+}

+ 28 - 0
education-api/src/main/java/com/education/api/controller/student/WebSiteConfigController.java

@@ -0,0 +1,28 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.system.WebsiteConfigService;
+import com.education.common.base.BaseController;
+import com.education.common.utils.Result;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @author zengjintao
+ * @create_at 2021/11/2 21:01
+ * @since version 1.0.3
+ */
+@RestController("student-webSite")
+@RequestMapping("/student/webSite")
+public class WebSiteConfigController extends BaseController {
+
+    @Resource
+    private WebsiteConfigService websiteConfigService;
+
+    @GetMapping
+    public Result getWebSiteConfig() {
+        return Result.success(websiteConfigService.getWebSiteConfig());
+    }
+}

+ 41 - 0
education-api/src/main/java/com/education/api/controller/student/WrongBookController.java

@@ -0,0 +1,41 @@
+package com.education.api.controller.student;
+
+import com.education.business.service.education.StudentWrongBookService;
+import com.education.business.session.UserSessionContext;
+import com.education.common.base.BaseController;
+import com.education.common.model.PageInfo;
+import com.education.common.utils.Result;
+import com.education.model.dto.QuestionInfoAnswer;
+import com.education.model.request.PageParam;
+import com.education.model.request.WrongBookQuery;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * 错题本管理接口
+ * @author zengjintao
+ * @version 1.0
+ * @create_at 2020/12/4 17:56
+ */
+@RestController
+@RequestMapping("/student/wrongBook")
+public class WrongBookController extends BaseController {
+
+    @Resource
+    private StudentWrongBookService studentWrongBookService;
+
+    /**
+     * 错题本列表
+     * @param pageParam
+     * @param wrongBookQuery
+     * @return
+     */
+    @GetMapping
+    public Result<PageInfo<QuestionInfoAnswer>> list(PageParam pageParam, WrongBookQuery wrongBookQuery) {
+        wrongBookQuery.setStudentId(UserSessionContext.getStudentId());
+        return Result.success(studentWrongBookService.selectPageList(pageParam, wrongBookQuery));
+    }
+}

+ 109 - 0
education-api/src/main/resources/application-dev.yml

@@ -0,0 +1,109 @@
+host: 127.0.0.1
+server:
+  port: 8081
+# oss 文件上传配置
+oss:
+  upload:
+    host: ${host}/uploads  // 文件访问域名
+    platform: local  #配置使用本地文件存储
+    bucketName: D:\\home\\ #配置文件上传目录
+## spring jdbc配置
+spring:
+  # flyway 数据库管理工具
+  flyway:
+    sql-migration-separator: _ #分隔符
+    clean-disabled: true #禁用clean操作
+    enabled: false #使flyway生效
+    baseline-on-migrate: true #初始化时如果不存在迁移记录表,默认新建一个
+    out-of-order: true #防止开发环境下漏掉没来得及apply的文件,产品环境最好设为false
+    ignore-ignored-migrations: true
+    locations: classpath:/db
+    url: jdbc:mysql://www.fznnic.cn:3306/education?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
+    user: root
+    password: f2fa84b09815fe08
+
+  redis:
+    jedis:
+      pool:
+        max-active: 20
+        max-wait: 30
+        max-idle: 8
+        min-idle: 0
+    host: www.fznnic.cn
+    password: hyxHYXhyx1114
+    port: 6379
+    db: 15
+  ## 文件上传大小限制
+  servlet:
+    multipart:
+      max-file-size: 500MB
+      max-request-size: 500MB
+  mail:
+    host: smtp.163.com
+    port: 25
+    username: 18296640717@163.com
+    password: KIZMPBYPLMWTIZGP
+    properties:
+      mail:
+        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
+        debug: true
+ueditor:
+  configFileName: oss-config-dev.json
+# 微信公众号配置
+weChat:
+  appId: wx7874d0c23d07e2aa
+  token: education
+  appSecret: e03f5ab03906d4d943675c233d4c3cb3
+
+# 是否开启  canal 数据同步
+canal:
+  openFlag: false
+
+#rabbitmq 队列配置
+rabbitmq:
+  socket:
+    queue: dev_socket_queue
+    routing-key: dev_socket_queue_routing_key
+    direct-exchange: dev_socket_direct_exchange
+  exam:
+    queue: dev_exam_queue
+    routing-key: dev_exam_queue_routing_key
+    direct-exchange: dev_exam_direct_exchange
+  canal:
+    queue: dev_canal_queue
+    routing-key: dev_canal_queue_routing_key
+    direct-exchange: dev_canal_direct_exchange
+
+# sharding jdbc 读写分离配置
+sharding:
+  jdbc:
+    datasource:
+      names: educationmaster,educationslave
+      educationmaster:
+        maximum-pool-size: 50
+          #最小空闲连接数量
+        minimum-idle: 10
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://www.fznnic.cn:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        username: root
+        password: f2fa84b09815fe08
+      educationslave:
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://www.fznnic.cn:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        username: root
+        password: f2fa84b09815fe08
+    config:
+      masterslave: # 配置读写分离
+        load-balance-algorithm-type: round_robin # 配置从库选择策略,提供轮询与随机,这里选择用轮询//random 随机 //round_robin 轮询
+        name: db1s2
+        master-data-source-name: educationmaster
+        slave-data-source-names: educationslave
+      props:
+        sql:
+          show: true
+logging:
+  file:
+    path: home/upoads/logs
+    name: education.log

+ 108 - 0
education-api/src/main/resources/application-dev1.yml

@@ -0,0 +1,108 @@
+host: 127.0.0.1
+server:
+  port: 80
+# oss 文件上传配置
+oss:
+  upload:
+    host: ${host}/uploads  // 文件访问域名
+    platform: local  #配置使用本地文件存储
+    bucketName: D:\\home\\ #配置文件上传目录
+## spring jdbc配置
+spring:
+  # flyway 数据库管理工具
+  flyway:
+    sql-migration-separator: _ #分隔符
+    clean-disabled: true #禁用clean操作
+    enabled: false #使flyway生效
+    baseline-on-migrate: true #初始化时如果不存在迁移记录表,默认新建一个
+    out-of-order: true #防止开发环境下漏掉没来得及apply的文件,产品环境最好设为false
+    ignore-ignored-migrations: true
+    locations: classpath:/db
+    url: jdbc:mysql://110.41.60.208:3306/education?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
+    user: root
+    password: lizhixian
+
+  redis:
+    jedis:
+      pool:
+        max-active: 20
+        max-wait: 30
+        max-idle: 8
+        min-idle: 0
+    host: 110.41.60.208
+    password: lizhixian
+    port: 6379
+  ## 文件上传大小限制
+  servlet:
+    multipart:
+      max-file-size: 500MB
+      max-request-size: 500MB
+  mail:
+    host: smtp.163.com
+    port: 25
+    username: 18296640717@163.com
+    password: KIZMPBYPLMWTIZGP
+    properties:
+      mail:
+        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
+        debug: true
+ueditor:
+  configFileName: oss-config-dev.json
+# 微信公众号配置
+weChat:
+  appId: wx7874d0c23d07e2aa
+  token: education
+  appSecret: e03f5ab03906d4d943675c233d4c3cb3
+
+# 是否开启  canal 数据同步
+canal:
+  openFlag: false
+
+#rabbitmq 队列配置
+rabbitmq:
+  socket:
+    queue: dev_socket_queue
+    routing-key: dev_socket_queue_routing_key
+    direct-exchange: dev_socket_direct_exchange
+  exam:
+    queue: dev_exam_queue
+    routing-key: dev_exam_queue_routing_key
+    direct-exchange: dev_exam_direct_exchange
+  canal:
+    queue: dev_canal_queue
+    routing-key: dev_canal_queue_routing_key
+    direct-exchange: dev_canal_direct_exchange
+
+# sharding jdbc 读写分离配置
+sharding:
+  jdbc:
+    datasource:
+      names: educationmaster,educationslave
+      educationmaster:
+        maximum-pool-size: 50
+          #最小空闲连接数量
+        minimum-idle: 10
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://110.41.60.208:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        username: root
+        password: lizhixian
+      educationslave:
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://110.41.60.208:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        username: root
+        password: lizhixian
+    config:
+      masterslave: # 配置读写分离
+        load-balance-algorithm-type: round_robin # 配置从库选择策略,提供轮询与随机,这里选择用轮询//random 随机 //round_robin 轮询
+        name: db1s2
+        master-data-source-name: educationmaster
+        slave-data-source-names: educationslave
+      props:
+        sql:
+          show: true
+logging:
+  file:
+    path: home/upoads/logs
+    name: education.log

+ 139 - 0
education-api/src/main/resources/application-prod.yml

@@ -0,0 +1,139 @@
+host: 127.0.0.1
+oss:
+  upload:
+    host: ${host}/uploads  // 文件访问域名
+    platform: local  #配置使用本地文件存储
+    bucketName: D:\\home\\ #配置文件上传目录
+server:
+  port: 8001
+canal:
+  openFlag: false
+  host: 110.40.147.26
+## spring jdbc配置
+spring:
+  flyway:
+    sql-migration-separator: _ #分隔符
+    clean-disabled: true #禁用clean操作
+    enabled: true #使flyway生效
+    baseline-on-migrate: true #初始化时如果不存在迁移记录表,默认新建一个
+    out-of-order: true #防止开发环境下漏掉没来得及apply的文件,产品环境最好设为false
+    ignore-ignored-migrations: true
+    locations: classpath:/db
+    url: jdbc:mysql://${host}:3306/education?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
+    user: root
+    password: 123456
+  redis:
+    jedis:
+      pool:
+        max-active: 8
+        max-wait: 30
+        max-idle: 8
+        min-idle: 0
+    host: ${host}
+    port: 6379
+    password: taoge
+  rabbitmq:
+    host: ${host}
+    port: 5672
+    username: rabbitmq
+    password: 123456
+    virtual-host: /
+    publisher-returns: true
+    listener:
+      simple:
+        acknowledge-mode: manual #开启手动确认模式
+    publisher-confirm-type: correlated
+  freemarker:
+    template-loader-path: classpath:/template/
+    suffix: .ftl
+    charset: utf-8
+  ## 文件上传大小限制
+  servlet:
+    multipart:
+      max-file-size: 500MB
+      max-request-size: 500MB
+  mail:
+    host: smtp.163.com
+    port: 25
+    username: 18296640717@163.com
+    password: KIZMPBYPLMWTIZGP
+    properties:
+      mail:
+        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
+        debug: true
+lbs:
+  key: MYOBZ-OOEW3-KYC3G-YWDXA-DMQJ6-SPBMH
+
+#rabbitmq 队列配置
+rabbitmq:
+  socket:
+    queue: socket_queue
+    routing-key: socket_queue_routing_key
+    direct-exchange: socket_direct_exchange
+  exam:
+    queue: exam_queue
+    routing-key: dev_exam_queue_routing_key
+    direct-exchange: exam_direct_exchange
+  canal:
+    queue: canal_queue
+    routing-key: canal_queue_routing_key
+    direct-exchange: canal_direct_exchange
+ueditor:
+  configFileName: oss-config.json
+
+# 微信公众号配置
+weChat:
+  appId: wxc5d3bf3c1fbf6d25
+  token: education
+  appSecret: cf05150f801935391f29d73695f04300
+
+# 配置日志文件输出目录及文件
+logging:
+  file:
+    path: /root/jar
+    name: education.log
+
+# sharding jdbc 读写分离配置
+sharding:
+  jdbc:
+    datasource:
+      names: educationmaster,educationslave
+      educationmaster:
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://${host}:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        idle-timeout: 60000
+        #数据库连接超时时间
+        connection-timeout: 30000
+        #连接池最大连接数,默认是10
+        maximum-pool-size: 60
+        #最小空闲连接数量
+        minimum-idle: 10
+        # 此属性控制池中连接的最长生命周期,值0表示无限生命周期
+        max-lifetime: 60000
+        username: root
+        password: 123456
+      educationslave:
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://${host}:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        idle-timeout: 60000
+        #数据库连接超时时间
+        connection-timeout: 30000
+        #连接池最大连接数,默认是10
+        maximum-pool-size: 60
+        #最小空闲连接数量
+        minimum-idle: 10
+        # 此属性控制池中连接的最长生命周期,值0表示无限生命周期
+        max-lifetime: 60000
+        username: root
+        password: 123456
+    config:
+      masterslave: # 配置读写分离
+        load-balance-algorithm-type: round_robin # 配置从库选择策略,提供轮询与随机,这里选择用轮询//random 随机 //round_robin 轮询
+        name: db1s2
+        master-data-source-name: educationmaster
+        slave-data-source-names: educationslave
+      props:
+        sql:
+          show: true

+ 114 - 0
education-api/src/main/resources/application-test.yml

@@ -0,0 +1,114 @@
+server:
+  port: 80
+canal:
+  open: true
+## spring jdbc配置
+spring:
+  flyway:
+    sql-migration-separator: _ #分隔符
+    clean-disabled: true #禁用clean操作
+    enabled: true #使flyway生效
+    baseline-on-migrate: true #初始化时如果不存在迁移记录表,默认新建一个
+    out-of-order: true #防止开发环境下漏掉没来得及apply的文件,产品环境最好设为false
+    ignore-ignored-migrations: true
+    locations: classpath:/db
+    url: jdbc:mysql://127.0.0.1:3306/education?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
+    user: root
+    password: 123456
+  redis:
+    jedis:
+      pool:
+        max-active: 8
+        max-wait: 30
+        max-idle: 8
+        min-idle: 0
+    host: 127.0.0.1
+    port: 6379
+    password: taoge
+  rabbitmq:
+    host: 127.0.0.1
+    port: 5672
+    username: rabbitmq
+    password: 123456
+    virtual-host: /
+    publisher-returns: true
+    listener:
+      simple:
+        acknowledge-mode: manual #开启手动确认模式
+    publisher-confirm-type: correlated
+  freemarker:
+    template-loader-path: classpath:/template/
+    suffix: .ftl
+    charset: utf-8
+  ## 文件上传大小限制
+  servlet:
+    multipart:
+      max-file-size: 500MB
+      max-request-size: 500MB
+  mail:
+    host: smtp.163.com
+    port: 25
+    username: 18296640717@163.com
+    password: KIZMPBYPLMWTIZGP
+    properties:
+      mail:
+        #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
+        debug: true
+lbs:
+  key: MYOBZ-OOEW3-KYC3G-YWDXA-DMQJ6-SPBMH
+## 虚拟文件上传路径
+file:
+  uploadPath: /root/uploads/
+ueditor:
+  configFileName: config-dev.json
+# 微信公众号配置
+weChat:
+  appId: wxc5d3bf3c1fbf6d25
+  token: education
+  appSecret: cf05150f801935391f29d73695f04300
+logging:
+  file:
+    path: /root/jar
+    name: education.log
+
+#rabbitmq 队列配置
+rabbitmq:
+  socket:
+    queue: test_socket_queue
+    routing-key: test_socket_queue_routing_key
+    direct-exchange: test_socket_direct_exchange
+  exam:
+    queue: test_exam_queue
+    routing-key: test_exam_queue_routing_key
+    direct-exchange: test_exam_direct_exchange
+  canal:
+    queue: test_canal_queue
+    routing-key: test_canal_queue_routing_key
+    direct-exchange: test_canal_direct_exchange
+
+# sharding jdbc 读写分离配置
+sharding:
+  jdbc:
+    datasource:
+      names: educationmaster,educationslave
+      educationmaster:
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://127.0.0.1:3306/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        username: root
+        password: 123456
+      educationslave:
+        type: com.zaxxer.hikari.HikariDataSource
+        jdbc-url: jdbc:mysql://127.0.0.1:3307/education?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        driver-class-name: com.mysql.cj.jdbc.Driver
+        username: root
+        password: 123456
+    config:
+      masterslave: # 配置读写分离
+        load-balance-algorithm-type: round_robin # 配置从库选择策略,提供轮询与随机,这里选择用轮询//random 随机 //round_robin 轮询
+        name: db1s2
+        master-data-source-name: educationmaster
+        slave-data-source-names: educationslave
+      props:
+        sql:
+          show: true

+ 14 - 0
education-api/src/main/resources/application.yml

@@ -0,0 +1,14 @@
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  profiles:
+    active: dev
+  cache:
+    type: redis
+  application:
+    name: education
+mybatis-plus:
+  type-aliases-package: com.education.model
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  mapper-locations: mapper/**/*.xml

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
education-api/src/main/resources/config-dev.json


+ 95 - 0
education-api/src/main/resources/config-test.json

@@ -0,0 +1,95 @@
+/* 前后端通信相关的配置,注释只允许使用多行方式 */
+{
+    /* 上传图片配置项 */
+    "basePath": "/root/uploads", /* 设置文件上传跟路劲 /root/uploads */
+    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
+    "imageFieldName": "upfile", /* 提交的图片表单名称 */
+    "imageMaxSize": 2048000, /* 上传大小限制,单位B */
+    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
+    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
+    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
+    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
+    "imageUrlPrefix": "http://120.79.144.34:8001/uploads",/* 图片访问路径前缀 */
+    "imagePathFormat": "/file/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+                                /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
+                                /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
+                                /* {time} 会替换成时间戳 */
+                                /* {yyyy} 会替换成四位年份 */
+                                /* {yy} 会替换成两位年份 */
+                                /* {mm} 会替换成两位月份 */
+                                /* {dd} 会替换成两位日期 */
+                                /* {hh} 会替换成两位小时 */
+                                /* {ii} 会替换成两位分钟 */
+                                /* {ss} 会替换成两位秒 */
+                                /* 非法字符 \ : * ? " < > | */
+                                /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
+
+    /* 涂鸦图片上传配置项 */
+    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
+    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
+    "scrawlPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
+    "scrawlUrlPrefix": "http://120.79.144.34:8001/uploads", /* 图片访问路径前缀 */
+    "scrawlInsertAlign": "none",
+
+    /* 截图工具上传 */
+    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
+    "snapscreenPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "snapscreenUrlPrefix": "http://120.79.144.34:8001/uploads", /* 图片访问路径前缀 */
+    "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
+
+    /* 抓取远程图片配置 */
+    "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
+    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
+    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
+    "catcherPathFormat": "/file/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "catcherUrlPrefix": "http://120.79.144.34:8001/uploads", /* 图片访问路径前缀 */
+    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
+    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
+
+    /* 上传视频配置 */
+    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
+    "videoFieldName": "upfile", /* 提交的视频表单名称 */
+    "videoPathFormat": "/file/video/ueditor/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "videoUrlPrefix": "http://120.79.144.34:8001/uploads", /*//* 视频访问路径前缀 */
+    "videoMaxSize": 512000000, /* 上传大小限制,单位B,默认500MB */
+    "videoAllowFiles": [
+        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
+        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
+
+    /* 上传文件配置 */
+    "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
+    "fileFieldName": "upfile", /* 提交的文件表单名称 */
+    "filePathFormat": "/file/attachment/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "fileUrlPrefix": "http://120.79.144.34:8001/uploads", /* 文件访问路径前缀 */
+    "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
+    "fileAllowFiles": [
+        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
+        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
+        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
+        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
+        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
+    ], /* 上传文件格式显示 */
+
+    /* 列出指定目录下的图片 */
+    "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
+    "imageManagerListPath": "/ueditor/jsp/upload/image/", /* 指定要列出图片的目录 */
+    "imageManagerListSize": 20, /* 每次列出文件数量 */
+    "imageManagerUrlPrefix": "http://120.79.144.34:8001/uploads", /* 图片访问路径前缀 */
+    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
+    "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
+
+    /* 列出指定目录下的文件 */
+    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
+    "fileManagerListPath": "/ueditor/jsp/upload/file/", /* 指定要列出文件的目录 */
+    "fileManagerUrlPrefix": "http://120.79.144.34:8001/uploads", /* 文件访问路径前缀 */
+    "fileManagerListSize": 20, /* 每次列出文件数量 */
+    "fileManagerAllowFiles": [
+        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
+        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
+        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
+        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
+        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
+    ] /* 列出的文件类型 */
+
+}

+ 95 - 0
education-api/src/main/resources/config.json

@@ -0,0 +1,95 @@
+/* 前后端通信相关的配置,注释只允许使用多行方式 */
+{
+    /* 上传图片配置项 */
+    "basePath": "/root/uploads", /* 设置文件上传跟路劲 /root/uploads */
+    "imageActionName": "uploadimage", /* 执行上传图片的action名称 */
+    "imageFieldName": "upfile", /* 提交的图片表单名称 */
+    "imageMaxSize": 2048000, /* 上传大小限制,单位B */
+    "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
+    "imageCompressEnable": true, /* 是否压缩图片,默认是true */
+    "imageCompressBorder": 1600, /* 图片压缩最长边限制 */
+    "imageInsertAlign": "none", /* 插入的图片浮动方式 */
+    "imageUrlPrefix": "http://47.103.4.213:8002/uploads",/* 图片访问路径前缀 */
+    "imagePathFormat": "/file/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
+    /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
+    /* {time} 会替换成时间戳 */
+    /* {yyyy} 会替换成四位年份 */
+    /* {yy} 会替换成两位年份 */
+    /* {mm} 会替换成两位月份 */
+    /* {dd} 会替换成两位日期 */
+    /* {hh} 会替换成两位小时 */
+    /* {ii} 会替换成两位分钟 */
+    /* {ss} 会替换成两位秒 */
+    /* 非法字符 \ : * ? " < > | */
+    /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
+
+    /* 涂鸦图片上传配置项 */
+    "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
+    "scrawlFieldName": "upfile", /* 提交的图片表单名称 */
+    "scrawlPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
+    "scrawlUrlPrefix": "http://47.103.4.213:8002/uploads", /* 图片访问路径前缀 */
+    "scrawlInsertAlign": "none",
+
+    /* 截图工具上传 */
+    "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
+    "snapscreenPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "snapscreenUrlPrefix": "http://47.103.4.213:8002/uploads", /* 图片访问路径前缀 */
+    "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
+
+    /* 抓取远程图片配置 */
+    "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
+    "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
+    "catcherFieldName": "source", /* 提交的图片列表表单名称 */
+    "catcherPathFormat": "/file/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "catcherUrlPrefix": "http://47.103.4.213:8002/uploads", /* 图片访问路径前缀 */
+    "catcherMaxSize": 2048000, /* 上传大小限制,单位B */
+    "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
+
+    /* 上传视频配置 */
+    "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
+    "videoFieldName": "upfile", /* 提交的视频表单名称 */
+    "videoPathFormat": "/file/video/ueditor/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "videoUrlPrefix": "http://47.103.4.213:8002/uploads", /*//* 视频访问路径前缀 */
+    "videoMaxSize": 512000000, /* 上传大小限制,单位B,默认500MB */
+    "videoAllowFiles": [
+        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
+        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
+
+    /* 上传文件配置 */
+    "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
+    "fileFieldName": "upfile", /* 提交的文件表单名称 */
+    "filePathFormat": "/file/attachment/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
+    "fileUrlPrefix": "http://47.103.4.213:8002/uploads", /* 文件访问路径前缀 */
+    "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
+    "fileAllowFiles": [
+        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
+        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
+        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
+        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
+        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
+    ], /* 上传文件格式显示 */
+
+    /* 列出指定目录下的图片 */
+    "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
+    "imageManagerListPath": "/ueditor/jsp/upload/image/", /* 指定要列出图片的目录 */
+    "imageManagerListSize": 20, /* 每次列出文件数量 */
+    "imageManagerUrlPrefix": "http://47.103.4.213:8002/uploads", /* 图片访问路径前缀 */
+    "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
+    "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
+
+    /* 列出指定目录下的文件 */
+    "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
+    "fileManagerListPath": "/ueditor/jsp/upload/file/", /* 指定要列出文件的目录 */
+    "fileManagerUrlPrefix": "http://47.103.4.213:8002/uploads", /* 文件访问路径前缀 */
+    "fileManagerListSize": 20, /* 每次列出文件数量 */
+    "fileManagerAllowFiles": [
+        ".png", ".jpg", ".jpeg", ".gif", ".bmp",
+        ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
+        ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
+        ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
+        ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
+    ] /* 列出的文件类型 */
+
+}

+ 24 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.1_system_admin.sql

@@ -0,0 +1,24 @@
+DROP TABLE IF EXISTS `system_admin`;
+CREATE TABLE `system_admin`  (
+     `id` int(11) NOT NULL AUTO_INCREMENT,
+     `login_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '登录名',
+     `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
+     `encrypt` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码加密hash',
+     `create_date` datetime(0) NULL DEFAULT NULL,
+     `disabled_flag` tinyint(2) NOT NULL DEFAULT 0 COMMENT '1 是 0 否',
+     `login_ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录ip',
+     `login_count` int(11) NOT NULL DEFAULT 0 COMMENT '登录次数',
+     `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
+     `last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间',
+     `create_type` tinyint(2) NOT NULL DEFAULT 2 COMMENT '创建类型 (1 系统默认 2. 管理员创建)',
+     `mobile` varchar(255) CHARACTER SET utf16 COLLATE utf16_general_ci NULL DEFAULT NULL COMMENT '手机号',
+     `super_flag` tinyint(2) NOT NULL DEFAULT 0 COMMENT '1 是 0 否',
+     `update_date` datetime(0) NULL DEFAULT NULL,
+     `ip_address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+     PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统管理员表' ROW_FORMAT = Dynamic;
+
+INSERT INTO `system_admin` VALUES (1, 'admin', '94a0cf41db339d8248ee3da1c232d326', 'af2244dbc451f1007a7ba8408e45b16f2939bdc3', '2020-04-25 09:32:14', 0, '223.84.238.44', 2248, '王军', '2021-10-02 13:34:47', 1, '12123123123', 1, '2021-09-01 15:01:42', '未知地址');
+
+
+

+ 46 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.2_system_dict_value.sql

@@ -0,0 +1,46 @@
+DROP TABLE IF EXISTS `system_dict_value`;
+CREATE TABLE `system_dict_value`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `system_dict_id` int(11) NOT NULL,
+  `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `code` int(11) NULL DEFAULT NULL,
+  `parent_id` int(11) NULL DEFAULT 0,
+  `sort` int(11) NOT NULL DEFAULT 0,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典类型值表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of system_dict_value
+-- ----------------------------
+INSERT INTO `system_dict_value` VALUES (1, 1, '小学', 1, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (2, 1, '初中', 2, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (3, 1, '高中', 3, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (4, 2, '一年级', 1, 1, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (5, 2, '二年级', 2, 1, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (6, 2, '三年级', 3, 1, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (7, 2, '四年级', 4, 1, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (8, 2, '五年级', 5, 1, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (9, 2, '六年级', 6, 1, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (10, 2, '初一', 7, 2, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (11, 2, '初二', 8, 2, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (12, 2, '初三', 9, 2, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (13, 2, '高一', 10, 3, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (14, 2, '高二', 11, 3, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (15, 2, '高三', 12, 3, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (16, 3, '填空题', 3, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (17, 3, '综合题', 4, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (18, 3, '单选', 1, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (20, 3, '不定项', 5, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (21, 3, '判断题', 6, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (22, 3, '计算题', 7, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (23, 1, 'dff', 2, 1, 0, '2020-06-28 11:42:55', NULL);
+INSERT INTO `system_dict_value` VALUES (24, 1, '大学', 4, 0, 0, '2020-07-02 11:31:22', NULL);
+INSERT INTO `system_dict_value` VALUES (25, 3, '多选题', 2, 0, 0, NULL, NULL);
+INSERT INTO `system_dict_value` VALUES (27, 0, '多岁的', 2, 0, 0, '2020-11-28 20:51:04', NULL);
+INSERT INTO `system_dict_value` VALUES (28, 0, '辅导费', 4, 0, 0, '2020-11-28 20:52:04', NULL);
+INSERT INTO `system_dict_value` VALUES (29, 0, '多岁的', 3, 0, 0, '2020-11-28 20:52:24', NULL);
+INSERT INTO `system_dict_value` VALUES (30, 0, '多岁的', 4, 0, 0, '2020-11-28 20:52:56', NULL);
+INSERT INTO `system_dict_value` VALUES (31, 0, '多岁的', 34, 0, 0, '2020-11-28 20:53:55', NULL);
+

+ 103 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.3_system_menu.sql

@@ -0,0 +1,103 @@
+
+DROP TABLE IF EXISTS `system_menu`;
+CREATE TABLE `system_menu`  (
+    `id` int(64) NOT NULL AUTO_INCREMENT,
+    `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+    `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+    `parent_id` int(11) NULL DEFAULT 0,
+    `permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+    `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+    `create_date` datetime(0) NULL DEFAULT NULL,
+    `update_date` datetime(0) NULL DEFAULT NULL,
+    `sort` int(11) NULL DEFAULT 0,
+    `type` tinyint(2) NOT NULL DEFAULT 1 COMMENT '类型(1菜单 2. 目录 3 按钮)',
+    `create_type` tinyint(2) NULL DEFAULT 1 COMMENT '创建类型(1 系统内置 2. 管理员创建)',
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统菜单表' ROW_FORMAT = Dynamic;
+
+
+INSERT INTO `system_menu` VALUES (1, '系统设置', '', 0, '', 'system', '2019-03-23 14:57:58', NULL, 4, 1, 1);
+INSERT INTO `system_menu` VALUES (5, '角色管理', '/role', 1, NULL, 'role', '2019-03-23 15:00:10', NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (8, '菜单管理', '/menu', 1, NULL, 'menu', '2020-11-16 11:10:25', NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (14, '管理员管理', '/admin', 1, NULL, 'admin', '2020-11-16 11:10:28', NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (15, '列表', NULL, 14, 'system:admin:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (16, '添加', NULL, 14, 'system:admin:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (17, '列表', NULL, 5, 'system:role:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (18, '添加', NULL, 5, 'system:role:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (19, '列表', '', 8, 'system:menu:list', NULL, '2020-06-15 20:16:43', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (20, '添加', '', 8, 'system:menu:save', NULL, '2020-06-15 20:17:30', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (21, '修改', '', 8, 'system:menu:update', NULL, '2020-06-15 20:21:50', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (22, '删除', '', 8, 'system:menu:deleteById', NULL, '2020-06-15 20:26:16', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (23, '修改', '', 14, 'system:admin:update', NULL, '2020-06-15 20:26:41', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (24, '删除', '', 14, 'system:admin:deleteById', NULL, '2020-06-15 20:27:06', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (25, '删除', '', 5, 'system:role:deleteById', NULL, '2020-06-15 20:29:20', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (26, '修改', '', 5, 'system:role:update', NULL, '2020-06-15 20:29:44', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (27, '重置密码', NULL, 14, 'system:admin:updatePassword', NULL, '2020-11-16 11:10:20', NULL, 0, 1, 1);
+INSERT INTO `system_menu` VALUES (28, '权限设置', '', 5, 'system:role:savePermission', NULL, '2020-06-17 18:04:17', NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (35, '日志管理', '/log', 1, NULL, 'log', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (36, '列表', NULL, 35, 'system:log:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (37, '删除', NULL, 35, 'system:log:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (38, '字典管理', '/dict', 1, NULL, 'dict', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (39, '列表', NULL, 38, 'system:dict:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (40, '删除', NULL, 38, 'system:dict:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (42, '添加', NULL, 38, 'system:dict:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (43, '修改', NULL, 38, 'system:dict:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (44, '字典值列表', NULL, 38, 'system:dictValue:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (45, '添加字典值', NULL, 38, 'system:dictValue:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (46, '修改字典值', NULL, 38, 'system:dictValue:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (47, '删除字典值', NULL, 38, 'system:dictValue:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (48, '系统监控', NULL, 0, NULL, 'monitor', NULL, NULL, 3, 1, 1);
+INSERT INTO `system_menu` VALUES (49, '在线用户管理', '/onlineUser', 48, NULL, 'admin', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (50, '列表', NULL, 49, '', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (51, '教育教学', NULL, 0, NULL, 'video', NULL, NULL, 0, 1, 1);
+INSERT INTO `system_menu` VALUES (52, '科目管理', '/subject', 51, NULL, 'subject', NULL, '2021-08-31 23:13:58', 0, 2, 1);
+INSERT INTO `system_menu` VALUES (53, '列表', NULL, 52, 'system:subject:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (54, '添加', NULL, 52, 'system:subject:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (55, '修改', NULL, 52, 'system:subject:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (56, '删除', NULL, 52, 'system:subject:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (57, '课程管理', '/course', 51, NULL, 'course', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (58, '列表', NULL, 57, 'system:course:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (59, '添加', NULL, 57, 'system:course:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (60, '修改', NULL, 57, 'system:course:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (61, '删除', NULL, 57, 'system:course:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (62, '学员管理', '/student', 51, NULL, 'student', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (63, '列表', NULL, 62, 'system:student:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (64, '添加', NULL, 62, 'system:student:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (65, '修改', NULL, 62, 'system:student:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (66, '删除', NULL, 62, 'system:student:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (67, '重置密码', NULL, 62, 'system:student:updatePassword', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (68, '导入', NULL, 62, 'system:student:import', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (69, '试卷批改', '/correctExam', 51, NULL, 'correct', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (70, '列表', NULL, 69, 'system:exam:list', '', NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (71, '批改', NULL, 69, 'system:exam:correct', '', NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (72, '年级管理', '/gradeInfo', 51, NULL, 'zhedie', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (73, '列表', NULL, 72, 'system:grade:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (74, '添加', NULL, 72, 'system:grade:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (75, '修改', NULL, 72, 'system:grade:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (76, '删除', NULL, 72, 'system:grade:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (77, '添加知识点', NULL, 52, 'system:languagePointsInfo:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (78, '知识点列表', NULL, 52, 'system:languagePointsInfo:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (79, '知识点修改', NULL, 52, 'system:languagePointsInfo:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (80, '删除知识点', NULL, 52, 'system:languagePointsInfo:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (81, '考试管理', NULL, 0, NULL, 'exam', NULL, NULL, 1, 1, 1);
+INSERT INTO `system_menu` VALUES (82, '试题管理', '/question', 81, NULL, 'question', NULL, '2021-08-31 21:30:25', 0, 2, 1);
+INSERT INTO `system_menu` VALUES (83, '列表', NULL, 82, 'system:question:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (84, '添加', NULL, 82, 'system:question:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (85, '修改', NULL, 82, 'system:question:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (86, '删除', NULL, 82, 'system:question:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (87, '试卷管理', '/testPaper', 81, NULL, 'testPaper', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (88, '列表', NULL, 87, 'system:testPaperInfo:list', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (89, '添加', NULL, 87, 'system:testPaperInfo:save', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (90, '修改', NULL, 87, 'system:testPaperInfo:update', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (91, '删除', NULL, 87, 'system:testPaperInfo:deleteById', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (92, '统计分析', NULL, 0, NULL, 'statistics', NULL, '2020-12-09 17:00:30', 2, 1, 1);
+INSERT INTO `system_menu` VALUES (93, '考试统计', '/examReport', 92, NULL, 'statistics-exam', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (94, '列表', NULL, 93, 'system:exam:examReportList', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (95, '试题管理', '', 87, 'system:testPaperInfo:relevanceQuestion', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (96, '发布', NULL, 87, 'system:testPaperInfo:publish', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (97, '撤回', NULL, 87, 'system:testPaperInfo:cancel', NULL, NULL, NULL, 0, 3, 1);
+INSERT INTO `system_menu` VALUES (98, '试题导入', '/questionImport', 81, NULL, 'importQuestion', NULL, NULL, 0, 2, 1);
+INSERT INTO `system_menu` VALUES (99, '测试菜单222', '', 8, '', '', '2021-10-02 13:35:24', NULL, 0, 3, 2);
+
+
+

+ 15 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.4_system_dict.sql

@@ -0,0 +1,15 @@
+DROP TABLE IF EXISTS `system_dict`;
+CREATE TABLE `system_dict`  (
+    `id` int(11) NOT NULL AUTO_INCREMENT,
+    `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `create_date` datetime(0) NULL DEFAULT NULL,
+    `update_date` datetime(0) NULL DEFAULT NULL,
+    `sort` int(11) NOT NULL DEFAULT 0,
+    `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典类型表' ROW_FORMAT = Dynamic;
+
+INSERT INTO `system_dict` VALUES (1, '阶段类型', 'school_type', '2020-05-21 15:50:43', '2021-09-14 10:31:29', 1, NULL);
+INSERT INTO `system_dict` VALUES (2, '年级类型', 'grade_type', '2020-05-21 15:51:03', '2020-05-21 15:51:04', 0, NULL);
+INSERT INTO `system_dict` VALUES (3, '试题类型', 'question_type', '2020-04-30 14:06:13', '2020-05-06 14:34:34', 0, NULL);

+ 12 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.5_system_role.sql

@@ -0,0 +1,12 @@
+DROP TABLE IF EXISTS `system_role`;
+CREATE TABLE `system_role`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统角色表' ROW_FORMAT = Dynamic;
+
+
+INSERT INTO `system_role` VALUES (1, '超级管理员', '2019-04-02 14:17:41', 'ces ', NULL);

+ 7 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.6_system_role_menu.sql

@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS `system_role_menu`;
+CREATE TABLE `system_role_menu`  (
+  `menu_id` int(11) NOT NULL,
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `role_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色菜单表' ROW_FORMAT = Dynamic;

+ 171 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.7_system_qrtz.sql

@@ -0,0 +1,171 @@
+DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
+DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
+DROP TABLE IF EXISTS QRTZ_LOCKS;
+DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_TRIGGERS;
+DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
+DROP TABLE IF EXISTS QRTZ_CALENDARS;
+
+CREATE TABLE QRTZ_JOB_DETAILS(
+SCHED_NAME VARCHAR(120) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+JOB_CLASS_NAME VARCHAR(250) NOT NULL,
+IS_DURABLE VARCHAR(1) NOT NULL,
+IS_NONCONCURRENT VARCHAR(1) NOT NULL,
+IS_UPDATE_DATA VARCHAR(1) NOT NULL,
+REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+JOB_NAME VARCHAR(200) NOT NULL,
+JOB_GROUP VARCHAR(200) NOT NULL,
+DESCRIPTION VARCHAR(250) NULL,
+NEXT_FIRE_TIME BIGINT(13) NULL,
+PREV_FIRE_TIME BIGINT(13) NULL,
+PRIORITY INTEGER NULL,
+TRIGGER_STATE VARCHAR(16) NOT NULL,
+TRIGGER_TYPE VARCHAR(8) NOT NULL,
+START_TIME BIGINT(13) NOT NULL,
+END_TIME BIGINT(13) NULL,
+CALENDAR_NAME VARCHAR(200) NULL,
+MISFIRE_INSTR SMALLINT(2) NULL,
+JOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
+REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+REPEAT_COUNT BIGINT(7) NOT NULL,
+REPEAT_INTERVAL BIGINT(12) NOT NULL,
+TIMES_TRIGGERED BIGINT(10) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_CRON_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+CRON_EXPRESSION VARCHAR(120) NOT NULL,
+TIME_ZONE_ID VARCHAR(80),
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_SIMPROP_TRIGGERS
+  (
+    SCHED_NAME VARCHAR(120) NOT NULL,
+    TRIGGER_NAME VARCHAR(200) NOT NULL,
+    TRIGGER_GROUP VARCHAR(200) NOT NULL,
+    STR_PROP_1 VARCHAR(512) NULL,
+    STR_PROP_2 VARCHAR(512) NULL,
+    STR_PROP_3 VARCHAR(512) NULL,
+    INT_PROP_1 INT NULL,
+    INT_PROP_2 INT NULL,
+    LONG_PROP_1 BIGINT NULL,
+    LONG_PROP_2 BIGINT NULL,
+    DEC_PROP_1 NUMERIC(13,4) NULL,
+    DEC_PROP_2 NUMERIC(13,4) NULL,
+    BOOL_PROP_1 VARCHAR(1) NULL,
+    BOOL_PROP_2 VARCHAR(1) NULL,
+    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_BLOB_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+BLOB_DATA BLOB NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
+INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
+FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
+REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_CALENDARS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+CALENDAR_NAME VARCHAR(200) NOT NULL,
+CALENDAR BLOB NOT NULL,
+PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_FIRED_TRIGGERS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+ENTRY_ID VARCHAR(95) NOT NULL,
+TRIGGER_NAME VARCHAR(200) NOT NULL,
+TRIGGER_GROUP VARCHAR(200) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+FIRED_TIME BIGINT(13) NOT NULL,
+SCHED_TIME BIGINT(13) NOT NULL,
+PRIORITY INTEGER NOT NULL,
+STATE VARCHAR(16) NOT NULL,
+JOB_NAME VARCHAR(200) NULL,
+JOB_GROUP VARCHAR(200) NULL,
+IS_NONCONCURRENT VARCHAR(1) NULL,
+REQUESTS_RECOVERY VARCHAR(1) NULL,
+PRIMARY KEY (SCHED_NAME,ENTRY_ID))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_SCHEDULER_STATE (
+SCHED_NAME VARCHAR(120) NOT NULL,
+INSTANCE_NAME VARCHAR(200) NOT NULL,
+LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
+CHECKIN_INTERVAL BIGINT(13) NOT NULL,
+PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
+ENGINE=InnoDB;
+
+CREATE TABLE QRTZ_LOCKS (
+SCHED_NAME VARCHAR(120) NOT NULL,
+LOCK_NAME VARCHAR(40) NOT NULL,
+PRIMARY KEY (SCHED_NAME,LOCK_NAME))
+ENGINE=InnoDB;
+
+CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
+
+CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
+CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
+CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
+
+CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
+CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
+CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
+CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
+CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
+
+commit;

+ 17 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.8_system_log.sql

@@ -0,0 +1,17 @@
+DROP TABLE IF EXISTS `system_log`;
+CREATE TABLE `system_log`  (
+   `id` int(11) NOT NULL AUTO_INCREMENT,
+   `request_url` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+   `method` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+   `request_time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+   `create_date` datetime(0) NULL DEFAULT NULL,
+   `user_id` int(11) NULL DEFAULT NULL,
+   `params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,
+   `ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+   `exception` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,
+   `platform_type` tinyint(2) NULL DEFAULT NULL,
+   `operation_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+   `operation_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+   `update_date` datetime(0) NULL DEFAULT NULL,
+   PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统日志表' ROW_FORMAT = Dynamic;

+ 7 - 0
education-api/src/main/resources/db/1.0.1/V1.0.1.9_system_admin_role.sql

@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS `system_admin_role`;
+CREATE TABLE `system_admin_role`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `admin_id` int(11) NOT NULL,
+  `role_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '管理员角色表' ROW_FORMAT = Dynamic;

+ 20 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.10_school_info.sql

@@ -0,0 +1,20 @@
+DROP TABLE IF EXISTS `school_info`;
+CREATE TABLE `school_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学校名称',
+  `simplicity` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学校简称',
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `mobile` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '联系方式',
+  `principal_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `school_type` int(11) NOT NULL,
+  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `lng` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `lat` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `province_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `city_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `county_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `town_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `account_number` int(4) NULL DEFAULT 0,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '学校信息表' ROW_FORMAT = Dynamic;

+ 10 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.11_student_course_collect.sql

@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS `student_course_collect`;
+CREATE TABLE `student_course_collect`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `course_id` int(11) NOT NULL,
+  `student_id` int(11) NOT NULL,
+  `create_date` datetime(0) NOT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4
+COLLATE = utf8mb4_general_ci COMMENT = '学员课程收藏表' ROW_FORMAT = Dynamic;

+ 28 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.12_student_info.sql

@@ -0,0 +1,28 @@
+DROP TABLE IF EXISTS `student_info`;
+CREATE TABLE `student_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `login_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `age` int(11) NOT NULL,
+  `sex` tinyint(2) NOT NULL,
+  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `mobile` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `mother_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '母亲姓名',
+  `father_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `head_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像',
+  `grade_info_id` int(11) NULL DEFAULT NULL,
+  `delete_flag` int(1) NOT NULL DEFAULT 0 COMMENT '删除标记',
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `encrypt` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `disabled_flag` tinyint(1) NOT NULL DEFAULT 0,
+  `login_count` int(11) NOT NULL DEFAULT 0,
+  `last_login_time` datetime(0) NULL DEFAULT NULL,
+  `login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `birthday` date NULL DEFAULT NULL COMMENT '生日',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '学员信息表' ROW_FORMAT = Dynamic;
+
+
+INSERT INTO `student_info` VALUES (89, 'student', '演示账号', 1, 1, 'sdsd', '18296640717', 'dsd', 'dsd', NULL, '2021-07-11 17:08:56', '/images/2020/12/27d1c635bb182f428e8ba159b4d13212e9.jpg', 1, 0, '94a0cf41db339d8248ee3da1c232d326', 'af2244dbc451f1007a7ba8408e45b16f2939bdc3', 0, 438, '2021-07-11 17:08:56', '127.0.0.1', NULL);

+ 15 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.13_student_question_answer.sql

@@ -0,0 +1,15 @@
+DROP TABLE IF EXISTS `student_question_answer`;
+CREATE TABLE `student_question_answer`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `student_id` int(11) NOT NULL COMMENT '学员id',
+  `question_info_id` int(11) NOT NULL COMMENT '试题id',
+  `student_answer` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学员答案',
+  `create_date` datetime(0) NOT NULL COMMENT '创建时间',
+  `update_date` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
+  `mark` int(11) NOT NULL DEFAULT 0 COMMENT '答题得分',
+  `comment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '评语',
+  `question_points` int(11) NOT NULL DEFAULT 0 COMMENT '试题分数',
+  `correct_status` tinyint(2) NOT NULL DEFAULT 0 COMMENT '批改状态 0 错误 1 正确 2 待批改 3.已批改(针对主观题)',
+  `exam_info_id` int(11) NOT NULL COMMENT '考试记录id',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '考生答题记录表' ROW_FORMAT = Dynamic;

+ 14 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.14_student_wrong_book.sql

@@ -0,0 +1,14 @@
+DROP TABLE IF EXISTS `student_wrong_book`;
+CREATE TABLE `student_wrong_book`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `student_id` int(11) NOT NULL COMMENT '学员id',
+  `question_info_id` int(11) NOT NULL COMMENT '试题id',
+  `create_date` datetime(0) NOT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `question_mark` int(4) NOT NULL DEFAULT 0 COMMENT '试题分数',
+  `student_answer` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学员答案',
+  `mark` int(2) NOT NULL DEFAULT 0 COMMENT '试题得分',
+  `correct_status` tinyint(2) NOT NULL DEFAULT 0 COMMENT '批改状态 0 错误 1 正确 2 待批改 3.已批改(针对主观题)',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `student_id`(`student_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '学员错题本信息表' ROW_FORMAT = Dynamic;

+ 14 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.15_study_history.sql

@@ -0,0 +1,14 @@
+DROP TABLE IF EXISTS `study_history`;
+CREATE TABLE `study_history`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `subject_id` int(11) NOT NULL,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update` datetime(0) NULL DEFAULT NULL,
+  `student_id` int(11) NULL DEFAULT NULL,
+  `study_time` int(11) NULL DEFAULT 0 COMMENT '学习时间(单位秒)',
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `course_id` int(11) NULL DEFAULT NULL,
+  `start_date` datetime(0) NULL DEFAULT NULL,
+  `end_date` datetime(0) NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci  COMMENT = '学习记录表' ROW_FORMAT = Dynamic;

+ 10 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.16_subject_info.sql

@@ -0,0 +1,10 @@
+DROP TABLE IF EXISTS `subject_info`;
+CREATE TABLE `subject_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `school_type` tinyint(2) NOT NULL DEFAULT 1 COMMENT '阶段(1 小学 2. 初中 3. 高中)',
+  `grade_info_id` int(11) NOT NULL COMMENT '所属年级id',
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '科目表' ROW_FORMAT = Dynamic;

+ 20 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.17_test_paper_info.sql

@@ -0,0 +1,20 @@
+DROP TABLE IF EXISTS `test_paper_info`;
+CREATE TABLE `test_paper_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '试卷名称',
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
+  `mark` int(11) NOT NULL DEFAULT 0 COMMENT '试卷总分',
+  `school_type` int(11) NOT NULL COMMENT '学校类型',
+  `grade_info_id` int(11) NOT NULL COMMENT '年级id',
+  `subject_id` int(11) NOT NULL COMMENT '所属科目id',
+  `sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
+  `exam_time` int(11) NOT NULL COMMENT '考试时间',
+  `exam_number` int(4) NOT NULL DEFAULT 0 COMMENT '考试人数',
+  `correct_number` int(4) NULL DEFAULT 0 COMMENT '已批改试卷数量',
+  `publish_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否发布',
+  `publish_time` datetime(0) NULL DEFAULT NULL COMMENT '发布时间',
+  `question_number` int(11) NOT NULL DEFAULT 0 COMMENT '试题数量',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '试卷信息表' ROW_FORMAT = Dynamic;

+ 15 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.18_test_paper_info_setting.sql

@@ -0,0 +1,15 @@
+DROP TABLE IF EXISTS `test_paper_info_setting`;
+CREATE TABLE `test_paper_info_setting`  (
+  `id` int(11) NOT NULL,
+  `test_paper_info_id` int(11) NOT NULL COMMENT '所属试卷id',
+  `commit_after_type` tinyint(2) NOT NULL COMMENT '提交后是否立即出分\r\n1. 批改后出分\r\n2. 立即显示分数',
+  `show_mark_sort` tinyint(1) NOT NULL COMMENT '是否显示成绩排名榜',
+  `show_student_sort` tinyint(2) NOT NULL COMMENT '是否显示学员成绩排名',
+  `create_date` datetime(0) NOT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `reference_number` int(4) NOT NULL DEFAULT 1 COMMENT '参考次数',
+  `start_time` datetime(0) NULL DEFAULT NULL COMMENT '开始时间',
+  `end_time` datetime(0) NULL DEFAULT NULL COMMENT '结束时间',
+  `exam_type` tinyint(2) NOT NULL DEFAULT 2 COMMENT '1.指定时间段 2. 永久有效',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '试卷设置表' ROW_FORMAT = Dynamic;

+ 11 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.19_test_paper_question_info.sql

@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `test_paper_question_info`;
+CREATE TABLE `test_paper_question_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `question_info_id` int(11) NOT NULL,
+  `test_paper_info_id` int(11) NOT NULL,
+  `mark` int(11) NOT NULL DEFAULT 0,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `sort` int(4) NOT NULL DEFAULT 0 COMMENT '排序',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '试卷试题关联表' ROW_FORMAT = Dynamic;

+ 11 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.1_message_info.sql

@@ -0,0 +1,11 @@
+DROP TABLE IF EXISTS `message_info`;
+CREATE TABLE `message_info`  (
+     `id` int(11) NOT NULL AUTO_INCREMENT,
+     `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+     `student_id` int(11) NOT NULL COMMENT '学员id',
+     `create_date` datetime(0) NOT NULL,
+     `update_date` datetime(0) NULL DEFAULT NULL,
+     `read_flag` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否已读',
+     `message_type` tinyint(2) NOT NULL DEFAULT 1 COMMENT '消息类型(1 试卷批改通知)',
+     PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

+ 13 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.2_grade_info.sql

@@ -0,0 +1,13 @@
+DROP TABLE IF EXISTS `grade_info`;
+CREATE TABLE `grade_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `school_type` tinyint(2) NOT NULL COMMENT '所属阶段',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '年级信息表' ROW_FORMAT = Dynamic;
+
+
+INSERT INTO `grade_info` VALUES (1, '一年级', '2020-11-29 14:50:11', NULL, 1);
+INSERT INTO `grade_info` VALUES (2, '三年级', '2020-11-29 14:51:44', '2020-11-29 14:52:11', 1);

+ 21 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.3_course_info.sql

@@ -0,0 +1,21 @@
+DROP TABLE IF EXISTS `course_info`;
+CREATE TABLE `course_info`  (
+    `id` int(11) NOT NULL AUTO_INCREMENT,
+    `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `grade_info_id` int(2) NOT NULL,
+    `school_type` int(2) NOT NULL,
+    `subject_id` int(11) NOT NULL,
+    `create_date` datetime(0) NULL DEFAULT NULL,
+    `update_date` datetime(0) NULL DEFAULT NULL,
+    `code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程编号',
+    `sort` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '排序',
+    `parent_id` int(11) NULL DEFAULT 0,
+    `head_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `represent` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程简介',
+    `recommend_index_flag` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否推荐到系统首页',
+    `study_number` int(11) NOT NULL DEFAULT 0,
+    `status` tinyint(2) NULL DEFAULT 1 COMMENT '状态 (0 下架 1 草稿 2. 已上架)',
+    `valuate_mark` decimal(4, 2) NOT NULL DEFAULT 10.00 COMMENT '评价分数',
+    `comment_number` int(4) NOT NULL DEFAULT 0 COMMENT '评论数量',
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '课程信息表' ROW_FORMAT = Dynamic;

+ 9 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.4_course_question_info.sql

@@ -0,0 +1,9 @@
+DROP TABLE IF EXISTS `course_question_info`;
+CREATE TABLE `course_question_info`  (
+  `sort` int(11) NOT NULL DEFAULT 0,
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `question_info_id` int(11) NOT NULL,
+  `course_id` int(11) NOT NULL,
+  `mark` int(11) NOT NULL DEFAULT 0,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '课程试题关联表' ROW_FORMAT = Dynamic;

+ 22 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.5_exam_info.sql

@@ -0,0 +1,22 @@
+DROP TABLE IF EXISTS `exam_info`;
+CREATE TABLE `exam_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `student_id` int(11) NOT NULL,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `mark` int(11) NOT NULL DEFAULT 0 COMMENT '总得分',
+  `test_paper_info_id` int(11) NOT NULL,
+  `correct_flag` tinyint(2) NOT NULL DEFAULT 0 COMMENT '1 已批改 0.待批改',
+  `system_mark` int(2) NOT NULL DEFAULT 0 COMMENT '系统判分',
+  `teacher_mark` int(2) NOT NULL DEFAULT 0 COMMENT '老师评分',
+  `exam_time` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '考试耗时(字符串存储)',
+  `correct_type` tinyint(2) NULL DEFAULT NULL COMMENT '批改形式(1 系统 2 .教师 3 系统 + 教师)',
+  `admin_id` int(11) NOT NULL DEFAULT 0 COMMENT '批改人',
+  `right_number` int(11) NOT NULL COMMENT '客观题答对题数',
+  `error_number` int(11) NOT NULL DEFAULT 0 COMMENT '客观题答错题数(包括主观题未作答数量)',
+  `subjective_question_number` int(11) NOT NULL DEFAULT 0 COMMENT '主观题数量',
+  `question_number` int(11) NULL DEFAULT NULL COMMENT '试题数量',
+  `exam_time_long_value` int(11) NOT NULL DEFAULT 0 COMMENT '考试时间(整数存储)',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `student_id`(`student_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '考试信息表' ROW_FORMAT = Dynamic;

+ 13 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.6_language_points_info.sql

@@ -0,0 +1,13 @@
+DROP TABLE IF EXISTS `language_points_info`;
+CREATE TABLE `language_points_info`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `grade_info_id` int(11) NOT NULL,
+  `subject_id` int(11) NOT NULL,
+  `parent_id` int(11) NOT NULL DEFAULT 0,
+  `create_date` datetime(0) NULL DEFAULT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `hasChildren` tinyint(1) NOT NULL DEFAULT 0,
+  `sort` int(11) NOT NULL DEFAULT 0,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '知识点信息表' ROW_FORMAT = Dynamic;

+ 16 - 0
education-api/src/main/resources/db/1.0.2/V1.0.2.7_message_log.sql

@@ -0,0 +1,16 @@
+DROP TABLE IF EXISTS `message_log`;
+CREATE TABLE `message_log`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '1.消息发送中 2.消息发送成功3.已消费4.消费失败5.消息发送失败',
+  `try_count` tinyint(2) NOT NULL DEFAULT 0 COMMENT '消息重发次数',
+  `create_date` datetime(0) NOT NULL,
+  `update_date` datetime(0) NULL DEFAULT NULL,
+  `content` json NULL COMMENT '消息内容',
+  `correlation_data_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `fail_send_cause` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '发送失败原因',
+  `consume_cause` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消费失败原因',
+  `exchange` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `routing_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+  `message_type` tinyint(2) NULL DEFAULT NULL COMMENT '消息类型(1 考试提交消息)',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '队列消息发送日志表' ROW_FORMAT = Dynamic;

Някои файлове не бяха показани, защото твърде много файлове са промени