韩星耀 преди 1 месец
ревизия
11269f075c
променени са 100 файла, в които са добавени 3891 реда и са изтрити 0 реда
  1. 38 0
      gig/.gitignore
  2. 8 0
      gig/.idea/.gitignore
  3. 17 0
      gig/.idea/dataSources.xml
  4. 22 0
      gig/.idea/encodings.xml
  5. 14 0
      gig/.idea/misc.xml
  6. 124 0
      gig/.idea/uiDesigner.xml
  7. 56 0
      gig/gig-api/pom.xml
  8. 4 0
      gig/gig-api/src/main/java/com/stellvoy/api/annotations/EnableCategoryCache.java
  9. 18 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/auth/AuthClient.java
  10. 23 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/course/CatalogueClient.java
  11. 18 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/course/CategoryClient.java
  12. 68 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/course/CourseClient.java
  13. 15 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/course/SubjectClient.java
  14. 35 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/exam/ExamClient.java
  15. 61 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/learning/LearningClient.java
  16. 45 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/learning/fallback/LearningClientFallback.java
  17. 17 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/remark/RemarkClient.java
  18. 24 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/remark/fallback/RemarkClientFallback.java
  19. 15 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/search/SearchClient.java
  20. 24 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/task/TaskClient.java
  21. 22 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/task/fallback/TaskClientFallback.java
  22. 46 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/trade/TradeClient.java
  23. 41 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/trade/fallback/TradeClientFallback.java
  24. 42 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/user/UserClient.java
  25. 37 0
      gig/gig-api/src/main/java/com/stellvoy/api/client/user/fallback/UserClientFallback.java
  26. 32 0
      gig/gig-api/src/main/java/com/stellvoy/api/config/FallbackConfig.java
  27. 22 0
      gig/gig-api/src/main/java/com/stellvoy/api/config/RequestIdRelayConfiguration.java
  28. 34 0
      gig/gig-api/src/main/java/com/stellvoy/api/constants/CourseStatus.java
  29. 5 0
      gig/gig-api/src/main/java/com/stellvoy/api/constants/SmsConstants.java
  30. 27 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/IdAndNumDTO.java
  31. 39 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/auth/RoleDTO.java
  32. 18 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CataSimpleInfoDTO.java
  33. 39 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CatalogueDTO.java
  34. 14 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CategoryBasicDTO.java
  35. 38 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CategoryDTO.java
  36. 54 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseDTO.java
  37. 48 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseFullInfoDTO.java
  38. 24 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CoursePurchaseInfoDTO.java
  39. 47 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseSearchDTO.java
  40. 45 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseSimpleInfoDTO.java
  41. 22 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/MediaQuoteDTO.java
  42. 20 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/SectionInfoDTO.java
  43. 26 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/SubNumAndCourseNumDTO.java
  44. 42 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/course/SubjectDTO.java
  45. 21 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/exam/QuestionBizDTO.java
  46. 38 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/exam/QuestionDTO.java
  47. 13 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningInterestDTO.java
  48. 16 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningLessonDTO.java
  49. 19 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningMedalDTO.java
  50. 14 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningRecordDTO.java
  51. 28 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningRecordFormDTO.java
  52. 19 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/remark/LikedTimesDTO.java
  53. 13 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/sms/SmsInfoDTO.java
  54. 31 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/task/NewTaskDTO.java
  55. 28 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/trade/OrderBasicDTO.java
  56. 22 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/user/LoginFormDTO.java
  57. 85 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/user/NewUserDTO.java
  58. 47 0
      gig/gig-api/src/main/java/com/stellvoy/api/dto/user/UserDTO.java
  59. 3 0
      gig/gig-api/src/main/resources/META-INF/spring.factories
  60. 14 0
      gig/gig-auth/.idea/compiler.xml
  61. 8 0
      gig/gig-auth/.idea/encodings.xml
  62. 12 0
      gig/gig-auth/.idea/misc.xml
  63. 53 0
      gig/gig-auth/.idea/workspace.xml
  64. 27 0
      gig/gig-auth/gig-auth-common/pom.xml
  65. 27 0
      gig/gig-auth/gig-auth-common/src/main/java/com/stellvoy/auth/common/constants/AuthErrorInfo.java
  66. 30 0
      gig/gig-auth/gig-auth-common/src/main/java/com/stellvoy/auth/common/constants/JwtConstants.java
  67. 13 0
      gig/gig-auth/gig-auth-common/src/main/java/com/stellvoy/auth/common/domain/PrivilegeRoleDTO.java
  68. 34 0
      gig/gig-auth/gig-auth-gateway-sdk/pom.xml
  69. 24 0
      gig/gig-auth/gig-auth-gateway-sdk/src/main/java/com/stellvoy/authsdk/gateway/config/AuthAutoConfiguration.java
  70. 176 0
      gig/gig-auth/gig-auth-gateway-sdk/src/main/java/com/stellvoy/authsdk/gateway/util/AuthUtil.java
  71. 110 0
      gig/gig-auth/gig-auth-gateway-sdk/src/main/java/com/stellvoy/authsdk/gateway/util/JwtSignerHolder.java
  72. 19 0
      gig/gig-auth/gig-auth-gateway-sdk/src/main/resources/META-INF/spring-configuration-metadata.json
  73. 2 0
      gig/gig-auth/gig-auth-gateway-sdk/src/main/resources/META-INF/spring.factories
  74. 42 0
      gig/gig-auth/gig-auth-resource-sdk/pom.xml
  75. 17 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/config/FeignRelayUserAutoConfiguration.java
  76. 14 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/config/ResourceAuthProperties.java
  77. 44 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/config/ResourceInterceptorConfiguration.java
  78. 17 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/interceptors/FeignRelayUserInterceptor.java
  79. 27 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/interceptors/LoginAuthInterceptor.java
  80. 38 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/interceptors/UserInfoInterceptor.java
  81. 31 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/resources/META-INF/spring-configuration-metadata.json
  82. 3 0
      gig/gig-auth/gig-auth-resource-sdk/src/main/resources/META-INF/spring.factories
  83. 93 0
      gig/gig-auth/gig-auth-service/pom.xml
  84. 41 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/AuthApplication.java
  85. 41 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/config/AuthConfig.java
  86. 6 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/constants/AuthConstants.java
  87. 66 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/AccountController.java
  88. 28 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/JwkController.java
  89. 143 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/MenuController.java
  90. 186 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/PrivilegeController.java
  91. 92 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/RoleController.java
  92. 25 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/dto/MenuDTO.java
  93. 30 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/dto/PrivilegeDTO.java
  94. 38 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/AccountRole.java
  95. 69 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/LoginRecord.java
  96. 116 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/Menu.java
  97. 111 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/Privilege.java
  98. 108 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/Role.java
  99. 44 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/RoleMenu.java
  100. 45 0
      gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/RolePrivilege.java

+ 38 - 0
gig/.gitignore

@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store

+ 8 - 0
gig/.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 17 - 0
gig/.idea/dataSources.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
+    <data-source source="LOCAL" name="@localhost" uuid="92c61b74-b99a-4473-9e01-ead430db397c">
+      <driver-ref>mysql.8</driver-ref>
+      <synchronize>true</synchronize>
+      <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
+      <jdbc-url>jdbc:mysql://localhost:3306</jdbc-url>
+      <jdbc-additional-properties>
+        <property name="com.intellij.clouds.kubernetes.db.host.port" />
+        <property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
+        <property name="com.intellij.clouds.kubernetes.db.container.port" />
+      </jdbc-additional-properties>
+      <working-dir>$ProjectFileDir$</working-dir>
+    </data-source>
+  </component>
+</project>

+ 22 - 0
gig/.idea/encodings.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/gig-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth/gig-auth-common/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth/gig-auth-gateway-sdk/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth/gig-auth-resource-sdk/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth/gig-auth-service/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-common/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-customer/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-gateway/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-learning/gig-message/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-learning/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-message/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-task/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-user/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 14 - 0
gig/.idea/misc.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>

+ 124 - 0
gig/.idea/uiDesigner.xml

@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>

+ 56 - 0
gig/gig-api/pom.xml

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.stellvoy</groupId>
+        <artifactId>gig</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>gig-api</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <!--httpClient的依赖 -->
+        <dependency>
+            <groupId>io.github.openfeign</groupId>
+            <artifactId>feign-httpclient</artifactId>
+        </dependency>
+        <!--common-->
+        <dependency>
+            <groupId>com.stellvoy</groupId>
+            <artifactId>gig-common</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.validator</groupId>
+            <artifactId>hibernate-validator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+            <version>2.6.2</version>
+        </dependency>
+        <!--sentinel-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-annotation</artifactId>
+            <version>3.5.3.1</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 4 - 0
gig/gig-api/src/main/java/com/stellvoy/api/annotations/EnableCategoryCache.java

@@ -0,0 +1,4 @@
+package com.stellvoy.api.annotations;
+
+public @interface EnableCategoryCache {
+}

+ 18 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/auth/AuthClient.java

@@ -0,0 +1,18 @@
+package com.stellvoy.api.client.auth;
+
+import com.stellvoy.api.dto.auth.RoleDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+import java.util.List;
+
+@FeignClient("auth-service")
+public interface AuthClient {
+
+    @GetMapping("/roles/{id}")
+    RoleDTO queryRoleById(@PathVariable("id") Long id);
+
+    @GetMapping("/roles/list")
+    List<RoleDTO> listAllRoles();
+}

+ 23 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/course/CatalogueClient.java

@@ -0,0 +1,23 @@
+package com.stellvoy.api.client.course;
+
+import com.stellvoy.api.dto.course.CataSimpleInfoDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(contextId = "catalogue", value = "course-service",path = "catalogues")
+public interface CatalogueClient {
+
+    /**
+     * 根据目录id列表查询目录信息
+     *
+     * @param ids 目录id列表
+     * @return id列表中对应的目录基础信息
+     */
+    @GetMapping("/batchQuery")
+    List<CataSimpleInfoDTO> batchQueryCatalogue(@RequestParam("ids") Iterable<Long> ids);
+
+
+}

+ 18 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/course/CategoryClient.java

@@ -0,0 +1,18 @@
+package com.stellvoy.api.client.course;
+
+import com.stellvoy.api.dto.course.CategoryBasicDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.util.List;
+
+@FeignClient(contextId = "category",value = "course-service",path = "categorys")
+public interface CategoryClient {
+
+    /**
+     * 获取所有课程及课程分类
+     * @return  所有课程及课程分类
+     */
+    @GetMapping("getAllOfOneLevel")
+    List<CategoryBasicDTO> getAllOfOneLevel();
+}

+ 68 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/course/CourseClient.java

@@ -0,0 +1,68 @@
+package com.stellvoy.api.client.course;
+
+import com.stellvoy.api.dto.course.*;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(contextId = "course", value = "course-service")
+public interface CourseClient {
+
+    /**
+     * 根据老师id列表获取老师出题数据和讲课数据
+     * @param teacherIds 老师id列表
+     * @return 老师id和老师对应的出题数和教课数
+     */
+    @GetMapping("/course/infoByTeacherIds")
+    List<SubNumAndCourseNumDTO> infoByTeacherIds(@RequestParam("teacherIds") Iterable<Long> teacherIds);
+
+    /**
+     * 根据小节id获取小节对应的mediaId和课程id
+     *
+     * @param sectionId 小节id
+     * @return 小节对应的mediaId和课程id
+     */
+    @GetMapping("/course/section/{id}")
+    SectionInfoDTO sectionInfo(@PathVariable("id") Long sectionId);
+
+    /**
+     * 根据媒资Id列表查询媒资被引用的次数
+     *
+     * @param mediaIds 媒资id列表
+     * @return 媒资id和媒资被引用的次数的列表
+     */
+    @GetMapping("/course/media/useInfo")
+    List<MediaQuoteDTO> mediaUserInfo(@RequestParam("mediaIds") Iterable<Long> mediaIds);
+
+    /**
+     * 根据课程id查询索引库需要的数据
+     *
+     * @param id 课程id
+     * @return 索引库需要的数据
+     */
+    @GetMapping("/course/{id}/searchInfo")
+    CourseSearchDTO getSearchInfo(@PathVariable("id") Long id);
+
+    /**
+     * 根据课程id集合查询课程简单信息
+     * @param ids id集合
+     * @return 课程简单信息的列表
+     */
+    @GetMapping("/courses/simpleInfo/list")
+    List<CourseSimpleInfoDTO> getSimpleInfoList(@RequestParam("ids") Iterable<Long> ids);
+
+    /**
+     * 根据课程id,获取课程、目录、教师信息
+     * @param id 课程id
+     * @return 课程信息、目录信息、教师信息
+     */
+    @GetMapping("/course/{id}")
+    CourseFullInfoDTO getCourseInfoById(
+            @PathVariable("id") Long id,
+            @RequestParam(value = "withCatalogue", required = false) boolean withCatalogue,
+            @RequestParam(value = "withTeachers", required = false) boolean withTeachers
+    );
+}

+ 15 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/course/SubjectClient.java

@@ -0,0 +1,15 @@
+package com.stellvoy.api.client.course;
+
+import com.stellvoy.api.dto.course.SubjectDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(value = "course-service", path = "subjects")
+public interface SubjectClient {
+
+    @GetMapping("list")
+    List<SubjectDTO> queryByIds(@RequestParam("ids") Iterable<Long> ids);
+}

+ 35 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/exam/ExamClient.java

