marxjaw hace 5 meses
commit
fcfc1e1918
Se han modificado 73 ficheros con 5213 adiciones y 0 borrados
  1. 38 0
      .gitignore
  2. 0 0
      .idea/.gitignore
  3. 21 0
      .idea/dataSources.local.xml
  4. 17 0
      .idea/dataSources.xml
  5. 1439 0
      .idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315.xml
  6. 2 0
      .idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/information_schema.FNRwLQ.meta
  7. 2 0
      .idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/mysql.osA4Bg.meta
  8. 2 0
      .idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/performance_schema.kIw0nw.meta
  9. 2 0
      .idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/sys.zb4BAA.meta
  10. 7 0
      .idea/dictionaries/project.xml
  11. 21 0
      .idea/encodings.xml
  12. 19 0
      .idea/misc.xml
  13. 6 0
      .idea/vcs.xml
  14. 224 0
      .idea/workspace.xml
  15. 66 0
      pom.xml
  16. 36 0
      yt-agent/agent-service/pom.xml
  17. 21 0
      yt-agent/agent-service/src/main/java/com/ytpm/AgentApplication.java
  18. 105 0
      yt-agent/agent-service/src/main/java/com/ytpm/config/CustomUserAuthenticationConverter.java
  19. 72 0
      yt-agent/agent-service/src/main/java/com/ytpm/config/ResourceServerConfig.java
  20. 33 0
      yt-agent/agent-service/src/main/java/com/ytpm/config/feign/FeignConfiguration.java
  21. 40 0
      yt-agent/agent-service/src/main/java/com/ytpm/config/swagger/SwaggerConfig.java
  22. 22 0
      yt-agent/agent-service/src/main/java/com/ytpm/controller/UserController.java
  23. 14 0
      yt-agent/agent-service/src/main/java/com/ytpm/dao/AgentUserMapper.java
  24. 40 0
      yt-agent/agent-service/src/main/java/com/ytpm/handle/AuthExceptionEntryPoint.java
  25. 35 0
      yt-agent/agent-service/src/main/resources/bootstrap.yml
  26. 12 0
      yt-agent/agent-service/src/main/resources/mapper/AgentUserMapper.xml
  27. 112 0
      yt-agent/pom.xml
  28. 106 0
      yt-common/pom.xml
  29. 37 0
      yt-common/src/main/java/com/ytpm/agent/view/AgentUserInfo.java
  30. 20 0
      yt-common/src/main/java/com/ytpm/constant/CacheConstant.java
  31. 59 0
      yt-common/src/main/java/com/ytpm/constant/StrConstant.java
  32. 63 0
      yt-common/src/main/java/com/ytpm/general/BaseParam.java
  33. 44 0
      yt-common/src/main/java/com/ytpm/general/PageMeta.java
  34. 98 0
      yt-common/src/main/java/com/ytpm/general/RepMessage.java
  35. 80 0
      yt-common/src/main/java/com/ytpm/general/Result.java
  36. 88 0
      yt-common/src/main/java/com/ytpm/general/ResultTable.java
  37. 111 0
      yt-common/src/main/java/com/ytpm/general/StatusCode.java
  38. 15 0
      yt-common/src/main/java/com/ytpm/handle/CustomerException.java
  39. 170 0
      yt-common/src/main/java/com/ytpm/handle/CustomerExceptionHandler.java
  40. 7 0
      yt-common/src/main/java/com/ytpm/handle/ValidatedException.java
  41. 56 0
      yt-common/src/main/java/com/ytpm/oauth/model/CaptchaValid.java
  42. 72 0
      yt-common/src/main/java/com/ytpm/oauth/model/YtPlatformUser.java
  43. 218 0
      yt-common/src/main/java/com/ytpm/util/CacheUtil.java
  44. 31 0
      yt-common/src/main/java/com/ytpm/util/CheckPwdUtil.java
  45. 20 0
      yt-common/src/main/java/com/ytpm/util/IDUtil.java
  46. 66 0
      yt-common/src/main/java/com/ytpm/util/RandomPasswordGenerator.java
  47. 231 0
      yt-common/src/main/java/com/ytpm/util/RedisService.java
  48. 73 0
      yt-gateway/pom.xml
  49. 29 0
      yt-gateway/src/main/java/com/ytpm/GatewayApplication.java
  50. 29 0
      yt-gateway/src/main/java/com/ytpm/cors/CustomerCorsConfiguration.java
  51. 31 0
      yt-gateway/src/main/resources/bootstrap.yml
  52. 90 0
      yt-oauth/oauth-service/pom.xml
  53. 22 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/OauthApplication.java
  54. 25 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/auth/AuthService.java
  55. 24 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/auth/CaptchaService.java
  56. 135 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/auth/impl/AuthServiceImpl.java
  57. 80 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/auth/impl/CaptchaServiceImpl.java
  58. 36 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/certify/UserDetailService.java
  59. 50 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/Oauth2Config.java
  60. 68 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/WebSecurityConfig.java
  61. 20 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/auth/AuthListenerConfig.java
  62. 58 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/ClientAuthentication.java
  63. 56 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/CustomAccessDecisionManager.java
  64. 35 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/CustomFilterInvocationSecurityMetadataSource.java
  65. 37 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/server/ResourceServerConfig.java
  66. 19 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/store/RedisTokenStoreConfig.java
  67. 40 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/config/swagger/SwaggerConfig.java
  68. 80 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/controller/OauthController.java
  69. 13 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/dao/YtPlatformUserMapper.java
  70. 15 0
      yt-oauth/oauth-service/src/main/java/com/ytpm/util/EncryptUtil.java
  71. 35 0
      yt-oauth/oauth-service/src/main/resources/bootstrap.yml
  72. 11 0
      yt-oauth/oauth-service/src/main/resources/mapper/YtPlatformUserMapper.xml
  73. 102 0
      yt-oauth/pom.xml

+ 38 - 0
.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

+ 0 - 0
.idea/.gitignore


