zhangyu vor 1 Woche
Commit
ae854ac97e
63 geänderte Dateien mit 4096 neuen und 0 gelöschten Zeilen
  1. 188 0
      BigGoose.iml
  2. 21 0
      README.md
  3. 124 0
      pom.xml
  4. 17 0
      src/main/java/com/futu/goose/BigGooseApplication.java
  5. 18 0
      src/main/java/com/futu/goose/config/CorsConfig.java
  6. 58 0
      src/main/java/com/futu/goose/config/RedisConfig.java
  7. 28 0
      src/main/java/com/futu/goose/course/controller/CourseController.java
  8. 20 0
      src/main/java/com/futu/goose/course/mapper/CourseCategoryMapper.java
  9. 20 0
      src/main/java/com/futu/goose/course/mapper/CourseChapterMapper.java
  10. 20 0
      src/main/java/com/futu/goose/course/mapper/CourseLessonMapper.java
  11. 20 0
      src/main/java/com/futu/goose/course/mapper/CourseMapper.java
  12. 20 0
      src/main/java/com/futu/goose/course/mapper/TeacherMapper.java
  13. 174 0
      src/main/java/com/futu/goose/course/pojo/Course.java
  14. 101 0
      src/main/java/com/futu/goose/course/pojo/CourseCategory.java
  15. 101 0
      src/main/java/com/futu/goose/course/pojo/CourseChapter.java
  16. 125 0
      src/main/java/com/futu/goose/course/pojo/CourseLesson.java
  17. 109 0
      src/main/java/com/futu/goose/course/pojo/Teacher.java
  18. 13 0
      src/main/java/com/futu/goose/course/service/CourseCategoryService.java
  19. 13 0
      src/main/java/com/futu/goose/course/service/CourseChapterService.java
  20. 13 0
      src/main/java/com/futu/goose/course/service/CourseLessonService.java
  21. 19 0
      src/main/java/com/futu/goose/course/service/CourseService.java
  22. 13 0
      src/main/java/com/futu/goose/course/service/TeacherService.java
  23. 22 0
      src/main/java/com/futu/goose/course/service/impl/CourseCategoryServiceImpl.java
  24. 22 0
      src/main/java/com/futu/goose/course/service/impl/CourseChapterServiceImpl.java
  25. 22 0
      src/main/java/com/futu/goose/course/service/impl/CourseLessonServiceImpl.java
  26. 40 0
      src/main/java/com/futu/goose/course/service/impl/CourseServiceImpl.java
  27. 22 0
      src/main/java/com/futu/goose/course/service/impl/TeacherServiceImpl.java
  28. 40 0
      src/main/java/com/futu/goose/dto/CourseCreationDTO.java
  29. 26 0
      src/main/java/com/futu/goose/user/controller/MinioController.java
  30. 34 0
      src/main/java/com/futu/goose/user/controller/UserController.java
  31. 30 0
      src/main/java/com/futu/goose/user/controller/ValidateCode.java
  32. 20 0
      src/main/java/com/futu/goose/user/mapper/TUserMapper.java
  33. 20 0
      src/main/java/com/futu/goose/user/mapper/WechatUsersMapper.java
  34. 20 0
      src/main/java/com/futu/goose/user/mapper/WxUsersMapper.java
  35. 402 0
      src/main/java/com/futu/goose/user/pojo/TUser.java
  36. 425 0
      src/main/java/com/futu/goose/user/pojo/WechatUsers.java
  37. 315 0
      src/main/java/com/futu/goose/user/pojo/WxUsers.java
  38. 19 0
      src/main/java/com/futu/goose/user/service/TUserService.java
  39. 5 0
      src/main/java/com/futu/goose/user/service/ValidateCodeService.java
  40. 13 0
      src/main/java/com/futu/goose/user/service/WechatUsersService.java
  41. 13 0
      src/main/java/com/futu/goose/user/service/WxUsersService.java
  42. 137 0
      src/main/java/com/futu/goose/user/service/impl/TUserServiceImpl.java
  43. 22 0
      src/main/java/com/futu/goose/user/service/impl/ValidateCodeServiceImpl.java
  44. 22 0
      src/main/java/com/futu/goose/user/service/impl/WechatUsersServiceImpl.java
  45. 22 0
      src/main/java/com/futu/goose/user/service/impl/WxUsersServiceImpl.java
  46. 45 0
      src/main/java/com/futu/goose/utils/AppHttpCodeEnum.java
  47. 119 0
      src/main/java/com/futu/goose/utils/AppJwtUtil.java
  48. 116 0
      src/main/java/com/futu/goose/utils/EsSyncUtils.java
  49. 93 0
      src/main/java/com/futu/goose/utils/MinioUtils.java
  50. 288 0
      src/main/java/com/futu/goose/utils/RedisClient.java
  51. 163 0
      src/main/java/com/futu/goose/utils/ResponseResult.java
  52. 44 0
      src/main/java/com/futu/goose/utils/Result.java
  53. 29 0
      src/main/resources/application.yml
  54. 20 0
      src/main/resources/mapper/CourseCategoryMapper.xml
  55. 20 0
      src/main/resources/mapper/CourseChapterMapper.xml
  56. 24 0
      src/main/resources/mapper/CourseLessonMapper.xml
  57. 32 0
      src/main/resources/mapper/CourseMapper.xml
  58. 32 0
      src/main/resources/mapper/TUserMapper.xml
  59. 22 0
      src/main/resources/mapper/TeacherMapper.xml
  60. 35 0
      src/main/resources/mapper/WechatUsersMapper.xml
  61. 28 0
      src/main/resources/mapper/WxUsersMapper.xml
  62. 38 0
      src/test/java/com/futu/goose/AppTest.java
  63. BIN
      项目模块.png

+ 188 - 0
BigGoose.iml

@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="web" name="Web">
+      <configuration>
+        <webroots />
+        <sourceRoots />
+      </configuration>
+    </facet>
+    <facet type="Spring" name="Spring">
+      <configuration />
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-test:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.13.3" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.30" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
+    <orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.26" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-test:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
+    <orderEntry type="library" name="Maven: net.minidev:json-smart:2.3" level="project" />
+    <orderEntry type="library" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
+    <orderEntry type="library" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.assertj:assertj-core:3.16.1" level="project" />
+    <orderEntry type="library" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.junit.jupiter:junit-jupiter:5.6.2" level="project" />
+    <orderEntry type="library" name="Maven: org.junit.jupiter:junit-jupiter-api:5.6.2" level="project" />
+    <orderEntry type="library" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.junit.platform:junit-platform-commons:1.6.2" level="project" />
+    <orderEntry type="library" name="Maven: org.junit.jupiter:junit-jupiter-params:5.6.2" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.6.2" level="project" />
+    <orderEntry type="library" name="Maven: org.junit.vintage:junit-vintage-engine:5.6.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
+    <orderEntry type="library" name="Maven: org.junit.platform:junit-platform-engine:1.6.2" level="project" />
+    <orderEntry type="library" name="Maven: junit:junit:4.13" level="project" />
+    <orderEntry type="library" name="Maven: org.mockito:mockito-core:3.3.3" level="project" />
+    <orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.10.13" level="project" />
+    <orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.13" level="project" />
+    <orderEntry type="library" name="Maven: org.objenesis:objenesis:2.6" level="project" />
+    <orderEntry type="library" name="Maven: org.mockito:mockito-junit-jupiter:3.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
+    <orderEntry type="library" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-test:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.xmlunit:xmlunit-core:2.7.0" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.37" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.37" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.21" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.1" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.1" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.1" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.1" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.1" level="project" />
+    <orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:3.2" level="project" />
+    <orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.6" level="project" />
+    <orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.5" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.30" level="project" />
+    <orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.8.16" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.glassfish:jakarta.el:3.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.1.5.Final" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba:druid:1.1.23" level="project" />
+    <orderEntry type="library" name="Maven: io.minio:minio:7.1.0" level="project" />
+    <orderEntry type="library" name="Maven: com.carrotsearch.thirdparty:simple-xml-safe:2.7.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:guava:25.1-jre" level="project" />
+    <orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.0.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.1.3" level="project" />
+    <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.14.9" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.okio:okio:1.17.2" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.github.spotbugs:spotbugs-annotations:4.0.0" level="project" />
+    <orderEntry type="library" name="Maven: net.jcip:jcip-annotations:1.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
+    <orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.lettuce:lettuce-core:5.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-common:4.1.51.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.51.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.51.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.51.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.51.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.51.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.3.8.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.client:elasticsearch-rest-high-level-client:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.plugin:mapper-extras:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.plugin:parent-join-client:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.plugin:aggs-matrix-stats-client:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.plugin:rank-eval-client:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.plugin:lang-mustache-client:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: com.github.spullara.mustache.java:compiler:0.9.3" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch.client:elasticsearch-rest-client:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.12" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.13" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpasyncclient:4.1.4" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore-nio:4.4.13" level="project" />
+    <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.14" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:elasticsearch:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:elasticsearch-core:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:elasticsearch-secure-sm:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:elasticsearch-x-content:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:elasticsearch-geo:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-core:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-analyzers-common:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-backward-codecs:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-grouping:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-highlighter:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-join:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-memory:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-misc:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-queries:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-queryparser:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-sandbox:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-spatial:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-spatial-extras:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-spatial3d:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.lucene:lucene-suggest:8.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:elasticsearch-cli:7.4.0" level="project" />
+    <orderEntry type="library" name="Maven: net.sf.jopt-simple:jopt-simple:5.0.2" level="project" />
+    <orderEntry type="library" name="Maven: com.carrotsearch:hppc:0.8.1" level="project" />
+    <orderEntry type="library" name="Maven: joda-time:joda-time:2.10.3" level="project" />
+    <orderEntry type="library" name="Maven: com.tdunning:t-digest:3.2" level="project" />
+    <orderEntry type="library" name="Maven: org.hdrhistogram:HdrHistogram:2.1.9" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.13.3" level="project" />
+    <orderEntry type="library" name="Maven: org.elasticsearch:jna:4.5.1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-mongodb:2.3.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:4.0.5" level="project" />
+    <orderEntry type="library" name="Maven: org.mongodb:bson:4.0.5" level="project" />
+    <orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:4.0.5" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-mongodb:3.0.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.3.2.RELEASE" level="project" />
+  </component>
+</module>

+ 21 - 0
README.md

@@ -0,0 +1,21 @@
+用户模块:user
+
+店铺模块:store
+
+课程模块:course
+
+订单模块:order
+
+老师模块:teacher
+
+消息模块:message
+
+支付模块:pay
+
+优惠券模块:discounts
+
+系统设置模块:system
+
+![项目模块](D:\2407\xiangmu\BigGoose\项目模块.png)
+
+服务器IP:47.111.97.7

+ 124 - 0
pom.xml