@@ -0,0 +1,35 @@
+package com.stellvoy.api.client.exam;
+
+import com.stellvoy.api.dto.exam.QuestionBizDTO;
+import com.stellvoy.api.dto.exam.QuestionDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+
+@FeignClient("exam-service")
+public interface ExamClient {
+
+    @PostMapping("/question-biz/list")
+    void saveQuestionBizInfoBatch(@RequestBody Iterable<QuestionBizDTO> qbs);
+
+    @GetMapping("/question-biz/biz/list")
+    List<QuestionBizDTO> queryQuestionIdsByBizIds(@RequestParam("ids") Iterable<Long> bizIds);
+
+    @GetMapping("/question-biz/scores")
+    Map<Long, Integer> queryQuestionScoresByBizIds(@RequestParam("ids") Iterable<Long> bizIds);
+
+    @GetMapping("/questions/list")
+    List<QuestionDTO> queryQuestionByIds( @RequestParam("ids") Iterable<Long> ids);
+
+    @GetMapping("/questions/numOfTeacher")
+    Map<Long, Integer> countSubjectNumOfTeacher(@RequestParam("ids") Iterable<Long> createrIds);
+
+    @GetMapping("/questions//scores")
+    Map<Long, Integer> queryQuestionScores(
+             @RequestParam("ids") Iterable<Long> ids);
+}

+ 61 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/learning/LearningClient.java

@@ -0,0 +1,61 @@
+package com.stellvoy.api.client.learning;
+
+import com.stellvoy.api.client.learning.fallback.LearningClientFallback;
+import com.stellvoy.api.dto.leanring.LearningInterestDTO;
+import com.stellvoy.api.dto.leanring.LearningLessonDTO;
+import com.stellvoy.api.dto.leanring.LearningMedalDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@FeignClient(value = "learning-service", fallbackFactory = LearningClientFallback.class)
+public interface LearningClient {
+    /**
+     * 根据勋章id集合查询勋章信息
+     */
+    @GetMapping("/medal/{ids}")
+    List<LearningMedalDTO> queryMedalByIds(@PathVariable("ids") ArrayList<Long> ids);
+    /**
+     * 查询所有勋章信息
+     */
+    @GetMapping("/medal")
+    List<LearningMedalDTO> queryMedal();
+    /**
+     * 根据兴趣标签id集合查询兴趣标签
+     */
+    @GetMapping("/interest/{ids}")
+    List<LearningInterestDTO> queryInterestByIds(@PathVariable("ids") ArrayList<Long> ids);
+    /**
+     * 查询所有兴趣标签
+     */
+    @GetMapping("/interest")
+    List<LearningInterestDTO> queryInterest();
+    /**
+     * 统计课程学习人数
+     * @param courseId 课程id
+     * @return 学习人数
+     */
+    @GetMapping("/lessons/{courseId}/count")
+    Integer countLearningLessonByCourse(@PathVariable("courseId") Long courseId);
+
+    /**
+     * 校验当前用户是否可以学习当前课程
+     * @param courseId 课程id
+     * @return lessonId,如果是报名了则返回lessonId,否则返回空
+     */
+    @GetMapping("/lessons/{courseId}/valid")
+    Long isLessonValid(@PathVariable("courseId") Long courseId);
+
+    /**
+     * 查询当前用户指定课程的学习进度
+     * @param courseId 课程id
+     * @return 课表信息、学习记录及进度信息
+     */
+    @GetMapping("/learning-records/course/{courseId}")
+    LearningLessonDTO queryLearningRecordByCourse(@PathVariable("courseId") Long courseId);
+
+}

+ 45 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/learning/fallback/LearningClientFallback.java

@@ -0,0 +1,45 @@
+package com.stellvoy.api.client.learning.fallback;
+
+import com.stellvoy.api.client.learning.LearningClient;
+import com.stellvoy.api.dto.leanring.LearningInterestDTO;
+import com.stellvoy.api.dto.leanring.LearningLessonDTO;
+import com.stellvoy.api.dto.leanring.LearningMedalDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+public class LearningClientFallback implements FallbackFactory<LearningClient> {
+
+    @Override
+    public LearningClient create(Throwable cause) {
+        log.error("查询学习服务异常", cause);
+        return new LearningClient() {
+            @Override
+            public List<LearningMedalDTO> queryMedalByIds(ArrayList<Long> ids){return null;}
+            @Override
+            public List<LearningMedalDTO> queryMedal(){return null;}
+            @Override
+            public List<LearningInterestDTO> queryInterest(){return null;}
+            @Override
+            public List<LearningInterestDTO> queryInterestByIds(ArrayList<Long> ids){return null;}
+            @Override
+            public Integer countLearningLessonByCourse(Long courseId) {
+                return 0;
+            }
+
+            @Override
+            public Long isLessonValid(Long courseId) {
+                return null;
+            }
+
+            @Override
+            public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
+                return null;
+            }
+        };
+    }
+}

+ 17 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/remark/RemarkClient.java

@@ -0,0 +1,17 @@
+package com.stellvoy.api.client.remark;
+
+import com.stellvoy.api.client.remark.fallback.RemarkClientFallback;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(value = "remark-service", fallbackFactory = RemarkClientFallback.class)
+public interface RemarkClient {
+
+    @GetMapping("/likes/list")
+    public List<Long> getLikedIds(@RequestParam List<Long> bizIds);
+
+    }
+

+ 24 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/remark/fallback/RemarkClientFallback.java

@@ -0,0 +1,24 @@
+package com.stellvoy.api.client.remark.fallback;
+
+import com.stellvoy.api.client.remark.RemarkClient;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.openfeign.FallbackFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+public class RemarkClientFallback implements FallbackFactory<RemarkClient> {
+
+    @Override
+    public RemarkClient create(Throwable cause) {
+        log.error("查询点赞服务异常", cause);
+        return new RemarkClient() {
+
+            @Override
+            public List<Long> getLikedIds(List<Long> bizIds) {
+                return new ArrayList<>();
+            }
+        };
+    }
+}

+ 15 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/search/SearchClient.java

@@ -0,0 +1,15 @@
+package com.stellvoy.api.client.search;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient("search-service")
+public interface SearchClient {
+
+    @GetMapping("/courses/name")
+    List<Long> queryCoursesIdByName(
+            @RequestParam(value = "keyword", required = false) String keyword);
+}

+ 24 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/task/TaskClient.java

@@ -0,0 +1,24 @@
+package com.stellvoy.api.client.task;
+
+
+import com.stellvoy.api.client.task.fallback.TaskClientFallback;
+import com.stellvoy.api.dto.task.NewTaskDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+@FeignClient(value = "task-service", fallbackFactory = TaskClientFallback.class)
+public interface TaskClient {
+    /**
+     * 根据id查任务信息
+     */
+    @GetMapping("/task/{id}")
+    NewTaskDTO queryTaskById(@PathVariable("id") Long id);
+    /**
+     * 根据ids查询任务信息
+     */
+    @GetMapping("/task/list/{ids}")
+    List<NewTaskDTO> queryTaskById(@PathVariable("ids") List<Long> ids);
+}

+ 22 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/task/fallback/TaskClientFallback.java

@@ -0,0 +1,22 @@
+package com.stellvoy.api.client.task.fallback;
+
+import com.stellvoy.api.client.task.TaskClient;
+import com.stellvoy.api.dto.task.NewTaskDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.openfeign.FallbackFactory;
+
+import java.util.List;
+
+@Slf4j
+public class TaskClientFallback implements FallbackFactory<TaskClient> {
+    @Override
+    public TaskClient create(Throwable cause) {
+        log.error("查询用户服务出现异常", cause);
+        return new TaskClient() {
+            @Override
+            public NewTaskDTO queryTaskById(Long id){return null;};
+            @Override
+            public List<NewTaskDTO> queryTaskById(List<Long> ids){return null;};
+        };
+    }
+}

+ 46 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/trade/TradeClient.java

@@ -0,0 +1,46 @@
+package com.stellvoy.api.client.trade;
+
+import com.stellvoy.api.client.trade.fallback.TradeClientFallback;
+import com.stellvoy.api.dto.course.CoursePurchaseInfoDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+
+@FeignClient(value = "trade-service", fallbackFactory = TradeClientFallback.class)
+public interface TradeClient {
+    /**
+     * 统计指定课程的报名人数
+     * @param courseIdList 课程id集合
+     * @return 统计结果
+     */
+    @GetMapping("/order-details/enrollNum")
+    Map<Long, Integer> countEnrollNumOfCourse(@RequestParam("courseIdList") List<Long> courseIdList);
+
+    /**
+     * 统计指定学生的报名课程数量
+     * @param studentIds 学生id集合
+     * @return 统计结果
+     */
+    @GetMapping("/order-details/enrollCourse")
+    Map<Long, Integer> countEnrollCourseOfStudent(@RequestParam("studentIds") List<Long> studentIds);
+
+    /**
+     * 检查当前用户是否报名指定课程
+     * @param id 课程id
+     * @return 是否报名
+     */
+    @GetMapping("/order-details/course/{id}")
+    Boolean checkMyLesson(@PathVariable("id") Long id);
+
+    /**
+     * 统计课程购买、退款状态
+     * @param courseId 课程id
+     * @return 统计结果
+     */
+    @GetMapping("/order-details/purchaseInfo")
+    CoursePurchaseInfoDTO getPurchaseInfoOfCourse(@RequestParam("courseId") Long courseId);
+}

+ 41 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/trade/fallback/TradeClientFallback.java

@@ -0,0 +1,41 @@
+package com.stellvoy.api.client.trade.fallback;
+
+import com.stellvoy.api.client.trade.TradeClient;
+import com.stellvoy.api.dto.course.CoursePurchaseInfoDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.openfeign.FallbackFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class TradeClientFallback implements FallbackFactory<TradeClient> {
+
+    @Override
+    public TradeClient create(Throwable cause) {
+        log.error("查询交易服务异常", cause);
+        return new TradeClient() {
+
+            @Override
+            public Map<Long, Integer> countEnrollNumOfCourse(List<Long> courseIdList) {
+                return new HashMap<>();
+            }
+
+            @Override
+            public Map<Long, Integer> countEnrollCourseOfStudent(List<Long> studentIds) {
+                return new HashMap<>();
+            }
+
+            @Override
+            public Boolean checkMyLesson(Long id) {
+                return false;
+            }
+
+            @Override
+            public CoursePurchaseInfoDTO getPurchaseInfoOfCourse(Long courseId) {
+                return new CoursePurchaseInfoDTO();
+            }
+        };
+    }
+}

+ 42 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/user/UserClient.java

@@ -0,0 +1,42 @@
+package com.stellvoy.api.client.user;
+
+
+import com.stellvoy.api.client.user.fallback.UserClientFallback;
+import com.stellvoy.api.dto.user.LoginFormDTO;
+import com.stellvoy.api.dto.user.NewUserDTO;
+import com.stellvoy.common.domain.dto.LoginUserDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+@FeignClient(value = "user-service", fallbackFactory = UserClientFallback.class)
+public interface UserClient {
+    /**
+     * 根据id查询用户信息
+     */
+    @GetMapping("/users/{id}")
+    NewUserDTO queryUserById(@PathVariable("id") Long id);
+    /**
+     * 根据id查询用户信息
+     */
+    @GetMapping("/users/list/{ids}")
+    List<NewUserDTO> queryUserByIds(@PathVariable("ids") List<Long> ids);
+    /**
+     * 根据手机号查询用户id
+     * @param phone 手机号
+     * @return 用户id
+     */
+    @GetMapping("/users/ids")
+    Long exchangeUserIdWithPhone(@RequestParam("phone") String phone);
+
+    /**
+     * 登录接口
+     * @param loginDTO 登录信息
+     * @param isStaff 是否是员工
+     * @return 用户详情
+     */
+    @PostMapping("/users/detail/{isStaff}")
+    LoginUserDTO queryUserDetail(@RequestBody LoginFormDTO loginDTO, @PathVariable("isStaff") boolean isStaff);
+}

+ 37 - 0
gig/gig-api/src/main/java/com/stellvoy/api/client/user/fallback/UserClientFallback.java

@@ -0,0 +1,37 @@
+package com.stellvoy.api.client.user.fallback;
+
+import com.stellvoy.api.client.user.UserClient;
+import com.stellvoy.api.dto.user.LoginFormDTO;
+import com.stellvoy.api.dto.user.NewUserDTO;
+import com.stellvoy.api.dto.user.UserDTO;
+import com.stellvoy.common.domain.dto.LoginUserDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+import java.util.Collections;
+import java.util.List;
+
+@Slf4j
+public class UserClientFallback implements FallbackFactory<UserClient> {
+    @Override
+    public UserClient create(Throwable cause) {
+        log.error("查询用户服务出现异常", cause);
+        return new UserClient() {
+            @Override
+            public NewUserDTO queryUserById(Long id){return null;};
+            @Override
+            public List<NewUserDTO> queryUserByIds(List<Long> ids){return null;};
+            @Override
+            public Long exchangeUserIdWithPhone(String phone) {
+                return null;
+            }
+
+            @Override
+            public LoginUserDTO queryUserDetail(LoginFormDTO loginDTO, boolean isStaff) {
+                return null;
+            }
+        };
+    }
+}

+ 32 - 0
gig/gig-api/src/main/java/com/stellvoy/api/config/FallbackConfig.java