+ 21 - 0
.idea/dataSources.local.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="dataSourceStorageLocal" created-in="IU-251.25410.109">
+    <data-source name="yt_platform@118.195.137.98" uuid="aeb38baa-93f9-4dd5-bb08-172a691fd315">
+      <database-info product="MySQL" version="5.7.44" jdbc-version="4.2" driver-name="MySQL Connector/J" driver-version="mysql-connector-j-8.2.0 (Revision: 06a1f724497fd81c6a659131fda822c9e5085b6c)" dbms="MYSQL" exact-version="5.7.44" exact-driver-version="8.2">
+        <extra-name-characters>#@</extra-name-characters>
+        <identifier-quote-string>`</identifier-quote-string>
+        <jdbc-catalog-is-schema>true</jdbc-catalog-is-schema>
+      </database-info>
+      <case-sensitivity plain-identifiers="exact" quoted-identifiers="exact" />
+      <secret-storage>master_key</secret-storage>
+      <user-name>yc_marx</user-name>
+      <schema-mapping>
+        <introspection-scope>
+          <node kind="schema" qname="@" />
+        </introspection-scope>
+      </schema-mapping>
+      <load-sources>user_and_system_sources</load-sources>
+    </data-source>
+  </component>
+</project>

+ 17 - 0
.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="yt_platform@118.195.137.98" uuid="aeb38baa-93f9-4dd5-bb08-172a691fd315">
+      <driver-ref>mysql.8</driver-ref>
+      <synchronize>true</synchronize>
+      <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
+      <jdbc-url>jdbc:mysql://118.195.137.98:3306/yt_platform</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>

+ 1439 - 0
.idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315.xml

@@ -0,0 +1,1439 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dataSource name="yt_platform@118.195.137.98">
+  <database-model serializer="dbm" dbms="MYSQL" family-id="MYSQL" format-version="4.53">
+    <root id="1">
+      <DefaultCasing>exact</DefaultCasing>
+      <DefaultEngine>InnoDB</DefaultEngine>
+      <DefaultTmpEngine>InnoDB</DefaultTmpEngine>
+      <ServerVersion>5.7.44</ServerVersion>
+    </root>
+    <collation id="2" parent="1" name="big5_chinese_ci">
+      <Charset>big5</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="3" parent="1" name="big5_bin">
+      <Charset>big5</Charset>
+    </collation>
+    <collation id="4" parent="1" name="dec8_swedish_ci">
+      <Charset>dec8</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="5" parent="1" name="dec8_bin">
+      <Charset>dec8</Charset>
+    </collation>
+    <collation id="6" parent="1" name="cp850_general_ci">
+      <Charset>cp850</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="7" parent="1" name="cp850_bin">
+      <Charset>cp850</Charset>
+    </collation>
+    <collation id="8" parent="1" name="hp8_english_ci">
+      <Charset>hp8</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="9" parent="1" name="hp8_bin">
+      <Charset>hp8</Charset>
+    </collation>
+    <collation id="10" parent="1" name="koi8r_general_ci">
+      <Charset>koi8r</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="11" parent="1" name="koi8r_bin">
+      <Charset>koi8r</Charset>
+    </collation>
+    <collation id="12" parent="1" name="latin1_german1_ci">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="13" parent="1" name="latin1_swedish_ci">
+      <Charset>latin1</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="14" parent="1" name="latin1_danish_ci">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="15" parent="1" name="latin1_german2_ci">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="16" parent="1" name="latin1_bin">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="17" parent="1" name="latin1_general_ci">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="18" parent="1" name="latin1_general_cs">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="19" parent="1" name="latin1_spanish_ci">
+      <Charset>latin1</Charset>
+    </collation>
+    <collation id="20" parent="1" name="latin2_czech_cs">
+      <Charset>latin2</Charset>
+    </collation>
+    <collation id="21" parent="1" name="latin2_general_ci">
+      <Charset>latin2</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="22" parent="1" name="latin2_hungarian_ci">
+      <Charset>latin2</Charset>
+    </collation>
+    <collation id="23" parent="1" name="latin2_croatian_ci">
+      <Charset>latin2</Charset>
+    </collation>
+    <collation id="24" parent="1" name="latin2_bin">
+      <Charset>latin2</Charset>
+    </collation>
+    <collation id="25" parent="1" name="swe7_swedish_ci">
+      <Charset>swe7</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="26" parent="1" name="swe7_bin">
+      <Charset>swe7</Charset>
+    </collation>
+    <collation id="27" parent="1" name="ascii_general_ci">
+      <Charset>ascii</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="28" parent="1" name="ascii_bin">
+      <Charset>ascii</Charset>
+    </collation>
+    <collation id="29" parent="1" name="ujis_japanese_ci">
+      <Charset>ujis</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="30" parent="1" name="ujis_bin">
+      <Charset>ujis</Charset>
+    </collation>
+    <collation id="31" parent="1" name="sjis_japanese_ci">
+      <Charset>sjis</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="32" parent="1" name="sjis_bin">
+      <Charset>sjis</Charset>
+    </collation>
+    <collation id="33" parent="1" name="hebrew_general_ci">
+      <Charset>hebrew</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="34" parent="1" name="hebrew_bin">
+      <Charset>hebrew</Charset>
+    </collation>
+    <collation id="35" parent="1" name="tis620_thai_ci">
+      <Charset>tis620</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="36" parent="1" name="tis620_bin">
+      <Charset>tis620</Charset>
+    </collation>
+    <collation id="37" parent="1" name="euckr_korean_ci">
+      <Charset>euckr</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="38" parent="1" name="euckr_bin">
+      <Charset>euckr</Charset>
+    </collation>
+    <collation id="39" parent="1" name="koi8u_general_ci">
+      <Charset>koi8u</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="40" parent="1" name="koi8u_bin">
+      <Charset>koi8u</Charset>
+    </collation>
+    <collation id="41" parent="1" name="gb2312_chinese_ci">
+      <Charset>gb2312</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="42" parent="1" name="gb2312_bin">
+      <Charset>gb2312</Charset>
+    </collation>
+    <collation id="43" parent="1" name="greek_general_ci">
+      <Charset>greek</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="44" parent="1" name="greek_bin">
+      <Charset>greek</Charset>
+    </collation>
+    <collation id="45" parent="1" name="cp1250_general_ci">
+      <Charset>cp1250</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="46" parent="1" name="cp1250_czech_cs">
+      <Charset>cp1250</Charset>
+    </collation>
+    <collation id="47" parent="1" name="cp1250_croatian_ci">
+      <Charset>cp1250</Charset>
+    </collation>
+    <collation id="48" parent="1" name="cp1250_bin">
+      <Charset>cp1250</Charset>
+    </collation>
+    <collation id="49" parent="1" name="cp1250_polish_ci">
+      <Charset>cp1250</Charset>
+    </collation>
+    <collation id="50" parent="1" name="gbk_chinese_ci">
+      <Charset>gbk</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="51" parent="1" name="gbk_bin">
+      <Charset>gbk</Charset>
+    </collation>
+    <collation id="52" parent="1" name="latin5_turkish_ci">
+      <Charset>latin5</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="53" parent="1" name="latin5_bin">
+      <Charset>latin5</Charset>
+    </collation>
+    <collation id="54" parent="1" name="armscii8_general_ci">
+      <Charset>armscii8</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="55" parent="1" name="armscii8_bin">
+      <Charset>armscii8</Charset>
+    </collation>
+    <collation id="56" parent="1" name="utf8_general_ci">
+      <Charset>utf8</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="57" parent="1" name="utf8_bin">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="58" parent="1" name="utf8_unicode_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="59" parent="1" name="utf8_icelandic_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="60" parent="1" name="utf8_latvian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="61" parent="1" name="utf8_romanian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="62" parent="1" name="utf8_slovenian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="63" parent="1" name="utf8_polish_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="64" parent="1" name="utf8_estonian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="65" parent="1" name="utf8_spanish_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="66" parent="1" name="utf8_swedish_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="67" parent="1" name="utf8_turkish_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="68" parent="1" name="utf8_czech_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="69" parent="1" name="utf8_danish_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="70" parent="1" name="utf8_lithuanian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="71" parent="1" name="utf8_slovak_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="72" parent="1" name="utf8_spanish2_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="73" parent="1" name="utf8_roman_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="74" parent="1" name="utf8_persian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="75" parent="1" name="utf8_esperanto_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="76" parent="1" name="utf8_hungarian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="77" parent="1" name="utf8_sinhala_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="78" parent="1" name="utf8_german2_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="79" parent="1" name="utf8_croatian_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="80" parent="1" name="utf8_unicode_520_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="81" parent="1" name="utf8_vietnamese_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="82" parent="1" name="utf8_general_mysql500_ci">
+      <Charset>utf8</Charset>
+    </collation>
+    <collation id="83" parent="1" name="ucs2_general_ci">
+      <Charset>ucs2</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="84" parent="1" name="ucs2_bin">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="85" parent="1" name="ucs2_unicode_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="86" parent="1" name="ucs2_icelandic_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="87" parent="1" name="ucs2_latvian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="88" parent="1" name="ucs2_romanian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="89" parent="1" name="ucs2_slovenian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="90" parent="1" name="ucs2_polish_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="91" parent="1" name="ucs2_estonian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="92" parent="1" name="ucs2_spanish_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="93" parent="1" name="ucs2_swedish_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="94" parent="1" name="ucs2_turkish_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="95" parent="1" name="ucs2_czech_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="96" parent="1" name="ucs2_danish_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="97" parent="1" name="ucs2_lithuanian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="98" parent="1" name="ucs2_slovak_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="99" parent="1" name="ucs2_spanish2_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="100" parent="1" name="ucs2_roman_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="101" parent="1" name="ucs2_persian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="102" parent="1" name="ucs2_esperanto_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="103" parent="1" name="ucs2_hungarian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="104" parent="1" name="ucs2_sinhala_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="105" parent="1" name="ucs2_german2_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="106" parent="1" name="ucs2_croatian_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="107" parent="1" name="ucs2_unicode_520_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="108" parent="1" name="ucs2_vietnamese_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="109" parent="1" name="ucs2_general_mysql500_ci">
+      <Charset>ucs2</Charset>
+    </collation>
+    <collation id="110" parent="1" name="cp866_general_ci">
+      <Charset>cp866</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="111" parent="1" name="cp866_bin">
+      <Charset>cp866</Charset>
+    </collation>
+    <collation id="112" parent="1" name="keybcs2_general_ci">
+      <Charset>keybcs2</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="113" parent="1" name="keybcs2_bin">
+      <Charset>keybcs2</Charset>
+    </collation>
+    <collation id="114" parent="1" name="macce_general_ci">
+      <Charset>macce</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="115" parent="1" name="macce_bin">
+      <Charset>macce</Charset>
+    </collation>
+    <collation id="116" parent="1" name="macroman_general_ci">
+      <Charset>macroman</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="117" parent="1" name="macroman_bin">
+      <Charset>macroman</Charset>
+    </collation>
+    <collation id="118" parent="1" name="cp852_general_ci">
+      <Charset>cp852</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="119" parent="1" name="cp852_bin">
+      <Charset>cp852</Charset>
+    </collation>
+    <collation id="120" parent="1" name="latin7_estonian_cs">
+      <Charset>latin7</Charset>
+    </collation>
+    <collation id="121" parent="1" name="latin7_general_ci">
+      <Charset>latin7</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="122" parent="1" name="latin7_general_cs">
+      <Charset>latin7</Charset>
+    </collation>
+    <collation id="123" parent="1" name="latin7_bin">
+      <Charset>latin7</Charset>
+    </collation>
+    <collation id="124" parent="1" name="utf8mb4_general_ci">
+      <Charset>utf8mb4</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="125" parent="1" name="utf8mb4_bin">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="126" parent="1" name="utf8mb4_unicode_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="127" parent="1" name="utf8mb4_icelandic_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="128" parent="1" name="utf8mb4_latvian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="129" parent="1" name="utf8mb4_romanian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="130" parent="1" name="utf8mb4_slovenian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="131" parent="1" name="utf8mb4_polish_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="132" parent="1" name="utf8mb4_estonian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="133" parent="1" name="utf8mb4_spanish_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="134" parent="1" name="utf8mb4_swedish_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="135" parent="1" name="utf8mb4_turkish_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="136" parent="1" name="utf8mb4_czech_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="137" parent="1" name="utf8mb4_danish_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="138" parent="1" name="utf8mb4_lithuanian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="139" parent="1" name="utf8mb4_slovak_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="140" parent="1" name="utf8mb4_spanish2_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="141" parent="1" name="utf8mb4_roman_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="142" parent="1" name="utf8mb4_persian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="143" parent="1" name="utf8mb4_esperanto_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="144" parent="1" name="utf8mb4_hungarian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="145" parent="1" name="utf8mb4_sinhala_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="146" parent="1" name="utf8mb4_german2_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="147" parent="1" name="utf8mb4_croatian_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="148" parent="1" name="utf8mb4_unicode_520_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="149" parent="1" name="utf8mb4_vietnamese_ci">
+      <Charset>utf8mb4</Charset>
+    </collation>
+    <collation id="150" parent="1" name="cp1251_bulgarian_ci">
+      <Charset>cp1251</Charset>
+    </collation>
+    <collation id="151" parent="1" name="cp1251_ukrainian_ci">
+      <Charset>cp1251</Charset>
+    </collation>
+    <collation id="152" parent="1" name="cp1251_bin">
+      <Charset>cp1251</Charset>
+    </collation>
+    <collation id="153" parent="1" name="cp1251_general_ci">
+      <Charset>cp1251</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="154" parent="1" name="cp1251_general_cs">
+      <Charset>cp1251</Charset>
+    </collation>
+    <collation id="155" parent="1" name="utf16_general_ci">
+      <Charset>utf16</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="156" parent="1" name="utf16_bin">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="157" parent="1" name="utf16_unicode_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="158" parent="1" name="utf16_icelandic_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="159" parent="1" name="utf16_latvian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="160" parent="1" name="utf16_romanian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="161" parent="1" name="utf16_slovenian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="162" parent="1" name="utf16_polish_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="163" parent="1" name="utf16_estonian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="164" parent="1" name="utf16_spanish_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="165" parent="1" name="utf16_swedish_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="166" parent="1" name="utf16_turkish_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="167" parent="1" name="utf16_czech_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="168" parent="1" name="utf16_danish_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="169" parent="1" name="utf16_lithuanian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="170" parent="1" name="utf16_slovak_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="171" parent="1" name="utf16_spanish2_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="172" parent="1" name="utf16_roman_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="173" parent="1" name="utf16_persian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="174" parent="1" name="utf16_esperanto_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="175" parent="1" name="utf16_hungarian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="176" parent="1" name="utf16_sinhala_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="177" parent="1" name="utf16_german2_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="178" parent="1" name="utf16_croatian_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="179" parent="1" name="utf16_unicode_520_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="180" parent="1" name="utf16_vietnamese_ci">
+      <Charset>utf16</Charset>
+    </collation>
+    <collation id="181" parent="1" name="utf16le_general_ci">
+      <Charset>utf16le</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="182" parent="1" name="utf16le_bin">
+      <Charset>utf16le</Charset>
+    </collation>
+    <collation id="183" parent="1" name="cp1256_general_ci">
+      <Charset>cp1256</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="184" parent="1" name="cp1256_bin">
+      <Charset>cp1256</Charset>
+    </collation>
+    <collation id="185" parent="1" name="cp1257_lithuanian_ci">
+      <Charset>cp1257</Charset>
+    </collation>
+    <collation id="186" parent="1" name="cp1257_bin">
+      <Charset>cp1257</Charset>
+    </collation>
+    <collation id="187" parent="1" name="cp1257_general_ci">
+      <Charset>cp1257</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="188" parent="1" name="utf32_general_ci">
+      <Charset>utf32</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="189" parent="1" name="utf32_bin">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="190" parent="1" name="utf32_unicode_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="191" parent="1" name="utf32_icelandic_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="192" parent="1" name="utf32_latvian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="193" parent="1" name="utf32_romanian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="194" parent="1" name="utf32_slovenian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="195" parent="1" name="utf32_polish_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="196" parent="1" name="utf32_estonian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="197" parent="1" name="utf32_spanish_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="198" parent="1" name="utf32_swedish_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="199" parent="1" name="utf32_turkish_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="200" parent="1" name="utf32_czech_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="201" parent="1" name="utf32_danish_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="202" parent="1" name="utf32_lithuanian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="203" parent="1" name="utf32_slovak_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="204" parent="1" name="utf32_spanish2_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="205" parent="1" name="utf32_roman_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="206" parent="1" name="utf32_persian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="207" parent="1" name="utf32_esperanto_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="208" parent="1" name="utf32_hungarian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="209" parent="1" name="utf32_sinhala_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="210" parent="1" name="utf32_german2_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="211" parent="1" name="utf32_croatian_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="212" parent="1" name="utf32_unicode_520_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="213" parent="1" name="utf32_vietnamese_ci">
+      <Charset>utf32</Charset>
+    </collation>
+    <collation id="214" parent="1" name="binary">
+      <Charset>binary</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="215" parent="1" name="geostd8_general_ci">
+      <Charset>geostd8</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="216" parent="1" name="geostd8_bin">
+      <Charset>geostd8</Charset>
+    </collation>
+    <collation id="217" parent="1" name="cp932_japanese_ci">
+      <Charset>cp932</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="218" parent="1" name="cp932_bin">
+      <Charset>cp932</Charset>
+    </collation>
+    <collation id="219" parent="1" name="eucjpms_japanese_ci">
+      <Charset>eucjpms</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="220" parent="1" name="eucjpms_bin">
+      <Charset>eucjpms</Charset>
+    </collation>
+    <collation id="221" parent="1" name="gb18030_chinese_ci">
+      <Charset>gb18030</Charset>
+      <DefaultForCharset>1</DefaultForCharset>
+    </collation>
+    <collation id="222" parent="1" name="gb18030_bin">
+      <Charset>gb18030</Charset>
+    </collation>
+    <collation id="223" parent="1" name="gb18030_unicode_520_ci">
+      <Charset>gb18030</Charset>
+    </collation>
+    <schema id="224" parent="1" name="information_schema">
+      <CollationName>utf8_general_ci</CollationName>
+    </schema>
+    <schema id="225" parent="1" name="mysql">
+      <CollationName>latin1_swedish_ci</CollationName>
+    </schema>
+    <schema id="226" parent="1" name="performance_schema">
+      <CollationName>utf8_general_ci</CollationName>
+    </schema>
+    <schema id="227" parent="1" name="reggie">
+      <CollationName>latin1_swedish_ci</CollationName>
+    </schema>
+    <schema id="228" parent="1" name="sky_take_out">
+      <CollationName>latin1_swedish_ci</CollationName>
+    </schema>
+    <schema id="229" parent="1" name="sys">
+      <CollationName>utf8_general_ci</CollationName>
+    </schema>
+    <schema id="230" parent="1" name="yc_cemetery">
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </schema>
+    <schema id="231" parent="1" name="yc_funeral">
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </schema>
+    <schema id="232" parent="1" name="yc_oauth">
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </schema>
+    <schema id="233" parent="1" name="yc_tech">
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </schema>
+    <schema id="234" parent="1" name="yt_platform">
+      <AutoIntrospectionLevel>3</AutoIntrospectionLevel>
+      <Current>1</Current>
+      <LastIntrospectionLevel>3</LastIntrospectionLevel>
+      <LastIntrospectionLocalTimestamp>2025-05-21.02:38:25</LastIntrospectionLocalTimestamp>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </schema>
+    <schema id="235" parent="1" name="zld_sl">
+      <CollationName>latin1_swedish_ci</CollationName>
+    </schema>
+    <user id="236" parent="1" name="root">
+      <Host>localhost</Host>
+    </user>
+    <user id="237" parent="1" name="mysql.session">
+      <Host>localhost</Host>
+    </user>
+    <user id="238" parent="1" name="mysql.sys">
+      <Host>localhost</Host>
+    </user>
+    <user id="239" parent="1" name="yc_marx"/>
+    <table id="240" parent="234" name="oauth_client_details">
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <Options>row_format
+COMPACT</Options>
+      <CollationName>utf8mb4_bin</CollationName>
+    </table>
+    <table id="241" parent="234" name="yt_app">
+      <Comment>易推平台应用表</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="242" parent="234" name="yt_bounty_task">
+      <Comment>易推赏金任务表</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="243" parent="234" name="yt_channel">
+      <Comment>易推渠道商信息</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="244" parent="234" name="yt_health_record">
+      <Comment>心跳检测记录表</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="245" parent="234" name="yt_platform_banned">
+      <Comment>易推平台封禁记录表</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="246" parent="234" name="yt_platform_deblocking">
+      <Comment>易推解封表</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="247" parent="234" name="yt_platform_user">
+      <Comment>易推平台用户</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <table id="248" parent="234" name="yt_risk_manage">
+      <Comment>易推风控表</Comment>
+      <DetailsLevel>3</DetailsLevel>
+      <Engine>InnoDB</Engine>
+      <CollationName>utf8mb4_general_ci</CollationName>
+    </table>
+    <column id="249" parent="240" name="client_id">
+      <Comment>请求的客户端ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(128)|0s</StoredType>
+    </column>
+    <column id="250" parent="240" name="resource_ids">
+      <Comment>请求的资源服务ID</Comment>
+      <Position>2</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <column id="251" parent="240" name="client_secret">
+      <Comment>客户端密钥</Comment>
+      <Position>3</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <column id="252" parent="240" name="scope">
+      <Comment>定义范围内允许换取token</Comment>
+      <Position>4</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <column id="253" parent="240" name="authorized_grant_types">
+      <Comment>授权类型 authorization_code 授权码 password 密码 client_credentials 客户端凭据</Comment>
+      <Position>5</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <column id="254" parent="240" name="web_server_redirect_uri">
+      <Position>6</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <column id="255" parent="240" name="authorities">
+      <Position>7</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <column id="256" parent="240" name="access_token_validity">
+      <Comment>access_token有效期</Comment>
+      <Position>8</Position>
+      <StoredType>int(11)|0s</StoredType>
+    </column>
+    <column id="257" parent="240" name="refresh_token_validity">
+      <Comment>refresh_token 有效期</Comment>
+      <Position>9</Position>
+      <StoredType>int(11)|0s</StoredType>
+    </column>
+    <column id="258" parent="240" name="additional_information">
+      <Position>10</Position>
+      <StoredType>varchar(4096)|0s</StoredType>
+    </column>
+    <column id="259" parent="240" name="autoapprove">
+      <Position>11</Position>
+      <StoredType>varchar(256)|0s</StoredType>
+    </column>
+    <index id="260" parent="240" name="PRIMARY">
+      <ColNames>client_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="261" parent="240" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="262" parent="241" name="user_id">
+      <Comment>用户ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="263" parent="241" name="app_id">
+      <Comment>应用ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="264" parent="241" name="app_name">
+      <Comment>应用名称</Comment>
+      <NotNull>1</NotNull>
+      <Position>3</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="265" parent="241" name="channel_id">
+      <Comment>渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="266" parent="241" name="app_type">
+      <Comment>应用类型</Comment>
+      <NotNull>1</NotNull>
+      <Position>5</Position>
+      <StoredType>int(2)|0s</StoredType>
+    </column>
+    <column id="267" parent="241" name="parent_id">
+      <Comment>上级应用ID</Comment>
+      <Position>6</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="268" parent="241" name="apk_url">
+      <Comment>apk安装包下载地址</Comment>
+      <Position>7</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="269" parent="241" name="qr_code">
+      <Comment>二维码</Comment>
+      <Position>8</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="270" parent="241" name="version_code">
+      <Comment>版本号</Comment>
+      <Position>9</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="271" parent="241" name="update_tips">
+      <Comment>更新提示</Comment>
+      <Position>10</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <index id="272" parent="241" name="PRIMARY">
+      <ColNames>user_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="273" parent="241" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="274" parent="242" name="task_id">
+      <Comment>任务ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="275" parent="242" name="task_name">
+      <Comment>任务名称</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="276" parent="242" name="user_rewards">
+      <Comment>用户奖励</Comment>
+      <Position>3</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="277" parent="242" name="channel_id">
+      <Comment>发布渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="278" parent="242" name="app_id">
+      <Comment>应用ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>5</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="279" parent="242" name="finish_condition">
+      <Comment>完成条件</Comment>
+      <NotNull>1</NotNull>
+      <Position>6</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="280" parent="242" name="bounty">
+      <Comment>赏金</Comment>
+      <Position>7</Position>
+      <StoredType>decimal(10,2 digit)|0s</StoredType>
+    </column>
+    <index id="281" parent="242" name="PRIMARY">
+      <ColNames>task_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="282" parent="242" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="283" parent="243" name="channel_id">
+      <Comment>渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="284" parent="243" name="channel_name">
+      <Comment>渠道商名称</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="285" parent="243" name="channel_account">
+      <Comment>渠道商登录账号</Comment>
+      <Position>3</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="286" parent="243" name="channel_pwd">
+      <Comment>渠道商加密密码</Comment>
+      <Position>4</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="287" parent="243" name="concat">
+      <Comment>联系人</Comment>
+      <NotNull>1</NotNull>
+      <Position>5</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="288" parent="243" name="phone">
+      <Comment>联系电话</Comment>
+      <NotNull>1</NotNull>
+      <Position>6</Position>
+      <StoredType>varchar(20)|0s</StoredType>
+    </column>
+    <column id="289" parent="243" name="credit_code">
+      <Comment>企业信用代码</Comment>
+      <NotNull>1</NotNull>
+      <Position>7</Position>
+      <StoredType>varchar(64)|0s</StoredType>
+    </column>
+    <column id="290" parent="243" name="legal">
+      <Comment>法人</Comment>
+      <NotNull>1</NotNull>
+      <Position>8</Position>
+      <StoredType>varchar(50)|0s</StoredType>
+    </column>
+    <column id="291" parent="243" name="legal_card">
+      <Comment>法人身份证</Comment>
+      <NotNull>1</NotNull>
+      <Position>9</Position>
+      <StoredType>varchar(20)|0s</StoredType>
+    </column>
+    <column id="292" parent="243" name="channel_status">
+      <Comment>渠道状态</Comment>
+      <NotNull>1</NotNull>
+      <Position>10</Position>
+      <StoredType>int(2)|0s</StoredType>
+    </column>
+    <column id="293" parent="243" name="enter_time">
+      <Comment>入驻时间</Comment>
+      <Position>11</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="294" parent="243" name="apply_time">
+      <Comment>申请入驻时间</Comment>
+      <NotNull>1</NotNull>
+      <Position>12</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="295" parent="243" name="auditor">
+      <Comment>审核人</Comment>
+      <Position>13</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <index id="296" parent="243" name="PRIMARY">
+      <ColNames>channel_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="297" parent="243" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="298" parent="244" name="record_id">
+      <Comment>心跳检测记录ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="299" parent="244" name="user_id">
+      <Comment>用户ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="300" parent="244" name="content">
+      <Comment>心跳包内容</Comment>
+      <NotNull>1</NotNull>
+      <Position>3</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="301" parent="244" name="send_time">
+      <Comment>发送时间</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="302" parent="244" name="response_time">
+      <Comment>响应时间</Comment>
+      <Position>5</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="303" parent="244" name="app_id">
+      <Comment>应用ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>6</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="304" parent="244" name="channel_id">
+      <Comment>渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>7</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="305" parent="244" name="origin_ip">
+      <Comment>源IP</Comment>
+      <Position>8</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="306" parent="244" name="client_info">
+      <Comment>客户端信息</Comment>
+      <Position>9</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <index id="307" parent="244" name="PRIMARY">
+      <ColNames>record_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="308" parent="244" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="309" parent="245" name="banned_id">
+      <Comment>封禁ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="310" parent="245" name="user_id">
+      <Comment>用户ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="311" parent="245" name="channel_id">
+      <Comment>渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>3</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="312" parent="245" name="banned_time">
+      <Comment>封禁时间</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="313" parent="245" name="banned_reason">
+      <Comment>封禁原因</Comment>
+      <NotNull>1</NotNull>
+      <Position>5</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="314" parent="245" name="banned_type">
+      <Comment>封禁类型</Comment>
+      <NotNull>1</NotNull>
+      <Position>6</Position>
+      <StoredType>int(5)|0s</StoredType>
+    </column>
+    <column id="315" parent="245" name="banned_limit">
+      <Comment>封禁期限</Comment>
+      <NotNull>1</NotNull>
+      <Position>7</Position>
+      <StoredType>int(10)|0s</StoredType>
+    </column>
+    <column id="316" parent="245" name="operator">
+      <Comment>操作人</Comment>
+      <NotNull>1</NotNull>
+      <Position>8</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <index id="317" parent="245" name="PRIMARY">
+      <ColNames>banned_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="318" parent="245" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="319" parent="246" name="deblocking_id">
+      <Comment>解禁ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="320" parent="246" name="banned_id">
+      <Comment>封禁ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="321" parent="246" name="user_id">
+      <Comment>用户ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>3</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="322" parent="246" name="channel_id">
+      <Comment>渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="323" parent="246" name="deblocking_time">
+      <Comment>解禁时间</Comment>
+      <NotNull>1</NotNull>
+      <Position>5</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="324" parent="246" name="deblocking_reason">
+      <Comment>解禁原因</Comment>
+      <NotNull>1</NotNull>
+      <Position>6</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="325" parent="246" name="operator">
+      <Comment>操作人</Comment>
+      <NotNull>1</NotNull>
+      <Position>7</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <index id="326" parent="246" name="PRIMARY">
+      <ColNames>deblocking_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="327" parent="246" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="328" parent="247" name="user_id">
+      <Comment>用户ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="329" parent="247" name="nick_name">
+      <Comment>用户昵称</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(50)|0s</StoredType>
+    </column>
+    <column id="330" parent="247" name="head_image">
+      <Comment>用户头像</Comment>
+      <Position>3</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="331" parent="247" name="login_name">
+      <Comment>登录用户名</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="332" parent="247" name="encrypt_pwd">
+      <Comment>登录密码</Comment>
+      <NotNull>1</NotNull>
+      <Position>5</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="333" parent="247" name="salt">
+      <Comment>盐</Comment>
+      <Position>6</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="334" parent="247" name="phone">
+      <Comment>手机号</Comment>
+      <NotNull>1</NotNull>
+      <Position>7</Position>
+      <StoredType>varchar(20)|0s</StoredType>
+    </column>
+    <column id="335" parent="247" name="last_login_time">
+      <Comment>最后登录时间</Comment>
+      <Position>8</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="336" parent="247" name="last_login_ip">
+      <Comment>最后登录IP</Comment>
+      <Position>9</Position>
+      <StoredType>varchar(20)|0s</StoredType>
+    </column>
+    <column id="337" parent="247" name="phone_brand">
+      <Comment>手机品牌</Comment>
+      <Position>10</Position>
+      <StoredType>varchar(50)|0s</StoredType>
+    </column>
+    <column id="338" parent="247" name="phone_model">
+      <Comment>手机型号</Comment>
+      <Position>11</Position>
+      <StoredType>varchar(100)|0s</StoredType>
+    </column>
+    <column id="339" parent="247" name="account_status">
+      <Comment>账户状态</Comment>
+      <Position>12</Position>
+      <StoredType>int(5)|0s</StoredType>
+    </column>
+    <column id="340" parent="247" name="channel_id">
+      <Comment>渠道ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>13</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="341" parent="247" name="user_type">
+      <Comment>用户类型</Comment>
+      <NotNull>1</NotNull>
+      <Position>14</Position>
+      <StoredType>int(5)|0s</StoredType>
+    </column>
+    <column id="342" parent="247" name="login_days">
+      <Comment>登录天数</Comment>
+      <Position>15</Position>
+      <StoredType>int(10)|0s</StoredType>
+    </column>
+    <column id="343" parent="247" name="total_income">
+      <Comment>总收益</Comment>
+      <Position>16</Position>
+      <StoredType>decimal(10,2 digit)|0s</StoredType>
+    </column>
+    <column id="344" parent="247" name="app_id">
+      <Comment>应用ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>17</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="345" parent="247" name="registry_time">
+      <Comment>注册时间</Comment>
+      <NotNull>1</NotNull>
+      <Position>18</Position>
+      <StoredType>datetime|0s</StoredType>
+    </column>
+    <column id="346" parent="247" name="transfer_amount">
+      <Comment>允许提现金额</Comment>
+      <Position>19</Position>
+      <StoredType>decimal(10,2 digit)|0s</StoredType>
+    </column>
+    <index id="347" parent="247" name="PRIMARY">
+      <ColNames>user_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="348" parent="247" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+    <column id="349" parent="248" name="risk_id">
+      <Comment>风控ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>1</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="350" parent="248" name="user_id">
+      <Comment>用户ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>2</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="351" parent="248" name="banned_id">
+      <Comment>封禁ID</Comment>
+      <NotNull>1</NotNull>
+      <Position>3</Position>
+      <StoredType>varchar(32)|0s</StoredType>
+    </column>
+    <column id="352" parent="248" name="risk_type">
+      <Comment>风控类型</Comment>
+      <NotNull>1</NotNull>
+      <Position>4</Position>
+      <StoredType>int(2)|0s</StoredType>
+    </column>
+    <column id="353" parent="248" name="risk_code">
+      <Comment>风控编码</Comment>
+      <Position>5</Position>
+      <StoredType>varchar(10)|0s</StoredType>
+    </column>
+    <column id="354" parent="248" name="enabled">
+      <Comment>是否启用</Comment>
+      <NotNull>1</NotNull>
+      <Position>6</Position>
+      <StoredType>int(2)|0s</StoredType>
+    </column>
+    <column id="355" parent="248" name="risk_content">
+      <Comment>风控内容</Comment>
+      <Position>7</Position>
+      <StoredType>text|0s</StoredType>
+    </column>
+    <column id="356" parent="248" name="risk_user_reason">
+      <Comment>用户风控原因</Comment>
+      <Position>8</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="357" parent="248" name="risk_agent_reason">
+      <Comment>渠道商风控原因</Comment>
+      <Position>9</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="358" parent="248" name="risk_tips">
+      <Comment>风控提示</Comment>
+      <Position>10</Position>
+      <StoredType>varchar(255)|0s</StoredType>
+    </column>
+    <column id="359" parent="248" name="risk_times">
+      <Comment>风控时间</Comment>
+      <Position>11</Position>
+      <StoredType>int(5)|0s</StoredType>
+    </column>
+    <index id="360" parent="248" name="PRIMARY">
+      <ColNames>risk_id</ColNames>
+      <Type>btree</Type>
+      <Unique>1</Unique>
+    </index>
+    <key id="361" parent="248" name="PRIMARY">
+      <NameSurrogate>1</NameSurrogate>
+      <Primary>1</Primary>
+      <UnderlyingIndexName>PRIMARY</UnderlyingIndexName>
+    </key>
+  </database-model>
+</dataSource>

+ 2 - 0
.idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/information_schema.FNRwLQ.meta

@@ -0,0 +1,2 @@
+#n:information_schema
+!<md> [null, 0, null, null, -2147483648, -2147483648]

+ 2 - 0
.idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/mysql.osA4Bg.meta

@@ -0,0 +1,2 @@
+#n:mysql
+!<md> [null, 0, null, null, -2147483648, -2147483648]

+ 2 - 0
.idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/performance_schema.kIw0nw.meta

@@ -0,0 +1,2 @@
+#n:performance_schema
+!<md> [null, 0, null, null, -2147483648, -2147483648]

+ 2 - 0
.idea/dataSources/aeb38baa-93f9-4dd5-bb08-172a691fd315/storage_v2/_src_/schema/sys.zb4BAA.meta

@@ -0,0 +1,2 @@
+#n:sys
+!<md> [null, 0, null, null, -2147483648, -2147483648]

+ 7 - 0
.idea/dictionaries/project.xml

@@ -0,0 +1,7 @@
+<component name="ProjectDictionaryState">
+  <dictionary name="project">
+    <words>
+      <w>ytpm</w>
+    </words>
+  </dictionary>
+</component>

+ 21 - 0
.idea/encodings.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/untitled/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/untitled/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-agent/agent-service/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-agent/agent-service/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-agent/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-agent/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-common/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-common/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-gateway/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-gateway/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-oauth/oauth-service/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-oauth/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/yt-oauth/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 19 - 0
.idea/misc.xml

@@ -0,0 +1,19 @@
+<?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>
+    <option name="ignoredFiles">
+      <set>
+        <option value="$PROJECT_DIR$/untitled/pom.xml" />
+      </set>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>

+ 224 - 0
.idea/workspace.xml

@@ -0,0 +1,224 @@
+<?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="f4ad10cb-8bf4-40dd-868b-2f98bb8f8cef" name="Changes" comment="">
+      <change afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/AgentApplication.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/config/CustomUserAuthenticationConverter.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/config/ResourceServerConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/config/feign/FeignConfiguration.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/config/swagger/SwaggerConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/controller/UserController.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/dao/AgentUserMapper.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/java/com/ytpm/handle/AuthExceptionEntryPoint.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/resources/bootstrap.yml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/agent-service/src/main/resources/mapper/AgentUserMapper.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-agent/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/agent/view/AgentUserInfo.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/constant/CacheConstant.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/constant/StrConstant.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/general/BaseParam.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/general/PageMeta.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/general/RepMessage.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/general/Result.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/general/ResultTable.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/general/StatusCode.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/handle/CustomerException.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/handle/CustomerExceptionHandler.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/handle/ValidatedException.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/oauth/model/CaptchaValid.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/oauth/model/YtPlatformUser.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/util/CacheUtil.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/util/CheckPwdUtil.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/util/IDUtil.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/util/RandomPasswordGenerator.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-common/src/main/java/com/ytpm/util/RedisService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-gateway/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-gateway/src/main/java/com/ytpm/GatewayApplication.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-gateway/src/main/java/com/ytpm/cors/CustomerCorsConfiguration.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-gateway/src/main/resources/bootstrap.yml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/OauthApplication.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/auth/AuthService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/auth/CaptchaService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/auth/impl/AuthServiceImpl.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/auth/impl/CaptchaServiceImpl.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/certify/UserDetailService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/Oauth2Config.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/WebSecurityConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/auth/AuthListenerConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/ClientAuthentication.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/CustomAccessDecisionManager.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/CustomFilterInvocationSecurityMetadataSource.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/server/ResourceServerConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/store/RedisTokenStoreConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/config/swagger/SwaggerConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/controller/OauthController.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/dao/YtPlatformUserMapper.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/java/com/ytpm/util/EncryptUtil.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/resources/bootstrap.yml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/oauth-service/src/main/resources/mapper/YtPlatformUserMapper.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/yt-oauth/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/../ytbasic-master/features/user/src/main/resources/base/profile/router_map.json" afterDir="false" />
+    </list>
+    <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="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="FxmlFile" />
+        <option value="Interface" />
+        <option value="Unnamed" />
+        <option value="mybatis" />
+        <option value="Class" />
+      </list>
+    </option>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
+  </component>
+  <component name="MavenImportPreferences">
+    <option name="generalSettings">
+      <MavenGeneralSettings>
+        <option name="customMavenHome" value="E:\marx\java\apache-maven-3.6.3" />
+        <option name="localRepository" value="E:\marx\java\.m2\repository" />
+        <option name="mavenHomeTypeForPersistence" value="CUSTOM" />
+        <option name="userSettingsFile" value="E:\marx\java\apache-maven-3.6.3\conf\settings.xml" />
+      </MavenGeneralSettings>
+    </option>
+  </component>
+  <component name="ProjectColorInfo">{
+  &quot;associatedIndex&quot;: 6
+}</component>
+  <component name="ProjectId" id="2xLrUPVcvcX81nKyzyzpJwuzXAW" />
+  <component name="ProjectViewState">
+    <option name="hideEmptyMiddlePackages" value="true" />
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent"><![CDATA[{
+  "keyToString": {
+    "Application.EncryptUtil.executor": "Run",
+    "Maven. [org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate].executor": "Run",
+    "ModuleVcsDetector.initialDetectionPerformed": "true",
+    "RequestMappingsPanelOrder0": "0",
+    "RequestMappingsPanelOrder1": "1",
+    "RequestMappingsPanelWidth0": "75",
+    "RequestMappingsPanelWidth1": "75",
+    "RunOnceActivity.ShowReadmeOnStart": "true",
+    "RunOnceActivity.git.unshallow": "true",
+    "Spring Boot.AgentApplication.executor": "Debug",
+    "Spring Boot.GatewayApplication.executor": "Run",
+    "Spring Boot.OauthApplication.executor": "Debug",
+    "git-widget-placeholder": "master",
+    "node.js.detected.package.eslint": "true",
+    "node.js.detected.package.tslint": "true",
+    "node.js.selected.package.eslint": "(autodetect)",
+    "node.js.selected.package.tslint": "(autodetect)",
+    "nodejs_package_manager_path": "npm",
+    "project.structure.last.edited": "Project",
+    "project.structure.proportion": "0.15",
+    "project.structure.side.proportion": "0.2",
+    "run.configurations.included.in.services": "true",
+    "settings.editor.selected.configurable": "fileTemplates",
+    "vue.rearranger.settings.migration": "true"
+  },
+  "keyToStringList": {
+    "DatabaseDriversLRU": [
+      "mysql"
+    ]
+  }
+}]]></component>
+  <component name="ReactorSettings">
+    <option name="notificationShown" value="true" />
+  </component>
+  <component name="RunDashboard">
+    <option name="configurationTypes">
+      <set>
+        <option value="KtorApplicationConfigurationType" />
+        <option value="MicronautRunConfigurationType" />
+        <option value="QuarkusRunConfigurationType" />
+        <option value="SpringBootApplicationConfigurationType" />
+      </set>
+    </option>
+  </component>
+  <component name="RunManager" selected="Application.EncryptUtil">
+    <configuration name="EncryptUtil" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
+      <option name="MAIN_CLASS_NAME" value="com.ytpm.util.EncryptUtil" />
+      <module name="oauth-service" />
+      <extension name="coverage">
+        <pattern>
+          <option name="PATTERN" value="com.ytpm.util.*" />
+          <option name="ENABLED" value="true" />
+        </pattern>
+      </extension>
+      <method v="2">
+        <option name="Make" enabled="true" />
+      </method>
+    </configuration>
+    <configuration name="AgentApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" temporary="true" nameIsGenerated="true">
+      <module name="agent-service" />
+      <option name="SPRING_BOOT_MAIN_CLASS" value="com.ytpm.AgentApplication" />
+      <extension name="coverage">
+        <pattern>
+          <option name="PATTERN" value="com.ytpm.*" />
+          <option name="ENABLED" value="true" />
+        </pattern>
+      </extension>
+      <method v="2">
+        <option name="Make" enabled="true" />
+      </method>
+    </configuration>
+    <configuration name="GatewayApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
+      <module name="yt-gateway" />
+      <option name="SPRING_BOOT_MAIN_CLASS" value="com.ytpm.GatewayApplication" />
+      <method v="2">
+        <option name="Make" enabled="true" />
+      </method>
+    </configuration>
+    <configuration name="OauthApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
+      <module name="oauth-service" />
+      <option name="SPRING_BOOT_MAIN_CLASS" value="com.ytpm.OauthApplication" />
+      <method v="2">
+        <option name="Make" enabled="true" />
+      </method>
+    </configuration>
+    <recent_temporary>
+      <list>
+        <item itemvalue="Spring Boot.AgentApplication" />
+        <item itemvalue="Application.EncryptUtil" />
+      </list>
+    </recent_temporary>
+  </component>
+  <component name="SharedIndexes">
+    <attachedChunks>
+      <set>
+        <option value="bundled-jdk-9823dce3aa75-fbdcb00ec9e3-intellij.indexing.shared.core-IU-251.25410.109" />
+        <option value="bundled-js-predefined-d6986cc7102b-6a121458b545-JavaScript-IU-251.25410.109" />
+      </set>
+    </attachedChunks>
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="f4ad10cb-8bf4-40dd-868b-2f98bb8f8cef" name="Changes" comment="" />
+      <created>1747728211181</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1747728211181</updated>
+      <workItem from="1747728212403" duration="8001000" />
+      <workItem from="1747788568939" duration="1474000" />
+      <workItem from="1747790135817" duration="7822000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="3" />
+  </component>
+</project>

+ 66 - 0
pom.xml

@@ -0,0 +1,66 @@
+<?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>
+
+    <groupId>com.ytpm</groupId>
+    <artifactId>yt_platform</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+    <modules>
+        <module>yt-common</module>
+        <module>yt-gateway</module>
+        <module>yt-oauth</module>
+        <module>yt-agent</module>
+    </modules>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <java.version>1.8</java.version>
+        <spring-boot.version>2.1.9.RELEASE</spring-boot.version>
+        <springcloud-alibaba.version>0.9.0.RELEASE</springcloud-alibaba.version>
+        <mybatis-plus.version>3.1.1</mybatis-plus.version>
+        <mysql.version>8.0.28</mysql.version>
+        <encoding>UTF-8</encoding>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <!--database-->
+            <dependency>
+                <groupId>mysql</groupId>
+                <artifactId>mysql-connector-java</artifactId>
+                <version>${mysql.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.baomidou</groupId>
+                <artifactId>mybatis-plus-boot-starter</artifactId>
+                <version>${mybatis-plus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
+                <version>${springcloud-alibaba.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>Greenwich.SR2</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+</project>

+ 36 - 0
yt-agent/agent-service/pom.xml

@@ -0,0 +1,36 @@
+<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.ytpm</groupId>
+        <artifactId>yt-agent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>agent-service</artifactId>
+    <packaging>jar</packaging>
+    <description>代理商后台</description>
+
+    <name>agent-service</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>31.0-jre</version>
+        </dependency>
+    </dependencies>
+</project>

+ 21 - 0
yt-agent/agent-service/src/main/java/com/ytpm/AgentApplication.java

@@ -0,0 +1,21 @@
+package com.ytpm;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@SpringBootApplication
+@EnableDiscoveryClient
+@MapperScan(basePackages = "com.ytpm.dao")
+//@EnableFeignClients(basePackages = {"com.source.cloud.feign"})
+public class AgentApplication
+{
+    public static void main( String[] args )
+    {
+
+        SpringApplication.run(AgentApplication.class, args);
+    }
+}

+ 105 - 0
yt-agent/agent-service/src/main/java/com/ytpm/config/CustomUserAuthenticationConverter.java

@@ -0,0 +1,105 @@
+package com.ytpm.config;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ytpm.agent.view.AgentUserInfo;
+import com.ytpm.constant.StrConstant;
+import com.ytpm.dao.AgentUserMapper;
+import com.ytpm.oauth.model.YtPlatformUser;
+import com.ytpm.util.RedisService;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 自定义Security上下文信息
+ */
+@Data
+@Component
+@Slf4j
+public class CustomUserAuthenticationConverter implements UserAuthenticationConverter {
+    private Collection<? extends GrantedAuthority> defaultAuthorities =
+            new ArrayList<>(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
+    private UserDetailsService userDetailsService;
+
+    @Autowired
+    private RedisService redisService;
+    @Autowired
+    private AgentUserMapper userMapper;
+
+    @Override
+    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
+        Map<String, Object> response = new LinkedHashMap();
+        response.put("username", authentication.getName());
+        if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
+            response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
+        }
+        return response;
+    }
+
+    @Override
+    public Authentication extractAuthentication(Map<String, ?> map) {
+        if (map.containsKey("user_name")) {
+            String userName = (String) map.get("user_name");
+            Object principal;
+            Collection<? extends GrantedAuthority> authorities = this.getAuthorities(map);
+            AgentUserInfo user = userMapper.getCurrentUserInfo(userName);
+            if(Objects.isNull(user)){
+                log.error("当前用户不存在,应该退出登录");
+                return null;
+            }
+            String key = StrConstant.USER_INFO_PRE + userName ;
+            if (redisService.hasKey(key)) {
+                String str = redisService.getStr(key);
+                AgentUserInfo jwtUser = JSONObject.parseObject(str, AgentUserInfo.class);
+                principal = jwtUser;
+                authorities = jwtUser.getAuthorities();
+            } else {
+                AgentUserInfo jwtUser = new AgentUserInfo();
+                BeanUtil.copyProperties(user,jwtUser);
+                authorities = jwtUser.getAuthorities();
+                principal = jwtUser;
+                redisService.setStr(key, JSON.toJSONString(user));
+            }
+            return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 用户资源授权的方法重写  暂时未使用
+     *
+     * @param map
+     * @return
+     */
+    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
+        if (!map.containsKey("authorities")) {
+            return this.defaultAuthorities;
+        } else {
+            Object authorities = map.get("authorities");
+            if (authorities instanceof String) {
+                return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
+            } else if (authorities instanceof Collection) {
+                return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection) authorities));
+            } else {
+                throw new IllegalArgumentException("Authorities must be either a String or a Collection");
+            }
+        }
+    }
+}

+ 72 - 0
yt-agent/agent-service/src/main/java/com/ytpm/config/ResourceServerConfig.java

@@ -0,0 +1,72 @@
+package com.ytpm.config;
+
+import com.ytpm.handle.AuthExceptionEntryPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
+import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
+
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
+    @Value("${security.oauth2.client.client-id}")
+    private String clientId;
+
+    @Value("${security.oauth2.client.client-secret}")
+    private String secret;
+
+    @Value("${security.oauth2.authorization.check-token-access}")
+    private String checkTokenEndpointUrl;
+
+    @Autowired
+    private RedisConnectionFactory redisConnectionFactory;
+
+    @Autowired
+    private AuthExceptionEntryPoint authExceptionEntryPoint;
+
+    @Autowired
+    private CustomUserAuthenticationConverter userAuthenticationConverter;
+
+    @Bean
+    public TokenStore redisTokenStore() {
+        return new RedisTokenStore(redisConnectionFactory);
+    }
+
+    @Bean
+    public RemoteTokenServices tokenService() {
+        RemoteTokenServices tokenService = new RemoteTokenServices();
+        tokenService.setClientId(clientId);
+        tokenService.setClientSecret(secret);
+        tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
+        DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();
+        defaultAccessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
+        tokenService.setAccessTokenConverter(defaultAccessTokenConverter);
+        return tokenService;
+    }
+
+    @Override
+    public void configure(ResourceServerSecurityConfigurer resources) {
+        resources.authenticationEntryPoint(authExceptionEntryPoint);
+        resources.resourceId("agent-service");
+    }
+
+    @Override
+    public void configure(HttpSecurity http) throws Exception {
+        http.headers().frameOptions().disable()
+                .and()
+                .authorizeRequests().antMatchers("/api/public/**","/doc.html","/api/v2/**","/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security",
+                        "/swagger-ui.html", "/webjars/**","/swagger-resources/configuration/ui","/swagger-ui.html").permitAll()
+                .anyRequest().authenticated();
+    }
+
+}

+ 33 - 0
yt-agent/agent-service/src/main/java/com/ytpm/config/feign/FeignConfiguration.java

@@ -0,0 +1,33 @@
+package com.ytpm.config.feign;
+
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+
+@Configuration
+public class FeignConfiguration implements RequestInterceptor {
+
+    @Override
+    public void apply(RequestTemplate requestTemplate) {
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
+                .getRequestAttributes();
+        if (attributes == null) {
+            return;
+        }
+        HttpServletRequest request = attributes.getRequest();
+
+        Enumeration<String> headerNames = request.getHeaderNames();
+        if (headerNames != null) {
+            while (headerNames.hasMoreElements()) {
+                String name = headerNames.nextElement();
+                String values = request.getHeader(name);
+                requestTemplate.header(name, values);
+            }
+        }
+    }
+}

+ 40 - 0
yt-agent/agent-service/src/main/java/com/ytpm/config/swagger/SwaggerConfig.java

@@ -0,0 +1,40 @@
+package com.ytpm.config.swagger;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+    private static final String VERSION = "1.0.0";
+
+    @Bean
+    public Docket createApi(){
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.ytpm.controller"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("")
+                .contact(new Contact("易推网络","http://www.sourcetreasure.com/index.html","marxjaw6466@163.com"))
+                .description("代理商管理系统")
+                .termsOfServiceUrl("https://juejin.cn/user/4310510864972254")
+                .license("The Apache License, Version 2.0")
+                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
+                .version(VERSION)
+                .build();
+    }
+}

+ 22 - 0
yt-agent/agent-service/src/main/java/com/ytpm/controller/UserController.java

@@ -0,0 +1,22 @@
+package com.ytpm.controller;
+
+import com.ytpm.agent.view.AgentUserInfo;
+import com.ytpm.general.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = "用户管理模块")
+@RestController
+@RequestMapping("/ytUser")
+public class UserController{
+
+    @ApiOperation(value = "获取当前登录用户", notes = "无需传参")
+    @GetMapping("/curUser")
+    public Result<AgentUserInfo> getCurrentUser(@AuthenticationPrincipal AgentUserInfo userInfo){
+        return Result.resultObjOk(userInfo);
+    }
+}

+ 14 - 0
yt-agent/agent-service/src/main/java/com/ytpm/dao/AgentUserMapper.java

@@ -0,0 +1,14 @@
+package com.ytpm.dao;
+
+import com.ytpm.agent.view.AgentUserInfo;
+import org.apache.ibatis.annotations.Param;
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface AgentUserMapper {
+    /**
+     * 获取当前登录用户信息
+     * @param loginName 用户名
+     */
+    AgentUserInfo getCurrentUserInfo(@Param("loginName")String loginName);
+}

+ 40 - 0
yt-agent/agent-service/src/main/java/com/ytpm/handle/AuthExceptionEntryPoint.java

@@ -0,0 +1,40 @@
+package com.ytpm.handle;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ytpm.general.RepMessage;
+import com.ytpm.general.StatusCode;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 客户端未授权的访问处理逻辑
+ */
+@Component
+@Slf4j
+public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {
+    @Override
+    public void commence(HttpServletRequest request, HttpServletResponse response,
+                         AuthenticationException authException) {
+        Throwable cause = authException.getCause();
+        response.setHeader("Content-Type", "application/json;charset=UTF-8");
+        try {
+            JSONObject body = new JSONObject();
+            body.put("code", StatusCode.MANAGE_NOT_LOGIN);
+            body.put("message", RepMessage.TOKEN_EXPIRE);
+            if (!(cause instanceof InvalidTokenException)) {
+                body.put("code", StatusCode.MANAGE_NOT_LOGIN);
+                body.put("message", RepMessage.TOKEN_INVALID);
+            }
+            response.getWriter().write(body.toJSONString());
+        } catch (IOException e) {
+            log.error("token认证失败={}", e);
+        }
+    }
+}

+ 35 - 0
yt-agent/agent-service/src/main/resources/bootstrap.yml

@@ -0,0 +1,35 @@
+spring:
+  profiles:
+    active: local
+---
+spring:
+  profiles: local
+  main:
+    allow-bean-definition-overriding: true
+  application:
+    name: agent-service
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 127.0.0.1:8848
+        namespace: 52439154-ea03-4121-9759-44d0cacc4765
+      config:
+        server-addr: 127.0.0.1:8848
+        file-extension: yml
+        namespace: 52439154-ea03-4121-9759-44d0cacc4765
+---
+spring:
+  profiles: dev
+  main:
+    allow-bean-definition-overriding: true
+  application:
+    name: yt-oauth
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 121.37.82.232:8848
+        namespace: 776851c5-aa23-4606-b2b2-941487de707f
+      config:
+        server-addr: 121.37.82.232:8848
+        file-extension: yml
+        namespace: 776851c5-aa23-4606-b2b2-941487de707f

+ 12 - 0
yt-agent/agent-service/src/main/resources/mapper/AgentUserMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ytpm.dao.AgentUserMapper">
+
+    <select id="getCurrentUserInfo" resultType="com.ytpm.agent.view.AgentUserInfo">
+        select
+            user_id, nick_name, head_image, login_name, encrypt_pwd, salt, phone, last_login_time, last_login_ip, phone_brand, phone_model, account_status, channel_id, user_type, login_days, total_income, app_id, registry_time, transfer_amount
+        from yt_platform_user
+        where account_status = 1
+        and login_name = #{loginName}
+    </select>
+</mapper>

+ 112 - 0
yt-agent/pom.xml

@@ -0,0 +1,112 @@
+<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.ytpm</groupId>
+        <artifactId>yt_platform</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>yt-agent</artifactId>
+    <packaging>pom</packaging>
+    <description>易推平台代理商系统</description>
+
+    <name>yt-agent</name>
+    <url>http://maven.apache.org</url>
+    <modules>
+        <module>agent-service</module>
+    </modules>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jsr305</artifactId>
+                    <groupId>com.google.code.findbugs</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+        </dependency>
+
+        <!--Spring Cloud Alibaba-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+
+        <!--database-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jsqlparser</artifactId>
+                    <groupId>com.github.jsqlparser</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ytpm</groupId>
+            <artifactId>yt-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jsqlparser</artifactId>
+                    <groupId>com.github.jsqlparser</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jsr305</artifactId>
+                    <groupId>com.google.code.findbugs</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 106 - 0
yt-common/pom.xml

@@ -0,0 +1,106 @@
+<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.ytpm</groupId>
+        <artifactId>yt_platform</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>yt-common</artifactId>
+    <packaging>jar</packaging>
+    <description>公共工具包</description>
+
+    <name>yt-common</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper</artifactId>
+            <version>5.3.3</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.2</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>23.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.25</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>5.1.3.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-oauth2</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>bcpkix-jdk15on</artifactId>
+                    <groupId>org.bouncycastle</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-core</artifactId>
+        </dependency>
+        <!-- 图片压缩 -->
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.20</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <skip>
+                        true
+                    </skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 37 - 0
yt-common/src/main/java/com/ytpm/agent/view/AgentUserInfo.java

@@ -0,0 +1,37 @@
+package com.ytpm.agent.view;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel("当前登录用户信息")
+public class AgentUserInfo {
+    @ApiModelProperty("用户ID")
+    private String userId;
+    @ApiModelProperty("用户昵称")
+    private String nickName;
+    @ApiModelProperty("头像")
+    private String headImage;
+    @ApiModelProperty("登录用户名")
+    private String loginName;
+    @ApiModelProperty("手机号")
+    private String phone;
+    @ApiModelProperty("最新登录时间")
+    private Date lastLoginTime;
+    @ApiModelProperty("最新登录IP")
+    private String lastLoginIp;
+
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return Collections.emptyList();
+    }
+}

+ 20 - 0
yt-common/src/main/java/com/ytpm/constant/CacheConstant.java

@@ -0,0 +1,20 @@
+package com.ytpm.constant;
+
+/**
+ * 缓存名
+ *
+ * @author xuwh
+ */
+public interface CacheConstant {
+
+
+    /**
+     * 缺省缓存
+     */
+    String DEFAULT_CACHE = "yt_other:";
+
+    /**
+     * 缺省缓存前缀
+     */
+    String DEFAULT_CACHE_PREFIX = "default:";
+}

+ 59 - 0
yt-common/src/main/java/com/ytpm/constant/StrConstant.java

@@ -0,0 +1,59 @@
+package com.ytpm.constant;
+
+public class StrConstant {
+    public static final String PRO_STR = "pro";
+    /**
+     * redis 存储用户信息前缀
+     */
+
+    public static final String USER_INFO_PRE = "ZL_PLATFORM_";
+    /**
+     * redis 用户登录短信 前缀
+     */
+    public static final String LOGIN_MSG_PRE = "YT_LOGIN_MSG_";
+    /**
+     * redis 修改手机号码 前缀
+     */
+    public static final String CHANGE_PHONE_NO_PRE = "YT_CHANGE_PHONE_NO_PRE_";
+    /**
+     * redis 修改登录密码 前缀
+     */
+    public static final String CHANGE_LOGIN_PWD_PRE = "YT_CHANGE_LOGIN_PWD_PRE_";
+    /**
+     * redis 期限
+     */
+    public static final String EXPIRES = "_EXPIRES";
+    /**
+     * redis 短信次数
+     */
+    public static final String TIMES = "_TIMES";
+
+    /**
+     * redis 存储用户信息 机构ID拼接
+     */
+    public static final String USER_ORGANIZATION_ID = "_ORGANIZATION_ID_";
+    /**
+     * redis 钉钉免登陆 检验code
+     */
+    public static final String DING_TALK_FREE_CHECK_CODE = "YT_DING_TALK_LOGIN_CHECK_";
+
+    /**   redis  菜单   */
+    public static final String MENU_LIST_PRE = "YT_MENU_";
+    /**
+     * redis 业务编号
+     */
+    public static final String ORDER_NO_KEY = "YT_ORDER_NO_KEY";
+
+    /**   智能审批标识   */
+    public static final String AUTO_AUDIT_FLAG = "YT_AUTO_AUDIT_FLAG_";
+
+    //===================================================================
+    /**
+     * 符合
+     */
+    public static final String CONFORMITY = "符合";
+    /**
+     * 不符合
+     */
+    public static final String INCONFORMITY = "不符合";
+}

+ 63 - 0
yt-common/src/main/java/com/ytpm/general/BaseParam.java

@@ -0,0 +1,63 @@
+package com.ytpm.general;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BaseParam extends PageMeta {
+    /** 创建时间 */
+    private Date createTime;
+    /** 创建人 */
+    private String createUserId;
+    /** 修改时间 */
+    private Date updateTime;
+    /** 修改人 */
+    private String updateUserId;
+    /** 逻辑删除 1-是 0-否 */
+    private Integer available;
+    /** 机构ID */
+    private String organId;
+    /** 是否超级管理员 */
+    private int superAdmin;
+
+    public BaseParam(Long total, Integer perPage, Integer currentPage, Integer lastPage) {
+        super(total, perPage, currentPage, lastPage);
+    }
+
+    /**
+     * 设置默认参数 创建
+     * @param userId
+     */
+    public void setDefaultParam(String userId){
+        this.createTime = new Date();
+        this.available = 1;
+        this.createUserId = userId;
+    }
+
+    /**
+     * 设置修改参数
+     * @param userId
+     */
+    public void setUpdateParam(String userId){
+        this.updateTime = new Date();
+        this.updateUserId = userId;
+    }
+
+    /**
+     * 设置删除参数
+     * @param userId
+     * @param available
+     */
+    public void setDeleteParam(String userId, Integer available){
+        this.updateTime = new Date();
+        this.updateUserId = userId;
+        this.available = available;
+    }
+}

+ 44 - 0
yt-common/src/main/java/com/ytpm/general/PageMeta.java

@@ -0,0 +1,44 @@
+package com.ytpm.general;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author Marx
+ * @date 2022/5/13 10:29
+ * @description
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "分页参数")
+public class PageMeta implements Serializable {
+
+
+    private static final long serialVersionUID = 5981214936303453944L;
+    /**
+     * 总条数
+     */
+    @ApiModelProperty(value = "总条数")
+    private Long total;
+    /**
+     * 当前页数量(查询量)
+     */
+    @ApiModelProperty(value = "当前页数量(查询量)")
+    private Integer limit;
+    /**
+     * 当前页码
+     */
+    @ApiModelProperty(value = "当前页码")
+    private Integer page;
+    /**
+     * 总页数
+     */
+    @ApiModelProperty(value = "总页数")
+    private Integer pageSizes;
+}

+ 98 - 0
yt-common/src/main/java/com/ytpm/general/RepMessage.java

@@ -0,0 +1,98 @@
+package com.ytpm.general;
+
+/**
+ * @author marx
+ * @date 2022/4/28 15:01
+ */
+public class RepMessage {
+    public static final String QUERY_SUCCESS = "查询成功";
+    public static final String QUERY_FAIL = "查询失败";
+    public static final String ADD_SUCCESS = "增加成功";
+    public static final String SAVE_SUCCESS = "保存成功";
+    public static final String SUBMIT_SUCCESS = "提交成功";
+    public static final String MODIFY_SUCCESS = "修改成功";
+    public static final String DELETE_SUCCESS = "删除成功";
+    public static final String LOGOUT_SUCCESS = "已退出登录";
+    public static final String NOT_LOGIN= "当前用户未登录";
+    public static final String LOGON_FAILURE= "登录已失效";
+    public static final String AUDIT_SUCCESS = "审核通过";
+    public static final String REFUSE_SUCCESS = "拒绝成功";
+    public static final String REJECT_SUCCESS = "退回成功";
+    public static final String APPOINT_SUCCESS = "预约成功";
+    public static final String VERIFICATION_CODE_SEND_SUCCESS = "验证码已发送";
+    public static final String SPOUSE_NOT_DELETE = "请先删除配偶再删除主借人";
+
+    public static final String DELETE_FAIL= "删除失败";
+    public static final String MODIFY_FAIL= "操作失败";
+    public static final String ACCESS_FAIL = "用户权限不足";
+    public static final String MENU_DEL_REMIND = "当前菜单节点有子菜单,请先删除子菜单";
+    public static final String USER_ID_EMPTY = "用户ID不能为空";
+    public static final String USER_NAME_EMPTY = "用户名不能为空";
+    public static final String PASSWORD_EMPTY = "密码不能为空";
+    public static final String USER_NOT_EXIST = "手机号不存在";
+    public static final String PHONE_NOT_EXIST = "手机号不在库";
+    public static final String USER_EXIST = "用户已存在";
+    public static final String PHONE_NO_EXIST = "手机号码已存在";
+    public static final String SEND_EXPIRES = "获取验证码需间隔60秒";
+    public static final String ROLE_EXIST = "角色已存在";
+    public static final String USER_NAME_EXIST = "用户名已存在";
+    public static final String USERNAME_OR_PASSWORD_ERROR = "用户名或密码错误";
+    public static final String PASSWORD_ERROR = "请输入正确的密码";
+    public static final String LOGIN_MSG_ERR = "验证码错误";
+    public static final String LOGIN_NON_MSG = "请输入验证码";
+    public static final String LOGIN_MSG_NOT_EXIST = "验证码已失效,请重新获取";
+    public static final String USER_ACCOUNT_DISABLED = "当前账号不可用";
+    public static final String METHOD_NOT_ARROW = "请求方式不允许";
+    public static final String TOKEN_EXPIRE = "登录超时,请重新登录";
+    public static final String TOKEN_INVALID = "登录已失效,请重新登录";
+    public static final String LOGOUT_FAIL = "用户注销失败";
+    public static final String BUSINESS_EMPTY = "业务订单不存在";
+    public static final String MODIFY_NOT_ALLOW = "已提交不可修改";
+    public static final String RISK_BUSINESS_NOT_FOUND = "风险审核记录不存在";
+    public static final String BUSINESS_ID_EMPTY = "已保存业务单ID不能为空";
+    public static final String REAL_ESTATE_INFO_ID_EMPTY = "房产ID不能为空";
+    public static final String BUSINESS_STATUS_ERROR="当前业务状态流程不允许操作";
+    public static final String BUSINESS_BORROWING_OPERATION_STATUS_ERROR="当前该笔借款状态不允许操作";
+    public static final String BUSINESS_CERTIFICATE_TYPE_STATUS_ERROR="证件格式不正确";
+    public static final String  BUSINESS_CURRENT_OPERATE_STATUS_ERROR="流程状态已变化,当前不能操作";
+    public static final String  RESERVE_LOAN_TIME_EMPTY="预约放款时间不能为空";
+    public static final String  HOUSE_TRANSFER_DATE_EMPTY="过户日期不能为空";
+    public static final String  HOUSE_TRANSFER_TIME_EMPTY="过户时间不能为空";
+    public static final String  ESTIMATED_FORENSICS_DATE_EMPTY="预计取证日期不能为空";
+    public static final String  ESTIMATED_FORENSICS_TIME_EMPTY="预计取证时间不能为空";
+    public static final String  HOUSE_TRANSFER_IMG_EMPTY="过户凭证不能为空";
+    public static final String  ORGANIZATION_ID_EMPTY="账户没有绑定机构,请联系管理员";
+    public static final String  TASK_NOT_EXIST="任务不存在";
+
+    public static final String  PWD_NOT_SAME="两次输入密码不一致";
+    public static final String  CODE_SENDING="验证码发送中,请稍候";
+    public static final String  VERIFY_CODE_ERROR="请输入正确的验证码";
+    public static final String  VERIFY_CODE_EMPTY="请输入验证码";
+
+    public static final String PERSON_EMPTY="人员配置不能为空";
+    public static final String PERSON_CASHIER_EMPTY="人员配置出纳员不能为空";
+    public static final String PERSON_CUSTOMER_MANAGER_EMPTY="人员配置客户经理不能为空";
+    public static final String PERSON_REPAYMENT_EMPTY="人员配置还款专员不能为空";
+    public static final String PERSON_MERCHANDISER_EMPTY="人员配置跟单员不能为空";
+    public static final String PERSON_OTHER_TASK_EMPTY="人员配置其他管理不能为空";
+
+    public static  final String PARAM_ERROR="请求参数有误";
+    public static  final String WHTHIN_NO_RECORD="无记录";
+
+
+    /**   文件不存在  */
+    public static  final String FILE_NOT_EXISTS="文件不存在";
+
+
+
+
+    /************************* 移动端MSG******************************************************/
+
+    public static  final String WEB_FREE_LOGIN_FAIL_NO_PHONE_MSG="免登陆获取手机号码失败";
+
+    public static  final String WEB_FREE_LOGIN_FAIL_MSG="免登陆失败";
+
+    public static  final String WEB_LOGIN_CHECK_FAIL_MSG="校验失败,请重新获取";
+
+
+}

+ 80 - 0
yt-common/src/main/java/com/ytpm/general/Result.java

@@ -0,0 +1,80 @@
+package com.ytpm.general;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author marx
+ * @date 2022/4/8 9:43
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Result<T> implements Serializable {
+    private Integer code;
+    private String message;
+    private T data;
+
+    /**
+     * 返回success
+     *
+     * @return
+     */
+    public static <T> Result resultOk(String msg) {
+        return resultOk(msg, null);
+    }
+    /**
+     * 返回成功,携带数据
+     *
+     * @return
+     */
+    public static <T> Result<T> resultObjOk(T data) {
+        return resultOk("SUCCESS", data);
+    }
+
+    /**
+     * 返回success
+     *
+     * @return
+     */
+    public static <T> Result<T> resultOk() {
+        return resultOk("SUCCESS", null);
+    }
+
+    /**
+     * 返回success 含参数
+     *
+     * @return
+     */
+    public static <T> Result<T> resultOk(String msg, T t) {
+        return new Result<T>(StatusCode.OK, msg, t);
+    }
+
+    /**
+     * 返回fail 自定义code
+     *
+     * @return
+     */
+    public static <T> Result<T> resultFail(int code, String msg) {
+        return new Result<T>(code, msg, null);
+    }
+
+    /**
+     * 返回ERROR  code = 801
+     *
+     * @return
+     */
+    public static <T> Result<T> resultErr(String msg) {
+        return resultFail(StatusCode.ERROR, msg);
+    }
+
+    public Result(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+        this.data = null;
+    }
+
+}

+ 88 - 0
yt-common/src/main/java/com/ytpm/general/ResultTable.java

@@ -0,0 +1,88 @@
+package com.ytpm.general;
+
+import com.github.pagehelper.PageInfo;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author marx
+ * @date 2022/5/13 10:27
+ * @description 列表数据返回实体
+ */
+@Data
+public class ResultTable<T> implements Serializable {
+
+    private Integer code;
+    private String message;
+    private List<T> data;
+    private PageMeta pageMeta;
+
+    public ResultTable() {
+    }
+
+    public ResultTable(Integer code, String message, List<T> data, PageMeta pageMeta) {
+        this.code = code;
+        this.message = message;
+        this.data = data;
+        this.pageMeta = pageMeta;
+    }
+
+    public ResultTable(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    /**
+     * 查询成功,返回实体
+     *
+     * @param list 返回列表集合
+     * @param total 总条数
+     * @param perPage 单页数量
+     * @param currentPage 当前页码
+     * @param lastPage 总页码
+     * @return
+     */
+    public static <T> ResultTable resultTableOk(List<T> list, Long total, Integer perPage, Integer currentPage, Integer lastPage) {
+        if(null == list){
+            list = new ArrayList<>();
+        }
+        PageMeta pageMeta = new PageMeta(total, perPage, currentPage, lastPage);
+        return new ResultTable<T>(StatusCode.OK, RepMessage.QUERY_SUCCESS, list, pageMeta);
+    }
+
+    /**
+     * 查询成功,返回实体
+     *
+     * @param pageInfo 分页插件返回实体
+     * @return
+     */
+    public static <T> ResultTable resultTableOk(PageInfo<T> pageInfo) {
+        //当前页
+        int currentPage = pageInfo.getPageNum();
+        //每页的数量
+         int perPage = pageInfo.getPageSize();
+
+        //总页数
+         int lastPage  = pageInfo.getPages();
+         long total  = pageInfo.getTotal();
+         List<T> list = pageInfo.getList();
+        if(null == list){
+            list = new ArrayList<>();
+        }
+        PageMeta pageMeta =  new PageMeta(total, perPage, currentPage, lastPage);
+        return new ResultTable(StatusCode.OK, RepMessage.QUERY_SUCCESS, list, pageMeta);
+    }
+
+    /**
+     * 查询失败,返回实体
+     * @param code
+     * @param msg
+     * @return
+     */
+    public static ResultTable resultFail(int code, String msg) {
+        return new ResultTable(code, msg);
+    }
+}

+ 111 - 0
yt-common/src/main/java/com/ytpm/general/StatusCode.java

@@ -0,0 +1,111 @@
+package com.ytpm.general;
+
+import lombok.Data;
+
+/**
+ * @author marx
+ * @date 2022/4/8 9:46
+ */
+@Data
+public class StatusCode {
+    public static final int OK = 200;
+
+    /** 访问错误 */
+    public static final int ACCESS_ERR = 301;
+    /** 参数缺失 */
+    public static final int MISSING_PARAMETER = 302;
+    /** 参数校验错误 */
+    public static final int PARAMETER_CHECK_ERR = 303;
+    /** 参数绑定错误 */
+    public static final int PARAMETER_BINDING_ERR = 306;
+    /** 用户不存在*/
+    public static final int USER_NOT_EXIST = 307;
+    /** 用户已存在 */
+    public static final int USER_EXIST = 327;
+    public static final int ROLE_EXIST = 329;
+    /** 账户密码错误 */
+    public static final int PWD_ERROR = 308;
+    /** 用户ID不能为空 */
+    public static final int USER_ID_EMPTY = 309;
+    public static final int DEPT_ID_EMPTY = 321;
+    /** 当前菜单节点有子菜单,请先删除子菜单 */
+    public static final int CHILD_NOT_DEL = 310;
+    /** RPC远程调用失败 */
+    public static final int RPC_FAIL = 311;
+    /** 业务订单不存在 */
+    public static final int BUSINESS_NOT_FOUND = 312;
+
+    /**已提交不可修改 修改失败*/
+    public static final int MODIFY_FAIL = 313;
+
+    /** 提交错误  操作失败*/
+    public static final int COMMIT_ERROR = 314;
+
+    /** 风险审核记录不存在 */
+    public static final int RISK_BUSINESS_NOT_FOUND = 315;
+
+    /** 业务状态错误 */
+    public static final int BUSINESS_STATUS_ERROR = 316;
+
+    /** 该笔业务对应当前借款的相关操作状态 **/
+    public static  final  int  BUSINESS_BORROWING_OPERATION_STATUS_ERROR=317;
+
+    /** 证件格式不正确 **/
+    public static  final  int  BUSINESS_CERTIFICATE_TYPE_STATUS_ERROR=318;
+
+    /** 当前节点操作状态错误 **/
+    public static  final  int  BUSINESS_CURRENT_OPERATE_STATUS_ERROR=319;
+
+    /** 手机号码不正确 */
+    public static  final  int  BUSINESS_CONCAT_NUMBER_ERROR=320;
+
+    /** 过户日期不能为空 */
+    public static  final  int  HOUSE_TRANSFER_DATE_EMPTY=322;
+    /** 过户时间不能为空 */
+    public static  final  int  HOUSE_TRANSFER_TIME_EMPTY=323;
+    /** 预计取证日期不能为空 */
+    public static  final  int  ESTIMATED_FORENSICS_DATE_EMPTY=324;
+    /** 预计取证时间不能为空 */
+    public static  final  int  ESTIMATED_FORENSICS_TIME_EMPTY=325;
+
+    public static  final  int  HOUSE_TRANSFER_IMG_EMPTY=326;
+    public static  final  int  PWD_NOT_SAME=327;
+
+    public static  final  int PHONE_NOT_EXIST=328;
+    /** 查档无记录 */
+    public static  final  int WHTHIN_NO_RECORD=329;
+
+    /**
+     * 登出
+     */
+    public static final int MANAGE_NOT_LOGIN = 1024;
+
+
+    public static final int ERROR = 801;
+
+    public static final int TIME_OUT = 802;
+
+    public static final int USER_NAME_EMPTY = 803;
+
+    public static final int PWD_EMPTY = 804;
+
+    public static final int RESERVE_LOAN_TIME_EMPTY = 805;
+
+    public static final int ORGANIZATION_ID_EMPTY = 806;
+
+    public static final int TASK_NOT_EXIST = 807;
+
+    /** 请求参数有误 **/
+
+    /**  接口 查询失败/访问失败    */
+    public  static  final  int PARAM_ERROR=809;
+
+
+
+    /************************* 移动端code******************************************************/
+        /**免登陆失败   */
+    public  static  final  int WEB_FREE_LOGIN_FAIL=10100;
+        /** 登录失败  */
+    public  static  final  int WEB_LOGIN_FAIL=10101;
+
+}

+ 15 - 0
yt-common/src/main/java/com/ytpm/handle/CustomerException.java

@@ -0,0 +1,15 @@
+package com.ytpm.handle;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CustomerException extends  RuntimeException{
+
+    private int code;
+
+    public CustomerException(String message){
+        super(message);
+    }
+}

+ 170 - 0
yt-common/src/main/java/com/ytpm/handle/CustomerExceptionHandler.java

@@ -0,0 +1,170 @@
+package com.ytpm.handle;
+
+import cn.hutool.core.util.StrUtil;
+import com.ytpm.general.Result;
+import com.ytpm.general.StatusCode;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.util.CollectionUtils;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.multipart.MultipartException;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Set;
+
+
+@Slf4j(topic = "customer-exception")
+@RestControllerAdvice(annotations = RestController.class)
+public class CustomerExceptionHandler implements HandlerExceptionResolver {
+
+    @ResponseBody
+    @ExceptionHandler(Exception.class)
+    public Result handleException(Exception ex) {
+        //打印异常信息
+        log.error("抛出异常信息,异常信息为:ex={}",ex);
+        ex.printStackTrace();
+        String msg = "操作失败,请联系管理员";
+        return new Result(StatusCode.ERROR,msg);
+    }
+
+    /**
+     * 对象参数校验失败
+     * @param ex
+     * @return
+     */
+    @ResponseBody
+    @ExceptionHandler(MissingServletRequestParameterException.class)
+    public Result handleMissingServletRequestParameterException(Exception ex) {
+        log.error("对象参数校验失败,异常信息为:e={}", ex);
+        String msg = MessageFormat.format("缺少参数{0}", ((MissingServletRequestParameterException) ex).getParameterName());
+        return new Result(StatusCode.MISSING_PARAMETER, msg);
+    }
+
+    /**
+     * 单个参数校验失败
+     * @param ex
+     * @return
+     */
+    @ResponseBody
+    @ExceptionHandler(ConstraintViolationException.class)
+    public Result handleConstraintViolationException(Exception ex) {
+        log.error("单个参数校验失败,异常信息为:ex={}",ex);
+        ex.printStackTrace();
+        Set<ConstraintViolation<?>> sets = ((ConstraintViolationException) ex).getConstraintViolations();
+        if (!CollectionUtils.isEmpty(sets)) {
+            StringBuilder sb = new StringBuilder();
+            sets.forEach(error -> {
+//                if (error instanceof FieldError) {
+//                    sb.append(((FieldError) error).getField()).append(":");
+//                }
+                sb.append(error.getMessage()).append(";");
+            });
+            String msg = sb.toString();
+            msg = StrUtil.sub(msg, 0, msg.length() - 1);
+            return new Result(StatusCode.PARAMETER_CHECK_ERR, msg);
+        }
+        return new Result(StatusCode.PARAMETER_CHECK_ERR, "参数校验失败");
+    }
+
+    /**
+     * 自定义校验异常信息捕获
+     * @param ex
+     * @return
+     */
+    @ResponseBody
+    @ExceptionHandler(IllegalArgumentException.class)
+    public Result handleSpringCheckException(Exception ex) {
+        log.error("自定义校验异常信息捕获,异常信息为:ex={}",ex);
+        ex.printStackTrace();
+        String msg = ex.getMessage();
+        return new Result(StatusCode.PARAMETER_CHECK_ERR, msg);
+    }
+
+    /**
+     * POST 请求参数校验失败
+     * @param ex
+     * @return
+     */
+    @ResponseBody
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Result handleMethodArgumentNotValidException(Exception ex) {
+        log.error(" 请求参数校验失败,异常信息为:ex={}",ex);
+        ex.printStackTrace();
+        List<ObjectError> errors = ((MethodArgumentNotValidException) ex).getBindingResult().getAllErrors();
+        String msg = getValidExceptionMsg(errors);
+        return new Result(StatusCode.PARAMETER_CHECK_ERR, msg);
+    }
+
+    @ResponseBody
+    @ExceptionHandler(ValidatedException.class)
+    public Result handleValidatedException(Exception ex) {
+        log.error(" 请求参数校验失败,异常信息为:ex={}",ex.getMessage());
+        return new Result(StatusCode.BUSINESS_CERTIFICATE_TYPE_STATUS_ERROR, ex.getMessage());
+    }
+
+    /**
+     * 获取属性校验异常信息
+     * @param errors
+     * @return
+     */
+    private String getValidExceptionMsg(List<ObjectError> errors) {
+        if(!CollectionUtils.isEmpty(errors)){
+            StringBuilder sb = new StringBuilder();
+            errors.forEach(error -> {
+//                if (error instanceof FieldError) {
+//                    sb.append(((FieldError)error).getField()).append(":");
+//                }
+                sb.append(error.getDefaultMessage()).append(";");
+            });
+            String msg = sb.toString();
+            msg = StrUtil.sub(msg,0, msg.length() -1);
+            return msg;
+        }
+        return "绑定异常";
+    }
+
+    @ResponseBody
+    @ExceptionHandler(MaxUploadSizeExceededException.class)
+    public Result handlerFileUploadException(MaxUploadSizeExceededException ex){
+        log.error("抛出异常信息,异常信息为:ex={}",ex);
+        return new Result(StatusCode.ERROR,"文件超出限制(10MB)");
+    }
+
+    @Override
+    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
+        log.error(" 系统异常,异常信息为:e={}", e.getMessage());
+        ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
+        if (e instanceof MultipartException) {
+            mv.addObject("message", "系统异常");
+            mv.addObject("code", "801");
+            mv.setStatus(HttpStatus.OK);
+        } else {
+            mv.addObject("msg", e.getMessage());
+        }
+        return mv;
+    }
+
+    @ResponseBody
+    @ExceptionHandler(CustomerException.class)
+    public Result handleCustomerException(Exception ex){
+        log.error("自定义校验异常信息捕获,异常信息为:ex={}", ex);
+        ex.printStackTrace();
+        String msg = ex.getMessage();
+        return new Result(StatusCode.PARAMETER_CHECK_ERR, msg);
+    }
+}

+ 7 - 0
yt-common/src/main/java/com/ytpm/handle/ValidatedException.java

@@ -0,0 +1,7 @@
+package com.ytpm.handle;
+
+public class ValidatedException extends RuntimeException{
+    public ValidatedException(String message) {
+        super(message);
+    }
+}

+ 56 - 0
yt-common/src/main/java/com/ytpm/oauth/model/CaptchaValid.java

@@ -0,0 +1,56 @@
+package com.ytpm.oauth.model;
+
+public class CaptchaValid {
+    /**
+     * 是否显示验证码
+     */
+    private Boolean showCaptcha;
+
+    /**
+     * 设置密码错误多少次显示验证码
+     */
+    private Integer settingErrorCountCaptcha;
+
+    /**
+     * 生成验证码主键
+     */
+    private String uuid;
+
+    /**
+     * 密码错误次数
+     */
+    private Integer errorCount;
+
+    /**
+     * 验证码
+     */
+    private String captcha;
+
+    public Boolean getShowCaptcha() {
+        return showCaptcha;
+    }
+
+    public Integer getSettingErrorCountCaptcha() {
+        return settingErrorCountCaptcha;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public Integer getErrorCount() {
+        return errorCount;
+    }
+
+    public String getCaptcha() {
+        return captcha;
+    }
+
+    public CaptchaValid(Boolean showCaptcha, Integer settingErrorCountCaptcha, String uuid, Integer errorCount, String captcha) {
+        this.showCaptcha = showCaptcha;
+        this.settingErrorCountCaptcha = settingErrorCountCaptcha;
+        this.uuid = uuid;
+        this.errorCount = errorCount;
+        this.captcha = captcha;
+    }
+}

+ 72 - 0
yt-common/src/main/java/com/ytpm/oauth/model/YtPlatformUser.java

@@ -0,0 +1,72 @@
+package com.ytpm.oauth.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class YtPlatformUser implements UserDetails {
+    private String userId;
+    private String nickName;
+    private String loginName;
+    private String headImage;
+    private String encryptPwd;
+    private String salt;
+    private String phone;
+    private Date lastLoginTime;
+    private String lastLoginIp;
+    private String phoneBrand;
+    private String phoneModel;
+    private Integer accountStatus;
+    private String channelId;
+    private Integer userType;
+    private Integer loginDays;
+    private BigDecimal totalIncome;
+    private String appId;
+    private Date registryTime;
+    private BigDecimal transferAmount;
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public String getPassword() {
+        return encryptPwd;
+    }
+
+    @Override
+    public String getUsername() {
+        return loginName;
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return false;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return true;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return false;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return false;
+    }
+}

+ 218 - 0
yt-common/src/main/java/com/ytpm/util/CacheUtil.java

@@ -0,0 +1,218 @@
+package com.ytpm.util;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import com.ytpm.constant.CacheConstant;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.lang.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 缓存工具类
+ *
+ * @author xuwh
+ */
+public class CacheUtil {
+
+    /**
+     * 获取缓存
+     *
+     * @param key 缓存键值
+     * @return Object
+     */
+    @Nullable
+    public static Object get(String key) {
+        return get(CacheConstant.DEFAULT_CACHE, CacheConstant.DEFAULT_CACHE_PREFIX, key);
+    }
+
+    /**
+     * 获取缓存
+     *
+     * @param cacheName 缓存名
+     * @param key       缓存键值
+     * @return Object
+     */
+    @Nullable
+    public static <T> T get(String cacheName, String prefixKey, String key, Class<T> type) {
+        Object value = get(cacheName, prefixKey, key);
+        if (value != null && type != null && !type.isInstance(value)) {
+            throw new IllegalStateException(
+                    "缓存值与类型不匹配 [" + type.getName() + "]: " + value);
+        }
+        return (T) value;
+    }
+
+    /**
+     * 获取缓存
+     *
+     * @param cacheName 缓存名
+     * @param prefixKey 缓存前缀
+     * @param key       缓存键值
+     * @return Object
+     */
+    @Nullable
+    public static Object get(String cacheName, String prefixKey, String key) {
+        return getRedisTemplate().opsForValue().get(formatCacheKey(cacheName, prefixKey, key));
+    }
+
+    /**
+     * 设置缓存,缓存key统一采用 缓存名+缓存前缀+缓存key 的格式,以便后续系统可以对部分缓存进行重新加载
+     *
+     * @param key   缓存键值
+     * @param value 缓存值
+     */
+    public static void put(String key, @Nullable Object value) {
+        put(key, value, -1);
+    }
+
+
+    /**
+     * 模糊匹配,返回string
+     *
+     * @param match
+     * @return
+     */
+    public static Map<String, String> getLike(String match) {
+
+        Map<String, String> rmap = new HashMap<>();
+        Set<String> keys = getRedisTemplate().keys(match);
+        if (CollectionUtil.isEmpty(keys)) {
+            return null;
+        }
+
+        for (String key : keys) {
+            rmap.put(key, getRedisTemplate().opsForValue().get(key).toString());
+        }
+
+        return rmap;
+    }
+
+    /**
+     * 模糊查询获取所有key
+     *
+     * @param match
+     * @return
+     */
+    public static Set<String> getKeySetLike(String match) {
+        Set<String> keys = getRedisTemplate().keys(match);
+        if (CollectionUtil.isEmpty(keys)) {
+            return null;
+        }
+        return keys;
+    }
+
+    /**
+     * 设置缓存,缓存key统一采用 缓存名+缓存前缀+缓存key 的格式,以便后续系统可以对部分缓存进行重新加载
+     *
+     * @param key   缓存键值
+     * @param value 缓存值
+     * @param ttl   有效时间(单位:秒)
+     */
+    public static void put(String key, @Nullable Object value, long ttl) {
+        put(CacheConstant.DEFAULT_CACHE, CacheConstant.DEFAULT_CACHE_PREFIX, key, value, ttl);
+    }
+
+    /**
+     * 设置缓存,缓存key统一采用 缓存名+缓存前缀+缓存key 的格式,以便后续系统可以对部分缓存进行重新加载
+     *
+     * @param cacheName 缓存名
+     * @param key       缓存键值
+     * @param key       缓存键值
+     * @param value     缓存值
+     */
+    public static void put(String cacheName, String prefixKey, String key, @Nullable Object value) {
+        put(cacheName, prefixKey, key, value, -1);
+    }
+
+    /**
+     * 设置缓存,缓存key统一采用 缓存名+缓存前缀+缓存key 的格式,以便后续系统可以对部分缓存进行重新加载
+     *
+     * @param cacheName 缓存名
+     * @param prefixKey 缓存键值前缀
+     * @param key       缓存键值
+     * @param value     缓存值
+     * @param ttl       有效时间(单位:秒)
+     */
+    public static void put(String cacheName, String prefixKey, String key, @Nullable Object value, long ttl) {
+        if (ttl > 0) {
+            getRedisTemplate().opsForValue().set(formatCacheKey(cacheName, prefixKey, key), value, ttl, TimeUnit.SECONDS);
+        } else {
+            getRedisTemplate().opsForValue().set(formatCacheKey(cacheName, prefixKey, key), value);
+        }
+    }
+
+
+    /**
+     * 清除缓存
+     *
+     * @param cacheName 缓存名
+     * @param prefixKey 缓存键值前缀
+     * @param key       缓存键值
+     */
+    public static void clear(String cacheName, String prefixKey, String key) {
+        if (StrUtil.isAllBlank(cacheName, prefixKey, key)) {
+            return;
+        }
+        getRedisTemplate().delete(formatCacheKey(cacheName, prefixKey, key));
+    }
+
+    /**
+     * 清除缓存
+     *
+     * @param cacheName 缓存名
+     * @param prefixKey 缓存键值前缀
+     */
+    public static void clear(String cacheName, String prefixKey) {
+        if (StrUtil.isAllBlank(cacheName, prefixKey)) {
+            return;
+        }
+        Set<String> keys = getRedisTemplate().keys(cacheName.concat(prefixKey).concat("*"));
+        getRedisTemplate().delete(keys);
+    }
+
+    /**
+     * 清空缓存
+     *
+     * @param cacheName 缓存名
+     */
+    public static void clear(String cacheName) {
+        if (StrUtil.isBlank(cacheName)) {
+            return;
+        }
+        Set<String> keys = getRedisTemplate().keys(cacheName.concat("*"));
+        getRedisTemplate().delete(keys);
+    }
+
+    public static RedisTemplate<String, Object> getRedisTemplateList() {
+        return getRedisTemplate();
+    }
+
+    /**
+     * 获取redisTemplate
+     *
+     * @return
+     */
+    private static RedisTemplate<String, Object> getRedisTemplate() {
+        return SpringUtil.getBean("redisTemplate", RedisTemplate.class);
+    }
+
+    /**
+     * 格式化缓存key
+     *
+     * @param cacheName 缓存名
+     * @param prefixKey 缓存前缀
+     * @param key       缓存key
+     * @return
+     */
+    private static String formatCacheKey(String cacheName, String prefixKey, String key) {
+        StringBuilder sb = new StringBuilder(cacheName.length() + prefixKey.length() + key.length() + 2);
+        sb.append(cacheName).append(':').append(prefixKey).append(':').append(key);
+        return sb.toString().replace("::",":");
+    }
+
+}

+ 31 - 0
yt-common/src/main/java/com/ytpm/util/CheckPwdUtil.java

@@ -0,0 +1,31 @@
+package com.ytpm.util;
+
+/**
+ * 密码复杂度校验工具
+ */
+public class CheckPwdUtil {
+
+    //数字
+    public static final String REG_NUMBER = ".*\\d+.*";
+    //小写字母
+    public static final String REG_UPPERCASE = ".*[A-Z]+.*";
+    //大写字母
+    public static final String REG_LOWERCASE = ".*[a-z]+.*";
+    //特殊符号
+    public static final String REG_SYMBOL = ".*[~!@#$%^&*()_+|<>,.?/:;'\\[\\]{}\"]+.*";
+    public static boolean checkPasswordRule(String password) {
+        //密码为空或者长度小于8位则返回false
+        if (password == null || password.length() < 8) return false;
+        int i = 0;
+        if (password.matches(REG_NUMBER)) i++;
+        if (password.matches(REG_LOWERCASE)) i++;
+        if (password.matches(REG_UPPERCASE)) i++;
+        if (password.matches(REG_SYMBOL)) i++;
+        if (i < 3) return false;
+        return true;
+    }
+
+    public static void main(String[] args) {
+        System.err.println(checkPasswordRule("asdggd."));
+    }
+}

+ 20 - 0
yt-common/src/main/java/com/ytpm/util/IDUtil.java

@@ -0,0 +1,20 @@
+package com.ytpm.util;
+
+import cn.hutool.core.util.IdUtil;
+public class IDUtil {
+    private final static String PREFIX = "zlTech_";
+
+    /**
+     * 雪花算法ID 生成
+     * @return
+     */
+    public static String generateFlowID(){
+       return PREFIX + IdUtil.getSnowflakeNextIdStr();
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i<30;i++){
+            System.err.println(generateFlowID());
+        }
+    }
+}

+ 66 - 0
yt-common/src/main/java/com/ytpm/util/RandomPasswordGenerator.java

@@ -0,0 +1,66 @@
+package com.ytpm.util;
+
+import java.security.SecureRandom;
+import java.util.HashSet;
+import java.util.Set;
+
+public class RandomPasswordGenerator {
+    private static final String LOWER_CASE = "abcdefghijklmnopqrstuvwxyz";
+    private static final String UPPER_CASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    private static final String NUMBERS = "0123456789";
+    private static final String SPECIAL_CHARACTERS = "!@#$%^&*()_+-=[]{}|;:,.<>?";
+    private static final String ALL_CHARACTERS = LOWER_CASE + UPPER_CASE + NUMBERS + SPECIAL_CHARACTERS;
+    private static final SecureRandom RANDOM = new SecureRandom();
+
+    public static String generatePassword(int length) {
+        if (length < 3) {
+            throw new IllegalArgumentException("Password length must be at least 3");
+        }
+
+        StringBuilder password = new StringBuilder(length);
+        Set<Character> charSet = new HashSet<>();
+
+        // 确保每种类型的字符至少有一个
+        password.append(getRandomChar(LOWER_CASE));
+        password.append(getRandomChar(UPPER_CASE));
+        password.append(getRandomChar(NUMBERS));
+        password.append(getRandomChar(SPECIAL_CHARACTERS));
+        charSet.add(LOWER_CASE.charAt(0)); // 示例,实际应从生成的字符中添加到集合中
+        charSet.add(UPPER_CASE.charAt(0)); // 示例,实际应从生成的字符中添加到集合中
+        charSet.add(NUMBERS.charAt(0)); // 示例,实际应从生成的字符中添加到集合中
+        charSet.add(SPECIAL_CHARACTERS.charAt(0)); // 示例,实际应从生成的字符中添加到集合中
+
+        // 填充剩余的字符直到达到所需长度
+        while (password.length() < length) {
+            char randomChar = getRandomChar(ALL_CHARACTERS);
+            if (!charSet.contains(randomChar)) { // 确保不会重复添加已存在的字符类型
+                password.append(randomChar);
+                charSet.add(randomChar); // 添加到已选择字符集合中,以避免重复
+            }
+        }
+
+        // 打乱顺序以确保随机性
+        password = shufflePassword(password);
+        return password.toString();
+    }
+
+    private static char getRandomChar(String characters) {
+        int index = RANDOM.nextInt(characters.length());
+        return characters.charAt(index);
+    }
+
+    private static StringBuilder shufflePassword(StringBuilder password) {
+        char[] passwordArray = password.toString().toCharArray();
+        for (int i = passwordArray.length - 1; i > 0; i--) {
+            int j = RANDOM.nextInt(i + 1); // 生成一个[0, i]之间的随机数
+            char temp = passwordArray[i]; // 交换数组中的两个元素
+            passwordArray[i] = passwordArray[j];
+            passwordArray[j] = temp;
+        }
+        return new StringBuilder(new String(passwordArray)); // 返回打乱后的字符串构建器对象
+    }
+
+    public static void main(String[] args) {
+        System.out.println("Generated Password: " + generatePassword(8));
+    }
+}

+ 231 - 0
yt-common/src/main/java/com/ytpm/util/RedisService.java

@@ -0,0 +1,231 @@
+package com.ytpm.util;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Calendar;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class RedisService {
+    @Autowired
+    StringRedisTemplate stringRedisTemplate;
+
+
+    @Resource(name = "stringRedisTemplate")
+    ValueOperations<String, String> valOpsStr;
+
+    @Autowired
+    RedisTemplate<Object, Object> redisTemplate;
+
+    @Autowired(required = false)
+    public void setRedisTemplate(RedisTemplate redisTemplate) {
+        //序列化key值,防止key值前面乱码
+        RedisSerializer stringSerializer = new StringRedisSerializer();
+        redisTemplate.setKeySerializer(stringSerializer);
+        redisTemplate.setHashKeySerializer(stringSerializer);
+        this.redisTemplate = redisTemplate;
+    }
+
+    @Resource(name = "redisTemplate")
+    ValueOperations<Object, Object> valOpsObj;
+
+    /**
+     * 根据指定key获取String
+     * @param key
+     * @return
+     */
+    public String getStr(String key){
+        return valOpsStr.get(key);
+    }
+
+    /**
+     * 设置Str缓存
+     * @param key
+     * @param val
+     */
+    public void setStr(String key, String val){
+        valOpsStr.set(key,val);
+    }
+
+    /**
+     * 设置Str缓存 timeOut单位  毫秒
+     * @param key
+     * @param val
+     */
+    public void setTimeOutStr(String key, String val ,long timeOut){
+        valOpsStr.set(key,val,timeOut, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * 判断是否存在key
+     * @param key
+     * @return
+     */
+    public Boolean hasKey(String key) {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 设置Str缓存 timeOut单位  小时
+     * @param key
+     * @param val
+     * @param timeOut
+     */
+    public void setTimeOutHoursStr(String key, String val ,long timeOut){
+        valOpsStr.set(key,val,timeOut, TimeUnit.HOURS);
+    }
+
+    /**
+     * 设置Str缓存 timeOut单位  分钟
+     * @param key
+     * @param val
+     * @param timeOut
+     */
+    public void setTimeOutMinutesStr(String key, String val ,long timeOut){
+        valOpsStr.set(key,val,timeOut, TimeUnit.MINUTES);
+    }
+
+    /**
+     * 删除指定key
+     * @param key
+     */
+    public void del(String key){
+        stringRedisTemplate.delete(key);
+    }
+
+    /**
+     * 设置指定key值的超时时间
+     * @param key
+     */
+    public void expire(String key,long timeOut){
+        TimeUnit timeUnit=TimeUnit.MILLISECONDS;
+        stringRedisTemplate.expire(key,timeOut, timeUnit);
+    }
+
+    /**
+     * 根据前缀批量删除
+     * @param keysPrefix
+     */
+    public void delKeys(String keysPrefix){
+        Set<String> set = stringRedisTemplate.keys(keysPrefix);
+        stringRedisTemplate.delete(set);
+    }
+
+
+
+    /**
+     * 根据指定o获取Object
+     * @param o
+     * @return
+     */
+    public Object getObj(Object o){
+        return valOpsObj.get(o);
+    }
+
+    /**
+     * 设置obj缓存
+     * @param o1
+     * @param o2
+     */
+    public void setObj(Object o1, Object o2){
+        valOpsObj.set(o1, o2);
+    }
+    /**
+     * 设置obj缓存
+     * @param o1
+     * @param o2
+     */
+    public void setObj(Object o1, Object o2,long timeout){
+        valOpsObj.set(o1, o2,timeout);
+    }
+
+
+    /**
+     * 删除Obj缓存
+     * @param o
+     */
+    public void delObj(Object o){
+        redisTemplate.delete(o);
+    }
+
+
+    /**
+     * 自增1
+     * @param key
+     * @return
+     */
+    public long incr(String key){
+        long num = valOpsStr.increment(key,1);
+        return num;
+    }
+    /**
+     * 自增1
+     * @param key
+     * @return
+     */
+    public long incrByExp(String key,long timeout){
+        long num = valOpsStr.increment(key,1);
+        TimeUnit timeUnit=TimeUnit.MILLISECONDS;
+        stringRedisTemplate.expire(key,timeout, timeUnit);
+        return num;
+    }
+    /**
+     * 自增
+     * @param key
+     * @param delta  自增值
+     * @return
+     */
+    public long incrByExp(String key,int delta,long timeout){
+        long num = valOpsStr.increment(key,delta);
+        TimeUnit timeUnit=TimeUnit.MILLISECONDS;
+        stringRedisTemplate.expire(key,timeout, timeUnit);
+        return num;
+    }
+    /**
+     * 自增
+     * @param key
+     * @param delta  自增值
+     * @return
+     */
+    public long incr(String key,long delta){
+        return valOpsStr.increment(key,delta);
+    }
+
+    /**
+     *
+     * 生成业务单编号
+     * @return
+     */
+    public String generateOrderNo(String key){
+        Calendar cl = Calendar.getInstance();
+        int year = cl.get(Calendar.YEAR);
+        int month = cl.get(Calendar.MONTH) + 1;
+        int day = cl.get(Calendar.DATE);
+        String orderNoPrefix = getTimeStr(year)+getTimeStr(month)+getTimeStr(day);
+        if(this.hasKey(key)){
+            String old = this.getStr(key);
+            String sub = old.substring(0,8);
+            if(sub.equals(orderNoPrefix)){
+                long incr = this.incr(key);
+                return String.valueOf(incr);
+            }
+        }
+        this.setStr(key,orderNoPrefix+"001");
+        return orderNoPrefix+"001";
+    }
+
+    private String getTimeStr(int num){
+        if(num>9) {
+            return String.valueOf(num);
+        }
+        return "0"+num;
+    }
+}

+ 73 - 0
yt-gateway/pom.xml

@@ -0,0 +1,73 @@
+<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.ytpm</groupId>
+        <artifactId>yt_platform</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>yt-gateway</artifactId>
+    <packaging>jar</packaging>
+    <description>网关</description>
+
+    <name>yt-gateway</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>eg-gateway</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                    <encoding>utf-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.5.3</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                    <mainClass>com.ytpm.GatewayApplication</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 29 - 0
yt-gateway/src/main/java/com/ytpm/GatewayApplication.java

@@ -0,0 +1,29 @@
+package com.ytpm;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
+import org.springframework.context.annotation.Bean;
+import reactor.core.publisher.Mono;
+
+import java.util.Objects;
+
+
+@SpringBootApplication
+@EnableDiscoveryClient
+public class GatewayApplication
+{
+    public static void main(String[] args) {
+        SpringApplication.run(GatewayApplication.class, args);
+    }
+    /**
+     * 自定义限流key
+     * exchange对象中获取服务ID、请求信息,用户信息等
+     * @return
+     */
+    @Bean
+    KeyResolver ipKeyResolver() {
+        return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostName());
+    }
+}

+ 29 - 0
yt-gateway/src/main/java/com/ytpm/cors/CustomerCorsConfiguration.java

@@ -0,0 +1,29 @@
+package com.ytpm.cors;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.reactive.CorsWebFilter;
+import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
+
+@Configuration
+public class CustomerCorsConfiguration {
+    @Bean // 添加过滤器
+    public CorsWebFilter corsWebFilter(){
+        //基于url跨域,选择reactive包下的
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        // 跨域配置信息
+        CorsConfiguration configuration = new CorsConfiguration();
+        // 允许跨域的头
+        configuration.addAllowedHeader("*");
+        // 允许跨域的请求方式
+        configuration.addAllowedMethod("*");
+        // 允许跨域的请求来源
+        configuration.addAllowedOrigin("*");
+        // 是否允许携带cookie跨域
+        configuration.setAllowCredentials(true);
+        // 任意url都要进行跨域配置
+        source.registerCorsConfiguration("/**", configuration);
+        return new CorsWebFilter(source);
+    }
+}

+ 31 - 0
yt-gateway/src/main/resources/bootstrap.yml

@@ -0,0 +1,31 @@
+spring:
+  profiles:
+    active: local
+---
+spring:
+  profiles: local
+  application:
+    name: yt-gateway
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 127.0.0.1:8848
+        namespace: 52439154-ea03-4121-9759-44d0cacc4765
+      config:
+        server-addr: 127.0.0.1:8848
+        file-extension: yml
+        namespace: 52439154-ea03-4121-9759-44d0cacc4765
+---
+spring:
+  profiles: dev
+  application:
+    name: yt-gateway
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 121.37.82.232:8848
+        namespace: 776851c5-aa23-4606-b2b2-941487de707f
+      config:
+        server-addr: 121.37.82.232:8848
+        file-extension: yml
+        namespace: 776851c5-aa23-4606-b2b2-941487de707f

+ 90 - 0
yt-oauth/oauth-service/pom.xml

@@ -0,0 +1,90 @@
+<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.ytpm</groupId>
+        <artifactId>yt-oauth</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>oauth-service</artifactId>
+    <packaging>jar</packaging>
+    <description>登录认证服务器</description>
+
+    <name>oauth-service</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ytpm</groupId>
+            <artifactId>yt-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>5.3.27</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>yt-oauth</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                    <encoding>utf-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                    <mainClass>com.ytpm.OauthApplication</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 22 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/OauthApplication.java

@@ -0,0 +1,22 @@
+package com.ytpm;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+
+@SpringBootApplication
+//对外开启暴露获取token的API接口
+@EnableResourceServer
+@EnableDiscoveryClient
+@MapperScan(basePackages = "com.ytpm.dao")
+//@EnableFeignClients(basePackages = {"com.zlsk.feign"})
+public class OauthApplication
+{
+    public static void main( String[] args )
+    {
+        SpringApplication.run(OauthApplication.class, args);
+    }
+}

+ 25 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/auth/AuthService.java

@@ -0,0 +1,25 @@
+package com.ytpm.auth;
+
+import com.ytpm.general.Result;
+
+import java.security.Principal;
+import java.util.Map;
+
+public interface AuthService {
+    /**
+     * token颁布
+     *
+     * @param principal
+     * @param parameters
+     * @return
+     */
+    Result<Map<String, Object>> createAccessToken(Principal principal, Map<String, String> parameters);
+
+    /**
+     * 登出
+     *
+     * @param accessToken
+     * @return
+     */
+    Result logout(String accessToken);
+}

+ 24 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/auth/CaptchaService.java

@@ -0,0 +1,24 @@
+package com.ytpm.auth;
+
+
+
+import com.ytpm.oauth.model.CaptchaValid;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public interface CaptchaService {
+
+    /**
+     * 生成验证码
+     */
+    void create(HttpServletResponse response, String uuid) throws IOException;
+
+    /**
+     * 验证验证码
+     *
+     * @param captchaValid
+     * @return
+     */
+    void valid(CaptchaValid captchaValid);
+}

+ 135 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/auth/impl/AuthServiceImpl.java

@@ -0,0 +1,135 @@
+package com.ytpm.auth.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.google.common.collect.Maps;
+import com.ytpm.auth.AuthService;
+import com.ytpm.general.RepMessage;
+import com.ytpm.general.Result;
+import com.ytpm.general.StatusCode;
+import com.ytpm.handle.CustomerException;
+import com.ytpm.oauth.model.CaptchaValid;
+import com.ytpm.util.CacheUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
+import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Objects;
+
+@Slf4j(topic = "auth-service")
+@Service
+public class AuthServiceImpl implements AuthService {
+    @Resource
+    private RedisTokenStore redisTokenStore;
+
+    @Resource
+    private TokenEndpoint tokenEndpoint;
+
+    private static final String USER_NAME = "username";
+    private static final String PASS_WORD = "password";
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Map<String, Object>> createAccessToken(Principal principal, Map<String, String> parameters) {
+        CaptchaValid captchaValid = new CaptchaValid(true,
+                3,
+                parameters.get("uuid"),
+                0,
+                parameters.get("captcha"));
+        validCode(captchaValid);
+        // 判断用户名密码是否正确,是否被锁定等逻辑
+        String loginName = parameters.get(USER_NAME);
+        String password = parameters.get(PASS_WORD);
+
+        if (StrUtil.isEmpty(loginName)) {
+            return new Result<>(StatusCode.USER_NAME_EMPTY, RepMessage.USER_NAME_EMPTY);
+        }
+
+        parameters.put(USER_NAME, loginName);
+        parameters.put(PASS_WORD, password);
+        return logoutAndReLogin(principal, parameters);
+    }
+
+    private void validCode(CaptchaValid bo){
+        log.info("验证码校验");
+
+        //判断是否需要输入验证码,密码错误次数大于配置错误次数
+        if (bo.getShowCaptcha() || bo.getErrorCount() > bo.getSettingErrorCountCaptcha()) {
+            if (StrUtil.isBlank(bo.getCaptcha())) {
+                throw new CustomerException("验证码不能为空");
+            }
+            if (StrUtil.isBlank(bo.getUuid())) {
+                throw new CustomerException("验证码已过期,请刷新后重试");
+            }
+            String vailCode = (String) CacheUtil.get("sms_captcha_" + bo.getUuid());
+            if (vailCode == null) {
+                throw new CustomerException("验证码已过期,请刷新后重试");
+            }
+            if (!bo.getCaptcha().equals(vailCode)) {
+                throw new CustomerException("验证码错误");
+            }
+        }
+    }
+    /**
+     * 登录或者重新登录
+     */
+    private Result<Map<String, Object>> logoutAndReLogin(Principal principal, Map<String, String> parameters) {
+        Map<String, Object> resultMap = Maps.newLinkedHashMap();
+        // 刷新并废弃掉当前token再重新生成token
+        OAuth2AccessToken accessToken = null;
+        try {
+            //首次拿到缓存中的旧token
+            accessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
+            if (Objects.isNull(accessToken)) {
+                return new Result<>(StatusCode.PWD_ERROR, RepMessage.USERNAME_OR_PASSWORD_ERROR);
+            }
+            String discardToken = accessToken.getValue();
+            // 注销token
+            logout(discardToken);
+            // 重新生成token
+            accessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
+            if (Objects.isNull(accessToken)) {
+                return new Result<>(StatusCode.MANAGE_NOT_LOGIN, RepMessage.TOKEN_INVALID);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return new Result<>(403, RepMessage.METHOD_NOT_ARROW);
+        }
+        resultMap.put("access_token", accessToken.getValue());
+        resultMap.put("refresh_token", accessToken.getRefreshToken().getValue());
+        resultMap.put("token_type", accessToken.getTokenType());
+        resultMap.put("expires_in", accessToken.getExpiresIn());
+        resultMap.put("scope", StringUtils.join(accessToken.getScope(), ","));
+        resultMap.putAll(accessToken.getAdditionalInformation());
+        resultMap.put("authorities", new ArrayList<>());
+        return new Result<>(StatusCode.OK, "成功", resultMap);
+    }
+
+    /**
+     * 登出接口
+     *
+     * @param accessToken
+     * @return
+     */
+    @Override
+    public Result logout(String accessToken) {
+        try {
+            if (StrUtil.isNotBlank(accessToken)) {
+                OAuth2AccessToken oAuth2AccessToken = redisTokenStore.readAccessToken(accessToken);
+                if (null != oAuth2AccessToken) {
+                    redisTokenStore.removeAccessToken(oAuth2AccessToken);
+                }
+            }
+            return new Result<>(200, RepMessage.LOGOUT_SUCCESS);
+        } catch (Exception e) {
+            return new Result<>(StatusCode.ERROR, RepMessage.LOGOUT_FAIL);
+        }
+    }
+}

+ 80 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/auth/impl/CaptchaServiceImpl.java

@@ -0,0 +1,80 @@
+package com.ytpm.auth.impl;
+
+import cn.hutool.captcha.CaptchaUtil;
+import cn.hutool.captcha.CircleCaptcha;
+import cn.hutool.captcha.generator.RandomGenerator;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.IOUtils;
+import com.ytpm.auth.CaptchaService;
+import com.ytpm.oauth.model.CaptchaValid;
+import com.ytpm.util.CacheUtil;
+import com.ytpm.util.RedisService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j(topic = "captcha")
+@Service
+public class CaptchaServiceImpl implements CaptchaService {
+
+
+    // 图片宽
+    private final int width = 200;
+    // 图片高
+    private final int height = 100;
+    // 字符个数
+    private final int codeCount = 4;
+    // 干扰圆圈条数
+    private final int circleCount = 20;
+    // 生成验证码长度
+    private final int length = 4;
+    // 过期时间
+    private final int ttl = 5 * 60;
+
+    @Resource
+    private RedisService redisService;
+
+    @Override
+    public void create(HttpServletResponse response, String uuid) throws IOException {
+
+        response.setHeader("Cache-Control", "no-store, no-cache");
+        response.setContentType("image/jpeg");
+
+        //获取图片验证码输出到流中
+        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height, codeCount, circleCount);
+        captcha.setGenerator(new RandomGenerator("0123456789",length));
+        //设置验证码到缓存中,5分钟过期
+
+        CacheUtil.put("sms_captcha_" + uuid, captcha.getCode(), ttl);
+        ServletOutputStream out = response.getOutputStream();
+        captcha.write(out);
+        IOUtils.closeQuietly(out);
+    }
+
+    @Override
+    public void valid(CaptchaValid captchaValid) {
+
+        log.info("验证码校验");
+
+        //判断是否需要输入验证码,密码错误次数大于配置错误次数
+        if (captchaValid.getShowCaptcha() || captchaValid.getErrorCount() > captchaValid.getSettingErrorCountCaptcha()) {
+            if (StrUtil.isBlank(captchaValid.getCaptcha())) {
+                throw new RuntimeException("验证码不能为空");
+            }
+            if (StrUtil.isBlank(captchaValid.getUuid())) {
+                throw new RuntimeException("验证码已过期,请刷新后重试");
+            }
+            String vailCode = (String) CacheUtil.get("sms_captcha_" + captchaValid.getUuid());
+            if (vailCode == null) {
+                throw new RuntimeException("验证码已过期,请刷新后重试");
+            }
+            if (!captchaValid.getCaptcha().equals(vailCode)) {
+                throw new RuntimeException("验证码错误");
+            }
+        }
+    }
+}

+ 36 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/certify/UserDetailService.java

@@ -0,0 +1,36 @@
+package com.ytpm.certify;
+
+import com.ytpm.dao.YtPlatformUserMapper;
+import com.ytpm.oauth.model.YtPlatformUser;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Objects;
+
+@Service
+public class UserDetailService implements UserDetailsService {
+
+    @Resource
+    private YtPlatformUserMapper userMapper;
+
+    @Override
+    public UserDetails loadUserByUsername(String loginName) throws UsernameNotFoundException {
+        //获取本地用户
+        YtPlatformUser platformUser = userMapper.selectByLoginName(loginName);
+        if(Objects.nonNull(platformUser)){
+            //需要返回Oauth2中的认证对象,因此这里的username实际上是login-name
+            //                    AuthorityUtils.createAuthorityList(systemUser.getRole())) ;
+            return new User(platformUser.getUsername(),
+                    platformUser.getPassword(),
+//                    AuthorityUtils.createAuthorityList(systemUser.getRole())) ;
+                    AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
+        }else{
+            throw new UsernameNotFoundException("用户["+platformUser+"]不存在");
+        }
+    }
+}

+ 50 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/Oauth2Config.java

@@ -0,0 +1,50 @@
+package com.ytpm.config;
+
+import com.ytpm.certify.UserDetailService;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+
+import javax.annotation.Resource;
+import javax.sql.DataSource;
+
+@Configuration
+@EnableAuthorizationServer
+public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
+
+    @Resource
+    PasswordEncoder passwordEncoder;
+    @Resource
+    UserDetailService userDetailService;
+    @Resource
+    AuthenticationManager authenticationManager;
+    @Resource
+    private TokenStore redisTokenStore;
+    @Resource
+    DataSource dataSource;
+
+    @Override
+    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
+        endpoints.authenticationManager(authenticationManager)
+                .userDetailsService(userDetailService)
+                .tokenStore(redisTokenStore);
+    }
+
+    @Override
+    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
+        clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
+    }
+
+    @Override
+    public void configure(AuthorizationServerSecurityConfigurer security){
+        security.allowFormAuthenticationForClients();
+        security.checkTokenAccess("isAuthenticated()");
+        security.tokenKeyAccess("isAuthenticated()");
+    }
+}

+ 68 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/WebSecurityConfig.java

@@ -0,0 +1,68 @@
+package com.ytpm.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.authentication.AuthenticationEventPublisher;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
+import org.springframework.security.config.annotation.ObjectPostProcessor;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.session.SessionRegistry;
+import org.springframework.security.core.session.SessionRegistryImpl;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
+import org.springframework.web.context.request.RequestContextListener;
+
+/**
+ * 自定义web安全配置类, 对web请求进行放行
+ */
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Bean
+    public RequestContextListener requestContextListener() {
+        return new RequestContextListener();
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    @Override
+    public AuthenticationManager authenticationManagerBean() throws Exception {
+        return super.authenticationManagerBean();
+    }
+
+    @Bean
+    public AuthenticationEventPublisher authenticationEventPublisher() {
+        return new DefaultAuthenticationEventPublisher();
+    }
+
+    /**
+     * 允许匿名访问所有接口 主要是 oauth 接口
+     * 此处加入 oauth token接口将导致 登录请求不走SecurityContextPersistenceFilter
+     * 资源服务器token丢失
+     */
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http.csrf().disable()
+                .authorizeRequests()
+                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
+                    @Override
+                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
+                        return o;
+                    }
+                })
+                .antMatchers("/**").permitAll();
+    }
+
+    @Bean
+    public SessionRegistry sessionRegistry() {
+        return new SessionRegistryImpl();
+    }
+
+}

+ 20 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/auth/AuthListenerConfig.java

@@ -0,0 +1,20 @@
+package com.ytpm.config.auth;
+
+import org.springframework.context.event.EventListener;
+import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
+import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AuthListenerConfig {
+    @EventListener
+    public void onSuccess(AuthenticationSuccessEvent successEvent){
+        System.err.println(successEvent.getAuthentication());
+        System.out.println(successEvent.getAuthentication().getName()+"认证成功");
+    }
+
+    @EventListener
+    public void onFailure(AbstractAuthenticationFailureEvent failureDisabledEvent){
+        System.out.println(failureDisabledEvent.getAuthentication().getName()+"认证失败,失败原因:"+failureDisabledEvent.getException().getMessage());
+    }
+}

+ 58 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/ClientAuthentication.java

@@ -0,0 +1,58 @@
+package com.ytpm.config.custom;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Collection;
+
+public class ClientAuthentication implements Authentication {
+    private static ClientAuthentication authentication = null;
+    private ClientAuthentication() {
+
+    }
+    public static ClientAuthentication getAuthentication() {
+        if (null == authentication) {
+            synchronized (ClientAuthentication.class) {
+                if (null == authentication) {
+                    authentication = new ClientAuthentication();
+                }
+            }
+
+        }
+        return authentication;
+    }
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return null;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return null;
+    }
+
+    @Override
+    public Object getDetails() {
+        return null;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return null;
+    }
+
+    @Override
+    public boolean isAuthenticated() {
+        return false;
+    }
+
+    @Override
+    public void setAuthenticated(boolean b) throws IllegalArgumentException {
+
+    }
+
+    @Override
+    public String getName() {
+        return "user-client";
+    }
+}

+ 56 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/CustomAccessDecisionManager.java

@@ -0,0 +1,56 @@
+package com.ytpm.config.custom;
+
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+
+@Component
+public class CustomAccessDecisionManager implements AccessDecisionManager {
+    /**
+     * 自定义访问控制策略
+     * @param authentication  当前用户的认证信息
+     * @param object
+     * @param configAttributes 当前请求需要的角色
+     * @throws AccessDeniedException
+     * @throws InsufficientAuthenticationException
+     */
+    @Override
+    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
+        for (ConfigAttribute configAttribute : configAttributes) {
+            //当前请求需要的权限
+            String needRole = configAttribute.getAttribute();
+            if ("ROLE_LOGIN".equals(needRole)) {
+                if (authentication instanceof AnonymousAuthenticationToken) {
+                    throw new AccessDeniedException("尚未登录,请登录!");
+                } else {
+                    return;
+                }
+            }
+            //当前用户所具有的权限
+            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
+            for (GrantedAuthority authority : authorities) {
+                if (authority.getAuthority().equals(needRole)) {
+                    return;
+                }
+            }
+        }
+        throw new AccessDeniedException("权限不足,请联系管理员!");
+    }
+
+    @Override
+    public boolean supports(ConfigAttribute attribute) {
+        return true;
+    }
+
+    @Override
+    public boolean supports(Class<?> clazz) {
+        return true;
+    }
+}

+ 35 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/custom/CustomFilterInvocationSecurityMetadataSource.java

@@ -0,0 +1,35 @@
+package com.ytpm.config.custom;
+
+import cn.hutool.core.text.AntPathMatcher;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+
+@Component
+public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
+    AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+    @Override
+    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+        String requestUrl = ((FilterInvocation) object).getRequestUrl();
+        if (antPathMatcher.match("/oauth/*", requestUrl)) {
+            return null;
+        }
+        //TODO 访问菜单角色权限控制
+        return SecurityConfig.createList("ROLE_LOGIN");
+    }
+
+    @Override
+    public Collection<ConfigAttribute> getAllConfigAttributes() {
+        return null;
+    }
+
+    @Override
+    public boolean supports(Class<?> aClass) {
+        return true;
+    }
+}

+ 37 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/server/ResourceServerConfig.java

@@ -0,0 +1,37 @@
+package com.ytpm.config.server;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
+
+import javax.annotation.Resource;
+
+
+/**
+ * 资源访问控制器  对资源服务进行放行
+ */
+@Configuration
+public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
+    @Resource
+    private RedisTokenStore redisTokenStore;
+    @Override
+    public void configure(HttpSecurity http) throws Exception {
+        http.authorizeRequests()
+                .antMatchers("/oauth/**",
+                        "/v2/api-docs/**",
+                        "/swagger-resources/**",
+                        "/swagger-ui.html",
+                        "/webjars/**").permitAll()
+                .anyRequest().authenticated()
+                .and()
+                .csrf().disable();
+    }
+
+    @Override
+    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
+        resources.tokenStore(redisTokenStore);
+        resources.resourceId("yt-oauth");
+    }
+}

+ 19 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/store/RedisTokenStoreConfig.java

@@ -0,0 +1,19 @@
+package com.ytpm.config.store;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
+
+@Configuration
+public class RedisTokenStoreConfig {
+    @Autowired
+    private RedisConnectionFactory redisConnectionFactory;
+
+    @Bean
+    public TokenStore redisTokenStore (){
+        return new RedisTokenStore(redisConnectionFactory);
+    }
+}

+ 40 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/config/swagger/SwaggerConfig.java

@@ -0,0 +1,40 @@
+package com.ytpm.config.swagger;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+    private static final String VERSION = "1.0.0";
+
+    @Bean
+    public Docket createApi(){
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.ytpm.controller"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("")
+                .contact(new Contact("易推网络","http://www.sourcetreasure.com/index.html","marxjaw6466@163.com"))
+                .description("易推网络渠道商营销管理系统")
+                .termsOfServiceUrl("https://juejin.cn/user/4310510864972254")
+                .license("The Apache License, Version 2.0")
+                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
+                .version(VERSION)
+                .build();
+    }
+}

+ 80 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/controller/OauthController.java

@@ -0,0 +1,80 @@
+package com.ytpm.controller;
+
+import com.ytpm.auth.AuthService;
+import com.ytpm.auth.CaptchaService;
+import com.ytpm.general.RepMessage;
+import com.ytpm.general.Result;
+import com.ytpm.general.StatusCode;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Locale;
+import java.util.Map;
+
+@Api(tags = "认证鉴权管理器")
+@Slf4j(topic = "oauth-controller")
+@RestController
+@RequestMapping("/oauth")
+public class OauthController {
+
+    @Resource
+    private AuthService authService;
+    @Resource
+    private CaptchaService captchaService;
+
+    /**
+     * 获取图片验证码
+     *
+     */
+    @ApiImplicitParam(name = "uuid", value = "根据当前时间生成唯一UUID用于本次登录验证码", required = true, paramType = "path")
+    @GetMapping(value = "/captcha.jpg")
+    public void getCaptcha(HttpServletResponse response, String uuid) throws IOException {
+        captchaService.create(response, uuid);
+    }
+
+    /**
+     * 重写/oauth/token接口
+     *
+     */
+    @ApiOperation(value = "登录")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "username", value = "用户名",required = true, paramType = "x-www-form-urlencoded"),
+            @ApiImplicitParam(name = "password", value = "密码",required = true, paramType = "x-www-form-urlencoded"),
+            @ApiImplicitParam(name = "scope", value = "作用范围",required = false, paramType = "x-www-form-urlencoded"),
+            @ApiImplicitParam(name = "grant_type", value = "授权类型",required = true, paramType = "x-www-form-urlencoded"),
+            @ApiImplicitParam(name = "uuid", value = "uuid 客户端获取验证码时生成的唯一ID",required = true, paramType = "x-www-form-urlencoded"),
+            @ApiImplicitParam(name = "captcha", value = "验证码",required = true, paramType = "x-www-form-urlencoded"),
+    })
+    @PostMapping("/token")
+    public Result postAccessToken(Principal principal,
+                                  @RequestParam Map<String, String> parameters) {
+        return authService.createAccessToken(principal, parameters);
+    }
+
+    /**
+     * 认证注销
+     *
+     * @return authLogout
+     */
+    @ApiOperation(value = "注销登录")
+    @PostMapping(value = "/logout")
+    public Result logOut(HttpServletRequest request) {
+        String token = request.getHeader("Authorization");
+        if (null == token) {
+            log.error("认证注销,未获取到登录信息");
+            return Result.resultFail(StatusCode.MANAGE_NOT_LOGIN, RepMessage.NOT_LOGIN);
+        } else {
+            token = token.toLowerCase(Locale.ROOT).startsWith("bearer")?token.substring(6).trim():token;
+        }
+        return authService.logout(token);
+    }
+}

+ 13 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/dao/YtPlatformUserMapper.java

@@ -0,0 +1,13 @@
+package com.ytpm.dao;
+
+import com.ytpm.oauth.model.YtPlatformUser;
+import org.apache.ibatis.annotations.Param;
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface YtPlatformUserMapper {
+    /**
+     * 根据用户名查询用户
+     */
+    YtPlatformUser selectByLoginName(@Param("loginName")String loginName);
+}

+ 15 - 0
yt-oauth/oauth-service/src/main/java/com/ytpm/util/EncryptUtil.java

@@ -0,0 +1,15 @@
+package com.ytpm.util;
+
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * 加密工具
+ */
+public class EncryptUtil {
+    private final static String CLIENT_SECRET = "yt-secret-2025";
+    private final static String PWD = "p@ssw0rd";
+    public static void main(String[] args) {
+        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+        System.err.println(encoder.encode(CLIENT_SECRET));
+    }
+}

+ 35 - 0
yt-oauth/oauth-service/src/main/resources/bootstrap.yml

@@ -0,0 +1,35 @@
+spring:
+  profiles:
+    active: local
+---
+spring:
+  profiles: local
+  main:
+    allow-bean-definition-overriding: true
+  application:
+    name: yt-oauth
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 127.0.0.1:8848
+        namespace: 52439154-ea03-4121-9759-44d0cacc4765
+      config:
+        server-addr: 127.0.0.1:8848
+        file-extension: yml
+        namespace: 52439154-ea03-4121-9759-44d0cacc4765
+---
+spring:
+  profiles: dev
+  main:
+    allow-bean-definition-overriding: true
+  application:
+    name: yt-oauth
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 121.37.82.232:8848
+        namespace: 776851c5-aa23-4606-b2b2-941487de707f
+      config:
+        server-addr: 121.37.82.232:8848
+        file-extension: yml
+        namespace: 776851c5-aa23-4606-b2b2-941487de707f

+ 11 - 0
yt-oauth/oauth-service/src/main/resources/mapper/YtPlatformUserMapper.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ytpm.dao.YtPlatformUserMapper">
+
+    <select id="selectByLoginName" resultType="com.ytpm.oauth.model.YtPlatformUser">
+        select
+            user_id, nick_name, head_image, login_name, encrypt_pwd, salt, phone, last_login_time, last_login_ip, phone_brand, phone_model, account_status, channel_id, user_type, login_days, total_income, app_id, registry_time, transfer_amount
+        from yt_platform_user
+        where account_status = 1 and login_name = #{loginName}
+    </select>
+</mapper>

+ 102 - 0
yt-oauth/pom.xml

@@ -0,0 +1,102 @@
+<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.ytpm</groupId>
+        <artifactId>yt_platform</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>yt-oauth</artifactId>
+    <packaging>pom</packaging>
+    <description>统一认证鉴权中心</description>
+
+    <name>yt-oauth</name>
+    <url>http://maven.apache.org</url>
+    <modules>
+        <module>oauth-service</module>
+    </modules>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
+            <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jsqlparser</artifactId>
+                    <groupId>com.github.jsqlparser</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.ytpm</groupId>
+            <artifactId>yt-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jsr305</artifactId>
+                    <groupId>com.google.code.findbugs</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>okio</artifactId>
+                    <groupId>com.squareup.okio</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>bcpkix-jdk15on</artifactId>
+                    <groupId>org.bouncycastle</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jsr305</artifactId>
+                    <groupId>com.google.code.findbugs</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+    </dependencies>
+</project>