@@ -0,0 +1,124 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>com.futu.goose</groupId>
+  <artifactId>BigGoose</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>BigGoose</name>
+  <url>http://maven.apache.org</url>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <parent>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-parent</artifactId>
+    <version>2.3.2.RELEASE</version>
+    <!--  使用合适的版本  -->
+  </parent>
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <version>2.3.2.RELEASE</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+      <version>2.3.2.RELEASE</version>
+    </dependency>
+    <!--     mysql -->
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+      <version>8.0.33</version>
+    </dependency>
+    <!--     mybatis-plus -->
+    <dependency>
+      <groupId>com.baomidou</groupId>
+      <artifactId>mybatis-plus-boot-starter</artifactId>
+      <version>3.5.4</version>
+    </dependency>
+    <!--     lombok -->
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <version>1.18.30</version>
+    </dependency>
+    <dependency>
+      <groupId>cn.hutool</groupId>
+      <artifactId>hutool-all</artifactId>
+      <version>5.8.16</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-validation</artifactId>
+      <version>2.3.2.RELEASE</version>
+    </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>druid</artifactId>
+      <version>1.1.23</version>
+    </dependency>
+    <dependency>
+      <groupId>com.baomidou</groupId>
+      <artifactId>mybatis-plus-boot-starter</artifactId>
+      <version>3.4.1</version>
+    </dependency>
+    <dependency>
+      <groupId>io.minio</groupId>
+      <artifactId>minio</artifactId>
+      <version>7.1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>io.jsonwebtoken</groupId>
+      <artifactId>jjwt</artifactId>
+      <version>0.9.1</version>
+    </dependency>
+<!--    Redis-->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-data-redis</artifactId>
+    </dependency>
+    <!--elasticsearch-->
+    <dependency>
+      <groupId>org.elasticsearch.client</groupId>
+      <artifactId>elasticsearch-rest-high-level-client</artifactId>
+      <version>7.4.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.elasticsearch.client</groupId>
+      <artifactId>elasticsearch-rest-client</artifactId>
+      <version>7.4.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.elasticsearch</groupId>
+      <artifactId>elasticsearch</artifactId>
+      <version>7.4.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-data-mongodb</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>8</source>
+          <target>8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

+ 17 - 0
src/main/java/com/futu/goose/BigGooseApplication.java

@@ -0,0 +1,17 @@
+package com.futu.goose;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Hello world!
+ *
+ */
+@SpringBootApplication
+public class BigGooseApplication
+{
+    public static void main( String[] args )
+    {
+        SpringApplication.run(BigGooseApplication.class,args);
+    }
+}

+ 18 - 0
src/main/java/com/futu/goose/config/CorsConfig.java

@@ -0,0 +1,18 @@
+package com.futu.goose.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class CorsConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+            .allowedOrigins("*")
+            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+            .maxAge(3600);
+    }
+
+}

+ 58 - 0
src/main/java/com/futu/goose/config/RedisConfig.java

@@ -0,0 +1,58 @@
+package com.futu.goose.config;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import org.springframework.stereotype.Component;
+
+import java.text.SimpleDateFormat;
+
+@Component
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(connectionFactory);
+
+        // Key/HashKey 使用字符串序列化
+        StringRedisSerializer stringSerializer = new StringRedisSerializer();
+        redisTemplate.setKeySerializer(stringSerializer);
+        redisTemplate.setHashKeySerializer(stringSerializer);
+
+        // Value/HashValue 使用 JSON 序列化(带类型信息)
+        GenericJackson2JsonRedisSerializer jsonSerializer = createJsonSerializer();
+        redisTemplate.setValueSerializer(jsonSerializer);
+        redisTemplate.setHashValueSerializer(jsonSerializer);
+
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+    /**
+     * 创建支持类型信息的 JSON 序列化器
+     */
+    private GenericJackson2JsonRedisSerializer createJsonSerializer() {
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        // 启用默认类型信息(解决嵌套对象反序列化问题)
+        objectMapper.activateDefaultTyping(
+                objectMapper.getPolymorphicTypeValidator(),
+                ObjectMapper.DefaultTyping.NON_FINAL,
+                JsonTypeInfo.As.PROPERTY
+        );
+
+        // 配置日期格式(根据实际需求调整)
+        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+        objectMapper.registerModule(new JavaTimeModule());
+        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+        return new GenericJackson2JsonRedisSerializer(objectMapper);
+    }
+}

+ 28 - 0
src/main/java/com/futu/goose/course/controller/CourseController.java

@@ -0,0 +1,28 @@
+package com.futu.goose.course.controller;
+
+import afu.org.checkerframework.checker.igj.qual.I;
+import com.futu.goose.course.pojo.Course;
+import com.futu.goose.course.service.CourseService;
+import com.futu.goose.utils.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/course")
+public class CourseController {
+    @Autowired
+    private CourseService courseService;
+    @RequestMapping("/listcourse")
+    public Result listcourse() {
+      List<Course> courseList= courseService.listcourse();
+        return new Result(true, "查询成功", courseList);
+    }
+    @RequestMapping("selectes")
+    public Result selectes(@RequestParam("title") String title) {
+        return courseService.selectes(title);
+    }
+}

+ 20 - 0
src/main/java/com/futu/goose/course/mapper/CourseCategoryMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.course.mapper;
+
+import com.futu.goose.course.pojo.CourseCategory;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【course_category(课程分类表)】的数据库操作Mapper
+* @createDate 2025-05-11 20:03:09
+* @Entity com.futu.goose.course.pojo.CourseCategory
+*/
+@Mapper
+public interface CourseCategoryMapper extends BaseMapper<CourseCategory> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/futu/goose/course/mapper/CourseChapterMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.course.mapper;
+
+import com.futu.goose.course.pojo.CourseChapter;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【course_chapter(课程章节表)】的数据库操作Mapper
+* @createDate 2025-05-11 20:03:09
+* @Entity com.futu.goose.course.pojo.CourseChapter
+*/
+@Mapper
+public interface CourseChapterMapper extends BaseMapper<CourseChapter> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/futu/goose/course/mapper/CourseLessonMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.course.mapper;
+
+import com.futu.goose.course.pojo.CourseLesson;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【course_lesson(课程课时表)】的数据库操作Mapper
+* @createDate 2025-05-11 20:03:09
+* @Entity com.futu.goose.course.pojo.CourseLesson
+*/
+@Mapper
+public interface CourseLessonMapper extends BaseMapper<CourseLesson> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/futu/goose/course/mapper/CourseMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.course.mapper;
+
+import com.futu.goose.course.pojo.Course;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【course(课程表)】的数据库操作Mapper
+* @createDate 2025-05-11 20:03:09
+* @Entity com.futu.goose.course.pojo.Course
+*/
+@Mapper
+public interface CourseMapper extends BaseMapper<Course> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/futu/goose/course/mapper/TeacherMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.course.mapper;
+
+import com.futu.goose.course.pojo.Teacher;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【teacher(教师表)】的数据库操作Mapper
+* @createDate 2025-05-11 20:03:09
+* @Entity com.futu.goose.course.pojo.Teacher
+*/
+@Mapper
+public interface TeacherMapper extends BaseMapper<Teacher> {
+
+}
+
+
+
+

+ 174 - 0
src/main/java/com/futu/goose/course/pojo/Course.java