@@ -0,0 +1,32 @@
+package com.stellvoy.api.config;
+
+import com.stellvoy.api.client.learning.fallback.LearningClientFallback;
+import com.stellvoy.api.client.remark.fallback.RemarkClientFallback;
+import com.stellvoy.api.client.trade.fallback.TradeClientFallback;
+import com.stellvoy.api.client.user.fallback.UserClientFallback;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class FallbackConfig {
+    @Bean
+    public LearningClientFallback learningClientFallback(){
+        return new LearningClientFallback();
+    }
+
+    @Bean
+    public TradeClientFallback tradeClientFallback(){
+        return new TradeClientFallback();
+    }
+
+    @Bean
+    public UserClientFallback userClientFallback(){
+        return new UserClientFallback();
+    }
+
+    @Bean
+    public RemarkClientFallback remarkClientFallback(){
+        return new RemarkClientFallback();
+    }
+
+}

+ 22 - 0
gig/gig-api/src/main/java/com/stellvoy/api/config/RequestIdRelayConfiguration.java

@@ -0,0 +1,22 @@
+package com.stellvoy.api.config;
+
+
+import feign.RequestInterceptor;
+import org.slf4j.MDC;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static com.stellvoy.common.constants.Constant.*;
+
+@Configuration
+@EnableFeignClients(basePackages = "com.stellvoy.api.client")
+public class RequestIdRelayConfiguration {
+
+    @Bean
+    public RequestInterceptor requestIdInterceptor(){
+        return template -> template
+                .header(REQUEST_ID_HEADER, MDC.get(REQUEST_ID_HEADER))
+                .header(REQUEST_FROM_HEADER, FEIGN_ORIGIN_NAME);
+    }
+}

+ 34 - 0
gig/gig-api/src/main/java/com/stellvoy/api/constants/CourseStatus.java

@@ -0,0 +1,34 @@
+package com.stellvoy.api.constants;
+
+import com.stellvoy.common.enums.BaseEnum;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author wusongsong
+ * @since 2022/7/18 16:07
+ * @version 1.0.0
+ **/
+@Getter
+@AllArgsConstructor
+public enum CourseStatus implements BaseEnum {
+    NO_UP_SHELF(1, "待上架"),
+    SHELF(2, "已上架"),
+    DOWN_SHELF(3, "下架"),
+    FINISHED(4, "已完结");
+
+    private final int value;
+    private final String desc;
+
+    public static String desc(Integer status) {
+        if (status == null) {
+            return "";
+        }
+        for (CourseStatus courseStatus : values()) {
+            if (courseStatus.getValue() == status) {
+                return courseStatus.getDesc();
+            }
+        }
+        return null;
+    }
+}

+ 5 - 0
gig/gig-api/src/main/java/com/stellvoy/api/constants/SmsConstants.java

@@ -0,0 +1,5 @@
+package com.stellvoy.api.constants;
+
+public interface SmsConstants {
+    String VERIFY_CODE_PARAM_NAME = "code";
+}

+ 27 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/IdAndNumDTO.java

@@ -0,0 +1,27 @@
+package com.stellvoy.api.dto;
+
+import com.stellvoy.common.utils.CollUtils;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * id和nun模型,一个id对应的数量可以用与查询id和num的关系
+ * @author wusongsong
+ * @since 2022/8/3 9:27
+ * @version 1.0.0
+ **/
+@Data
+public class IdAndNumDTO {
+    private Long id;
+    private Integer num;
+
+    public static Map<Long, Integer> toMap(List<IdAndNumDTO> list){
+        if (CollUtils.isEmpty(list)) {
+            return CollUtils.emptyMap();
+        }
+        return list.stream().collect(Collectors.toMap(IdAndNumDTO::getId, IdAndNumDTO::getNum));
+    }
+}

+ 39 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/auth/RoleDTO.java

@@ -0,0 +1,39 @@
+package com.stellvoy.api.dto.auth;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 角色表
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+//@ApiModel(description = "角色实体")
+public class RoleDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+//    @ApiModelProperty(value = "主键", example = "1")
+    private Long id;
+
+    /**
+     * 角色代号,例如:admin
+     */
+//    @ApiModelProperty(value = "角色代号", example = "admin")
+    private String code;
+
+    /**
+     * 角色描述
+     */
+//    @ApiModelProperty(value = "角色名称", example = "教师")
+    private String name;
+}

+ 18 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CataSimpleInfoDTO.java

@@ -0,0 +1,18 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+/**
+ * @author wusongsong
+ * @since 2022/7/27 14:22
+ * @version 1.0.0
+ **/
+@Data
+public class CataSimpleInfoDTO {
+//    @ApiModelProperty("目录id")
+    private Long id;
+//    @ApiModelProperty("目录名称")
+    private String name;
+//    @ApiModelProperty("数字序号,不包含章序号")
+    private Integer cIndex;
+}

+ 39 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CatalogueDTO.java

@@ -0,0 +1,39 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author wusongsong
+ * @since 2022/7/11 16:42
+ * @version 1.0.0
+ **/
+@Data
+//@ApiModel(description = "课程目录")
+public class CatalogueDTO {
+//    @ApiModelProperty("章、节、练习id")
+    private Long id;
+//    @ApiModelProperty("序号")
+    private Integer index;
+//    @ApiModelProperty("章节练习名称")
+    private String name;
+//    @ApiModelProperty("课程总时长,单位秒")
+    private Integer mediaDuration;
+//    @ApiModelProperty("是否支持免费试看")
+    private Boolean trailer;
+//    @ApiModelProperty("媒资名称")
+    private String mediaName;
+//    @ApiModelProperty("媒资id")
+    private Long mediaId;
+//    @ApiModelProperty("目录类型1:章,2:节,3:测试")
+    private Integer type;
+//    @ApiModelProperty("题目数量")
+    private Integer subjectNum;
+//    @ApiModelProperty("题目总分")
+    private Integer totalScore;
+//    @ApiModelProperty("是否可以修改,默认不能修改")
+    private Boolean canUpdate = false;
+//    @ApiModelProperty("该章的所有小节和练习")
+    private List<CatalogueDTO> sections;
+}

+ 14 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CategoryBasicDTO.java

@@ -0,0 +1,14 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+@Data
+//@ApiModel(description = "分类id和名称信息")
+public class CategoryBasicDTO {
+//    @ApiModelProperty(value = "分类id", example = "1")
+    private Long id;
+//    @ApiModelProperty(value = "分类名称", example = "Java")
+    private String name;
+//    @ApiModelProperty(value = "父分类id", example = "0")
+    private Long parentId;
+}

+ 38 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CategoryDTO.java

@@ -0,0 +1,38 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * @ClassName CategoryDTO
+ * @author wusongsong
+ * @since 2022/7/21 14:51
+ * @version 1.0.0
+ **/
+@Data
+//@ApiModel("课程分类")
+public class CategoryDTO {
+//    @ApiModelProperty("课程分类id")
+    private Long id;
+//    @ApiModelProperty("课程分类名称")
+    private String name;
+//    @ApiModelProperty("三级分类数量")
+    private Integer thirdCategoryNum;
+//    @ApiModelProperty("课程数量")
+    private Integer courseNum;
+//    @ApiModelProperty("状态:1:正常,2:禁用")
+    private Integer status;
+//    @ApiModelProperty("状态描述")
+    private String statusDesc;
+//    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+//    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
+//    @ApiModelProperty("排序")
+    private Integer index;
+//    @ApiModelProperty("父id")
+    private Long parentId;
+//    @ApiModelProperty("级别")
+    private Integer level;
+}

+ 54 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseDTO.java

@@ -0,0 +1,54 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+//@ApiModel("课程信息")
+@Data
+public class CourseDTO {
+//    @ApiModelProperty("课程id")
+    private Long id;
+//    @ApiModelProperty("课程名称")
+    private String name;
+//    @ApiModelProperty("一级课程分类id")
+    private Long categoryIdLv1;
+//    @ApiModelProperty("二级课程分类id")
+    private Long categoryIdLv2;
+//    @ApiModelProperty("三级课程分类id")
+    private Long categoryIdLv3;
+//    @ApiModelProperty("课程封面")
+    private String coverUrl;
+//    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+//    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
+//    @ApiModelProperty("价格")
+    private Integer price;
+//    @ApiModelProperty("视频播放时长")
+    private Integer duration;
+//    @ApiModelProperty("课程有效期天数")
+    private Integer validDuration;
+//    @ApiModelProperty("是否免费")
+    private Boolean free;
+//    @ApiModelProperty("发布时间")
+    private LocalDateTime publishTime;
+//    @ApiModelProperty("章节数")
+    private Integer sections;
+//    @ApiModelProperty("课程状态")
+    private  Byte status;
+//    @ApiModelProperty("老师id")
+    private Long teacher;
+//    @ApiModelProperty("课程类型,1:直播课程,2:录播课程")
+    private Integer courseType;
+//    @ApiModelProperty("更新时间")
+    private Long updater;
+//    @ApiModelProperty("课程进行到的步骤,1:基本信息,2:目录,3:课程视频,4:课程题目,5:课程老师")
+    private Integer step;
+//    @ApiModelProperty(value = "课程报名人数(销量)", example = "3920")
+    private Integer sold = 0;
+//    @ApiModelProperty(value = "课程评价得分,45代表4.5星", example = "35")
+    private Integer score = 0;
+//    @ApiModelProperty("课程是否禁用,0:禁用,1:启用")
+    private Integer enable;
+}

+ 48 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseFullInfoDTO.java

@@ -0,0 +1,48 @@
+package com.stellvoy.api.dto.course;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 课程信息
+ *
+ * @author wusongsong
+ * @since 2022/8/5 16:54
+ * @version 1.0.0
+ **/
+@Data
+//@ApiModel(description = "课程详细信息,包含课程、目录、教师")
+public class CourseFullInfoDTO {
+//    @ApiModelProperty("课程id")
+    private Long id;
+//    @ApiModelProperty("课程名称")
+    private String name;
+//    @ApiModelProperty("封面链接")
+    private String coverUrl;
+//    @ApiModelProperty("价格")
+    private Integer price;
+//    @ApiModelProperty("一级课程分类id")
+    private Long firstCateId;
+//    @ApiModelProperty("二级课程分类id")
+    private Long secondCateId;
+//    @ApiModelProperty("三级课程分类id")
+    private Long thirdCateId;
+//    @ApiModelProperty("课程总节数")
+    private Integer sectionNum;
+//    @ApiModelProperty("课程购买有效期结束时间")
+    private LocalDateTime purchaseEndTime;
+//    @ApiModelProperty("课程学习有效期")
+    private Integer validDuration;
+//    @ApiModelProperty("课程章信息")
+    private List<CatalogueDTO> chapters;
+//    @ApiModelProperty("老师列表")
+    private List<Long> teacherIds;
+    @JsonIgnore
+    public List<Long> getCategoryIds(){
+        return Arrays.asList(firstCateId, secondCateId, thirdCateId);
+    }
+}

+ 24 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CoursePurchaseInfoDTO.java

@@ -0,0 +1,24 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 课程支付相关信息 课程状态
+ * @author wusongsong
+ * @since 2022/7/26 20:41
+ * @version 1.0.0
+ **/
+@Data
+//@ApiModel("课程购买信息")
+@NoArgsConstructor
+@AllArgsConstructor
+public class CoursePurchaseInfoDTO {
+//    @ApiModelProperty("报名人数")
+    private Integer enrollNum;
+//    @ApiModelProperty("退款人数")
+    private Integer refundNum;
+//    @ApiModelProperty("实付总金额")
+    private Integer realPayAmount;
+}

+ 47 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseSearchDTO.java

@@ -0,0 +1,47 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 课程信息
+ * @ClassName CourseDTO
+ * @author wusongsong
+ * @since 2022/7/18 13:12
+ * @version 1.0.0
+ **/
+//@ApiModel(description = "课程信息")
+@Data
+public class CourseSearchDTO {
+//    @ApiModelProperty("课程id")
+    private Long id;
+//    @ApiModelProperty("课程名称")
+    private String name;
+//    @ApiModelProperty("一级课程分类id")
+    private Long categoryIdLv1;
+//    @ApiModelProperty("二级课程分类id")
+    private Long categoryIdLv2;
+//    @ApiModelProperty("三级课程分类id")
+    private Long categoryIdLv3;
+//    @ApiModelProperty("课程封面")
+    private String coverUrl;
+//    @ApiModelProperty("价格")
+    private Integer price;
+//    @ApiModelProperty("是否免费")
+    private Boolean free;
+//    @ApiModelProperty("发布时间")
+    private LocalDateTime publishTime;
+//    @ApiModelProperty("章节数")
+    private Integer sections;
+//    @ApiModelProperty("课程时长")
+    private Integer duration;
+//    @ApiModelProperty("老师id")
+    private Long teacher;
+//    @ApiModelProperty("课程类型,1:直播课程,2:录播课程")
+    private Integer courseType;
+//    @ApiModelProperty(value = "课程报名人数(销量)", example = "3920")
+    private Integer sold = 0;
+//    @ApiModelProperty(value = "课程评价得分,45代表4.5星", example = "35")
+    private Integer score = 0;
+}

+ 45 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/CourseSimpleInfoDTO.java

@@ -0,0 +1,45 @@
+package com.stellvoy.api.dto.course;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author wusongsong
+ * @since 2022/7/27 14:32
+ * @version 1.0.0
+ **/
+@Data
+public class CourseSimpleInfoDTO {
+//    @ApiModelProperty("课程id")
+    private Long id;
+//    @ApiModelProperty("课程名称")
+    private String name;
+//    @ApiModelProperty("封面url")
+    private String coverUrl;
+//    @ApiModelProperty("价格")
+    private Integer price;
+//    @ApiModelProperty("课程状态")
+    private Integer status;
+//    @ApiModelProperty("是否是免费课程")
+    private Boolean free;
+//    @ApiModelProperty("一级分类id")
+    private Long firstCateId;
+//    @ApiModelProperty("二级分类id")
+    private Long secondCateId;
+//    @ApiModelProperty("三级分类id")
+    private Long thirdCateId;
+//    @ApiModelProperty("小节数量")
+    private Integer sectionNum;
+//    @ApiModelProperty("课程购买有效期结束时间")
+    private LocalDateTime purchaseEndTime;
+//    @ApiModelProperty("课程学习有效期,单位:月")
+    private Integer validDuration;
+    @JsonIgnore
+    public List<Long> getCategoryIds(){
+        return Arrays.asList(firstCateId, secondCateId, thirdCateId);
+    }
+}

+ 22 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/MediaQuoteDTO.java

@@ -0,0 +1,22 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @ClassName MediaQuoteDTO
+ * @author wusongsong
+ * @since 2022/7/18 17:43
+ * @version 1.0.0
+ **/
+//@ApiModel("媒资被引用情况")
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class MediaQuoteDTO {
+//    @ApiModelProperty("媒资id")
+    private Long mediaId;
+//    @ApiModelProperty("引用数")
+    private Integer quoteNum;
+}

+ 20 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/SectionInfoDTO.java

@@ -0,0 +1,20 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+//@ApiModel("小节信息,包含课程id和媒资id")
+@AllArgsConstructor
+@NoArgsConstructor
+public class SectionInfoDTO {
+//    @ApiModelProperty("课程id")
+    private Long courseId;
+//    @ApiModelProperty("媒资id")
+    private Long mediaId;
+//    @ApiModelProperty("是否支持免费试看")
+    private Boolean trailer;
+//    @ApiModelProperty("免费时长,不免费为0,单位分钟")
+    private Integer freeDuration;
+}

+ 26 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/SubNumAndCourseNumDTO.java

@@ -0,0 +1,26 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 老师负责的课程数和出题数目的集合
+ * @ClassName SubNumAndCourseNumDTO
+ * @author wusongsong
+ * @since 2022/7/18 15:12
+ * @version 1.0.0
+ **/
+@Data
+@AllArgsConstructor
+@NotNull
+//@ApiModel("老师id和老师对应的课程数,出题数")
+public class SubNumAndCourseNumDTO {
+//    @ApiModelProperty("老师id")
+    private Long teacherId;
+//    @ApiModelProperty("老师负责的课程数")
+    private Integer courseNum;
+//    @ApiModelProperty("老师出题数")
+    private Integer subjectNum;
+}

+ 42 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/course/SubjectDTO.java

@@ -0,0 +1,42 @@
+package com.stellvoy.api.dto.course;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <p>
+ * 考试记录表
+ * </p>
+ */
+@Data
+//@ApiModel(description = "考试问题详情")
+public class SubjectDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+//    @ApiModelProperty("问题id")
+    private Long id;
+
+//    @ApiModelProperty("题干")
+    private String name;
+
+//    @ApiModelProperty("选择题的选项")
+    private List<String> options;
+
+//    @ApiModelProperty("分值")
+    private Integer score;
+
+//    @ApiModelProperty("问题类型,1:单选题,2:多选题,3:不定向选择题,4:判断题,5:主观题")
+    private Integer subjectType;
+
+//    @ApiModelProperty("难易度,1:简单,2:中等,3:困难")
+    private Integer difficulty;
+
+//    @ApiModelProperty("解析")
+    private String analysis;
+
+//    @ApiModelProperty("选择题答案,0对应A,1对应B,可填多个")
+    private List<Integer> answers;
+}

+ 21 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/exam/QuestionBizDTO.java

@@ -0,0 +1,21 @@
+package com.stellvoy.api.dto.exam;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Data
+//@ApiModel(description = "题目与业务关联信息")
+@Accessors(chain = true)
+@AllArgsConstructor(staticName = "of")
+@NoArgsConstructor
+public class QuestionBizDTO{
+
+//    @ApiModelProperty("业务id,要关联问题的某业务id,例如小节id")
+    private Long bizId;
+
+//    @ApiModelProperty("题目id")
+    private Long questionId;
+
+}

+ 38 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/exam/QuestionDTO.java

@@ -0,0 +1,38 @@
+package com.stellvoy.api.dto.exam;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+//@ApiModel(description = "题目数据")
+public class QuestionDTO {
+
+//    @ApiModelProperty("题目id")
+    private Long id;
+
+//    @ApiModelProperty("题目名称,题干")
+    private String name;
+
+//    @ApiModelProperty("题目类型,1:单选题,2:多选题,3:不定向选择题,4:判断题,5:主观题")
+    private String type;
+
+//    @ApiModelProperty("难易度,1:简单,2:中等,3:困难")
+    private Integer difficulty;
+
+//    @ApiModelProperty("分值")
+    private Integer score;
+
+//    @ApiModelProperty("选择题选项,json数组格式")
+    private List<String> options;
+
+//    @ApiModelProperty("选择题正确答案1到10,如果有多个答案,中间使用逗号隔开,如果是判断题,1:代表正确,其他代表错误")
+    private String answer;
+
+//    @ApiModelProperty("答案解析")
+    private String analysis;
+}

+ 13 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningInterestDTO.java

@@ -0,0 +1,13 @@
+package com.stellvoy.api.dto.leanring;
+
+import lombok.Data;
+
+@Data
+public class LearningInterestDTO {
+    //    兴趣标签id
+    private Long id;
+    //    兴趣标签名称
+    private String interestName;
+    //    0未选择1已选择
+    private Integer type;
+}

+ 16 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningLessonDTO.java

@@ -0,0 +1,16 @@
+package com.stellvoy.api.dto.leanring;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+//@ApiModel(description = "学习课表进度信息")
+public class LearningLessonDTO {
+//    @ApiModelProperty("课表id")
+    private Long id;
+//    @ApiModelProperty("最近学习的小节id")
+    private Long latestSectionId;
+//    @ApiModelProperty("学习过的小节的记录")
+    private List<LearningRecordDTO> records;
+}

+ 19 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningMedalDTO.java

@@ -0,0 +1,19 @@
+package com.stellvoy.api.dto.leanring;
+
+import lombok.Data;
+
+@Data
+public class LearningMedalDTO {
+    //    勋章id
+    private Long id;
+    //    勋章名称
+    private String name;
+    //    勋章描述
+    private String description;
+    //    勋章图标
+    private String url;
+    //    勋章获取途径
+    private String way;
+    //    0未激活1已激活
+    private Integer type;
+}

+ 14 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningRecordDTO.java

@@ -0,0 +1,14 @@
+package com.stellvoy.api.dto.leanring;
+
+import lombok.Data;
+
+@Data
+//@ApiModel(description = "小节信息及学习进度")
+public class LearningRecordDTO {
+//    @ApiModelProperty("对应节的id")
+    private Long sectionId;
+//    @ApiModelProperty("视频的当前观看时长,单位秒")
+    private Integer moment;
+//    @ApiModelProperty("是否完成学习,默认false")
+    private Boolean finished;
+}

+ 28 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/leanring/LearningRecordFormDTO.java

@@ -0,0 +1,28 @@
+package com.stellvoy.api.dto.leanring;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+//@ApiModel(description = "学习记录表单数据")
+public class LearningRecordFormDTO {
+
+//    @ApiModelProperty("小节类型:1-视频,2-考试")
+    private Integer sectionType;
+
+//    @ApiModelProperty("课表id")
+    private Long lessonId;
+
+//    @ApiModelProperty("对应节的id")
+    private Long sectionId;
+
+//    @ApiModelProperty("视频总时长,单位秒")
+    private Integer duration;
+
+//    @ApiModelProperty("视频的当前观看时长,单位秒,第一次提交填0")
+    private Integer moment;
+
+//    @ApiModelProperty("提交时间")
+    private LocalDateTime commitTime;
+}

+ 19 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/remark/LikedTimesDTO.java

@@ -0,0 +1,19 @@
+package com.stellvoy.api.dto.remark;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class LikedTimesDTO {
+    /**
+     * 点赞的业务id
+     */
+    private Long bizId;
+    /**
+     * 总的点赞次数
+     */
+    private Integer likedTimes;
+}

+ 13 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/sms/SmsInfoDTO.java

@@ -0,0 +1,13 @@
+package com.stellvoy.api.dto.sms;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+//@ApiModel(description = "短信发送参数")
+public class SmsInfoDTO {
+    private String templateCode;
+    private Iterable<String> phones;
+    private Map<String, String> templateParams;
+}

+ 31 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/task/NewTaskDTO.java

@@ -0,0 +1,31 @@
+package com.stellvoy.api.dto.task;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class NewTaskDTO {
+    private Long id;
+    private String taskName;//任务名称
+    private String taskDescription;//任务描述
+    private LocalDateTime createTime;//任务创建时间
+    private LocalDateTime endTime;//任务完成时间
+    private LocalDateTime startTime;//任务开始时间
+    private LocalDateTime updateTime;//任务修改时间,分派时间
+    private String projectCycle;//项目周期
+    private Long createId;//创建人id
+    private String createName;//创建人姓名
+    private Long labelId;//标签
+    private Long number;//所需人数
+    private Long recruitedNumber;//已招券人数
+    private Long status;//任务状态:0,库存中;1,已出库;2,已完成
+    private String image;//推送任务显示图
+    private String pdfFile;//任务要求(pdf,文件格式)
+    private Double taskRate; // 任务单价(元/条)
+    private String requirementType; // 需求类型
+    private LocalDateTime feedback; // 报名反馈
+    private String code;//工会二维码
+    private LocalDateTime  applicationDeadline;//报名截止时间
+    private Long totalWorkload;//任务总量
+}

+ 28 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/trade/OrderBasicDTO.java

@@ -0,0 +1,28 @@
+package com.stellvoy.api.dto.trade;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@Builder
+public class OrderBasicDTO {
+    /**
+     * 订单id
+     */
+    private Long orderId;
+    /**
+     * 下单用户id
+     */
+    private Long userId;
+    /**
+     * 下单的课程id集合
+     */
+    private List<Long> courseIds;
+    /**
+     * 订单完成时间
+     */
+    private LocalDateTime finishTime;
+}

+ 22 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/user/LoginFormDTO.java

@@ -0,0 +1,22 @@
+package com.stellvoy.api.dto.user;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+//@ApiModel(description = "登录表单实体")
+public class LoginFormDTO {
+//    @ApiModelProperty(value = "登录方式:1-密码登录; 2-验证码登录", example = "1", required = true)
+    @NotNull
+    private Integer type;
+//    @ApiModelProperty(value = "用户名", example = "jack")
+    private String username;
+//    @ApiModelProperty(value = "手机号", example = "13800010001")
+    private String cellPhone;
+//    @ApiModelProperty(value = "密码", example = "123", required = true)
+    @NotNull
+    private String password;
+//    @ApiModelProperty(value = "7天免密登录", example = "true")
+    private Boolean rememberMe = false;
+}

+ 85 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/user/NewUserDTO.java

@@ -0,0 +1,85 @@
+package com.stellvoy.api.dto.user;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class NewUserDTO {
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 手机号
+     */
+    private String cellPhone;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 账户状态:0-禁用,1-正常
+     */
+    private Integer status;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+    /**
+     * 创建者id
+     */
+
+    private Long creater;
+    /**
+     * 修改者id
+     */
+
+    private Long updater;
+    /**
+     * 头像
+     */
+
+    private String image;
+    /**
+     * 身份证号
+     */
+    private String identityCardId;
+    /**
+     * 邮箱
+     */
+    private String email;
+    /**
+     * 是否第一次登录后进入首页 0否1是
+     */
+    private Integer isNew;
+    /**
+     * 学校
+     */
+    private String school;
+    /**
+     * 专业
+     */
+    private String major;
+    /**
+     * 简历
+     */
+    private String resume;
+    private Integer sex;//性别:0,男;1,女
+}

+ 47 - 0
gig/gig-api/src/main/java/com/stellvoy/api/dto/user/UserDTO.java

@@ -0,0 +1,47 @@
+package com.stellvoy.api.dto.user;
+
+import com.stellvoy.common.constants.RegexConstants;
+import com.stellvoy.common.validate.annotations.EnumValid;
+import lombok.Data;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+@Data
+//@ApiModel(description = "用户详情")
+public class UserDTO {
+//    @ApiModelProperty(value = "用户id", example = "1")
+    private Long id;
+//    @ApiModelProperty(value = "手机", example = "13890011009")
+    @Pattern(regexp = RegexConstants.PHONE_PATTERN, message = "手机号格式错误")
+    private String cellPhone;
+//    @ApiModelProperty(value = "用户名称/昵称", example = "李四")
+    private String name;
+//    @ApiModelProperty(value = "角色id,老师和学生不用填", example = "5")
+    private Long roleId;
+//    @ApiModelProperty(value = "头像", example = "default-user-icon.jpg")
+    private String icon;
+//    @ApiModelProperty(value = "岗位", example = "讲师")
+    private String job;
+//    @ApiModelProperty(value = "个人介绍", example = "黑马高级Java讲师")
+    private String intro;
+//    @ApiModelProperty(value = "形象照地址", example = "default-teacher-photo.jpg")
+    private String photo;
+//    @ApiModelProperty(value = "用户名", example = "13800010004")
+    private String username;
+//    @ApiModelProperty(value = "邮箱")
+    @Email
+    private String email;
+//    @ApiModelProperty(value = "QQ号码")
+    private String qq;
+//    @ApiModelProperty(value = "省")
+    private String province;
+//    @ApiModelProperty(value = "市")
+    private String city;
+//    @ApiModelProperty(value = "区")
+    private String district;
+//    @ApiModelProperty(value = "性别:0-男性,1-女性", example = "0")
+    @EnumValid(enumeration = {0, 1}, message = "性别格式不正确")
+    private Integer gender;
+}