@@ -0,0 +1,174 @@
+package com.futu.goose.course.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 课程表
+ * @TableName course
+ */
+@TableName(value ="course")
+@Data
+public class Course implements Serializable {
+    /**
+     * 课程ID(雪花ID)
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 课程标题
+     */
+    private String title;
+
+    /**
+     * 课程副标题
+     */
+    private String subtitle;
+
+    /**
+     * 封面图URL
+     */
+    private String coverImage;
+
+    /**
+     * 分类ID
+     */
+    private Long categoryId;
+
+    /**
+     * 主讲教师ID
+     */
+    private Long teacherId;
+
+    /**
+     * 课程价格
+     */
+    private BigDecimal price;
+
+    /**
+     * 原价
+     */
+    private BigDecimal originalPrice;
+
+    /**
+     * 总课时数
+     */
+    private Integer duration;
+
+    /**
+     * 状态:0-未发布,1-已发布,2-已下架
+     */
+    private Integer status;
+
+    /**
+     * 课程详情
+     */
+    private String description;
+
+    /**
+     * 学习目标
+     */
+    private String learnGoals;
+
+    /**
+     * 学习要求
+     */
+    private String requirements;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        Course other = (Course) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
+            && (this.getSubtitle() == null ? other.getSubtitle() == null : this.getSubtitle().equals(other.getSubtitle()))
+            && (this.getCoverImage() == null ? other.getCoverImage() == null : this.getCoverImage().equals(other.getCoverImage()))
+            && (this.getCategoryId() == null ? other.getCategoryId() == null : this.getCategoryId().equals(other.getCategoryId()))
+            && (this.getTeacherId() == null ? other.getTeacherId() == null : this.getTeacherId().equals(other.getTeacherId()))
+            && (this.getPrice() == null ? other.getPrice() == null : this.getPrice().equals(other.getPrice()))
+            && (this.getOriginalPrice() == null ? other.getOriginalPrice() == null : this.getOriginalPrice().equals(other.getOriginalPrice()))
+            && (this.getDuration() == null ? other.getDuration() == null : this.getDuration().equals(other.getDuration()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getDescription() == null ? other.getDescription() == null : this.getDescription().equals(other.getDescription()))
+            && (this.getLearnGoals() == null ? other.getLearnGoals() == null : this.getLearnGoals().equals(other.getLearnGoals()))
+            && (this.getRequirements() == null ? other.getRequirements() == null : this.getRequirements().equals(other.getRequirements()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        result = prime * result + ((getSubtitle() == null) ? 0 : getSubtitle().hashCode());
+        result = prime * result + ((getCoverImage() == null) ? 0 : getCoverImage().hashCode());
+        result = prime * result + ((getCategoryId() == null) ? 0 : getCategoryId().hashCode());
+        result = prime * result + ((getTeacherId() == null) ? 0 : getTeacherId().hashCode());
+        result = prime * result + ((getPrice() == null) ? 0 : getPrice().hashCode());
+        result = prime * result + ((getOriginalPrice() == null) ? 0 : getOriginalPrice().hashCode());
+        result = prime * result + ((getDuration() == null) ? 0 : getDuration().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode());
+        result = prime * result + ((getLearnGoals() == null) ? 0 : getLearnGoals().hashCode());
+        result = prime * result + ((getRequirements() == null) ? 0 : getRequirements().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", title=").append(title);
+        sb.append(", subtitle=").append(subtitle);
+        sb.append(", coverImage=").append(coverImage);
+        sb.append(", categoryId=").append(categoryId);
+        sb.append(", teacherId=").append(teacherId);
+        sb.append(", price=").append(price);
+        sb.append(", originalPrice=").append(originalPrice);
+        sb.append(", duration=").append(duration);
+        sb.append(", status=").append(status);
+        sb.append(", description=").append(description);
+        sb.append(", learnGoals=").append(learnGoals);
+        sb.append(", requirements=").append(requirements);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 101 - 0
src/main/java/com/futu/goose/course/pojo/CourseCategory.java

@@ -0,0 +1,101 @@
+package com.futu.goose.course.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 课程分类表
+ * @TableName course_category
+ */
+@TableName(value ="course_category")
+@Data
+public class CourseCategory implements Serializable {
+    /**
+     * 分类ID(雪花ID)
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 分类名称
+     */
+    private String name;
+
+    /**
+     * 父分类ID
+     */
+    private Long parentId;
+
+    /**
+     * 排序权重
+     */
+    private Integer sortOrder;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        CourseCategory other = (CourseCategory) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
+            && (this.getParentId() == null ? other.getParentId() == null : this.getParentId().equals(other.getParentId()))
+            && (this.getSortOrder() == null ? other.getSortOrder() == null : this.getSortOrder().equals(other.getSortOrder()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((getParentId() == null) ? 0 : getParentId().hashCode());
+        result = prime * result + ((getSortOrder() == null) ? 0 : getSortOrder().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", name=").append(name);
+        sb.append(", parentId=").append(parentId);
+        sb.append(", sortOrder=").append(sortOrder);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 101 - 0
src/main/java/com/futu/goose/course/pojo/CourseChapter.java

@@ -0,0 +1,101 @@
+package com.futu.goose.course.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 课程章节表
+ * @TableName course_chapter
+ */
+@TableName(value ="course_chapter")
+@Data
+public class CourseChapter implements Serializable {
+    /**
+     * 章节ID(雪花ID)
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 课程ID
+     */
+    private Long courseId;
+
+    /**
+     * 章节标题
+     */
+    private String title;
+
+    /**
+     * 排序权重
+     */
+    private Integer sortOrder;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        CourseChapter other = (CourseChapter) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getCourseId() == null ? other.getCourseId() == null : this.getCourseId().equals(other.getCourseId()))
+            && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
+            && (this.getSortOrder() == null ? other.getSortOrder() == null : this.getSortOrder().equals(other.getSortOrder()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getCourseId() == null) ? 0 : getCourseId().hashCode());
+        result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        result = prime * result + ((getSortOrder() == null) ? 0 : getSortOrder().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", courseId=").append(courseId);
+        sb.append(", title=").append(title);
+        sb.append(", sortOrder=").append(sortOrder);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 125 - 0
src/main/java/com/futu/goose/course/pojo/CourseLesson.java

@@ -0,0 +1,125 @@
+package com.futu.goose.course.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 课程课时表
+ * @TableName course_lesson
+ */
+@TableName(value ="course_lesson")
+@Data
+public class CourseLesson implements Serializable {
+    /**
+     * 课时ID(雪花ID)
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 章节ID
+     */
+    private Long chapterId;
+
+    /**
+     * 课时标题
+     */
+    private String title;
+
+    /**
+     * 视频URL
+     */
+    private String videoUrl;
+
+    /**
+     * 时长(秒)
+     */
+    private Integer duration;
+
+    /**
+     * 是否免费:0-否,1-是
+     */
+    private Integer isFree;
+
+    /**
+     * 排序权重
+     */
+    private Integer sortOrder;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        CourseLesson other = (CourseLesson) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getChapterId() == null ? other.getChapterId() == null : this.getChapterId().equals(other.getChapterId()))
+            && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
+            && (this.getVideoUrl() == null ? other.getVideoUrl() == null : this.getVideoUrl().equals(other.getVideoUrl()))
+            && (this.getDuration() == null ? other.getDuration() == null : this.getDuration().equals(other.getDuration()))
+            && (this.getIsFree() == null ? other.getIsFree() == null : this.getIsFree().equals(other.getIsFree()))
+            && (this.getSortOrder() == null ? other.getSortOrder() == null : this.getSortOrder().equals(other.getSortOrder()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getChapterId() == null) ? 0 : getChapterId().hashCode());
+        result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        result = prime * result + ((getVideoUrl() == null) ? 0 : getVideoUrl().hashCode());
+        result = prime * result + ((getDuration() == null) ? 0 : getDuration().hashCode());
+        result = prime * result + ((getIsFree() == null) ? 0 : getIsFree().hashCode());
+        result = prime * result + ((getSortOrder() == null) ? 0 : getSortOrder().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", chapterId=").append(chapterId);
+        sb.append(", title=").append(title);
+        sb.append(", videoUrl=").append(videoUrl);
+        sb.append(", duration=").append(duration);
+        sb.append(", isFree=").append(isFree);
+        sb.append(", sortOrder=").append(sortOrder);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 109 - 0
src/main/java/com/futu/goose/course/pojo/Teacher.java

@@ -0,0 +1,109 @@
+package com.futu.goose.course.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 教师表
+ * @TableName teacher
+ */
+@TableName(value ="teacher")
+@Data
+public class Teacher implements Serializable {
+    /**
+     * 教师ID(雪花ID)
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 教师姓名
+     */
+    private String name;
+
+    /**
+     * 职称
+     */
+    private String title;
+
+    /**
+     * 教师简介
+     */
+    private String introduction;
+
+    /**
+     * 头像URL
+     */
+    private String avatar;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        Teacher other = (Teacher) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
+            && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
+            && (this.getIntroduction() == null ? other.getIntroduction() == null : this.getIntroduction().equals(other.getIntroduction()))
+            && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        result = prime * result + ((getIntroduction() == null) ? 0 : getIntroduction().hashCode());
+        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", name=").append(name);
+        sb.append(", title=").append(title);
+        sb.append(", introduction=").append(introduction);
+        sb.append(", avatar=").append(avatar);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 13 - 0
src/main/java/com/futu/goose/course/service/CourseCategoryService.java

@@ -0,0 +1,13 @@
+package com.futu.goose.course.service;
+
+import com.futu.goose.course.pojo.CourseCategory;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 张大宇
+* @description 针对表【course_category(课程分类表)】的数据库操作Service
+* @createDate 2025-05-11 20:03:09
+*/
+public interface CourseCategoryService extends IService<CourseCategory> {
+
+}

+ 13 - 0
src/main/java/com/futu/goose/course/service/CourseChapterService.java

@@ -0,0 +1,13 @@
+package com.futu.goose.course.service;
+
+import com.futu.goose.course.pojo.CourseChapter;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 张大宇
+* @description 针对表【course_chapter(课程章节表)】的数据库操作Service
+* @createDate 2025-05-11 20:03:09
+*/
+public interface CourseChapterService extends IService<CourseChapter> {
+
+}

+ 13 - 0
src/main/java/com/futu/goose/course/service/CourseLessonService.java

@@ -0,0 +1,13 @@
+package com.futu.goose.course.service;
+
+import com.futu.goose.course.pojo.CourseLesson;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 张大宇
+* @description 针对表【course_lesson(课程课时表)】的数据库操作Service
+* @createDate 2025-05-11 20:03:09
+*/
+public interface CourseLessonService extends IService<CourseLesson> {
+
+}

+ 19 - 0
src/main/java/com/futu/goose/course/service/CourseService.java

@@ -0,0 +1,19 @@
+package com.futu.goose.course.service;
+
+import com.futu.goose.course.pojo.Course;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.futu.goose.utils.Result;
+
+import java.util.List;
+
+/**
+* @author 张大宇
+* @description 针对表【course(课程表)】的数据库操作Service
+* @createDate 2025-05-11 20:03:09
+*/
+public interface CourseService extends IService<Course> {
+
+    List<Course> listcourse();
+
+    Result selectes(String title);
+}

+ 13 - 0
src/main/java/com/futu/goose/course/service/TeacherService.java

@@ -0,0 +1,13 @@
+package com.futu.goose.course.service;
+
+import com.futu.goose.course.pojo.Teacher;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 张大宇
+* @description 针对表【teacher(教师表)】的数据库操作Service
+* @createDate 2025-05-11 20:03:09
+*/
+public interface TeacherService extends IService<Teacher> {
+
+}

+ 22 - 0
src/main/java/com/futu/goose/course/service/impl/CourseCategoryServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.course.pojo.CourseCategory;
+import com.futu.goose.course.service.CourseCategoryService;
+import com.futu.goose.course.mapper.CourseCategoryMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 张大宇
+* @description 针对表【course_category(课程分类表)】的数据库操作Service实现
+* @createDate 2025-05-11 20:03:09
+*/
+@Service
+public class CourseCategoryServiceImpl extends ServiceImpl<CourseCategoryMapper, CourseCategory>
+    implements CourseCategoryService{
+
+}
+
+
+
+

+ 22 - 0
src/main/java/com/futu/goose/course/service/impl/CourseChapterServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.course.pojo.CourseChapter;
+import com.futu.goose.course.service.CourseChapterService;
+import com.futu.goose.course.mapper.CourseChapterMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 张大宇
+* @description 针对表【course_chapter(课程章节表)】的数据库操作Service实现
+* @createDate 2025-05-11 20:03:09
+*/
+@Service
+public class CourseChapterServiceImpl extends ServiceImpl<CourseChapterMapper, CourseChapter>
+    implements CourseChapterService{
+
+}
+
+
+
+

+ 22 - 0
src/main/java/com/futu/goose/course/service/impl/CourseLessonServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.course.pojo.CourseLesson;
+import com.futu.goose.course.service.CourseLessonService;
+import com.futu.goose.course.mapper.CourseLessonMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 张大宇
+* @description 针对表【course_lesson(课程课时表)】的数据库操作Service实现
+* @createDate 2025-05-11 20:03:09
+*/
+@Service
+public class CourseLessonServiceImpl extends ServiceImpl<CourseLessonMapper, CourseLesson>
+    implements CourseLessonService{
+
+}
+
+
+
+

+ 40 - 0
src/main/java/com/futu/goose/course/service/impl/CourseServiceImpl.java

@@ -0,0 +1,40 @@
+package com.futu.goose.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.course.pojo.Course;
+import com.futu.goose.course.service.CourseService;
+import com.futu.goose.course.mapper.CourseMapper;
+import com.futu.goose.utils.EsSyncUtils;
+import com.futu.goose.utils.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+* @author 张大宇
+* @description 针对表【course(课程表)】的数据库操作Service实现
+* @createDate 2025-05-11 20:03:09
+*/
+@Service
+public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
+    implements CourseService{
+    @Autowired
+    private CourseMapper courseMapper;
+    @Autowired
+    private EsSyncUtils esSyncUtils;
+    @Override
+    public List<Course> listcourse() {
+        esSyncUtils.syncDataToEs(courseMapper,"course");
+       return courseMapper.selectList(null);
+    }
+
+    @Override
+    public Result selectes(String title) {
+        return esSyncUtils.searchDataByIndexAndName("course",title);
+    }
+}
+
+
+
+

+ 22 - 0
src/main/java/com/futu/goose/course/service/impl/TeacherServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.course.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.course.pojo.Teacher;
+import com.futu.goose.course.service.TeacherService;
+import com.futu.goose.course.mapper.TeacherMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 张大宇
+* @description 针对表【teacher(教师表)】的数据库操作Service实现
+* @createDate 2025-05-11 20:03:09
+*/
+@Service
+public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher>
+    implements TeacherService{
+
+}
+
+
+
+

+ 40 - 0
src/main/java/com/futu/goose/dto/CourseCreationDTO.java

@@ -0,0 +1,40 @@
+package com.futu.goose.dto;
+
+import com.futu.goose.course.pojo.Course;
+import lombok.Data;
+
+import java.util.Date;
+@Data
+public class CourseCreationDTO {
+//    课程表
+    /**
+     * 课程名称
+     */
+    private String courseName;
+
+    /**
+     * 课程简介
+     */
+    private String courseIntroduction;
+
+    /**
+     * 课程总时长(分钟)
+     */
+    private Integer courseDuration;
+
+    /**
+     * 课程难度级别(如 1 - 初级,2 - 中级,3 - 高级)
+     */
+    private Integer courseLevel;
+
+    /**
+     * 课程创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 课程更新时间
+     */
+    private Date updateTime;
+
+}

+ 26 - 0
src/main/java/com/futu/goose/user/controller/MinioController.java

@@ -0,0 +1,26 @@
+package com.futu.goose.user.controller;
+
+import com.futu.goose.utils.MinioUtils;
+import com.futu.goose.utils.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestController
+@RequestMapping("minio")
+public class MinioController {
+    @Autowired
+    private MinioUtils minioUtils;
+    @RequestMapping("upload")
+    public Result upload(@RequestParam("file") MultipartFile file, @RequestParam("objectName") String objectName){
+        try {
+            minioUtils.uploadImage(file);
+            return new Result(true,"上传成功");
+        }catch (Exception e){
+            e.printStackTrace();
+            return new Result(false,"上传失败");
+        }
+    }
+}

+ 34 - 0
src/main/java/com/futu/goose/user/controller/UserController.java

@@ -0,0 +1,34 @@
+package com.futu.goose.user.controller;
+
+import com.futu.goose.user.pojo.TUser;
+import com.futu.goose.user.service.TUserService;
+import com.futu.goose.utils.ResponseResult;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@RestController
+@RequestMapping("user")
+public class UserController {
+    @Autowired
+    private TUserService tUserService;
+    /**
+     * 登录
+     * @param user
+     * @return
+     */
+    @RequestMapping("login")
+    public ResponseResult login(@RequestBody TUser user){
+        return tUserService.login(user);
+    }
+    @RequestMapping("phonelogin")
+    public ResponseResult phonelogin(@RequestBody TUser user){
+        return tUserService.phonelogin(user);
+    }
+    @PostMapping("/regist")
+    public ResponseResult regist(@RequestBody TUser user){
+        return tUserService.regist(user);
+    }
+}

+ 30 - 0
src/main/java/com/futu/goose/user/controller/ValidateCode.java

@@ -0,0 +1,30 @@
+package com.futu.goose.user.controller;
+import com.futu.goose.user.service.ValidateCodeService;
+import com.futu.goose.utils.RedisClient;
+import com.futu.goose.utils.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+
+@RestController
+@RequestMapping("/validateCode")
+public class ValidateCode {
+
+
+    @Autowired
+    private ValidateCodeService validateCodeService;
+
+    @Autowired
+    private RedisClient redisClient;
+
+    @RequestMapping("/send4Order")
+    public Result send4Order(@RequestParam("telephone") String telephone) {
+        Integer code = validateCodeService.send4Order(telephone);
+        redisClient.set("CODE", code);
+        redisClient.expire("CODE", 60);
+        System.out.println("您的验证码为:------"+code);
+        return new Result(true,"验证码发送成功");
+    }
+}

+ 20 - 0
src/main/java/com/futu/goose/user/mapper/TUserMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.user.mapper;
+
+import com.futu.goose.user.pojo.TUser;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【t_user(基础用户表)】的数据库操作Mapper
+* @createDate 2025-05-06 09:39:58
+* @Entity com.futu.goose.user.pojo.TUser
+*/
+@Mapper
+public interface TUserMapper extends BaseMapper<TUser> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/futu/goose/user/mapper/WechatUsersMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.user.mapper;
+
+import com.futu.goose.user.pojo.WechatUsers;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【wechat_users(微信用户信息表)】的数据库操作Mapper
+* @createDate 2025-05-06 09:39:58
+* @Entity com.futu.goose.user.pojo.WechatUsers
+*/
+@Mapper
+public interface WechatUsersMapper extends BaseMapper<WechatUsers> {
+
+}
+
+
+
+

+ 20 - 0
src/main/java/com/futu/goose/user/mapper/WxUsersMapper.java

@@ -0,0 +1,20 @@
+package com.futu.goose.user.mapper;
+
+import com.futu.goose.user.pojo.WxUsers;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【wx_users(微信用户表)】的数据库操作Mapper
+* @createDate 2025-05-06 09:39:58
+* @Entity com.futu.goose.user.pojo.WxUsers
+*/
+@Mapper
+public interface WxUsersMapper extends BaseMapper<WxUsers> {
+
+}
+
+
+
+

+ 402 - 0
src/main/java/com/futu/goose/user/pojo/TUser.java

@@ -0,0 +1,402 @@
+package com.futu.goose.user.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 基础用户表
+ * @TableName t_user
+ */
+@TableName(value ="t_user")
+public class TUser implements Serializable {
+    /**
+     * 用户ID,主键
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 盐值
+     */
+    private String salt;
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    // 添加无参构造函数
+    public TUser() {
+    }
+
+    public TUser(String code) {
+        this.code = code;
+    }
+
+    /**
+     * 验证码
+     */
+    @TableField(exist = false)
+    private String code;
+    /**
+     * 密码(加密存储)
+     */
+    private String password;
+
+    /**
+     * 邮箱
+     */
+    private String email;
+
+    /**
+     * 手机号
+     */
+    private String phone;
+
+    /**
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 头像URL
+     */
+    private String avatar;
+
+    /**
+     * 性别(0-未知 1-男 2-女)
+     */
+    private Integer gender;
+
+    /**
+     * 生日
+     */
+    private Date birthday;
+
+    /**
+     * 状态(0-禁用 1-正常)
+     */
+    private Integer status;
+
+    /**
+     * 最后登录时间
+     */
+    private Date lastLoginTime;
+
+    /**
+     * 最后登录IP
+     */
+    private String lastLoginIp;
+
+    /**
+     * 创建时间
+     */
+    private Date createdTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updatedTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID,主键
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * 用户ID,主键
+     */
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    /**
+     * 用户名
+     */
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * 用户名
+     */
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    /**
+     * 盐值
+     */
+    public String getSalt() {
+        return salt;
+    }
+
+    /**
+     * 盐值
+     */
+    public void setSalt(String salt) {
+        this.salt = salt;
+    }
+
+    /**
+     * 密码(加密存储)
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * 密码(加密存储)
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * 邮箱
+     */
+    public String getEmail() {
+        return email;
+    }
+
+    /**
+     * 邮箱
+     */
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    /**
+     * 手机号
+     */
+    public String getPhone() {
+        return phone;
+    }
+
+    /**
+     * 手机号
+     */
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    /**
+     * 昵称
+     */
+    public String getNickname() {
+        return nickname;
+    }
+
+    /**
+     * 昵称
+     */
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    /**
+     * 头像URL
+     */
+    public String getAvatar() {
+        return avatar;
+    }
+
+    /**
+     * 头像URL
+     */
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    /**
+     * 性别(0-未知 1-男 2-女)
+     */
+    public Integer getGender() {
+        return gender;
+    }
+
+    /**
+     * 性别(0-未知 1-男 2-女)
+     */
+    public void setGender(Integer gender) {
+        this.gender = gender;
+    }
+
+    /**
+     * 生日
+     */
+    public Date getBirthday() {
+        return birthday;
+    }
+
+    /**
+     * 生日
+     */
+    public void setBirthday(Date birthday) {
+        this.birthday = birthday;
+    }
+
+    /**
+     * 状态(0-禁用 1-正常)
+     */
+    public Integer getStatus() {
+        return status;
+    }
+
+    /**
+     * 状态(0-禁用 1-正常)
+     */
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    /**
+     * 最后登录时间
+     */
+    public Date getLastLoginTime() {
+        return lastLoginTime;
+    }
+
+    /**
+     * 最后登录时间
+     */
+    public void setLastLoginTime(Date lastLoginTime) {
+        this.lastLoginTime = lastLoginTime;
+    }
+
+    /**
+     * 最后登录IP
+     */
+    public String getLastLoginIp() {
+        return lastLoginIp;
+    }
+
+    /**
+     * 最后登录IP
+     */
+    public void setLastLoginIp(String lastLoginIp) {
+        this.lastLoginIp = lastLoginIp;
+    }
+
+    /**
+     * 创建时间
+     */
+    public Date getCreatedTime() {
+        return createdTime;
+    }
+
+    /**
+     * 创建时间
+     */
+    public void setCreatedTime(Date createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    /**
+     * 更新时间
+     */
+    public Date getUpdatedTime() {
+        return updatedTime;
+    }
+
+    /**
+     * 更新时间
+     */
+    public void setUpdatedTime(Date updatedTime) {
+        this.updatedTime = updatedTime;
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        TUser other = (TUser) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
+            && (this.getSalt() == null ? other.getSalt() == null : this.getSalt().equals(other.getSalt()))
+            && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
+            && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
+            && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
+            && (this.getNickname() == null ? other.getNickname() == null : this.getNickname().equals(other.getNickname()))
+            && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getBirthday() == null ? other.getBirthday() == null : this.getBirthday().equals(other.getBirthday()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getLastLoginTime() == null ? other.getLastLoginTime() == null : this.getLastLoginTime().equals(other.getLastLoginTime()))
+            && (this.getLastLoginIp() == null ? other.getLastLoginIp() == null : this.getLastLoginIp().equals(other.getLastLoginIp()))
+            && (this.getCreatedTime() == null ? other.getCreatedTime() == null : this.getCreatedTime().equals(other.getCreatedTime()))
+            && (this.getUpdatedTime() == null ? other.getUpdatedTime() == null : this.getUpdatedTime().equals(other.getUpdatedTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
+        result = prime * result + ((getSalt() == null) ? 0 : getSalt().hashCode());
+        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
+        result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
+        result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
+        result = prime * result + ((getNickname() == null) ? 0 : getNickname().hashCode());
+        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getBirthday() == null) ? 0 : getBirthday().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getLastLoginTime() == null) ? 0 : getLastLoginTime().hashCode());
+        result = prime * result + ((getLastLoginIp() == null) ? 0 : getLastLoginIp().hashCode());
+        result = prime * result + ((getCreatedTime() == null) ? 0 : getCreatedTime().hashCode());
+        result = prime * result + ((getUpdatedTime() == null) ? 0 : getUpdatedTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", username=").append(username);
+        sb.append(", salt=").append(salt);
+        sb.append(", password=").append(password);
+        sb.append(", email=").append(email);
+        sb.append(", phone=").append(phone);
+        sb.append(", nickname=").append(nickname);
+        sb.append(", avatar=").append(avatar);
+        sb.append(", gender=").append(gender);
+        sb.append(", birthday=").append(birthday);
+        sb.append(", status=").append(status);
+        sb.append(", lastLoginTime=").append(lastLoginTime);
+        sb.append(", lastLoginIp=").append(lastLoginIp);
+        sb.append(", createdTime=").append(createdTime);
+        sb.append(", updatedTime=").append(updatedTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 425 - 0
src/main/java/com/futu/goose/user/pojo/WechatUsers.java

@@ -0,0 +1,425 @@
+package com.futu.goose.user.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 微信用户信息表
+ * @TableName wechat_users
+ */
+@TableName(value ="wechat_users")
+public class WechatUsers implements Serializable {
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 关联的用户ID
+     */
+    private Long userId;
+
+    /**
+     * 微信开放平台唯一标识
+     */
+    private String openid;
+
+    /**
+     * 微信联合ID(跨应用唯一)
+     */
+    private String unionid;
+
+    /**
+     * 微信昵称
+     */
+    private String nickname;
+
+    /**
+     * 微信头像URL
+     */
+    private String avatarUrl;
+
+    /**
+     * 性别(0-未知 1-男 2-女)
+     */
+    private Integer gender;
+
+    /**
+     * 国家
+     */
+    private String country;
+
+    /**
+     * 省份
+     */
+    private String province;
+
+    /**
+     * 城市
+     */
+    private String city;
+
+    /**
+     * 语言
+     */
+    private String language;
+
+    /**
+     * 小程序会话密钥
+     */
+    private String sessionKey;
+
+    /**
+     * 访问令牌
+     */
+    private String accessToken;
+
+    /**
+     * 刷新令牌
+     */
+    private String refreshToken;
+
+    /**
+     * 令牌过期时间(秒)
+     */
+    private Integer expiresIn;
+
+    /**
+     * 创建时间
+     */
+    private Date createdTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updatedTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * 主键ID
+     */
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    /**
+     * 关联的用户ID
+     */
+    public Long getUserId() {
+        return userId;
+    }
+
+    /**
+     * 关联的用户ID
+     */
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    /**
+     * 微信开放平台唯一标识
+     */
+    public String getOpenid() {
+        return openid;
+    }
+
+    /**
+     * 微信开放平台唯一标识
+     */
+    public void setOpenid(String openid) {
+        this.openid = openid;
+    }
+
+    /**
+     * 微信联合ID(跨应用唯一)
+     */
+    public String getUnionid() {
+        return unionid;
+    }
+
+    /**
+     * 微信联合ID(跨应用唯一)
+     */
+    public void setUnionid(String unionid) {
+        this.unionid = unionid;
+    }
+
+    /**
+     * 微信昵称
+     */
+    public String getNickname() {
+        return nickname;
+    }
+
+    /**
+     * 微信昵称
+     */
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    /**
+     * 微信头像URL
+     */
+    public String getAvatarUrl() {
+        return avatarUrl;
+    }
+
+    /**
+     * 微信头像URL
+     */
+    public void setAvatarUrl(String avatarUrl) {
+        this.avatarUrl = avatarUrl;
+    }
+
+    /**
+     * 性别(0-未知 1-男 2-女)
+     */
+    public Integer getGender() {
+        return gender;
+    }
+
+    /**
+     * 性别(0-未知 1-男 2-女)
+     */
+    public void setGender(Integer gender) {
+        this.gender = gender;
+    }
+
+    /**
+     * 国家
+     */
+    public String getCountry() {
+        return country;
+    }
+
+    /**
+     * 国家
+     */
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    /**
+     * 省份
+     */
+    public String getProvince() {
+        return province;
+    }
+
+    /**
+     * 省份
+     */
+    public void setProvince(String province) {
+        this.province = province;
+    }
+
+    /**
+     * 城市
+     */
+    public String getCity() {
+        return city;
+    }
+
+    /**
+     * 城市
+     */
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    /**
+     * 语言
+     */
+    public String getLanguage() {
+        return language;
+    }
+
+    /**
+     * 语言
+     */
+    public void setLanguage(String language) {
+        this.language = language;
+    }
+
+    /**
+     * 小程序会话密钥
+     */
+    public String getSessionKey() {
+        return sessionKey;
+    }
+
+    /**
+     * 小程序会话密钥
+     */
+    public void setSessionKey(String sessionKey) {
+        this.sessionKey = sessionKey;
+    }
+
+    /**
+     * 访问令牌
+     */
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    /**
+     * 访问令牌
+     */
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    /**
+     * 刷新令牌
+     */
+    public String getRefreshToken() {
+        return refreshToken;
+    }
+
+    /**
+     * 刷新令牌
+     */
+    public void setRefreshToken(String refreshToken) {
+        this.refreshToken = refreshToken;
+    }
+
+    /**
+     * 令牌过期时间(秒)
+     */
+    public Integer getExpiresIn() {
+        return expiresIn;
+    }
+
+    /**
+     * 令牌过期时间(秒)
+     */
+    public void setExpiresIn(Integer expiresIn) {
+        this.expiresIn = expiresIn;
+    }
+
+    /**
+     * 创建时间
+     */
+    public Date getCreatedTime() {
+        return createdTime;
+    }
+
+    /**
+     * 创建时间
+     */
+    public void setCreatedTime(Date createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    /**
+     * 更新时间
+     */
+    public Date getUpdatedTime() {
+        return updatedTime;
+    }
+
+    /**
+     * 更新时间
+     */
+    public void setUpdatedTime(Date updatedTime) {
+        this.updatedTime = updatedTime;
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        WechatUsers other = (WechatUsers) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
+            && (this.getOpenid() == null ? other.getOpenid() == null : this.getOpenid().equals(other.getOpenid()))
+            && (this.getUnionid() == null ? other.getUnionid() == null : this.getUnionid().equals(other.getUnionid()))
+            && (this.getNickname() == null ? other.getNickname() == null : this.getNickname().equals(other.getNickname()))
+            && (this.getAvatarUrl() == null ? other.getAvatarUrl() == null : this.getAvatarUrl().equals(other.getAvatarUrl()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getCountry() == null ? other.getCountry() == null : this.getCountry().equals(other.getCountry()))
+            && (this.getProvince() == null ? other.getProvince() == null : this.getProvince().equals(other.getProvince()))
+            && (this.getCity() == null ? other.getCity() == null : this.getCity().equals(other.getCity()))
+            && (this.getLanguage() == null ? other.getLanguage() == null : this.getLanguage().equals(other.getLanguage()))
+            && (this.getSessionKey() == null ? other.getSessionKey() == null : this.getSessionKey().equals(other.getSessionKey()))
+            && (this.getAccessToken() == null ? other.getAccessToken() == null : this.getAccessToken().equals(other.getAccessToken()))
+            && (this.getRefreshToken() == null ? other.getRefreshToken() == null : this.getRefreshToken().equals(other.getRefreshToken()))
+            && (this.getExpiresIn() == null ? other.getExpiresIn() == null : this.getExpiresIn().equals(other.getExpiresIn()))
+            && (this.getCreatedTime() == null ? other.getCreatedTime() == null : this.getCreatedTime().equals(other.getCreatedTime()))
+            && (this.getUpdatedTime() == null ? other.getUpdatedTime() == null : this.getUpdatedTime().equals(other.getUpdatedTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
+        result = prime * result + ((getOpenid() == null) ? 0 : getOpenid().hashCode());
+        result = prime * result + ((getUnionid() == null) ? 0 : getUnionid().hashCode());
+        result = prime * result + ((getNickname() == null) ? 0 : getNickname().hashCode());
+        result = prime * result + ((getAvatarUrl() == null) ? 0 : getAvatarUrl().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getCountry() == null) ? 0 : getCountry().hashCode());
+        result = prime * result + ((getProvince() == null) ? 0 : getProvince().hashCode());
+        result = prime * result + ((getCity() == null) ? 0 : getCity().hashCode());
+        result = prime * result + ((getLanguage() == null) ? 0 : getLanguage().hashCode());
+        result = prime * result + ((getSessionKey() == null) ? 0 : getSessionKey().hashCode());
+        result = prime * result + ((getAccessToken() == null) ? 0 : getAccessToken().hashCode());
+        result = prime * result + ((getRefreshToken() == null) ? 0 : getRefreshToken().hashCode());
+        result = prime * result + ((getExpiresIn() == null) ? 0 : getExpiresIn().hashCode());
+        result = prime * result + ((getCreatedTime() == null) ? 0 : getCreatedTime().hashCode());
+        result = prime * result + ((getUpdatedTime() == null) ? 0 : getUpdatedTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", userId=").append(userId);
+        sb.append(", openid=").append(openid);
+        sb.append(", unionid=").append(unionid);
+        sb.append(", nickname=").append(nickname);
+        sb.append(", avatarUrl=").append(avatarUrl);
+        sb.append(", gender=").append(gender);
+        sb.append(", country=").append(country);
+        sb.append(", province=").append(province);
+        sb.append(", city=").append(city);
+        sb.append(", language=").append(language);
+        sb.append(", sessionKey=").append(sessionKey);
+        sb.append(", accessToken=").append(accessToken);
+        sb.append(", refreshToken=").append(refreshToken);
+        sb.append(", expiresIn=").append(expiresIn);
+        sb.append(", createdTime=").append(createdTime);
+        sb.append(", updatedTime=").append(updatedTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 315 - 0
src/main/java/com/futu/goose/user/pojo/WxUsers.java

@@ -0,0 +1,315 @@
+package com.futu.goose.user.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 微信用户表
+ * @TableName wx_users
+ */
+@TableName(value ="wx_users")
+public class WxUsers implements Serializable {
+    /**
+     * 
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 微信openid
+     */
+    private String openid;
+
+    /**
+     * 微信unionid
+     */
+    private String unionid;
+
+    /**
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 头像
+     */
+    private String avatar;
+
+    /**
+     * 性别 0-未知 1-男 2-女
+     */
+    private Integer gender;
+
+    /**
+     * 国家
+     */
+    private String country;
+
+    /**
+     * 省份
+     */
+    private String province;
+
+    /**
+     * 城市
+     */
+    private String city;
+
+    /**
+     * 语言
+     */
+    private String language;
+
+    /**
+     * 
+     */
+    private Date createTime;
+
+    /**
+     * 
+     */
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * 
+     */
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    /**
+     * 微信openid
+     */
+    public String getOpenid() {
+        return openid;
+    }
+
+    /**
+     * 微信openid
+     */
+    public void setOpenid(String openid) {
+        this.openid = openid;
+    }
+
+    /**
+     * 微信unionid
+     */
+    public String getUnionid() {
+        return unionid;
+    }
+
+    /**
+     * 微信unionid
+     */
+    public void setUnionid(String unionid) {
+        this.unionid = unionid;
+    }
+
+    /**
+     * 昵称
+     */
+    public String getNickname() {
+        return nickname;
+    }
+
+    /**
+     * 昵称
+     */
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    /**
+     * 头像
+     */
+    public String getAvatar() {
+        return avatar;
+    }
+
+    /**
+     * 头像
+     */
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    /**
+     * 性别 0-未知 1-男 2-女
+     */
+    public Integer getGender() {
+        return gender;
+    }
+
+    /**
+     * 性别 0-未知 1-男 2-女
+     */
+    public void setGender(Integer gender) {
+        this.gender = gender;
+    }
+
+    /**
+     * 国家
+     */
+    public String getCountry() {
+        return country;
+    }
+
+    /**
+     * 国家
+     */
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    /**
+     * 省份
+     */
+    public String getProvince() {
+        return province;
+    }
+
+    /**
+     * 省份
+     */
+    public void setProvince(String province) {
+        this.province = province;
+    }
+
+    /**
+     * 城市
+     */
+    public String getCity() {
+        return city;
+    }
+
+    /**
+     * 城市
+     */
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    /**
+     * 语言
+     */
+    public String getLanguage() {
+        return language;
+    }
+
+    /**
+     * 语言
+     */
+    public void setLanguage(String language) {
+        this.language = language;
+    }
+
+    /**
+     * 
+     */
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    /**
+     * 
+     */
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    /**
+     * 
+     */
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    /**
+     * 
+     */
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        WxUsers other = (WxUsers) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getOpenid() == null ? other.getOpenid() == null : this.getOpenid().equals(other.getOpenid()))
+            && (this.getUnionid() == null ? other.getUnionid() == null : this.getUnionid().equals(other.getUnionid()))
+            && (this.getNickname() == null ? other.getNickname() == null : this.getNickname().equals(other.getNickname()))
+            && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getCountry() == null ? other.getCountry() == null : this.getCountry().equals(other.getCountry()))
+            && (this.getProvince() == null ? other.getProvince() == null : this.getProvince().equals(other.getProvince()))
+            && (this.getCity() == null ? other.getCity() == null : this.getCity().equals(other.getCity()))
+            && (this.getLanguage() == null ? other.getLanguage() == null : this.getLanguage().equals(other.getLanguage()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getOpenid() == null) ? 0 : getOpenid().hashCode());
+        result = prime * result + ((getUnionid() == null) ? 0 : getUnionid().hashCode());
+        result = prime * result + ((getNickname() == null) ? 0 : getNickname().hashCode());
+        result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getCountry() == null) ? 0 : getCountry().hashCode());
+        result = prime * result + ((getProvince() == null) ? 0 : getProvince().hashCode());
+        result = prime * result + ((getCity() == null) ? 0 : getCity().hashCode());
+        result = prime * result + ((getLanguage() == null) ? 0 : getLanguage().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", openid=").append(openid);
+        sb.append(", unionid=").append(unionid);
+        sb.append(", nickname=").append(nickname);
+        sb.append(", avatar=").append(avatar);
+        sb.append(", gender=").append(gender);
+        sb.append(", country=").append(country);
+        sb.append(", province=").append(province);
+        sb.append(", city=").append(city);
+        sb.append(", language=").append(language);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", serialVersionUID=").append(serialVersionUID);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 19 - 0
src/main/java/com/futu/goose/user/service/TUserService.java

@@ -0,0 +1,19 @@
+package com.futu.goose.user.service;
+
+import com.futu.goose.user.pojo.TUser;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.futu.goose.utils.ResponseResult;
+
+/**
+* @author 张大宇
+* @description 针对表【t_user(基础用户表)】的数据库操作Service
+* @createDate 2025-05-06 09:39:58
+*/
+public interface TUserService extends IService<TUser> {
+
+    ResponseResult login(TUser user);
+
+    ResponseResult regist(TUser user);
+
+    ResponseResult phonelogin(TUser user);
+}

+ 5 - 0
src/main/java/com/futu/goose/user/service/ValidateCodeService.java

@@ -0,0 +1,5 @@
+package com.futu.goose.user.service;
+
+public interface ValidateCodeService {
+    public Integer send4Order(String telephone);
+}

+ 13 - 0
src/main/java/com/futu/goose/user/service/WechatUsersService.java

@@ -0,0 +1,13 @@
+package com.futu.goose.user.service;
+
+import com.futu.goose.user.pojo.WechatUsers;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 张大宇
+* @description 针对表【wechat_users(微信用户信息表)】的数据库操作Service
+* @createDate 2025-05-06 09:39:58
+*/
+public interface WechatUsersService extends IService<WechatUsers> {
+
+}

+ 13 - 0
src/main/java/com/futu/goose/user/service/WxUsersService.java

@@ -0,0 +1,13 @@
+package com.futu.goose.user.service;
+
+import com.futu.goose.user.pojo.WxUsers;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 张大宇
+* @description 针对表【wx_users(微信用户表)】的数据库操作Service
+* @createDate 2025-05-06 09:39:58
+*/
+public interface WxUsersService extends IService<WxUsers> {
+
+}

+ 137 - 0
src/main/java/com/futu/goose/user/service/impl/TUserServiceImpl.java

@@ -0,0 +1,137 @@
+package com.futu.goose.user.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.user.pojo.TUser;
+import com.futu.goose.user.service.TUserService;
+import com.futu.goose.user.mapper.TUserMapper;
+import com.futu.goose.utils.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.DigestUtils;
+import org.springframework.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.UUID;
+
+/**
+* @author 张大宇
+* @description 针对表【t_user(基础用户表)】的数据库操作Service实现
+* @createDate 2025-05-06 09:39:58
+*/
+@Service
+public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser>
+    implements TUserService{
+    private static final Logger logger = LoggerFactory.getLogger(TUserService.class);
+    @Autowired
+    private TUserMapper userMapper;
+    @Autowired
+    private RedisClient redisClient;
+    @Override
+    public ResponseResult login(TUser user) {
+        if (StringUtils.isEmpty(user.getUsername())||StringUtils.isEmpty(user.getUsername())){
+            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
+        }
+        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
+        TUser selectOne = userMapper.selectOne(wrapper.lambda().eq(TUser::getUsername, user.getUsername()));
+        if (selectOne==null){
+            return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST);
+        }
+
+        String salt = selectOne.getSalt();
+        String password = user.getPassword();
+        String md5 = DigestUtils.md5DigestAsHex((password + salt).getBytes(StandardCharsets.UTF_8));
+        if (!md5.equals(selectOne.getPassword())){
+            return ResponseResult.errorResult(202,"密码错误");
+        }
+        String token = AppJwtUtil.getToken(selectOne.getId().longValue());
+        HashMap<String, String> map = new HashMap<>();
+        map.put("token",token);
+        map.put("name",selectOne.getUsername());
+        return ResponseResult.okResult(map);
+    }
+
+    @Override
+    public ResponseResult regist(TUser user) {
+        // 验证码验证
+        Object code = redisClient.get("CODE");
+        if (code == null) {
+            return new ResponseResult(201, "验证码已过期");
+        }
+// 将从 Redis 获取的 Integer 类型的 code 转换为 String 类型
+        String codeStr = String.valueOf(code);
+// 获取用户输入的验证码
+        String userCode = user.getCode();
+        if (!codeStr.equals(userCode)) {
+            return new ResponseResult(201, "验证码错误");
+        }
+        // 先判断账号是否存在
+        QueryWrapper<TUser> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(TUser::getUsername, user.getUsername());
+        TUser user1 = userMapper.selectOne(queryWrapper);
+        if (user1 != null) {
+            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "账号已存在");
+        }
+
+        // 盐
+        String salt = UUID.randomUUID().toString();
+        user.setSalt(salt);
+
+        // 密码加密
+        user.setPassword(DigestUtils.md5DigestAsHex((user.getPassword() + salt).getBytes(StandardCharsets.UTF_8)));
+
+        // 插入用户数据
+        userMapper.insert(user);
+
+        return ResponseResult.okResult(200, "注册成功");
+    }
+
+    /**
+     * 手机号验证码登录
+     * @param user
+     * @return
+     */
+
+    @Override
+    public ResponseResult phonelogin(TUser user) {
+        // 从Redis获取验证码及有效期
+        Object codeObj = redisClient.get("CODE");
+        if (codeObj == null) {
+            logger.info("用户尝试登录,验证码已过期");
+            return new ResponseResult(201, "验证码已过期");
+        }
+        // 将从Redis获取的验证码转换为String类型
+        String codeStr = String.valueOf(codeObj);
+
+        // 获取用户输入的验证码
+        String userCode = user.getCode();
+        if (!codeStr.equals(userCode)) {
+            logger.info("用户尝试登录,验证码错误");
+            return new ResponseResult(201, "验证码错误");
+        }
+        // 先判断账号是否存在
+        QueryWrapper<TUser> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(TUser::getPhone, user.getPhone());
+        TUser user1 = userMapper.selectOne(queryWrapper);
+        if (user1 == null) {
+            user.setUsername("");
+            userMapper.insert(user);
+            Long id = user.getId();
+            String token = AppJwtUtil.getToken(id);
+            HashMap<String, String> map = new HashMap<>();
+            map.put("token",token);
+            return ResponseResult.okResult(map);
+        }
+        String token = AppJwtUtil.getToken(user1.getId().longValue());
+        HashMap<String, String> map = new HashMap<>();
+        map.put("token",token);
+        map.put("name",user1.getUsername());
+        return ResponseResult.okResult(map);
+    }
+}
+
+
+
+

+ 22 - 0
src/main/java/com/futu/goose/user/service/impl/ValidateCodeServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.user.service.impl;
+
+
+import com.futu.goose.user.service.ValidateCodeService;
+import org.springframework.stereotype.Service;
+
+import java.util.Random;
+
+
+@Service
+public class ValidateCodeServiceImpl implements ValidateCodeService {
+    @Override
+    public Integer send4Order(String telephone) {
+        String substring = telephone.substring(2, 6);
+        Random random = new Random();
+        int j = random.nextInt(Integer.valueOf(substring));
+        if (j < 1000) {
+            j += 1000;
+        }
+        return j;
+    }
+}

+ 22 - 0
src/main/java/com/futu/goose/user/service/impl/WechatUsersServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.user.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.user.pojo.WechatUsers;
+import com.futu.goose.user.service.WechatUsersService;
+import com.futu.goose.user.mapper.WechatUsersMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 张大宇
+* @description 针对表【wechat_users(微信用户信息表)】的数据库操作Service实现
+* @createDate 2025-05-06 09:39:58
+*/
+@Service
+public class WechatUsersServiceImpl extends ServiceImpl<WechatUsersMapper, WechatUsers>
+    implements WechatUsersService{
+
+}
+
+
+
+

+ 22 - 0
src/main/java/com/futu/goose/user/service/impl/WxUsersServiceImpl.java

@@ -0,0 +1,22 @@
+package com.futu.goose.user.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.futu.goose.user.pojo.WxUsers;
+import com.futu.goose.user.service.WxUsersService;
+import com.futu.goose.user.mapper.WxUsersMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 张大宇
+* @description 针对表【wx_users(微信用户表)】的数据库操作Service实现
+* @createDate 2025-05-06 09:39:58
+*/
+@Service
+public class WxUsersServiceImpl extends ServiceImpl<WxUsersMapper, WxUsers>
+    implements WxUsersService{
+
+}
+
+
+
+

+ 45 - 0
src/main/java/com/futu/goose/utils/AppHttpCodeEnum.java

@@ -0,0 +1,45 @@
+package com.futu.goose.utils;
+
+public enum AppHttpCodeEnum {
+
+    // 成功段0
+    SUCCESS(200,"操作成功"),
+    // 登录段1~50
+    NEED_LOGIN(1,"需要登录后操作"),
+    LOGIN_PASSWORD_ERROR(2,"密码错误"),
+    // TOKEN50~100
+    TOKEN_INVALID(50,"无效的TOKEN"),
+    TOKEN_EXPIRE(51,"TOKEN已过期"),
+    TOKEN_REQUIRE(52,"TOKEN是必须的"),
+    // SIGN验签 100~120
+    SIGN_INVALID(100,"无效的SIGN"),
+    SIG_TIMEOUT(101,"SIGN已过期"),
+    // 参数错误 500~1000
+    PARAM_REQUIRE(500,"缺少参数"),
+    PARAM_INVALID(501,"无效参数"),
+    PARAM_IMAGE_FORMAT_ERROR(502,"图片格式有误"),
+    SERVER_ERROR(503,"服务器内部错误"),
+    // 数据错误 1000~2000
+    DATA_EXIST(1000,"数据已经存在"),
+    AP_USER_DATA_NOT_EXIST(1001,"ApUser数据不存在"),
+    DATA_NOT_EXIST(1002,"数据不存在"),
+    // 数据错误 3000~3500
+    NO_OPERATOR_AUTH(3000,"无权限操作"),
+    NEED_ADMIND(3001,"需要管理员权限");
+
+    int code;
+    String errorMessage;
+
+    AppHttpCodeEnum(int code, String errorMessage){
+        this.code = code;
+        this.errorMessage = errorMessage;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+}

+ 119 - 0
src/main/java/com/futu/goose/utils/AppJwtUtil.java

@@ -0,0 +1,119 @@
+package com.futu.goose.utils;
+
+import io.jsonwebtoken.*;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.*;
+
+public class AppJwtUtil {
+
+    // TOKEN的有效期一天(S)
+    private static final int TOKEN_TIME_OUT = 3_600;
+    // 加密KEY
+    private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
+    // 最小刷新间隔(S)
+    private static final int REFRESH_TIME = 300;
+
+    // 生产ID
+    public static String getToken(Long id){
+        Map<String, Object> claimMaps = new HashMap<>();
+        claimMaps.put("id",id);
+        long currentTime = System.currentTimeMillis();
+        return Jwts.builder()
+                .setId(UUID.randomUUID().toString())
+                .setIssuedAt(new Date(currentTime))  //签发时间
+                .setSubject("system")  //说明
+                .setIssuer("") //签发者信息
+                .setAudience("app")  //接收用户
+                .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
+                .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
+                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000))  //过期时间戳
+                .addClaims(claimMaps) //cla信息
+                .compact();
+    }
+
+    /**
+     * 获取token中的claims信息
+     *
+     * @param token
+     * @return
+     */
+    private static Jws<Claims> getJws(String token) {
+            return Jwts.parser()
+                    .setSigningKey(generalKey())
+                    .parseClaimsJws(token);
+    }
+
+    /**
+     * 获取payload body信息
+     *
+     * @param token
+     * @return
+     */
+    public static Claims getClaimsBody(String token) {
+        try {
+            return getJws(token).getBody();
+        }catch (ExpiredJwtException e){
+            return null;
+        }
+    }
+
+    /**
+     * 获取hearder body信息
+     *
+     * @param token
+     * @return
+     */
+    public static JwsHeader getHeaderBody(String token) {
+        return getJws(token).getHeader();
+    }
+
+    /**
+     * 是否过期
+     *
+     * @param claims
+     * @return -1:有效,0:有效,1:过期,2:过期
+     */
+    public static int verifyToken(Claims claims) {
+        if(claims==null){
+            return 1;
+        }
+        try {
+            claims.getExpiration()
+                    .before(new Date());
+            // 需要自动刷新TOKEN
+            if((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){
+                return -1;
+            }else {
+                return 0;
+            }
+        } catch (ExpiredJwtException ex) {
+            return 1;
+        }catch (Exception e){
+            return 2;
+        }
+    }
+
+    /**
+     * 由字符串生成加密key
+     *
+     * @return
+     */
+    public static SecretKey generalKey() {
+        byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
+        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
+        return key;
+    }
+
+    public static void main(String[] args) {
+       /* Map map = new HashMap();
+        map.put("id","11");*/
+        System.out.println(AppJwtUtil.getToken(1102L));
+        Jws<Claims> jws = AppJwtUtil.getJws("eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAADWLQQqEMAwA_5KzhURNt_qb1KZYQSi0wi6Lf9942NsMw3zh6AVW2DYmDGl2WabkZgreCaM6VXzhFBfJMcMARTqsxIG9Z888QLui3e3Tup5Pb81013KKmVzJTGo11nf9n8v4nMUaEY73DzTabjmDAAAA.4SuqQ42IGqCgBai6qd4RaVpVxTlZIWC826QA9kLvt9d-yVUw82gU47HDaSfOzgAcloZedYNNpUcd18Ne8vvjQA");
+        Claims claims = jws.getBody();
+        System.out.println(claims.get("id"));
+
+    }
+
+}

+ 116 - 0
src/main/java/com/futu/goose/utils/EsSyncUtils.java

@@ -0,0 +1,116 @@
+package com.futu.goose.utils;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.futu.goose.course.pojo.Course;
+import org.apache.http.HttpHost;
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
+import org.elasticsearch.action.bulk.BulkRequest;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.support.master.AcknowledgedResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.CreateIndexRequest;
+import org.elasticsearch.client.indices.CreateIndexResponse;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.MatchAllQueryBuilder;
+import org.elasticsearch.index.query.MatchQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class EsSyncUtils {
+    private static final Logger logger = LoggerFactory.getLogger(EsSyncUtils.class);
+    private RestHighLevelClient restHighLevelClient;
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+    public EsSyncUtils() {
+        this.restHighLevelClient = new RestHighLevelClient(
+                RestClient.builder(new HttpHost("localhost", 9200, "http")));
+    }
+
+    public <T> void syncDataToEs(BaseMapper<T> mapper, String esIndex) {
+        try {
+            // 判断索引是否存在
+            GetIndexRequest getIndexRequest = new GetIndexRequest();
+            getIndexRequest.indices(esIndex);
+            boolean indexExists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
+            if (indexExists) {
+                // 删除索引
+                AcknowledgedResponse deleteIndexResponse = restHighLevelClient.indices().delete(
+                        new org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest(esIndex),
+                        RequestOptions.DEFAULT);
+                if (!deleteIndexResponse.isAcknowledged()) {
+                    logger.error("删除 Elasticsearch 索引 {} 失败", esIndex);
+                }
+            } else {
+                logger.info("Elasticsearch 索引 {} 不存在,跳过删除步骤", esIndex);
+            }
+            // 从 MySQL 中查询所有数据
+            List<T> dataList = mapper.selectList(null);
+
+            // 创建批量请求
+            BulkRequest bulkRequest = new BulkRequest();
+            for (T data : dataList) {
+                IndexRequest indexRequest = new IndexRequest(esIndex);
+                String jsonString = objectMapper.writeValueAsString(data);
+                indexRequest.source(jsonString, XContentType.JSON);
+                bulkRequest.add(indexRequest);
+            }
+
+            // 执行批量请求
+            BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
+            if (bulkResponse.hasFailures()) {
+                logger.error("数据同步到 Elasticsearch 部分失败:{}", bulkResponse.buildFailureMessage());
+            }
+        } catch (IOException e) {
+            logger.error("同步数据到 Elasticsearch 时发生 IO 异常", e);
+        }
+    }
+
+    public Result searchDataByIndexAndName(String esIndex, String title) {
+        try {
+            SearchRequest searchRequest = new SearchRequest(esIndex);
+            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+
+            if (title == null || title.isEmpty()) {
+                searchSourceBuilder.query(QueryBuilders.matchAllQuery());
+            } else {
+                searchSourceBuilder.query(QueryBuilders.matchQuery("title", title));
+            }
+
+            searchRequest.source(searchSourceBuilder);
+            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
+            SearchHits hits = search.getHits();
+
+            if (hits.getTotalHits().value == 0) {
+                return new Result(false, "没有查询到数据");
+            }
+
+            List<Course> courseList = new ArrayList<>();
+            for (SearchHit hit : hits) {
+                // 将JSON数据映射到Course实体类
+                Course course = objectMapper.readValue(hit.getSourceAsString(), Course.class);
+                courseList.add(course);
+            }
+            return new Result(true, "查询成功", courseList);
+        } catch (Exception e) {
+            logger.error("查询Elasticsearch数据失败", e);
+            return new Result(false, "查询失败");
+        }
+    }
+}    

+ 93 - 0
src/main/java/com/futu/goose/utils/MinioUtils.java

@@ -0,0 +1,93 @@
+package com.futu.goose.utils;
+
+import io.minio.*;
+import io.minio.errors.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+
+@Component
+public class MinioUtils {
+
+    @Value("${minio.endpoint}")
+    private String endpoint;
+
+    @Value("${minio.accessKey}")
+    private String accessKey;
+
+    @Value("${minio.accessSecret}")
+    private String accessSecret;
+
+    @Value("${minio.bucketName}")
+    private String bucketName;
+
+    private MinioClient minioClient;
+
+    public MinioUtils() {
+    }
+
+    private MinioClient getMinioClient() {
+        if (minioClient == null) {
+            minioClient = MinioClient.builder()
+                    .endpoint(endpoint)
+                    .credentials(accessKey, accessSecret)
+                    .build();
+        }
+        return minioClient;
+    }
+
+    /**
+     * 生成随机文件名
+     * @param originalFileName 原始文件名
+     * @return 随机文件名
+     */
+    private String generateRandomFileName(String originalFileName) {
+        // 获取文件扩展名
+        String extension = "";
+        int dotIndex = originalFileName.lastIndexOf('.');
+        if (dotIndex > 0) {
+            extension = originalFileName.substring(dotIndex);
+        }
+        // 生成随机 UUID 作为文件名
+        String uuid = UUID.randomUUID().toString();
+        return uuid + extension;
+    }
+
+    /**
+     * 上传图片到 MinIO
+     * @param file 上传的图片文件
+     * @return 图片的访问 URL
+     * @throws IOException 输入输出异常
+     * @throws ServerException 服务器异常
+     * @throws InsufficientDataException 数据不足异常
+     * @throws ErrorResponseException 错误响应异常
+     * @throws NoSuchAlgorithmException 无此算法异常
+     * @throws InvalidKeyException 无效密钥异常
+     * @throws InvalidResponseException 无效响应异常
+     * @throws XmlParserException XML 解析异常
+     * @throws InternalException 内部异常
+     */
+    public String uploadImage(MultipartFile file) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException, InvalidBucketNameException, RegionConflictException {
+        MinioClient client = getMinioClient();
+        // 检查存储桶是否存在
+        if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
+            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+        }
+        // 生成随机文件名
+        String objectName = generateRandomFileName(file.getOriginalFilename());
+        // 上传文件
+        client.putObject(PutObjectArgs.builder()
+                .bucket(bucketName)
+                .object(objectName)
+                .stream(file.getInputStream(), file.getSize(), -1)
+                .contentType(file.getContentType())
+                .build());
+        // 返回文件的访问 URL
+        return endpoint + "/" + bucketName + "/" + objectName;
+    }
+}

+ 288 - 0
src/main/java/com/futu/goose/utils/RedisClient.java

@@ -0,0 +1,288 @@
+package com.futu.goose.utils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisClient {
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    /**
+     * 指定缓存失效时间
+     * @param key 键
+     * @param time 时间(秒)
+     * @return
+     */
+    public boolean expire(String key,long time){
+        try {
+            if(time>0){
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据key 获取过期时间
+     * @param key 键 不能为null
+     * @return 时间(秒) 返回0代表为永久有效
+     */
+    public long ttl(String key){
+        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 判断key是否存在
+     * @param key 键
+     * @return true 存在 false不存在
+     */
+    public Boolean exists(String key){
+        return redisTemplate.hasKey(key);
+    }
+
+    //============================String=============================
+    /**
+     * 普通缓存获取
+     * @param key 键
+     * @return 值
+     */
+    public Object get(String key){
+        return key==null?null:redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * 普通缓存放入
+     * @param key 键
+     * @param value 值
+     * @return true成功 false失败
+     */
+    public boolean set(String key,Object value) {
+        try {
+            redisTemplate.opsForValue().set(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除缓存
+     * @param key 可以传一个值 或多个
+     */
+    public Boolean del(String key){
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 递增
+     * @param key 键
+     * @param delta 要增加几(大于0)
+     * @return
+     */
+    public long incr(String key, long delta){
+        if(delta<0){
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 递减
+     * @param key 键
+     * @param delta 要减少几(小于0)
+     * @return
+     */
+    public long decr(String key, long delta){
+        if(delta<0){
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().decrement(key, -delta);
+    }
+
+    //================================hash=================================
+    /**
+     * HashGet
+     * @param key 键 不能为null
+     * @param item 项 不能为null
+     * @return 值
+     */
+    public Object hget(String key,String item){
+        return redisTemplate.opsForHash().get(key, item);
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     * @param key 键
+     * @param item 项
+     * @param value 值
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key,String item,Object value) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除hash表中的值
+     * @param key 键 不能为null
+     * @param item 项 可以使多个 不能为null
+     */
+    public void hdel(String key, Object... item){
+        redisTemplate.opsForHash().delete(key,item);
+    }
+
+    //============================set=============================
+    /**
+     * 根据key获取Set中的所有值
+     * @param key 键
+     * @return
+     */
+    public Set<Object> smembers(String key){
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 将数据放入set缓存
+     * @param key 键
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public long sadd(String key, Object...values) {
+        try {
+            return redisTemplate.opsForSet().add(key, values);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+
+    /**
+     * 移除值为value的
+     * @param key 键
+     * @param values 值 可以是多个
+     * @return 移除的个数
+     */
+    public long srem(String key, Object ...values) {
+        try {
+            Long count = redisTemplate.opsForSet().remove(key, values);
+            return count;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 求差集
+     * @param key1
+     * @param key2
+     * @return
+     */
+    public Set<Object> diff(String key1, String key2) {
+        try {
+            return redisTemplate.opsForSet().difference(key1, key2);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    //===============================list=================================
+
+    /**
+     * 获取list缓存的内容
+     * @param key 键
+     * @param start 开始
+     * @param end 结束  0 到 -1代表所有值
+     * @return
+     */
+    public List<Object> lrange(String key, long start, long end){
+        try {
+            return redisTemplate.opsForList().range(key, start, end);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     * @param key 键
+     * @param value 值
+     * @return
+     */
+    public boolean rpush(String key, Object value) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     * @param key 键
+     * @param value 值
+     * @return
+     */
+    public boolean lpush(String key, List<Object> value) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public Set<Object> sdiff(String keya,String keyb){
+        try {
+            return   redisTemplate.opsForSet().difference(keya,keyb);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+
+    }
+
+    /**
+     * 移除N个值为value
+     * @param key 键
+     * @param count 移除多少个
+     * @param value 值
+     * @return 移除的个数
+     */
+    public long lrem(String key,long count,Object value) {
+        try {
+            Long remove = redisTemplate.opsForList().remove(key, count, value);
+            return remove;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+}

+ 163 - 0
src/main/java/com/futu/goose/utils/ResponseResult.java

@@ -0,0 +1,163 @@
+package com.futu.goose.utils;
+
+import java.io.Serializable;
+
+/**
+ * 通用的结果返回类
+ * @param <T>
+ */
+public class ResponseResult<T> implements Serializable {
+
+    private String host;
+
+    private Integer code;
+
+    private String errorMessage;
+
+    private T data;
+
+    public ResponseResult() {
+        this.code = 200;
+    }
+
+    public ResponseResult(Integer code, T data) {
+        this.code = code;
+        this.data = data;
+    }
+
+    public ResponseResult(Integer code, String msg, T data) {
+        this.code = code;
+        this.errorMessage = msg;
+        this.data = data;
+    }
+
+    public ResponseResult(Integer code, String msg) {
+        this.code = code;
+        this.errorMessage = msg;
+    }
+
+    public static ResponseResult errorResult(int code, String msg) {
+        ResponseResult result = new ResponseResult();
+        return result.error(code, msg);
+    }
+
+    public static ResponseResult okResult(int code, String msg) {
+        ResponseResult result = new ResponseResult();
+        return result.ok(code, null, msg);
+    }
+
+    public static ResponseResult okResult(Object data) {
+        ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getErrorMessage());
+        if(data!=null) {
+            result.setData(data);
+        }
+        return result;
+    }
+
+    public static ResponseResult errorResult(AppHttpCodeEnum enums){
+        return setAppHttpCodeEnum(enums,enums.getErrorMessage());
+    }
+
+    public static ResponseResult errorResult(AppHttpCodeEnum enums, String errorMessage){
+        return setAppHttpCodeEnum(enums,errorMessage);
+    }
+
+    public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums){
+        return okResult(enums.getCode(),enums.getErrorMessage());
+    }
+
+    private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String errorMessage){
+        return okResult(enums.getCode(),errorMessage);
+    }
+
+    public ResponseResult<?> error(Integer code, String msg) {
+        this.code = code;
+        this.errorMessage = msg;
+        return this;
+    }
+
+    public ResponseResult<?> ok(Integer code, T data) {
+        this.code = code;
+        this.data = data;
+        return this;
+    }
+
+    public ResponseResult<?> ok(Integer code, T data, String msg) {
+        this.code = code;
+        this.data = data;
+        this.errorMessage = msg;
+        return this;
+    }
+
+    public ResponseResult<?> ok(T data) {
+        this.data = data;
+        return this;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+
+    public static void main(String[] args) {
+        //前置
+        /*AppHttpCodeEnum success = AppHttpCodeEnum.SUCCESS;
+        System.out.println(success.getCode());
+        System.out.println(success.getErrorMessage());*/
+
+        //查询一个对象
+        /*Map map = new HashMap();
+        map.put("name","zhangsan");
+        map.put("age",18);
+        ResponseResult result = ResponseResult.okResult(map);
+        System.out.println(JSON.toJSONString(result));*/
+
+
+        //新增,修改,删除  在项目中统一返回成功即可
+       /* ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.SUCCESS);
+        System.out.println(JSON.toJSONString(result));*/
+
+
+        //根据不用的业务返回不同的提示信息  比如:当前操作需要登录、参数错误
+        /*ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
+        System.out.println(JSON.toJSONString(result));*/
+
+        //查询分页信息
+//        PageResponseResult responseResult = new PageResponseResult(1,5,50);
+//        List list = new ArrayList();
+//        list.add("itcast");
+//        list.add("it");
+//        responseResult.setData(list);
+//        System.out.println(JSON.toJSONString(responseResult));
+
+    }
+
+}

+ 44 - 0
src/main/java/com/futu/goose/utils/Result.java

@@ -0,0 +1,44 @@
+package com.futu.goose.utils;
+
+import java.io.Serializable;
+
+/**
+ * 封装返回结果
+ */
+public class Result implements Serializable{
+    private boolean flag;//执行结果,true为执行成功 false为执行失败
+    private String message;//返回结果信息
+    private Object data;//返回数据
+    public Result(boolean flag, String message) {
+        super();
+        this.flag = flag;
+        this.message = message;
+    }
+
+    public Result(boolean flag, String message, Object data) {
+        this.flag = flag;
+        this.message = message;
+        this.data = data;
+    }
+
+    public boolean isFlag() {
+        return flag;
+    }
+    public void setFlag(boolean flag) {
+        this.flag = flag;
+    }
+    public String getMessage() {
+        return message;
+    }
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+}

+ 29 - 0
src/main/resources/application.yml

@@ -0,0 +1,29 @@
+server:
+  port: 8080
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://47.111.97.7:3306/project?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
+    username: root
+    password: root
+  redis:
+    host: 127.0.0.1
+    port: 6379
+  elasticsearch:
+    rest:
+      uris: http://127.0.0.1:9200
+mybatis-plus:
+  type-aliases-package: com.futu.goose.domain
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  mapper-locations: classpath:mapper/*.xml
+minio:
+  endpoint: http://47.111.97.7:19000
+  accessKey: minioadmin
+  accessSecret: minioadmin
+  bucketName: test
+logging:
+  level:
+    cn:
+      zhentao: debug

+ 20 - 0
src/main/resources/mapper/CourseCategoryMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.course.mapper.CourseCategoryMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.course.pojo.CourseCategory">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="name" column="name" jdbcType="VARCHAR"/>
+            <result property="parentId" column="parent_id" jdbcType="BIGINT"/>
+            <result property="sortOrder" column="sort_order" jdbcType="INTEGER"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,name,parent_id,
+        sort_order,create_time,update_time
+    </sql>
+</mapper>

+ 20 - 0
src/main/resources/mapper/CourseChapterMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.course.mapper.CourseChapterMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.course.pojo.CourseChapter">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="courseId" column="course_id" jdbcType="BIGINT"/>
+            <result property="title" column="title" jdbcType="VARCHAR"/>
+            <result property="sortOrder" column="sort_order" jdbcType="INTEGER"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,course_id,title,
+        sort_order,create_time,update_time
+    </sql>
+</mapper>

+ 24 - 0
src/main/resources/mapper/CourseLessonMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.course.mapper.CourseLessonMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.course.pojo.CourseLesson">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="chapterId" column="chapter_id" jdbcType="BIGINT"/>
+            <result property="title" column="title" jdbcType="VARCHAR"/>
+            <result property="videoUrl" column="video_url" jdbcType="VARCHAR"/>
+            <result property="duration" column="duration" jdbcType="INTEGER"/>
+            <result property="isFree" column="is_free" jdbcType="TINYINT"/>
+            <result property="sortOrder" column="sort_order" jdbcType="INTEGER"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,chapter_id,title,
+        video_url,duration,is_free,
+        sort_order,create_time,update_time
+    </sql>
+</mapper>

+ 32 - 0
src/main/resources/mapper/CourseMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.course.mapper.CourseMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.course.pojo.Course">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="title" column="title" jdbcType="VARCHAR"/>
+            <result property="subtitle" column="subtitle" jdbcType="VARCHAR"/>
+            <result property="coverImage" column="cover_image" jdbcType="VARCHAR"/>
+            <result property="categoryId" column="category_id" jdbcType="BIGINT"/>
+            <result property="teacherId" column="teacher_id" jdbcType="BIGINT"/>
+            <result property="price" column="price" jdbcType="DECIMAL"/>
+            <result property="originalPrice" column="original_price" jdbcType="DECIMAL"/>
+            <result property="duration" column="duration" jdbcType="INTEGER"/>
+            <result property="status" column="status" jdbcType="TINYINT"/>
+            <result property="description" column="description" jdbcType="VARCHAR"/>
+            <result property="learnGoals" column="learn_goals" jdbcType="VARCHAR"/>
+            <result property="requirements" column="requirements" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,title,subtitle,
+        cover_image,category_id,teacher_id,
+        price,original_price,duration,
+        status,description,learn_goals,
+        requirements,create_time,update_time
+    </sql>
+</mapper>

+ 32 - 0
src/main/resources/mapper/TUserMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.user.mapper.TUserMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.user.pojo.TUser">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="username" column="username" jdbcType="VARCHAR"/>
+            <result property="salt" column="salt" jdbcType="VARCHAR"/>
+            <result property="password" column="password" jdbcType="VARCHAR"/>
+            <result property="email" column="email" jdbcType="VARCHAR"/>
+            <result property="phone" column="phone" jdbcType="VARCHAR"/>
+            <result property="nickname" column="nickname" jdbcType="VARCHAR"/>
+            <result property="avatar" column="avatar" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="TINYINT"/>
+            <result property="birthday" column="birthday" jdbcType="DATE"/>
+            <result property="status" column="status" jdbcType="TINYINT"/>
+            <result property="lastLoginTime" column="last_login_time" jdbcType="TIMESTAMP"/>
+            <result property="lastLoginIp" column="last_login_ip" jdbcType="VARCHAR"/>
+            <result property="createdTime" column="created_time" jdbcType="TIMESTAMP"/>
+            <result property="updatedTime" column="updated_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,username,salt,
+        password,email,phone,
+        nickname,avatar,gender,
+        birthday,status,last_login_time,
+        last_login_ip,created_time,updated_time
+    </sql>
+</mapper>

+ 22 - 0
src/main/resources/mapper/TeacherMapper.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.course.mapper.TeacherMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.course.pojo.Teacher">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="name" column="name" jdbcType="VARCHAR"/>
+            <result property="title" column="title" jdbcType="VARCHAR"/>
+            <result property="introduction" column="introduction" jdbcType="VARCHAR"/>
+            <result property="avatar" column="avatar" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,name,title,
+        introduction,avatar,create_time,
+        update_time
+    </sql>
+</mapper>

+ 35 - 0
src/main/resources/mapper/WechatUsersMapper.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.user.mapper.WechatUsersMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.user.pojo.WechatUsers">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="userId" column="user_id" jdbcType="BIGINT"/>
+            <result property="openid" column="openid" jdbcType="VARCHAR"/>
+            <result property="unionid" column="unionid" jdbcType="VARCHAR"/>
+            <result property="nickname" column="nickname" jdbcType="VARCHAR"/>
+            <result property="avatarUrl" column="avatar_url" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="TINYINT"/>
+            <result property="country" column="country" jdbcType="VARCHAR"/>
+            <result property="province" column="province" jdbcType="VARCHAR"/>
+            <result property="city" column="city" jdbcType="VARCHAR"/>
+            <result property="language" column="language" jdbcType="VARCHAR"/>
+            <result property="sessionKey" column="session_key" jdbcType="VARCHAR"/>
+            <result property="accessToken" column="access_token" jdbcType="VARCHAR"/>
+            <result property="refreshToken" column="refresh_token" jdbcType="VARCHAR"/>
+            <result property="expiresIn" column="expires_in" jdbcType="INTEGER"/>
+            <result property="createdTime" column="created_time" jdbcType="TIMESTAMP"/>
+            <result property="updatedTime" column="updated_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,user_id,openid,
+        unionid,nickname,avatar_url,
+        gender,country,province,
+        city,language,session_key,
+        access_token,refresh_token,expires_in,
+        created_time,updated_time
+    </sql>
+</mapper>

+ 28 - 0
src/main/resources/mapper/WxUsersMapper.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.futu.goose.user.mapper.WxUsersMapper">
+
+    <resultMap id="BaseResultMap" type="com.futu.goose.user.pojo.WxUsers">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="openid" column="openid" jdbcType="VARCHAR"/>
+            <result property="unionid" column="unionid" jdbcType="VARCHAR"/>
+            <result property="nickname" column="nickname" jdbcType="VARCHAR"/>
+            <result property="avatar" column="avatar" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="TINYINT"/>
+            <result property="country" column="country" jdbcType="VARCHAR"/>
+            <result property="province" column="province" jdbcType="VARCHAR"/>
+            <result property="city" column="city" jdbcType="VARCHAR"/>
+            <result property="language" column="language" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,openid,unionid,
+        nickname,avatar,gender,
+        country,province,city,
+        language,create_time,update_time
+    </sql>
+</mapper>

+ 38 - 0
src/test/java/com/futu/goose/AppTest.java

@@ -0,0 +1,38 @@
+package com.futu.goose;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}

BIN
项目模块.png