+ 3 - 0
gig/gig-api/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.stellvoy.api.config.RequestIdRelayConfiguration, \
+  com.stellvoy.api.config.FallbackConfig

+ 14 - 0
gig/gig-auth/.idea/compiler.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile name="Maven default annotation processors profile" enabled="true">
+        <sourceOutputDir name="target/generated-sources/annotations" />
+        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
+        <outputRelativeToContentRoot value="true" />
+        <module name="gig-auth-common" />
+        <module name="gig-auth-gateway-sdk" />
+      </profile>
+    </annotationProcessing>
+  </component>
+</project>

+ 8 - 0
gig/gig-auth/.idea/encodings.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/gig-auth-common/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/gig-auth-gateway-sdk/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+  </component>
+</project>

+ 12 - 0
gig/gig-auth/.idea/misc.xml

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

+ 53 - 0
gig/gig-auth/.idea/workspace.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AutoImportSettings">
+    <option name="autoReloadType" value="SELECTIVE" />
+  </component>
+  <component name="ChangeListManager">
+    <list default="true" id="46612830-e5a1-40b8-9cb3-93b9a06c57f7" name="Changes" comment="" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="ProjectColorInfo"><![CDATA[{
+  "associatedIndex": 6
+}]]></component>
+  <component name="ProjectId" id="2k2nvuslNmVVdZiQ1Jy2TQj1e5o" />
+  <component name="ProjectViewState">
+    <option name="hideEmptyMiddlePackages" value="true" />
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent"><![CDATA[{
+  "keyToString": {
+    "RunOnceActivity.ShowReadmeOnStart": "true",
+    "kotlin-language-version-configured": "true",
+    "last_opened_file_path": "C:/Users/JT/Desktop/gig/gig-auth",
+    "nodejs_package_manager_path": "npm",
+    "vue.rearranger.settings.migration": "true"
+  }
+}]]></component>
+  <component name="SharedIndexes">
+    <attachedChunks>
+      <set>
+        <option value="bundled-jdk-9f38398b9061-18abd8497189-intellij.indexing.shared.core-IU-241.14494.240" />
+        <option value="bundled-js-predefined-1d06a55b98c1-74d2a5396914-JavaScript-IU-241.14494.240" />
+      </set>
+    </attachedChunks>
+  </component>
+  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="46612830-e5a1-40b8-9cb3-93b9a06c57f7" name="Changes" comment="" />
+      <created>1722490772916</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1722490772916</updated>
+      <workItem from="1722490773998" duration="5000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="3" />
+  </component>
+</project>

+ 27 - 0
gig/gig-auth/gig-auth-common/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.stellvoy</groupId>
+        <artifactId>gig-auth</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>gig-auth-common</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <!--domain-->
+        <dependency>
+            <groupId>com.stellvoy</groupId>
+            <artifactId>gig-common</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+    </dependencies>
+</project>

+ 27 - 0
gig/gig-auth/gig-auth-common/src/main/java/com/stellvoy/auth/common/constants/AuthErrorInfo.java

@@ -0,0 +1,27 @@
+package com.stellvoy.auth.common.constants;
+
+public interface AuthErrorInfo {
+
+    interface Msg {
+        String INVALID_STAFF_TYPE = "无效的账户类型";
+
+
+        String INVALID_ROLE_ID = "绑定的角色不存在";
+        String PRIVILEGE_EXISTS = "权限信息已存在";
+        String PRIVILEGE_NOT_FOUND = "权限数据不存在";
+        String ROLE_NOT_FOUND = "角色数据不存在";
+        String MENU_NOT_FOUND = "菜单数据不存在";
+        String UNAUTHORIZED = "未登录";
+        String FORBIDDEN = "无访问权限";
+        String INVALID_TOKEN = "无效的token";
+        String EXPIRED_TOKEN = "token已过期";
+        String INVALID_TOKEN_PAYLOAD = "token参数格式错误";
+    }
+
+    interface Code {
+        // 过期token
+        int EXPIRED_TOKEN_CODE = 40101;
+        // 无效token
+        int INVALID_TOKEN_CODE = 40102;
+    }
+}

+ 30 - 0
gig/gig-auth/gig-auth-common/src/main/java/com/stellvoy/auth/common/constants/JwtConstants.java

@@ -0,0 +1,30 @@
+package com.stellvoy.auth.common.constants;
+
+import java.time.Duration;
+
+public class JwtConstants {
+    public static final String PAYLOAD_USER_KEY = "user";
+    public static final String PAYLOAD_JTI_KEY = "jti";
+
+    public static final String JWT_REDIS_KEY_PREFIX = "jwt:uid:";
+    // token过期时间,测试期间改为 1天,正常是5分钟
+    public static final Duration JWT_TOKEN_TTL = Duration.ofMinutes(5);
+    // public static final Duration JWT_TOKEN_TTL = Duration.ofMinutes(60 * 24);
+    public static final Duration JWT_REFRESH_TTL = Duration.ofMinutes(30);
+
+    public static final Duration JWT_REMEMBER_ME_TTL = Duration.ofDays(7);
+
+    public static final String JWT_ALGORITHM = "rs256";
+    public static final String AUTHORIZATION_HEADER = "authorization";
+    public static final String REFRESH_HEADER = "refresh";
+    public static final String ADMIN_REFRESH_HEADER = "admin-refresh";
+
+    public static final String USER_HEADER = "user-info";
+
+    /* 权限缓存 KEY  begin */
+    public static final String AUTH_PRIVILEGE_KEY = "auth:privileges";
+    public static final String AUTH_PRIVILEGE_VERSION_KEY = "version";
+    public static final String LOCK_AUTH_PRIVILEGE_KEY = "lock:auth:privileges";
+    /* 权限缓存 KEY  end */
+
+}

+ 13 - 0
gig/gig-auth/gig-auth-common/src/main/java/com/stellvoy/auth/common/domain/PrivilegeRoleDTO.java

@@ -0,0 +1,13 @@
+package com.stellvoy.auth.common.domain;
+
+import lombok.Data;
+
+import java.util.Set;
+
+@Data
+public class PrivilegeRoleDTO {
+    private Long id;
+    private String antPath;
+    private Boolean internal;
+    private Set<Long> roles;
+}

+ 34 - 0
gig/gig-auth/gig-auth-gateway-sdk/pom.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.stellvoy</groupId>
+        <artifactId>gig-auth</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>gig-auth-gateway-sdk</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.stellvoy</groupId>
+            <artifactId>gig-auth-common</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-commons</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 24 - 0
gig/gig-auth/gig-auth-gateway-sdk/src/main/java/com/stellvoy/authsdk/gateway/config/AuthAutoConfiguration.java

@@ -0,0 +1,24 @@
+package com.stellvoy.authsdk.gateway.config;
+
+import com.stellvoy.authsdk.gateway.util.AuthUtil;
+import com.stellvoy.authsdk.gateway.util.JwtSignerHolder;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+@Configuration
+public class AuthAutoConfiguration {
+
+    @Bean
+    @ConditionalOnClass(DiscoveryClient.class)
+    public JwtSignerHolder jwtSignerHolder(DiscoveryClient discoveryClient){
+        return new JwtSignerHolder(discoveryClient);
+    }
+
+    @Bean
+    public AuthUtil authUtil(JwtSignerHolder jwtSignerHolder, StringRedisTemplate stringRedisTemplate){
+        return new AuthUtil(jwtSignerHolder, stringRedisTemplate);
+    }
+}

+ 176 - 0
gig/gig-auth/gig-auth-gateway-sdk/src/main/java/com/stellvoy/authsdk/gateway/util/AuthUtil.java

@@ -0,0 +1,176 @@
+package com.stellvoy.authsdk.gateway.util;
+
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.exceptions.ValidateException;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import cn.hutool.jwt.JWT;
+import cn.hutool.jwt.JWTValidator;
+import com.stellvoy.auth.common.domain.PrivilegeRoleDTO;
+import com.stellvoy.common.domain.R;
+import com.stellvoy.common.domain.dto.LoginUserDTO;
+import com.stellvoy.common.exceptions.ForbiddenException;
+import com.stellvoy.common.exceptions.UnauthorizedException;
+import com.stellvoy.common.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.BoundHashOperations;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.util.AntPathMatcher;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.stellvoy.auth.common.constants.AuthErrorInfo.Code.EXPIRED_TOKEN_CODE;
+import static com.stellvoy.auth.common.constants.AuthErrorInfo.Code.INVALID_TOKEN_CODE;
+import static com.stellvoy.auth.common.constants.AuthErrorInfo.Msg.*;
+import static com.stellvoy.auth.common.constants.JwtConstants.*;
+
+@Slf4j
+public class AuthUtil {
+    // 缓存权限信息
+    private Map<String, PrivilegeRoleDTO> privileges = new HashMap<>();
+    // 要拦截的路径匹配符的集合
+    private Set<String> paths = new HashSet<>();
+    // 权限版本信息,减少不必要的缓存处理
+    private int privilegeVersion;
+
+    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
+    private final JwtSignerHolder jwtSignerHolder;
+    private final StringRedisTemplate stringRedisTemplate;
+    private final BoundHashOperations<String, String, String> hashOps;
+
+    public AuthUtil(JwtSignerHolder jwtSignerHolder, StringRedisTemplate stringRedisTemplate) {
+        this.jwtSignerHolder = jwtSignerHolder;
+        this.stringRedisTemplate = stringRedisTemplate;
+        this.hashOps = stringRedisTemplate.boundHashOps(AUTH_PRIVILEGE_KEY);
+    }
+
+    public R<LoginUserDTO> parseToken(String token) {
+        // 1.校验token是否为空
+        if(StringUtils.isBlank(token)){
+            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN);
+        }
+        JWT jwt = null;
+        try {
+            jwt = JWT.of(token).setSigner(jwtSignerHolder.getJwtSigner());
+        } catch (Exception e) {
+            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN);
+        }
+        // 2.校验jwt是否有效
+        if (!jwt.verify()) {
+            // 验证失败,返回空
+            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN);
+        }
+        // 3.校验是否过期
+        try {
+            JWTValidator.of(jwt).validateDate();
+        } catch (ValidateException e) {
+            return R.error(EXPIRED_TOKEN_CODE, EXPIRED_TOKEN);
+        }
+        // 4.数据格式校验
+        Object userPayload = jwt.getPayload(PAYLOAD_USER_KEY);
+        if (userPayload == null) {
+            // 数据为空
+            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN_PAYLOAD);
+        }
+
+        // 5.数据解析
+        LoginUserDTO userDTO;
+        try {
+            userDTO = ((JSONObject)userPayload).toBean(LoginUserDTO.class);
+        } catch (RuntimeException e) {
+            // token格式有误
+            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN_PAYLOAD);
+        }
+
+        // 6.返回
+        return R.ok(userDTO);
+    }
+
+    public void checkAuth(String antPath, R<LoginUserDTO> r){
+        // 1.判断是否是需要权限的路径
+        String matchPath = findMatchPath(antPath);
+        if(matchPath == null){
+            // 没有权限限制,直接放行
+            return;
+        }
+        // 2.判断是否登录成功
+        if(!r.success()){
+            // 未登录,直接报错
+            throw new UnauthorizedException(r.getCode(), r.getMsg());
+        }
+        // 3.获取当前路径所需权限
+        PrivilegeRoleDTO pathPrivilege = findPathPrivilege(matchPath);
+
+        // 4.权限判断
+        Set<Long> requiredRoles = pathPrivilege.getRoles();
+        if (!CollectionUtil.contains(requiredRoles, r.getData().getRoleId())) {
+            // 没有访问权限
+            throw new ForbiddenException(FORBIDDEN);
+        }
+    }
+
+    private String findMatchPath(String antPath){
+        String matchPath = null;
+        for (String pathPattern : paths) {
+            if(antPathMatcher.match(pathPattern, antPath)){
+                matchPath = pathPattern;
+                break;
+            }
+        }
+        return matchPath;
+    }
+
+    private PrivilegeRoleDTO findPathPrivilege(String path){
+        return privileges.get(path);
+    }
+
+    private List<PrivilegeRoleDTO> loadPrivileges(){
+        List<String> values = hashOps.values();
+        if(CollUtil.isEmpty(values)){
+            return Collections.emptyList();
+        }
+        return values.stream()
+                .map(json -> JSONUtil.toBean(json, PrivilegeRoleDTO.class))
+                .collect(Collectors.toList());
+    }
+
+    private int currentVersion() {
+        String version = stringRedisTemplate.opsForValue().get(AUTH_PRIVILEGE_VERSION_KEY);
+        if(StrUtil.isEmpty(version)){
+            return 0;
+        }
+        return Integer.parseInt(version);
+    }
+
+
+    @Scheduled(fixedDelay = 20000)
+    public void refreshTask(){
+        // 1.获取版本号
+        int currentVersion = currentVersion();
+        if (currentVersion == this.privilegeVersion) {
+            // 版本一致,说明数据没有更新,直接结束任务
+            return;
+        }
+        // 2.获取最新权限信息
+        List<PrivilegeRoleDTO> privilegeRoleDTOS = loadPrivileges();
+        if(CollUtil.isEmpty(privilegeRoleDTOS)){
+            // 更新版本
+            this.privilegeVersion = currentVersion;
+            return;
+        }
+        // 3.数据处理
+        Map<String, PrivilegeRoleDTO> map = new HashMap<>();
+        for (PrivilegeRoleDTO p : privilegeRoleDTOS) {
+            map.put(p.getAntPath(), p);
+            this.privileges = map;
+        }
+        this.paths = map.keySet();
+        // 4.更新版本
+        this.privilegeVersion = currentVersion;
+    }
+}

+ 110 - 0
gig/gig-auth/gig-auth-gateway-sdk/src/main/java/com/stellvoy/authsdk/gateway/util/JwtSignerHolder.java

@@ -0,0 +1,110 @@
+package com.stellvoy.authsdk.gateway.util;
+
+import cn.hutool.crypto.KeyUtil;
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.jwt.signers.JWTSigner;
+import cn.hutool.jwt.signers.JWTSignerUtil;
+import com.stellvoy.auth.common.constants.JwtConstants;
+import com.stellvoy.common.utils.CollUtils;
+import com.stellvoy.common.utils.MarkedRunnable;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+
+import javax.annotation.PostConstruct;
+import java.nio.charset.StandardCharsets;
+import java.security.PublicKey;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@Data
+@Slf4j
+public class JwtSignerHolder {
+
+    private volatile JWTSigner jwtSigner;
+
+    private DiscoveryClient discoveryClient;
+
+    public JwtSignerHolder(DiscoveryClient discoveryClient) {
+        this.discoveryClient = discoveryClient;
+    }
+
+    private final ExecutorService ses = new ThreadPoolExecutor(
+            1,
+            1,
+            10,
+            TimeUnit.SECONDS,
+            new ArrayBlockingQueue<>(1),
+            r -> new Thread(r, "AuthFetchJwkThread")
+    );
+
+    @PostConstruct
+    public void init(){
+        // 尝试获取jwk秘钥
+        ses.submit(new MarkedRunnable(new JwkTask(discoveryClient)));
+    }
+
+    public void shutdown(){
+        ses.shutdown();
+        log.debug("销毁加载秘钥线程 AuthFetchJwkThread");
+    }
+    public static void sleep(long time){
+        try {
+            Thread.sleep(time);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+    class JwkTask implements Runnable{
+        private final DiscoveryClient discoveryClient;
+
+        public JwkTask(DiscoveryClient discoveryClient) {
+            this.discoveryClient = discoveryClient;
+        }
+
+        @Override
+        public void run() {
+            while (jwtSigner == null) {
+                try {
+                    log.info("尝试加载auth服务地址");
+                    List<ServiceInstance> instances = discoveryClient.getInstances("auth-service");
+                    if(CollUtils.isEmpty(instances)){
+                        log.error("加载auth服务地址失败,原因:数据为空");
+                        sleep(10000);
+                        continue;
+                    }
+                    ServiceInstance instance = instances.get(0);
+                    String jwkUri = String.format("http://%s:%d/jwks", instance.getHost(), instance.getPort());
+                    log.info("加载auth服务地址成功,{}", jwkUri);
+
+                    log.info("尝试加载jwk秘钥");
+                    // 请求获取jwk
+                    String result = HttpUtil.get(jwkUri, StandardCharsets.UTF_8);
+                    if(result == null){
+                        log.error("加载jwk秘钥失败,原因:数据为空");
+                        sleep(10000);
+                        continue;
+                    }
+                    // 解析
+                    PublicKey publicKey = KeyUtil.generatePublicKey(
+                            AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue(),
+                            SecureUtil.decode(result)
+                    );
+                    jwtSigner = JWTSignerUtil.createSigner(JwtConstants.JWT_ALGORITHM, publicKey);
+                    log.info("加载jwk秘钥成功!");
+                } catch (Exception e) {
+                    log.error("加载jwk秘钥失败,原因:{}", e.getMessage());
+                    sleep(10000);
+                }
+            }
+            // 关闭线程池
+            shutdown();
+        }
+    }
+}

+ 19 - 0
gig/gig-auth/gig-auth-gateway-sdk/src/main/resources/META-INF/spring-configuration-metadata.json

@@ -0,0 +1,19 @@
+{
+  "groups": [
+    {
+      "name": "gig.auth.gateway",
+      "type": "com.stellvoy.authsdk.gateway.config.AuthAutoConfiguration",
+      "sourceType": "com.stellvoy.authsdk.gateway.config.AuthProperties"
+    }
+  ],
+  "properties": [
+    {
+      "name": "gig.auth.excludePath",
+      "type": "java.util.Set",
+      "description": "不用登录就能访问的路径,ant风格通配符",
+      "sourceType": "com.stellvoy.authsdk.gateway.config.AuthProperties",
+      "defaultValue": ""
+    }
+  ],
+  "hints": []
+}

+ 2 - 0
gig/gig-auth/gig-auth-gateway-sdk/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.stellvoy.authsdk.gateway.config.AuthAutoConfiguration

+ 42 - 0
gig/gig-auth/gig-auth-resource-sdk/pom.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.stellvoy</groupId>
+        <artifactId>gig-auth</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>gig-auth-resource-sdk</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.stellvoy</groupId>
+            <artifactId>gig-auth-common</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.github.openfeign</groupId>
+            <artifactId>feign-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 17 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/config/FeignRelayUserAutoConfiguration.java

@@ -0,0 +1,17 @@
+package com.stellvoy.authsdk.resource.config;
+
+import com.stellvoy.authsdk.resource.interceptors.FeignRelayUserInterceptor;
+import feign.Feign;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnClass(Feign.class)
+public class FeignRelayUserAutoConfiguration {
+
+    @Bean
+    public FeignRelayUserInterceptor feignRelayUserInterceptor(){
+        return new FeignRelayUserInterceptor();
+    }
+}

+ 14 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/config/ResourceAuthProperties.java

@@ -0,0 +1,14 @@
+package com.stellvoy.authsdk.resource.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.List;
+
+@Data
+@ConfigurationProperties(prefix = "gig.auth.resource")
+public class ResourceAuthProperties {
+    private Boolean enable = false;
+    private List<String> includeLoginPaths;
+    private List<String> excludeLoginPaths;
+}

+ 44 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/config/ResourceInterceptorConfiguration.java

@@ -0,0 +1,44 @@
+package com.stellvoy.authsdk.resource.config;
+
+import cn.hutool.core.collection.CollUtil;
+import com.stellvoy.authsdk.resource.interceptors.LoginAuthInterceptor;
+import com.stellvoy.authsdk.resource.interceptors.UserInfoInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@EnableConfigurationProperties(ResourceAuthProperties.class)
+public class ResourceInterceptorConfiguration implements WebMvcConfigurer {
+
+    private final ResourceAuthProperties authProperties;
+
+    @Autowired
+    public ResourceInterceptorConfiguration(ResourceAuthProperties resourceAuthProperties) {
+        this.authProperties = resourceAuthProperties;
+    }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 1.添加用户信息拦截器
+        registry.addInterceptor(new UserInfoInterceptor()).order(0);
+        // 2.是否需要做登录拦截
+        if(!authProperties.getEnable()){
+            // 无需登录拦截
+            return;
+        }
+        // 2.添加登录拦截器
+        InterceptorRegistration registration = registry.addInterceptor(new LoginAuthInterceptor()).order(1);
+        // 2.1.添加拦截器路径
+        if(CollUtil.isNotEmpty(authProperties.getIncludeLoginPaths())){
+            registration.addPathPatterns(authProperties.getIncludeLoginPaths());
+        }
+        // 2.2.添加排除路径
+        if(CollUtil.isNotEmpty(authProperties.getExcludeLoginPaths())){
+            registration.excludePathPatterns(authProperties.getExcludeLoginPaths());
+        }
+    }
+}

+ 17 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/interceptors/FeignRelayUserInterceptor.java

@@ -0,0 +1,17 @@
+package com.stellvoy.authsdk.resource.interceptors;
+
+import com.stellvoy.auth.common.constants.JwtConstants;
+import com.stellvoy.common.utils.UserContext;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+
+public class FeignRelayUserInterceptor implements RequestInterceptor {
+    @Override
+    public void apply(RequestTemplate template) {
+        Long userId = UserContext.getUser();
+        if (userId == null) {
+            return;
+        }
+        template.header(JwtConstants.USER_HEADER, userId.toString());
+    }
+}

+ 27 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/interceptors/LoginAuthInterceptor.java

@@ -0,0 +1,27 @@
+package com.stellvoy.authsdk.resource.interceptors;
+
+import com.stellvoy.common.utils.UserContext;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Slf4j
+public class LoginAuthInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        // 1.尝试获取用户信息
+        Long userId = UserContext.getUser();
+        // 2.判断是否登录
+        if (userId == null) {
+            response.setStatus(401);
+            response.sendError(401, "未登录用户无法访问!");
+            // 2.3.未登录,直接拦截
+            return false;
+        }
+        // 3.登录则放行
+        return true;
+    }
+}

+ 38 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/java/com/stellvoy/authsdk/resource/interceptors/UserInfoInterceptor.java

@@ -0,0 +1,38 @@
+package com.stellvoy.authsdk.resource.interceptors;
+
+import com.stellvoy.auth.common.constants.JwtConstants;
+import com.stellvoy.common.utils.UserContext;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Slf4j
+public class UserInfoInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        // 1.尝试获取头信息中的用户信息
+        String authorization = request.getHeader(JwtConstants.USER_HEADER);
+        // 2.判断是否为空
+        if (authorization == null) {
+            return true;
+        }
+        // 3.转为用户id并保存
+        try {
+            Long userId = Long.valueOf(authorization);
+            UserContext.setUser(userId);
+            return true;
+        } catch (NumberFormatException e) {
+            log.error("用户身份信息格式不正确,{}, 原因:{}", authorization, e.getMessage());
+            return true;
+        }
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        // 清理用户信息
+        UserContext.removeUser();
+    }
+}

+ 31 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/resources/META-INF/spring-configuration-metadata.json

@@ -0,0 +1,31 @@
+{
+  "groups": [
+    {
+      "name": "gig.auth.resource",
+      "type": "com.stellvoy.authsdk.resource.config.ResourceInterceptorConfiguration",
+      "sourceType": "com.stellvoy.authsdk.resource.config.ResourceAuthProperties"
+    }
+  ],
+  "properties": [
+    {
+      "name": "gig.auth.resource.enable",
+      "type": "java.lang.Boolean",
+      "description": "是否开启登录拦截功能,如果开启则需要指定拦截路径,默认拦截所有",
+      "sourceType": "com.stellvoy.authsdk.resource.config.ResourceAuthProperties",
+      "defaultValue": false
+    },
+    {
+      "name": "gig.auth.resource.includeLoginPaths",
+      "type": "java.util.List",
+      "description": "要拦截的路径,例如:/user/**",
+      "sourceType": "com.stellvoy.authsdk.resource.config.ResourceAuthProperties"
+    },
+    {
+      "name": "gig.auth.resource.excludeLoginPaths",
+      "type": "java.util.List",
+      "description": "不拦截的路径,例如:/user/**",
+      "sourceType": "com.stellvoy.authsdk.resource.config.ResourceAuthProperties"
+    }
+  ],
+  "hints": []
+}

+ 3 - 0
gig/gig-auth/gig-auth-resource-sdk/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+  com.stellvoy.authsdk.resource.config.ResourceInterceptorConfiguration, \
+  com.stellvoy.authsdk.resource.config.FeignRelayUserAutoConfiguration

+ 93 - 0
gig/gig-auth/gig-auth-service/pom.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.stellvoy</groupId>
+        <artifactId>gig-auth</artifactId>
+        <version>1.0.0</version>
+    </parent>
+
+    <artifactId>gig-auth-service</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.stellvoy</groupId>
+            <artifactId>gig-api</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <!--Redis-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <!--redisson-->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+        </dependency>
+        <!--commons-pool2-->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+        <!--discovery-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!--config-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <!--loadbalancer-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+        <!--sdk-->
+        <dependency>
+            <groupId>com.stellvoy</groupId>
+            <artifactId>gig-auth-resource-sdk</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build-info</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <mainClass>com.stellvoy.auth.AuthApplication</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 41 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/AuthApplication.java

@@ -0,0 +1,41 @@
+package com.stellvoy.auth;
+
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+@MapperScan("com.stellvoy.auth.mapper")
+@SpringBootApplication
+@EnableScheduling
+@Slf4j
+public class AuthApplication {
+    public static void main(String[] args) throws UnknownHostException {
+        SpringApplication app = new SpringApplicationBuilder(AuthApplication.class).build(args);
+        Environment env = app.run(args).getEnvironment();
+        String protocol = "http";
+        if (env.getProperty("server.ssl.key-store") != null) {
+            protocol = "https";
+        }
+        log.info("--/\n---------------------------------------------------------------------------------------\n\t" +
+                        "Application '{}' is running! Access URLs:\n\t" +
+                        "Local: \t\t{}://localhost:{}\n\t" +
+                        "External: \t{}://{}:{}\n\t" +
+                        "Profile(s): \t{}" +
+                        "\n---------------------------------------------------------------------------------------",
+                env.getProperty("spring.application.name"),
+                protocol,
+                env.getProperty("server.port"),
+                protocol,
+                InetAddress.getLocalHost().getHostAddress(),
+                env.getProperty("server.port"),
+                env.getActiveProfiles());
+        log.info("--/\n------------------------------------------------------------------------------\n\t" );
+    }
+}

+ 41 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/config/AuthConfig.java

@@ -0,0 +1,41 @@
+package com.stellvoy.auth.config;
+
+import org.apache.tomcat.util.http.LegacyCookieProcessor;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
+import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
+
+import java.security.KeyPair;
+
+@Configuration
+@EnableConfigurationProperties(KeyProperties.class)
+public class AuthConfig {
+
+    @Bean
+    @ConfigurationProperties(prefix = "encrypt")
+    public KeyProperties keyProperties(){
+        return new KeyProperties();
+    }
+
+    @Bean
+    public KeyPair keyPair(KeyProperties keyProperties){
+        // 获取秘钥工厂
+        KeyStoreKeyFactory keyStoreKeyFactory =
+                new KeyStoreKeyFactory(
+                        keyProperties.getKeyStore().getLocation(),
+                        keyProperties.getKeyStore().getPassword().toCharArray());
+        //读取钥匙对
+        return keyStoreKeyFactory.getKeyPair(
+                keyProperties.getKeyStore().getAlias(),
+                keyProperties.getKeyStore().getSecret().toCharArray());
+    }
+
+    @Bean
+    public TomcatContextCustomizer cookieTomcatContextCustomizer(){
+        return context -> context.setCookieProcessor(new LegacyCookieProcessor());
+    }
+}

+ 6 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/constants/AuthConstants.java

@@ -0,0 +1,6 @@
+package com.stellvoy.auth.constants;
+
+public abstract class AuthConstants {
+    /*管理员的角色ID*/
+    public static final Long ADMIN_ROLE_ID = 1L;
+}

+ 66 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/AccountController.java

@@ -0,0 +1,66 @@
+package com.stellvoy.auth.controller;
+
+
+import com.stellvoy.api.dto.user.LoginFormDTO;
+import com.stellvoy.auth.common.constants.JwtConstants;
+import com.stellvoy.auth.service.IAccountService;
+import com.stellvoy.common.exceptions.BadRequestException;
+import com.stellvoy.common.utils.WebUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * 账户登录相关接口
+ */
+@RestController
+@RequestMapping("/accounts")
+//@Api(tags = "账户管理")
+@RequiredArgsConstructor
+public class AccountController {
+
+    private final IAccountService accountService;
+
+//    @ApiOperation("登录并获取token")
+    @PostMapping(value = "/login")
+    public String loginByPw(@RequestBody LoginFormDTO loginFormDTO) {
+        return accountService.login(loginFormDTO, false);
+    }
+
+//    @ApiOperation("管理端登录并获取token")
+    @PostMapping(value = "/admin/login")
+    public String adminLoginByPw(@RequestBody LoginFormDTO loginFormDTO) {
+        return accountService.login(loginFormDTO, true);
+    }
+
+//    @ApiOperation("退出登录")
+    @PostMapping(value = "/logout")
+    public void logout() {
+        accountService.logout();
+    }
+
+//    @ApiOperation("刷新token")
+    @GetMapping(value = "/refresh")
+    public String refreshToken(
+            @CookieValue(value = JwtConstants.REFRESH_HEADER, required = false) String studentToken,
+            @CookieValue(value = JwtConstants.ADMIN_REFRESH_HEADER, required = false) String adminToken
+    ) {
+        if (studentToken == null && adminToken == null) {
+            throw new BadRequestException("登录超时");
+        }
+        String host = WebUtils.getHeader("origin");
+        if (host == null) {
+            throw new BadRequestException("登录超时");
+        }
+        String token = host.startsWith("www", 7) ? studentToken : adminToken;
+        if (token == null) {
+            throw new BadRequestException("登录超时");
+        }
+        try {
+            return accountService.refreshToken(WebUtils.cookieBuilder().decode(token));
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 28 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/JwkController.java

@@ -0,0 +1,28 @@
+package com.stellvoy.auth.controller;
+
+import cn.hutool.core.codec.Base64;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.KeyPair;
+
+@RestController
+@RequestMapping("jwks")
+public class JwkController {
+
+    private final KeyPair keyPair;
+
+    @Autowired
+    public JwkController(KeyPair keyPair) {
+        this.keyPair = keyPair;
+    }
+
+    @GetMapping
+    public String getJwk(){
+        // TODO 可以加入clientId和clientSecret校验
+        // 获取公钥并转码
+        return Base64.encode(keyPair.getPublic().getEncoded());
+    }
+}

+ 143 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/MenuController.java

@@ -0,0 +1,143 @@
+package com.stellvoy.auth.controller;
+
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.stellvoy.auth.domain.dto.MenuDTO;
+import com.stellvoy.auth.domain.po.Menu;
+import com.stellvoy.auth.domain.vo.MenuOptionVO;
+import com.stellvoy.auth.service.IMenuService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 权限表,包括菜单权限和访问路径权限 前端控制器
+ * </p>
+ */
+@RestController
+@RequestMapping("/menus")
+//@Api(tags = "菜单管理")
+@RequiredArgsConstructor
+public class MenuController {
+
+    private final IMenuService menuService;
+
+    /**
+     * 根据父菜单id查询子菜单
+     * @param pid 父菜单id,如果给 0 就是查询1级菜单
+     * @return 菜单集合
+     */
+    @GetMapping("/parent/{pid}")
+    public List<MenuOptionVO> listMenusByParent(
+             @PathVariable("pid") Long pid){
+        // 1.根据父id查询
+        List<Menu> list = menuService.lambdaQuery().eq(Menu::getParentId, pid).list();
+        // 2.非空判断
+        if (CollectionUtil.isEmpty(list)) {
+            return Collections.emptyList();
+        }
+        // 3.数据转换
+        return list.stream().map(MenuOptionVO::new).collect(Collectors.toList());
+    }
+
+    @GetMapping("{id}")
+//    @ApiOperation("根据id查询菜单")
+    public MenuOptionVO getMenuById( @PathVariable("id") Long id) {
+        Menu menu = menuService.getById(id);
+        if (menu == null) {
+            return null;
+        }
+        return new MenuOptionVO(menu);
+    }
+
+    /**
+     * 查询菜单,按照多级菜单组成树结构
+     * @return 菜单列表,组成树结构
+     */
+    @GetMapping
+    public List<MenuOptionVO> listMenuTree(){
+        // 1.查询所有菜单
+        List<Menu> menus = menuService.list();
+        return convert2MenuDTOs(menus);
+    }
+
+    private List<MenuOptionVO> convert2MenuDTOs(List<Menu> menus) {
+        if (CollectionUtil.isEmpty(menus)) {
+            return Collections.emptyList();
+        }
+        // 2.按照父菜单id分组
+        Map<Long, List<MenuOptionVO>> menuMap = menus.stream()
+                .map(MenuOptionVO::new)
+                .collect(Collectors.groupingBy(MenuOptionVO::getParentId));
+        // 3.组合
+        // 3.1.获取1级菜单
+        List<MenuOptionVO> parents = menuMap.get(0L);
+        // 3.2.获取2级菜单
+        for (MenuOptionVO parent : parents) {
+            List<MenuOptionVO> subMenus = menuMap.get(parent.getId());
+            subMenus.sort(Comparator.comparingInt(MenuOptionVO::getPriority));
+            parent.setSubMenus(subMenus);
+        }
+        // 3.3.排序
+        parents.sort(Comparator.comparingInt(MenuOptionVO::getPriority));
+        return parents;
+    }
+
+    /**
+     * 根据当前登录用户的权限查询菜单选项,按照多级菜单组成树结构
+     * @return 菜单列表,组成树结构
+     */
+    @GetMapping("me")
+    public List<MenuOptionVO> listMenuTreeByUser(){
+        // 1.查询所有菜单
+        List<Menu> menus = menuService.listMenuByUser();
+        return convert2MenuDTOs(menus);
+    }
+
+    @PostMapping
+//    @ApiOperation("新增菜单")
+    public void saveMenu(@RequestBody MenuDTO menuDTO){
+        // 1.数据转换
+        Menu menu = new Menu(menuDTO);
+        // 2.保存
+        menuService.saveMenu(menu);
+    }
+
+    @PutMapping("{id}")
+//    @ApiOperation("更新菜单")
+    public void updateMenu(
+            @RequestBody MenuDTO menuDTO,
+            @PathVariable("id") Long id) {
+        menuDTO.setId(id);
+        menuService.updateById(new Menu(menuDTO));
+    }
+
+    @DeleteMapping("{id}")
+//    @ApiOperation("根据id删除菜单")
+    public void deleteMenu(
+            @PathVariable("id") Long id) {
+        menuService.deleteMenu(id);
+    }
+
+    @PostMapping("/role/{roleId}")
+//    @ApiOperation("绑定角色与菜单权限")
+    public void bindRoleMenus(
+             @PathVariable("roleId") Long roleId,
+             List<Long> menuIds){
+        menuService.bindRoleMenus(roleId, menuIds);
+    }
+
+    @DeleteMapping("/role/{roleId}")
+//    @ApiOperation("解除角色的菜单权限")
+    public void deleteRoleMenus(
+             @PathVariable("roleId") Long roleId,
+             List<Long> menuIds){
+        menuService.deleteRoleMenus(roleId, menuIds);
+    }
+}

+ 186 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/PrivilegeController.java

@@ -0,0 +1,186 @@
+package com.stellvoy.auth.controller;
+
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.stellvoy.auth.domain.dto.PrivilegeDTO;
+import com.stellvoy.auth.domain.po.Privilege;
+import com.stellvoy.auth.domain.vo.PrivilegeOptionVO;
+import com.stellvoy.auth.service.IPrivilegeService;
+import com.stellvoy.common.domain.dto.PageDTO;
+import com.stellvoy.common.domain.query.PageQuery;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 权限表,包括菜单权限和访问路径权限 前端控制器
+ * </p>
+ */
+@RestController
+@RequestMapping("/privileges")
+//@Api(tags = "权限管理接口")
+@RequiredArgsConstructor
+public class PrivilegeController {
+
+    private final IPrivilegeService privilegesService;
+
+    /**
+     * 分页查询所有权限
+     *
+     * @param pageQuery 分页查询条件
+     * @return 分页结果
+     */
+//    @ApiOperation("分页查询所有权限")
+    @GetMapping
+    public PageDTO<PrivilegeDTO> listAllPrivileges(PageQuery pageQuery) {
+        // 1.分页查询
+        Page<Privilege> page = privilegesService.listPrivilegesByPage(pageQuery);
+        // 2.非空判断
+        List<Privilege> list = page.getRecords();
+        if (CollectionUtil.isEmpty(list)) {
+            // 结果为空,返回空结果 添加总页码数
+            return new PageDTO<>(page.getTotal(), page.getPages(), Collections.emptyList());
+        }
+        // 3.数据转换
+        List<PrivilegeDTO> dtoList = list.stream().map(Privilege::toDTO).collect(Collectors.toList());
+        // 4.封装返回
+        return new PageDTO<>(page.getTotal(), page.getPages(), dtoList);
+    }
+
+    /**
+     * 查询所有权限,作为下拉选框菜单
+     *
+     * @return 分页结果
+     */
+//    @ApiOperation("查询菜单下的所有权限,作为下拉选框菜单")
+    @GetMapping("options/{menuId}")
+    public List<PrivilegeOptionVO> listAllPrivilegesOptionsByMenuId(
+             @PathVariable("menuId") Long menuId
+    ) {
+        // 1.查询菜单下的权限
+        List<Privilege> list = privilegesService.lambdaQuery()
+                .eq(Privilege::getMenuId, menuId)
+                .eq(Privilege::getInternal, false)
+                .list();
+        // 2.非空判断
+        if (CollectionUtil.isEmpty(list)) {
+            // 结果为空,返回空结果
+            return Collections.emptyList();
+        }
+        // 3.数据转换
+        return list.stream()
+                .map(PrivilegeOptionVO::new).collect(Collectors.toList());
+    }
+
+    /**
+     * 查询某个角色的权限
+     *
+     * @return 某个角色的权限列表
+     */
+//    @ApiOperation("查询菜单下的权限列表,某个角色的权限")
+    @GetMapping("/roles/{roleId}/{menuId}")
+    public List<PrivilegeOptionVO> listPrivilegeByRoleId(
+             @PathVariable("roleId") Long roleId,
+             @PathVariable("menuId") Long menuId
+    ) {
+        // 1.查询角色对应的权限id
+        Set<Long> privilegeIds = privilegesService.listPrivilegeByRoleId(roleId);
+        if (CollectionUtil.isEmpty(privilegeIds)) {
+            return Collections.emptyList();
+        }
+        // 2.查询菜单下所有权限
+        List<PrivilegeOptionVO> vos = listAllPrivilegesOptionsByMenuId(menuId);
+        // 3.标记
+        for (PrivilegeOptionVO vo : vos) {
+            vo.setChecked(privilegeIds.contains(vo.getId()));
+        }
+        return vos;
+    }
+
+    /**
+     * 新增权限
+     *
+     * @param privilegeDTO 权限数据
+     * @return 新增成功的权限数据
+     */
+//    @ApiOperation("新增权限")
+    @PostMapping
+    public PrivilegeDTO savePrivilege(@Validated @RequestBody PrivilegeDTO privilegeDTO) {
+        // 域对象转换
+        Privilege privilege = new Privilege(privilegeDTO);
+        // 新增
+        privilegesService.savePrivilege(privilege);
+        // 返回
+        return privilege.toDTO();
+    }
+
+    /**
+     * 修改权限
+     *
+     * @param privilegeDTO 权限数据
+     * @param id           要修改的权限的id
+     * @return 修改后的权限结果
+     */
+//    @ApiOperation("修改权限")
+    @PutMapping("{id}")
+    public PrivilegeDTO updatePrivilege(
+            @RequestBody PrivilegeDTO privilegeDTO,
+            @PathVariable("id") Long id) {
+        // 域对象转换
+        Privilege privilege = new Privilege(privilegeDTO);
+        privilege.setId(id);
+        // 修改
+        privilegesService.updateById(privilege);
+        // 返回
+        return privilege.toDTO();
+    }
+
+    /**
+     * 删除权限
+     *
+     * @param id 权限id
+     */
+//    @ApiOperation("删除权限")
+    @DeleteMapping("{id}")
+    public void removePrivilegeById(
+            @PathVariable("id") Long id) {
+        privilegesService.removePrivilegeById(id);
+    }
+
+    /**
+     * 绑定角色与API权限
+     *
+     * @param roleId       角色id
+     * @param privilegeIds 权限id集合
+     */
+    @PostMapping("/role/{roleId}")
+//    @ApiOperation("绑定角色与API权限")
+    public void bindRolePrivileges(
+             @PathVariable("roleId") Long roleId,
+             List<Long> privilegeIds) {
+        privilegesService.bindRolePrivileges(roleId, privilegeIds);
+    }
+
+    /**
+     * 解除角色的API权限
+     *
+     * @param roleId       角色id
+     * @param privilegeIds 权限id集合
+     */
+    @DeleteMapping("/role/{roleId}")
+//    @ApiOperation("解除角色的API权限")
+    public void deleteRolePrivileges(
+             @PathVariable("roleId") Long roleId,
+             List<Long> privilegeIds) {
+        privilegesService.deleteRolePrivileges(roleId, privilegeIds);
+    }
+
+
+}

+ 92 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/controller/RoleController.java

@@ -0,0 +1,92 @@
+package com.stellvoy.auth.controller;
+
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.stellvoy.api.dto.auth.RoleDTO;
+import com.stellvoy.auth.domain.po.Role;
+import com.stellvoy.auth.service.IRoleService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+
+//@Api(tags = "角色管理")
+@RestController
+@RequestMapping("/roles")
+@RequiredArgsConstructor
+public class RoleController {
+
+    private final IRoleService roleService;
+
+//    @ApiOperation("查询员工角色列表")
+    @GetMapping("/list")
+    public List<RoleDTO> listAllRoles(){
+        // 1.查询
+        List<Role> list = roleService.list();
+        if (CollectionUtil.isEmpty(list)) {
+            return Collections.emptyList();
+        }
+        // 3.数据转换
+        return list.stream().map(Role::toDTO).collect(Collectors.toList());
+    }
+
+//    @ApiOperation("查询员工角色列表")
+    @GetMapping
+    public List<RoleDTO> listStaffRoles(){
+        // 1.查询
+        List<Role> list = roleService.lambdaQuery().eq(Role::getType, Role.RoleType.CUSTOM).list();
+        if (CollectionUtil.isEmpty(list)) {
+            return Collections.emptyList();
+        }
+        // 3.数据转换
+        return list.stream().map(Role::toDTO).collect(Collectors.toList());
+    }
+
+//    @ApiOperation("根据id查询角色")
+    @GetMapping("/{id}")
+    public RoleDTO queryRoleById(@PathVariable("id") Long id){
+        // 1.查询
+        Role role = roleService.getById(id);
+        if (role == null) {
+            return null;
+        }
+        // 2.数据转换
+        return role.toDTO();
+    }
+
+
+
+//    @ApiOperation("新增角色")
+    @PostMapping
+    public RoleDTO saveRole(@RequestBody RoleDTO roleDTO) {
+        Role role = new Role(roleDTO);
+        role.setType(Role.RoleType.CUSTOM);
+        // 1.新增
+        roleService.save(role);
+        // 2.返回
+        roleDTO.setId(role.getId());
+        return roleDTO;
+    }
+
+//    @ApiOperation("修改角色信息")
+    @PutMapping("{id}")
+    public void updateRole(
+            @RequestBody RoleDTO roleDTO,
+            @PathVariable("id") Long id
+    ) {
+        // 1.数据转换
+        Role role = new Role(roleDTO);
+        role.setId(id);
+        // 2.修改
+        roleService.updateById(role);
+    }
+
+//    @ApiOperation("删除角色信息")
+    @DeleteMapping("{id}")
+    public void deleteRole( @PathVariable("id") Long id) {
+        roleService.deleteRole(id);
+    }
+}

+ 25 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/dto/MenuDTO.java

@@ -0,0 +1,25 @@
+package com.stellvoy.auth.domain.dto;
+
+import lombok.Data;
+
+@Data
+//@ApiModel(description = "菜单表单实体")
+public class MenuDTO {
+//    @ApiModelProperty(value = "菜单id", example = "1")
+    private Long id;
+
+//    @ApiModelProperty(value = "父菜单id", example = "0")
+    private Long parentId;
+
+//    @ApiModelProperty(value = "菜单文本", example = "系统管理")
+    private String label;
+
+//    @ApiModelProperty(value = "菜单路径", example = "/sys/index")
+    private String path;
+
+//    @ApiModelProperty(value = "菜单图标", example = "el-icon-sys")
+    private String icon;
+
+//    @ApiModelProperty(value = "菜单顺序", example = "1")
+    private Integer priority;
+}

+ 30 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/dto/PrivilegeDTO.java

@@ -0,0 +1,30 @@
+package com.stellvoy.auth.domain.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+//@ApiModel(description = "API权限")
+public class PrivilegeDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+//    @ApiModelProperty(value = "权限id", example = "1")
+    private Long id;
+//    @ApiModelProperty(value = "权限所属菜单id", example = "1")
+    private Long menuId;
+//    @ApiModelProperty(value = "权限说明", example = "新增员工")
+    @NotNull(message = "权限说明不能为空")
+    private String intro;
+//    @ApiModelProperty(value = "API请求方式", example = "GET")
+    @Pattern(regexp = "^GET|POST|PUT|DELETE$", message = "请求方式必须是大写")
+    private String method;
+//    @ApiModelProperty(value = "API请求路径", example = "/account/staff")
+    @NotNull(message = "uri不能为空")
+    private String uri;
+//    @ApiModelProperty("是否是内部权限")
+    private Boolean internal;
+}

+ 38 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/AccountRole.java

@@ -0,0 +1,38 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 账户、角色关联表
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("account_role")
+public class AccountRole implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 账户id
+     */
+    private Long accountId;
+
+    /**
+     * 角色id
+     */
+    private Long roleId;
+
+}

+ 69 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/LoginRecord.java

@@ -0,0 +1,69 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 登录信息记录表
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("login_record")
+public class LoginRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 用户id
+     */
+    private String cellPhone;
+
+    /**
+     * 登录时间
+     */
+    private LocalDateTime loginTime;
+
+    /**
+     * 登出时间
+     */
+    private LocalDateTime logoutTime;
+
+    /**
+     * 登录日期
+     */
+    private LocalDate loginDate;
+
+    /**
+     * 登录时长,单位是秒
+     */
+    private Long duration;
+
+    /**
+     * ip地址
+     */
+    private String ipv4;
+
+
+}

+ 116 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/Menu.java

@@ -0,0 +1,116 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.stellvoy.auth.domain.dto.MenuDTO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 权限表,包括菜单权限和访问路径权限
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("menu")
+@NoArgsConstructor
+public class Menu implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 父菜单id,默认0代表没有父菜单
+     */
+    private Long parentId;
+
+    /**
+     * 是否有子菜单,默认false
+     */
+    private Boolean hasChildren;
+
+    /**
+     * 菜单文本
+     */
+    private String label;
+
+    /**
+     * 菜单路径
+     */
+    private String path;
+
+    /**
+     * 菜单图标
+     */
+    private String icon;
+
+    /**
+     * 顺序优先级,默认127
+     */
+    private Integer priority;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 创建者id
+     */
+
+    private Long creater;
+
+    /**
+     * 更新者id
+     */
+
+    private Long updater;
+
+    /**
+     * 部门id
+     */
+    private Long depId;
+
+    /**
+     * 逻辑删除,默认0
+     */
+    private Integer deleted;
+
+
+    public Menu(MenuDTO dto) {
+        this.id = dto.getId();
+        this.parentId = dto.getParentId();
+        this.label = dto.getLabel();
+        this.path = dto.getPath();
+        this.icon = dto.getIcon();
+        this.priority = dto.getPriority();
+    }
+
+    public MenuDTO toDTO(){
+        MenuDTO dto = new MenuDTO();
+        dto.setId(id);
+        dto.setPath(path);
+        dto.setParentId(parentId);
+        dto.setLabel(label);
+        dto.setIcon(icon);
+        dto.setPriority(priority);
+        return dto;
+    }
+}

+ 111 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/Privilege.java

@@ -0,0 +1,111 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.stellvoy.auth.domain.dto.PrivilegeDTO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 权限表,包括菜单权限和访问路径权限
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("`privilege`")
+public class Privilege implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 菜单id
+     */
+    private Long menuId;
+
+    /**
+     * 说明
+     */
+    private String intro;
+
+    /**
+     * API权限的请求方式
+     */
+    private String method;
+
+    /**
+     * API权限的请求路径
+     */
+    private String uri;
+
+    /**
+     * 是否是内部接口
+     */
+    private Boolean internal;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 创建者id
+     */
+
+    private Long creater;
+
+    /**
+     * 更新者id
+     */
+
+    private Long updater;
+
+    /**
+     * 部门id
+     */
+    private Long depId;
+
+    /**
+     * 逻辑删除,默认0
+     */
+    private Integer deleted;
+
+    public Privilege() {
+    }
+
+    public Privilege(PrivilegeDTO dto) {
+        this.id = dto.getId();
+        this.menuId = dto.getMenuId();
+        this.intro = dto.getIntro();
+        this.method = dto.getMethod();
+        this.uri = dto.getUri();
+        this.internal = dto.getInternal();
+    }
+
+    public PrivilegeDTO toDTO(){
+        PrivilegeDTO dto = new PrivilegeDTO();
+        dto.setId(id);
+        dto.setMenuId(menuId);
+        dto.setIntro(intro);
+        dto.setMethod(method);
+        dto.setUri(uri);
+        dto.setInternal(internal);
+        return dto;
+    }
+}

+ 108 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/Role.java

@@ -0,0 +1,108 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.stellvoy.api.dto.auth.RoleDTO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 角色表
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("role")
+@NoArgsConstructor
+public class Role implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 角色代号,例如:admin
+     */
+    private String code;
+
+    /**
+     * 角色名称
+     */
+    private String name;
+
+    /**
+     * 角色类型:0-固定角色(不可选)1-自定义角色
+     */
+    private RoleType type;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 创建者id
+     */
+
+    private Long creater;
+
+    /**
+     * 更新者id
+     */
+
+    private Long updater;
+    /**
+     * 部门id
+     */
+    private Long depId;
+
+    /**
+     * 逻辑删除,默认0
+     */
+    private Integer deleted;
+
+    public Role(RoleDTO dto) {
+        this.id = dto.getId();
+        this.code = dto.getCode();
+        this.name = dto.getName();
+    }
+
+    public RoleDTO toDTO(){
+        RoleDTO dto = new RoleDTO();
+        dto.setId(id);
+        dto.setCode(code);
+        dto.setName(name);
+        return dto;
+    }
+
+    @Getter
+    public enum RoleType{
+        CONSTANT(0, "固定角色"),
+        CUSTOM(1, "自定义角色"),
+        ;
+        @EnumValue
+        int value;
+        String desc;
+
+        RoleType(int value, String desc) {
+            this.value = value;
+            this.desc = desc;
+        }
+    }
+}

+ 44 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/RoleMenu.java

@@ -0,0 +1,44 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 账户、角色关联表
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("role_menu")
+@NoArgsConstructor
+public class RoleMenu implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 角色id
+     */
+    private Long roleId;
+
+    /**
+     * 菜单id
+     */
+    private Long menuId;
+
+    public RoleMenu(Long roleId, Long menuId) {
+        this.roleId = roleId;
+        this.menuId = menuId;
+    }
+}

+ 45 - 0
gig/gig-auth/gig-auth-service/src/main/java/com/stellvoy/auth/domain/po/RolePrivilege.java

@@ -0,0 +1,45 @@
+package com.stellvoy.auth.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 账户、角色关联表
+ * </p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("role_privilege")
+@NoArgsConstructor
+public class RolePrivilege implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 角色id
+     */
+    private Long roleId;
+
+    /**
+     * 权限id
+     */
+    private Long privilegeId;
+
+
+    public RolePrivilege(Long roleId, Long privilegeId) {
+        this.roleId = roleId;
+        this.privilegeId = privilegeId;
+    }
+}

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