CJ před 1 rokem
rodič
revize
9f1f4f4cda
100 změnil soubory, kde provedl 7474 přidání a 0 odebrání
  1. 8 0
      dtok-api/.idea/.gitignore
  2. 51 0
      dtok-api/.idea/JPASupport-project.xml
  3. 23 0
      dtok-api/.idea/compiler.xml
  4. 12 0
      dtok-api/.idea/dataSources.xml
  5. 21 0
      dtok-api/.idea/deployment.xml
  6. 17 0
      dtok-api/.idea/encodings.xml
  7. 36 0
      dtok-api/.idea/inspectionProfiles/Project_Default.xml
  8. 40 0
      dtok-api/.idea/jarRepositories.xml
  9. 15 0
      dtok-api/.idea/misc.xml
  10. 9 0
      dtok-api/.idea/modules.xml
  11. 9 0
      dtok-api/.idea/sqldialects.xml
  12. 8 0
      dtok-api/.idea/sshConfigs.xml
  13. 124 0
      dtok-api/.idea/uiDesigner.xml
  14. 7 0
      dtok-api/.idea/vcs.xml
  15. 21 0
      dtok-api/.idea/webServers.xml
  16. 33 0
      dtok-api/api/.gitignore
  17. 118 0
      dtok-api/api/.mvn/wrapper/MavenWrapperDownloader.java
  18. binární
      dtok-api/api/.mvn/wrapper/maven-wrapper.jar
  19. 2 0
      dtok-api/api/.mvn/wrapper/maven-wrapper.properties
  20. 310 0
      dtok-api/api/mvnw
  21. 182 0
      dtok-api/api/mvnw.cmd
  22. 68 0
      dtok-api/api/pom.xml
  23. 25 0
      dtok-api/api/src/main/java/com/dtok/api/ApiApplication.java
  24. 64 0
      dtok-api/api/src/main/java/com/dtok/api/controller/AppInfoController.java
  25. 118 0
      dtok-api/api/src/main/java/com/dtok/api/controller/CommonItemController.java
  26. 144 0
      dtok-api/api/src/main/java/com/dtok/api/controller/LoginController.java
  27. 63 0
      dtok-api/api/src/main/java/com/dtok/api/controller/LoginHistoryController.java
  28. 102 0
      dtok-api/api/src/main/java/com/dtok/api/controller/PermissionController.java
  29. 113 0
      dtok-api/api/src/main/java/com/dtok/api/controller/RoleController.java
  30. 13 0
      dtok-api/api/src/main/java/com/dtok/api/controller/ScriptController.java
  31. 145 0
      dtok-api/api/src/main/java/com/dtok/api/controller/UserController.java
  32. 11 0
      dtok-api/api/src/test/java/com/dtok/api/test.java
  33. 15 0
      dtok-api/entity/entity.iml
  34. 27 0
      dtok-api/entity/pom.xml
  35. 115 0
      dtok-api/entity/src/main/java/com/dtok/entity/Account.java
  36. 34 0
      dtok-api/entity/src/main/java/com/dtok/entity/AccountRole.java
  37. 40 0
      dtok-api/entity/src/main/java/com/dtok/entity/AppInfo.java
  38. 59 0
      dtok-api/entity/src/main/java/com/dtok/entity/CommonItem.java
  39. 92 0
      dtok-api/entity/src/main/java/com/dtok/entity/Devices.java
  40. 56 0
      dtok-api/entity/src/main/java/com/dtok/entity/LoginHistory.java
  41. 56 0
      dtok-api/entity/src/main/java/com/dtok/entity/Permission.java
  42. 35 0
      dtok-api/entity/src/main/java/com/dtok/entity/RolePermission.java
  43. 74 0
      dtok-api/entity/src/main/java/com/dtok/entity/Script.java
  44. 53 0
      dtok-api/entity/src/main/java/com/dtok/entity/ScriptHistory.java
  45. 24 0
      dtok-api/entity/src/main/java/com/dtok/entity/emum/LOGIN_DEVICE.java
  46. 26 0
      dtok-api/entity/src/main/java/com/dtok/entity/params/PermissionNode.java
  47. 16 0
      dtok-api/entity/src/main/java/com/dtok/entity/params/UserResponse.java
  48. binární
      dtok-api/entity/target/classes/com/dtok/entity/Account.class
  49. binární
      dtok-api/entity/target/classes/com/dtok/entity/AccountRole.class
  50. binární
      dtok-api/entity/target/classes/com/dtok/entity/AppInfo.class
  51. binární
      dtok-api/entity/target/classes/com/dtok/entity/CommonItem.class
  52. binární
      dtok-api/entity/target/classes/com/dtok/entity/Devices.class
  53. binární
      dtok-api/entity/target/classes/com/dtok/entity/LoginHistory.class
  54. binární
      dtok-api/entity/target/classes/com/dtok/entity/Permission.class
  55. binární
      dtok-api/entity/target/classes/com/dtok/entity/RolePermission.class
  56. binární
      dtok-api/entity/target/classes/com/dtok/entity/Script.class
  57. binární
      dtok-api/entity/target/classes/com/dtok/entity/ScriptHistory.class
  58. binární
      dtok-api/entity/target/classes/com/dtok/entity/emum/LOGIN_DEVICE.class
  59. binární
      dtok-api/entity/target/classes/com/dtok/entity/params/PermissionNode.class
  60. binární
      dtok-api/entity/target/classes/com/dtok/entity/params/UserResponse.class
  61. binární
      dtok-api/entity/target/entity-0.1.jar
  62. 5 0
      dtok-api/entity/target/maven-archiver/pom.properties
  63. 25 0
      dtok-api/entity/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  64. 25 0
      dtok-api/entity/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  65. 95 0
      dtok-api/framework/pom.xml
  66. 100 0
      dtok-api/framework/src/main/java/com/dtok/framework/aop/GlobalExceptionHandler.java
  67. 40 0
      dtok-api/framework/src/main/java/com/dtok/framework/authenticate/StpInterfaceImpl.java
  68. 189 0
      dtok-api/framework/src/main/java/com/dtok/framework/base/BaseController.java
  69. 52 0
      dtok-api/framework/src/main/java/com/dtok/framework/configure/RedisConfig.java
  70. 32 0
      dtok-api/framework/src/main/java/com/dtok/framework/configure/SaTokenConfigure.java
  71. 33 0
      dtok-api/framework/src/main/java/com/dtok/framework/configure/ServerConfig.java
  72. 48 0
      dtok-api/framework/src/main/java/com/dtok/framework/configure/SwaggerConfig.java
  73. 37 0
      dtok-api/framework/src/main/java/com/dtok/framework/configure/WebConfigurer.java
  74. 7 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/AbstractBaseExceptionEnum.java
  75. 34 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/AuthenticateException.java
  76. 127 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/BizExceptionEnum.java
  77. 34 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/BusinessException.java
  78. 34 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/ConnectionAlreadyExist.java
  79. 84 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/CoreExceptionEnum.java
  80. 34 0
      dtok-api/framework/src/main/java/com/dtok/framework/exception/ServiceException.java
  81. 51 0
      dtok-api/framework/src/main/java/com/dtok/framework/http/LoggingInterceptor.java
  82. 149 0
      dtok-api/framework/src/main/java/com/dtok/framework/http/OkHttpUtil.java
  83. 85 0
      dtok-api/framework/src/main/java/com/dtok/framework/listener/MySaTokenListener.java
  84. 46 0
      dtok-api/framework/src/main/java/com/dtok/framework/response/ErrorResponseData.java
  85. 95 0
      dtok-api/framework/src/main/java/com/dtok/framework/response/ResponseData.java
  86. 41 0
      dtok-api/framework/src/main/java/com/dtok/framework/response/SuccessResponseData.java
  87. 21 0
      dtok-api/framework/src/main/java/com/dtok/framework/sql/SqlServerDialect.java
  88. 15 0
      dtok-api/framework/src/main/java/com/dtok/framework/sql/UpperTableStrategy.java
  89. 261 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/ConnectionOptionWrapper.java
  90. 68 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/FileUtils.java
  91. 81 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/HttpContext.java
  92. 81 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/IpUtil.java
  93. 36 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/MD5Util.java
  94. 54 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/PasswordUtil.java
  95. 54 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/RedisConstants.java
  96. 2307 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/RedisUtil.java
  97. 22 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/RenderUtil.java
  98. 43 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/SerializeUtil.java
  99. 9 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/StateParameter.java
  100. 286 0
      dtok-api/framework/src/main/java/com/dtok/framework/util/ToolUtil.java

+ 8 - 0
dtok-api/.idea/.gitignore

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

+ 51 - 0
dtok-api/.idea/JPASupport-project.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AutoGeneratorSettingsState">
+    <option name="addSchemaNameToTableName" value="true" />
+    <option name="ignoredFields">
+      <set>
+        <option value="" />
+      </set>
+    </option>
+    <option name="moduleName" value="repository" />
+    <option name="moduleNameToSettings">
+      <map>
+        <entry key="entity">
+          <value>
+            <ModuleSettings>
+              <option name="entityPackageName" value="com.ciemis.entity.wxa" />
+              <option name="entityParentDirectory" value="$PROJECT_DIR$/entity/src/main/java" />
+              <option name="repositoryPackageName" value="com.ciemis.repository.wxa" />
+              <option name="repositoryParentDirectory" value="$PROJECT_DIR$/entity/src/main/java" />
+            </ModuleSettings>
+          </value>
+        </entry>
+        <entry key="he3-checkup">
+          <value>
+            <ModuleSettings>
+              <option name="entityPackageName" value="com.ciemis.entity.wxa" />
+              <option name="entityParentDirectory" value="$PROJECT_DIR$/src/main/java" />
+              <option name="repositoryPackageName" value="com.ciemis.repository.wxa" />
+              <option name="repositoryParentDirectory" value="$PROJECT_DIR$/src/main/java" />
+            </ModuleSettings>
+          </value>
+        </entry>
+        <entry key="repository">
+          <value>
+            <ModuleSettings>
+              <option name="entityPackageName" value="com.ciemis.entity.wxa" />
+              <option name="repositoryPackageName" value="com.ciemis.repository.wxa" />
+              <option name="repositoryParentDirectory" value="$PROJECT_DIR$/repository/src/main/java" />
+            </ModuleSettings>
+          </value>
+        </entry>
+      </map>
+    </option>
+    <option name="removeEntityPrefix" value="" />
+    <option name="removeFieldPrefix" value="" />
+    <option name="useJava8DateType" value="true" />
+  </component>
+  <component name="DatabaseSettingsState">
+    <option name="language" value="zh-CN" />
+  </component>
+</project>

+ 23 - 0
dtok-api/.idea/compiler.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile default="true" name="Default" enabled="true" />
+      <profile name="Maven default annotation processors profile" enabled="true">
+        <sourceOutputDir name="target/generated-sources/annotations" />
+        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
+        <outputRelativeToContentRoot value="true" />
+        <module name="api" />
+        <module name="framework" />
+        <module name="repository" />
+        <module name="entity" />
+        <module name="service" />
+      </profile>
+    </annotationProcessing>
+  </component>
+  <component name="JavacSettings">
+    <option name="ADDITIONAL_OPTIONS_OVERRIDE">
+      <module name="api" options="" />
+    </option>
+  </component>
+</project>

+ 12 - 0
dtok-api/.idea/dataSources.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
+    <data-source source="LOCAL" name="@rm-uf67t3vw28yp475tf1o.mysql.rds.aliyuncs.com" uuid="150fb651-f83e-421f-94c7-7a290165da30">
+      <driver-ref>mysql.8</driver-ref>
+      <synchronize>true</synchronize>
+      <jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
+      <jdbc-url>jdbc:mysql://rm-uf67t3vw28yp475tf1o.mysql.rds.aliyuncs.com:3306</jdbc-url>
+      <working-dir>$ProjectFileDir$</working-dir>
+    </data-source>
+  </component>
+</project>

+ 21 - 0
dtok-api/.idea/deployment.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PublishConfigData" serverName="checkup" remoteFilesAllowedToDisappearOnAutoupload="false">
+    <serverData>
+      <paths name="bi">
+        <serverdata>
+          <mappings>
+            <mapping deploy="/opt/bi" local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+      <paths name="checkup">
+        <serverdata>
+          <mappings>
+            <mapping deploy="/opt/checkup" local="$PROJECT_DIR$" web="/" />
+          </mappings>
+        </serverdata>
+      </paths>
+    </serverData>
+  </component>
+</project>

+ 17 - 0
dtok-api/.idea/encodings.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/api/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/entity/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/entity/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/framework/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/framework/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/repository/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/repository/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/service/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/service/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 36 - 0
dtok-api/.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,36 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="TOP_LEVEL_CLASS_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="INNER_CLASS_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="METHOD_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+        </value>
+      </option>
+      <option name="FIELD_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="IGNORE_DEPRECATED" value="false" />
+      <option name="IGNORE_JAVADOC_PERIOD" value="true" />
+      <option name="IGNORE_DUPLICATED_THROWS" value="false" />
+      <option name="IGNORE_POINT_TO_ITSELF" value="false" />
+      <option name="myAdditionalJavadocTags" value="Description,Author,Date" />
+    </inspection_tool>
+  </profile>
+</component>

+ 40 - 0
dtok-api/.idea/jarRepositories.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="public" />
+      <option name="name" value="aliyun nexus" />
+      <option name="url" value="https://maven.aliyun.com/repository/public" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Central Repository" />
+      <option name="url" value="https://repo.maven.apache.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Central Repository" />
+      <option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="public" />
+      <option name="name" value="aliyun nexus" />
+      <option name="url" value="http://maven.aliyun.com/nexus/content/groups/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Central Repository" />
+      <option name="url" value="https://maven.aliyun.com/repository/public" />
+    </remote-repository>
+  </component>
+</project>

+ 15 - 0
dtok-api/.idea/misc.xml

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

+ 9 - 0
dtok-api/.idea/modules.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/entity/entity.iml" filepath="$PROJECT_DIR$/entity/entity.iml" />
+      <module fileurl="file://$PROJECT_DIR$/service/service.iml" filepath="$PROJECT_DIR$/service/service.iml" />
+    </modules>
+  </component>
+</project>

+ 9 - 0
dtok-api/.idea/sqldialects.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="SqlDialectMappings">
+    <file url="PROJECT" dialect="TSQL" />
+  </component>
+  <component name="SqlResolveMappings">
+    <file url="PROJECT" scope="{&quot;node&quot;:{  &quot;@negative&quot;:&quot;1&quot;,  &quot;group&quot;:{   &quot;@kind&quot;:&quot;root&quot;,   &quot;node&quot;:{    &quot;name&quot;:{     &quot;@qname&quot;:&quot;5418e9ab-5299-4e62-b570-9a3530a378de&quot;    },    &quot;group&quot;:{     &quot;@kind&quot;:&quot;database&quot;,     &quot;node&quot;:{      &quot;name&quot;:{       &quot;@qname&quot;:&quot;WxIF&quot;      },      &quot;group&quot;:{       &quot;@kind&quot;:&quot;schema&quot;,       &quot;node&quot;:{        &quot;name&quot;:{         &quot;@qname&quot;:&quot;dbo&quot;        }       }      }     }    }   }  } }}" />
+  </component>
+</project>

+ 8 - 0
dtok-api/.idea/sshConfigs.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="SshConfigs">
+    <configs>
+      <sshConfig authType="PASSWORD" host="s3.z100.vip" id="6034675c-22b2-4382-9691-1d73ca0a9f8f" port="32005" nameFormat="DESCRIPTIVE" username="pi" useOpenSSHConfig="true" />
+    </configs>
+  </component>
+</project>

+ 124 - 0
dtok-api/.idea/uiDesigner.xml

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

+ 7 - 0
dtok-api/.idea/vcs.xml

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

+ 21 - 0
dtok-api/.idea/webServers.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="WebServers">
+    <option name="servers">
+      <webServer id="af19333f-5495-4597-a6c8-5877080e811b" name="checkup">
+        <fileTransfer accessType="SFTP" host="s3.z100.vip" port="32005" sshConfigId="6034675c-22b2-4382-9691-1d73ca0a9f8f" sshConfig="pi@s3.z100.vip:32005 password">
+          <advancedOptions>
+            <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" />
+          </advancedOptions>
+        </fileTransfer>
+      </webServer>
+      <webServer id="3e3f20b8-6711-401e-aa65-3e73dcd551ce" name="bi">
+        <fileTransfer accessType="SFTP" host="s3.z100.vip" port="32005" sshConfigId="6034675c-22b2-4382-9691-1d73ca0a9f8f" sshConfig="pi@s3.z100.vip:32005 password">
+          <advancedOptions>
+            <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" />
+          </advancedOptions>
+        </fileTransfer>
+      </webServer>
+    </option>
+  </component>
+</project>

+ 33 - 0
dtok-api/api/.gitignore

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

+ 118 - 0
dtok-api/api/.mvn/wrapper/MavenWrapperDownloader.java

@@ -0,0 +1,118 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+    private static final String WRAPPER_VERSION = "0.5.6";
+    /**
+     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+     */
+    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+            + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+    /**
+     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+     * use instead of the default one.
+     */
+    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+            ".mvn/wrapper/maven-wrapper.properties";
+
+    /**
+     * Path where the maven-wrapper.jar will be saved to.
+     */
+    private static final String MAVEN_WRAPPER_JAR_PATH =
+            ".mvn/wrapper/maven-wrapper.jar";
+
+    /**
+     * Name of the property which should be used to override the default download url for the wrapper.
+     */
+    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+    public static void main(String args[]) {
+        System.out.println("- Downloader started");
+        File baseDirectory = new File(args[0]);
+        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+        // If the maven-wrapper.properties exists, read it and check if it contains a custom
+        // wrapperUrl parameter.
+        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+        String url = DEFAULT_DOWNLOAD_URL;
+        if (mavenWrapperPropertyFile.exists()) {
+            FileInputStream mavenWrapperPropertyFileInputStream = null;
+            try {
+                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+                Properties mavenWrapperProperties = new Properties();
+                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+            } catch (IOException e) {
+                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+            } finally {
+                try {
+                    if (mavenWrapperPropertyFileInputStream != null) {
+                        mavenWrapperPropertyFileInputStream.close();
+                    }
+                } catch (IOException e) {
+                    // Ignore ...
+                }
+            }
+        }
+        System.out.println("- Downloading from: " + url);
+
+        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+        if (!outputFile.getParentFile().exists()) {
+            if (!outputFile.getParentFile().mkdirs()) {
+                System.out.println(
+                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+            }
+        }
+        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+        try {
+            downloadFileFromURL(url, outputFile);
+            System.out.println("Done");
+            System.exit(0);
+        } catch (Throwable e) {
+            System.out.println("- Error downloading");
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+            String username = System.getenv("MVNW_USERNAME");
+            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+            Authenticator.setDefault(new Authenticator() {
+                @Override
+                protected PasswordAuthentication getPasswordAuthentication() {
+                    return new PasswordAuthentication(username, password);
+                }
+            });
+        }
+        URL website = new URL(urlString);
+        ReadableByteChannel rbc;
+        rbc = Channels.newChannel(website.openStream());
+        FileOutputStream fos = new FileOutputStream(destination);
+        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+        fos.close();
+        rbc.close();
+    }
+
+}

binární
dtok-api/api/.mvn/wrapper/maven-wrapper.jar


+ 2 - 0
dtok-api/api/.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

+ 310 - 0
dtok-api/api/mvnw

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

+ 182 - 0
dtok-api/api/mvnw.cmd

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

+ 68 - 0
dtok-api/api/pom.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>dtok-api</artifactId>
+        <groupId>com.dtok</groupId>
+        <version>0.1</version>
+    </parent>
+
+    <artifactId>api</artifactId>
+    <name>DTok</name>
+    <description>Demo project for Spring Boot</description>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <build>
+        <finalName>DTok</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.4.2</version>
+                <configuration>
+                    <!-- 指定该Main Class为全局的唯一入口 -->
+                    <mainClass>com.dtok.api.ApiApplication</mainClass>
+                    <layout>ZIP</layout>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dtok</groupId>
+            <artifactId>service</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.dtok</groupId>
+            <artifactId>framework</artifactId>
+        </dependency>
+
+
+    </dependencies>
+
+
+</project>

+ 25 - 0
dtok-api/api/src/main/java/com/dtok/api/ApiApplication.java

@@ -0,0 +1,25 @@
+package com.dtok.api;
+
+
+import cn.dev33.satoken.SaManager;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@ComponentScan(basePackages = {"com.dtok.framework", "com.dtok.api.controller", "com.dtok.framework.configure",
+        "com.dtok.framework.listener",  "com.dtok.framework.authenticate","com.dtok.service"})
+@EnableJpaRepositories(basePackages = {"com.dtok.repository"})
+@EntityScan(basePackages = {"com.dtok.entity"})
+@SpringBootApplication
+public class ApiApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(ApiApplication.class, args);
+        System.out.println("启动成功:Sa-Token配置如下:" + SaManager.getConfig());
+
+
+    }
+
+}

+ 64 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/AppInfoController.java

@@ -0,0 +1,64 @@
+package com.dtok.api.controller;
+
+import com.dtok.entity.AppInfo;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.repository.AppInfoRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.xml.ws.Action;
+import java.util.Objects;
+
+@RestController
+@RequestMapping("/appInfo")
+public class AppInfoController {
+
+    @Autowired
+    AppInfoRepository appInfoRepository;
+
+    @GetMapping("/search")
+    public ResponseData search(@RequestParam("name") String name) {
+        if (StringUtils.hasLength(name)) {
+            return ResponseData.success(appInfoRepository.findAllByNameLike(name));
+        } else {
+            return ResponseData.success(appInfoRepository.findAll());
+        }
+    }
+
+    @PostMapping("/add")
+    public ResponseData add(AppInfo appInfo) {
+        if (Objects.isNull(appInfo)) {
+            throw new NullPointerException(BizExceptionEnum.SERVER_ERROR.getMessage());
+        }
+        if (!StringUtils.hasLength(appInfo.getPackageName())) {
+            throw new NullPointerException(BizExceptionEnum.SERVER_ERROR.getMessage());
+        }
+
+        appInfoRepository.save(appInfo);
+        return ResponseData.success("添加成功");
+    }
+
+    @PostMapping("/update")
+    public ResponseData update(AppInfo appInfo) {
+        if (Objects.isNull(appInfo)) {
+            throw new NullPointerException(BizExceptionEnum.SERVER_ERROR.getMessage());
+        }
+        if (!StringUtils.hasLength(appInfo.getPackageName())) {
+            throw new NullPointerException(BizExceptionEnum.SERVER_ERROR.getMessage());
+        }
+        appInfoRepository.save(appInfo);
+        return ResponseData.success("修改成功");
+    }
+
+    @PostMapping("/delete/{id}")
+    public ResponseData delete(@PathVariable String id) {
+        if (Objects.isNull(id)) {
+            throw new NullPointerException(BizExceptionEnum.SERVER_ERROR.getMessage());
+        }
+        appInfoRepository.deleteById(id);
+        return ResponseData.success("修改成功");
+    }
+
+}

+ 118 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/CommonItemController.java

@@ -0,0 +1,118 @@
+package com.dtok.api.controller;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.dtok.entity.Account;
+import com.dtok.entity.CommonItem;
+import com.dtok.entity.LoginHistory;
+import com.dtok.framework.exception.AuthenticateException;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.ToolUtil;
+import com.dtok.repository.CommonItemRepository;
+import io.swagger.models.auth.In;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.persistence.criteria.Predicate;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+@RestController
+@RequestMapping("/commonItem")
+public class CommonItemController {
+
+    @Autowired
+    CommonItemRepository commonItemRepository;
+
+    @GetMapping("/search")
+    public ResponseData search(@RequestParam("app") String app, @RequestParam("content") String content, @RequestParam("type") String type) {
+        Specification<CommonItem> query = (root, query1, criteriaBuilder) -> {
+            Predicate predicate = criteriaBuilder.conjunction();
+            if (ToolUtil.isNotEmpty(app)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("app"), app)));
+            }
+            if (ToolUtil.isNotEmpty(content)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("content"), "%" + content + "%")));
+            }
+            if (ToolUtil.isNotEmpty(type)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("type"), "%" + type + "%")));
+            }
+            predicate.getExpressions().add(criteriaBuilder.and(criteriaBuilder.equal(root.get("isDefault"), true)));
+
+            predicate.getExpressions().add(criteriaBuilder.and(criteriaBuilder.equal(root.get("createdAt"), ((Account) StpUtil.getLoginId()).getId())));
+
+            return predicate;
+        };
+        List<CommonItem> result = commonItemRepository.findAll(query);
+        return ResponseData.success(result);
+    }
+
+
+    @PostMapping("/add")
+    public ResponseData search(CommonItem commonItem) {
+        if (Objects.isNull(commonItem)) {
+            throw new NullPointerException("对象不存在");
+        }
+        if (!StringUtils.hasLength(commonItem.getContent()) || !StringUtils.hasLength(commonItem.getApp()) || !StringUtils.hasLength(commonItem.getType())) {
+            throw new NullPointerException("属性缺省");
+        }
+        if (!((Account) StpUtil.getLoginId()).getIsSuper() && commonItem.getIsDefault()) {
+            throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
+        }
+
+        commonItem.setCreatedAt(((Account) StpUtil.getLoginId()).getId());
+        commonItem.setCreatedTime(new Date());
+        commonItemRepository.save(commonItem);
+        return ResponseData.success("添加成功");
+    }
+
+    @PostMapping("/update/{id}")
+    public ResponseData update(CommonItem commonItem, @PathVariable Integer id) {
+        if (Objects.isNull(id)) {
+            throw new NullPointerException("对象不存在");
+        }
+
+        if (Objects.isNull(commonItem)) {
+            throw new NullPointerException("对象不存在");
+        }
+        if (!StringUtils.hasLength(commonItem.getContent()) || !StringUtils.hasLength(commonItem.getApp()) || !StringUtils.hasLength(commonItem.getType())) {
+            throw new NullPointerException("属性缺省");
+        }
+        if (!((Account) StpUtil.getLoginId()).getIsSuper() && commonItem.getIsDefault()) {
+            throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
+        }
+
+        commonItem.setId(Long.valueOf(id));
+        commonItem.setCreatedAt(((Account) StpUtil.getLoginId()).getId());
+        commonItem.setCreatedTime(new Date());
+        commonItemRepository.save(commonItem);
+        return ResponseData.success("添加成功");
+    }
+
+    @PostMapping("/delete/{id}")
+    public ResponseData delete(CommonItem commonItem, @PathVariable Integer id) {
+        if (Objects.isNull(commonItem)) {
+            throw new NullPointerException("对象不存在");
+        }
+        if (!StringUtils.hasLength(commonItem.getContent()) || !StringUtils.hasLength(commonItem.getApp()) || !StringUtils.hasLength(commonItem.getType())) {
+            throw new NullPointerException("属性缺省");
+        }
+
+        if (Objects.isNull(id)) {
+            throw new NullPointerException("对象不存在");
+        }
+
+        CommonItem commonItemAlready = commonItemRepository.getOne(String.valueOf(id));
+
+        if (!((Account) StpUtil.getLoginId()).getIsSuper() && commonItemAlready.getIsDefault()) {
+            throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
+        }
+
+        commonItemRepository.delete(commonItemAlready);
+        return ResponseData.success("添加成功");
+    }
+
+}

+ 144 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/LoginController.java

@@ -0,0 +1,144 @@
+package com.dtok.api.controller;
+
+import cn.dev33.satoken.secure.SaSecureUtil;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.crypto.SecureUtil;
+
+import com.dtok.entity.Account;
+import com.dtok.entity.AccountRole;
+import com.dtok.entity.LoginHistory;
+import com.dtok.entity.emum.LOGIN_DEVICE;
+import com.dtok.entity.params.UserResponse;
+import com.dtok.framework.exception.AuthenticateException;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.exception.ServiceException;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.IpUtil;
+import com.dtok.repository.AccountRepository;
+import com.dtok.repository.AccountRoleRepository;
+import com.dtok.repository.LoginHistoryRepository;
+import com.dtok.service.PermissionService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@RestController
+@Api(value = "登录", tags = {"登录"})
+@Slf4j
+public class LoginController {
+
+
+    final
+    AccountRepository userRepository;
+
+    final
+    LoginHistoryRepository loginHistoryRepository;
+
+    final
+    PermissionService permissionService;
+
+    final
+    AccountRoleRepository roleRepository;
+
+    private static final Logger LOGIN_LOG = LoggerFactory.getLogger("LoginLog");
+
+
+    public LoginController(AccountRepository userRepository, LoginHistoryRepository loginHistoryRepository, PermissionService permissionService, AccountRoleRepository roleRepository) {
+        this.userRepository = userRepository;
+        this.loginHistoryRepository = loginHistoryRepository;
+        this.permissionService = permissionService;
+        this.roleRepository = roleRepository;
+    }
+
+
+    @GetMapping("/login")
+    @ResponseBody
+    @ApiOperation("登录")
+    public ResponseData login(String username, String password, String loginDevice) {
+        // get user
+        Account user = userRepository.getFirstByUsername(username);
+        if (Objects.isNull(user)) {
+            throw new AuthenticateException(BizExceptionEnum.NO_THIS_USER);
+        }
+
+        if (!SaSecureUtil.aesEncrypt(user.getSalt(), password).equals(user.getPassword())) {
+            throw new AuthenticateException(BizExceptionEnum.AUTH_REQUEST_ERROR);
+        }
+
+        if (!user.getStatus()) {
+            throw new AuthenticateException(BizExceptionEnum.ACCOUNT_FREEZED);
+        }
+
+        if (user.getRoleCode().isEmpty()) {
+            throw new AuthenticateException(BizExceptionEnum.NOT_ROLE_EXCEPTION);
+        }
+
+        if (!loginDevice.equals(LOGIN_DEVICE.DEVICE.getType()) && !loginDevice.equals(LOGIN_DEVICE.PC.getType())) {
+            throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
+        }
+
+        Optional<AccountRole> role = roleRepository.findById(user.getRoleCode());
+        if (!role.isPresent()) {
+            throw new AuthenticateException(BizExceptionEnum.ROLE_ERROR);
+        }
+
+
+        // set login info
+        StpUtil.login(user, loginDevice);
+
+        StpUtil.getSession().set("loginUser", user);
+
+        String token = StpUtil.getTokenValue();
+
+        LOGIN_LOG.info(String.format("用户 %s 登录 ... token: %s", user.getName(), token));
+        UserResponse userResponse = new UserResponse();
+        userResponse.setUser(user);
+        userResponse.setToken(token);
+        userResponse.setRole(role.get());
+        userResponse.setPermissions(permissionService.getTree(user.getUsername()));
+
+        //记录登录日志
+        LoginHistory loginHistory = new LoginHistory();
+        loginHistory.setIp(IpUtil.getLocalhostIp());
+        loginHistory.setUser(user.getId());
+        loginHistory.setHappenTime(new DateTime());
+        loginHistory.setActionType(1);
+        loginHistory.setUsername(username);
+        loginHistory.setLoginSys(loginDevice);
+        loginHistoryRepository.save(loginHistory);
+        return ResponseData.success(userResponse);
+    }
+
+    @GetMapping("/logout")
+    public ResponseData logout(@RequestParam("loginDevice") String loginDevice) {
+        if (!StringUtils.hasLength(loginDevice)){
+            throw new ServiceException(BizExceptionEnum.SERVER_ERROR);
+        }
+
+        if (!loginDevice.equals(LOGIN_DEVICE.DEVICE.getType()) && !loginDevice.equals(LOGIN_DEVICE.PC.getType())) {
+            throw new AuthenticateException(BizExceptionEnum.NO_PERMISSION);
+        }
+        LoginHistory loginHistory = new LoginHistory();
+        loginHistory.setIp(IpUtil.getLocalhostIp());
+        loginHistory.setUser(((Account)StpUtil.getSession().get("loginUser")).getId());
+        loginHistory.setHappenTime(new DateTime());
+        loginHistory.setActionType(0);
+        loginHistory.setUsername(((Account)StpUtil.getSession().get("loginUser")).getUsername());
+        loginHistory.setLoginSys(loginDevice);
+        loginHistoryRepository.save(loginHistory);
+        StpUtil.logout();
+        return ResponseData.success("注销成功");
+    }
+
+
+}

+ 63 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/LoginHistoryController.java

@@ -0,0 +1,63 @@
+package com.dtok.api.controller;
+
+import com.dtok.entity.Account;
+import com.dtok.entity.AccountRole;
+import com.dtok.entity.LoginHistory;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.ToolUtil;
+import com.dtok.repository.LoginHistoryRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.hibernate.query.internal.NativeQueryImpl;
+import org.hibernate.transform.Transformers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.persistence.criteria.Predicate;
+import java.util.List;
+
+@RestController
+@RequestMapping("/loginHistory")
+@Slf4j
+public class LoginHistoryController {
+
+    @Autowired
+    EntityManager entityManager;
+
+    @Autowired
+    LoginHistoryRepository loginHistoryRepository;
+    @GetMapping("/search")
+    public ResponseData search(@RequestParam("loginSys")String loginSys,@RequestParam("ip") String ip, @RequestParam("username") String username,
+                               @RequestParam("actionType") String actionType,@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) {
+        Specification<LoginHistory> query = (root, query1, criteriaBuilder) -> {
+            Predicate predicate = criteriaBuilder.conjunction();
+            if (ToolUtil.isNotEmpty(ip)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("code"), "%" + ip + "%")));
+            }
+            if (ToolUtil.isNotEmpty(username)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("name"), "%" + username + "%")));
+            }
+            if (ToolUtil.isNotEmpty(actionType)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("actionType"), actionType)));
+            }
+            if (ToolUtil.isNotEmpty(loginSys)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("loginSys"), loginSys)));
+            }
+            if (ToolUtil.isNotEmpty(startTime)) {
+                predicate.getExpressions().add(criteriaBuilder.greaterThanOrEqualTo(root.get("happenTime").as(String.class), startTime));
+            }
+            if (ToolUtil.isNotEmpty(endTime)) {
+                predicate.getExpressions().add(criteriaBuilder.lessThanOrEqualTo(root.get("happenTime").as(String.class), endTime));
+            }
+            return predicate;
+        };
+        List<LoginHistory> result = loginHistoryRepository.findAll(query);
+        return ResponseData.success(result);
+    }
+}

+ 102 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/PermissionController.java

@@ -0,0 +1,102 @@
+package com.dtok.api.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaCheckRole;
+import com.dtok.entity.Account;
+import com.dtok.entity.Permission;
+import com.dtok.entity.params.PermissionNode;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.ToolUtil;
+import com.dtok.repository.PermissionRepository;
+import com.dtok.repository.RolePermissionRepository;
+import com.dtok.service.PermissionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.web.bind.annotation.*;
+
+import javax.persistence.criteria.Predicate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/permission")
+public class PermissionController {
+
+    @Autowired
+    PermissionRepository permissionRepository;
+
+    @Autowired
+    RolePermissionRepository rolePermissionRepository;
+
+    @Autowired
+    PermissionService permissionService;
+
+
+    @GetMapping("/search")
+    @SaCheckPermission("permission")
+    public ResponseData search(@RequestParam(value = "code", required = false) String code, @RequestParam(value = "name", required = false) String name) {
+        Specification<Permission> query = (root, query1, criteriaBuilder) -> {
+            Predicate predicate = criteriaBuilder.conjunction();
+            if (ToolUtil.isNotEmpty(code)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("code"), code)));
+            }
+            if (ToolUtil.isNotEmpty(name)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("name"), "%" + name + "%")));
+            }
+            return predicate;
+        };
+        List<Permission> roleList = permissionRepository.findAll(query);
+        return ResponseData.success(roleList);
+    }
+
+    @PostMapping("/add")
+    @SaCheckPermission("permission")
+    public ResponseData add(Permission permission) {
+        permissionRepository.save(permission);
+        return ResponseData.success("添加成功");
+    }
+
+    @PostMapping("/update")
+    @SaCheckPermission("permission")
+    public ResponseData update(Permission permission) {
+        permissionRepository.save(permission);
+        return ResponseData.success("修改成功");
+    }
+
+    @GetMapping("/delete/{code}")
+    @SaCheckPermission("permission")
+    public ResponseData delete(@PathVariable String code) {
+        Optional<Permission> permissionOptional = permissionRepository.findById(code);
+        if (!permissionOptional.isPresent()) {
+            throw new NullPointerException("没有找到该权限");
+        }
+        permissionRepository.deleteById(code);
+        return ResponseData.success("删除成功");
+    }
+
+    @GetMapping("/getTree/{roleCode}")
+    public ResponseData getTree(@PathVariable String roleCode) {
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("tree", permissionService.getTree());
+        result.put("userPermission", rolePermissionRepository.findRolePermissionsByRoleCode(roleCode));
+        return ResponseData.success(result);
+    }
+
+
+    @GetMapping("/getPermission/{username}")
+    public ResponseData getPermission(@PathVariable String username) {
+        return ResponseData.success(permissionService.getTree(username));
+    }
+
+    @SaCheckRole(Account.FINAL_ROLE)
+    @PostMapping("/authPermission/{roleCode}")
+    public ResponseData authPermission(@RequestBody List<PermissionNode> permissions, @PathVariable String roleCode) {
+        permissionService.authPermission(permissions, roleCode);
+        return ResponseData.success("更新成功");
+    }
+
+
+}

+ 113 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/RoleController.java

@@ -0,0 +1,113 @@
+package com.dtok.api.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+import com.dtok.entity.Account;
+import com.dtok.entity.AccountRole;
+import com.dtok.entity.RolePermission;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.exception.ServiceException;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.ToolUtil;
+import com.dtok.repository.AccountRepository;
+import com.dtok.repository.AccountRoleRepository;
+import com.dtok.repository.RolePermissionRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.persistence.criteria.Predicate;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("role")
+public class RoleController {
+
+    @Autowired
+    AccountRoleRepository roleRepository;
+
+    @Autowired
+    AccountRepository userRepository;
+
+    @Autowired
+    RolePermissionRepository rolePermissionRepository;
+
+    @GetMapping("/search")
+    @ResponseBody
+    public ResponseData search(@RequestParam(value = "code", required = false) String code, @RequestParam(value = "name", required = false) String name) {
+        Specification<AccountRole> query = (root, query1, criteriaBuilder) -> {
+            Predicate predicate = criteriaBuilder.conjunction();
+            if (ToolUtil.isNotEmpty(code)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("code"), code)));
+            }
+            if (ToolUtil.isNotEmpty(name)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("name"), "%" + name + "%")));
+            }
+            return predicate;
+        };
+        List<AccountRole> roleList = roleRepository.findAll(query);
+        return ResponseData.success(roleList);
+    }
+
+    @GetMapping("/authRole/{userCode}/{roleCode}")
+    @SaCheckPermission("role")
+    public ResponseData roleAuthorization(@PathVariable String roleCode, @PathVariable String userCode) {
+        Optional<AccountRole> roleOptional = roleRepository.findById(roleCode);
+        Account account = userRepository.findUserByUsername(userCode);
+        if (!roleOptional.isPresent()) {
+            throw new NullPointerException(BizExceptionEnum.ROLE_ERROR.getMessage());
+        }
+        if (Objects.isNull(account)) {
+            throw new NullPointerException(BizExceptionEnum.USER_NOT_EXISTED.getMessage());
+        }
+
+        if (account.getRoleCode().equals(Account.FINAL_ROLE)) {
+            throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN);
+        }
+
+        account.setRoleCode(roleOptional.get().getCode());
+        userRepository.save(account);
+        return ResponseData.success("授权成功!");
+    }
+
+    @PostMapping("/update/{oldCode}")
+    @SaCheckPermission("role")
+    @Transactional(rollbackFor = Exception.class)
+    public ResponseData update( AccountRole role, @PathVariable String oldCode) {
+        if (Objects.isNull(role)) {
+            throw new NullPointerException("角色不能为空");
+        }
+        role.setCode(oldCode);
+        roleRepository.save(role);
+        return ResponseData.success("修改成功");
+    }
+
+    @GetMapping("/delete/{code}")
+    @SaCheckPermission("role")
+    @Transactional(rollbackFor = Exception.class)
+    public ResponseData delete(@PathVariable String code) {
+        List<Account> users = userRepository.findUsersByRoleCode(code);
+        if (users.isEmpty()) {
+            Optional<AccountRole> roleOptional = roleRepository.findById(code);
+            if (!roleOptional.isPresent()) {
+                throw new NullPointerException("角色不存在");
+            }
+            List<RolePermission> rolePermissions = rolePermissionRepository.findRolePermissionsByRoleCode(code);
+            rolePermissionRepository.deleteAll(rolePermissions);
+            roleRepository.delete(roleOptional.get());
+            return ResponseData.success("删除成功");
+        } else {
+            throw new ServiceException(400, "该角色正在被使用,无法删除");
+        }
+    }
+
+    @PostMapping("/add")
+    @SaCheckPermission("role")
+    public ResponseData add(AccountRole role) {
+        roleRepository.save(role);
+        return ResponseData.success("添加完成");
+    }
+}

+ 13 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/ScriptController.java

@@ -0,0 +1,13 @@
+package com.dtok.api.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/script")
+public class ScriptController {
+
+
+    @RequestParam("/")
+}

+ 145 - 0
dtok-api/api/src/main/java/com/dtok/api/controller/UserController.java

@@ -0,0 +1,145 @@
+package com.dtok.api.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.secure.SaSecureUtil;
+import cn.hutool.crypto.SecureUtil;
+
+import com.dtok.entity.Account;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.exception.ServiceException;
+import com.dtok.framework.response.ResponseData;
+import com.dtok.framework.util.PasswordUtil;
+import com.dtok.framework.util.ToolUtil;
+import com.dtok.repository.AccountRepository;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.persistence.criteria.JoinType;
+import javax.persistence.criteria.Predicate;
+import java.util.*;
+
+@RequestMapping("/user")
+@RestController
+@ApiOperation(value = "用户")
+public class UserController {
+
+    @Autowired
+    AccountRepository userRepository;
+
+
+    @GetMapping("/search")
+    public ResponseData search(@RequestParam(value = "username", required = false) String username,
+                               @RequestParam(value = "name", required = false) String name) {
+        Specification<Account> query = (root, query1, criteriaBuilder) -> {
+            Predicate predicate = criteriaBuilder.conjunction();
+            root.join("role", JoinType.LEFT);
+            if (ToolUtil.isNotEmpty(username)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.equal(root.get("username"), username)));
+            }
+            if (ToolUtil.isNotEmpty(name)) {
+                predicate.getExpressions().add(criteriaBuilder.or(criteriaBuilder.like(root.get("name"), "%" + name + "%")));
+            }
+            return predicate;
+        };
+
+        List<Account> users = userRepository.findAll(query);
+        return ResponseData.success(users);
+    }
+
+
+    @GetMapping("/delete/{id}")
+
+    @Transactional(rollbackFor = Exception.class)
+    public ResponseData delete(@PathVariable("id") Integer id) {
+        Optional<Account> userOptional = userRepository.findById(id);
+        if (!userOptional.isPresent()) {
+            throw new ServiceException(BizExceptionEnum.NO_THIS_USER);
+        }
+        Account user = userOptional.get();
+
+        if (user.getRoleCode().equals(Account.FINAL_ROLE)) {
+            throw new ServiceException(BizExceptionEnum.CANT_DELETE_ADMIN);
+        }
+        userRepository.delete(user);
+        return ResponseData.success("删除成功");
+    }
+
+    @PostMapping("/update")
+    public ResponseData update(Account user) {
+        Account account = userRepository.getFirstByUsername(user.getUsername());
+        if (Objects.isNull(account)) {
+            throw new ServiceException(BizExceptionEnum.NO_THIS_USER);
+        }
+
+        if (account.getIsSuper() && !user.getStatus()) {
+            throw new ServiceException(BizExceptionEnum.CANT_FREEZE_ADMIN);
+        }
+
+        if (account.getIsSuper() && !user.getIsSuper()) {
+            throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN);
+        }
+
+        if (account.getIsSuper() && !user.getRoleCode().equals(Account.FINAL_ROLE)) {
+            throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN);
+        }
+
+        account.setName(user.getName());
+        account.setRoleCode(user.getRoleCode());
+        account.setExpireAt(user.getExpireAt());
+        account.setMaxDevices(user.getMaxDevices());
+        account.setPhoneNumber(user.getPhoneNumber());
+        userRepository.save(account);
+        return ResponseData.success("修改成功");
+    }
+
+    @PostMapping("/add")
+    public ResponseData add(Account user) {
+        if (!ToolUtil.isNotEmpty(user.getUsername())) {
+            throw new NullPointerException("用户名不能为空");
+        }
+        if (!ToolUtil.isNotEmpty(user.getPassword())) {
+            throw new NullPointerException("密码不能为空");
+        }
+        if (!ToolUtil.isNotEmpty(user.getRoleCode())) {
+            throw new NullPointerException("角色不能为空");
+        }
+        if (!ToolUtil.isNotEmpty(user.getName())) {
+            throw new NullPointerException("姓名不能为空");
+        }
+        if (user.getIsSuper()) {
+            user.setRoleCode(Account.FINAL_ROLE);
+        }
+
+        String salt = PasswordUtil.getSalt();
+        user.setPassword(SaSecureUtil.aesEncrypt(salt, user.getPassword()));
+        user.setSalt(salt);
+        user.setCreatedAt(new Date());
+        user.setStatus(true);
+        userRepository.save(user);
+        return ResponseData.success(user);
+    }
+
+    @PostMapping("/disable/{code}")
+    public ResponseData disable(@PathVariable("code") String code) {
+        Account account = userRepository.getFirstByUsername(code);
+        if (Objects.isNull(account)) {
+            throw new NullPointerException(BizExceptionEnum.NO_THIS_USER.getMessage());
+        }
+        if (Account.FINAL_ROLE.equals(account.getRoleCode())) {
+            throw new ServiceException(BizExceptionEnum.CANT_FREEZE_ADMIN);
+        }
+        account.setStatus(!account.getStatus());
+        userRepository.save(account);
+        if (account.getStatus()) {
+            return ResponseData.success("启用成功");
+        } else {
+            return ResponseData.success("禁用成功");
+        }
+    }
+
+
+}

+ 11 - 0
dtok-api/api/src/test/java/com/dtok/api/test.java

@@ -0,0 +1,11 @@
+package com.dtok.api;
+
+//import cn.dev33.satoken.secure.SaSecureUtil;
+//
+//public class test {
+//    public static void main(String[] args) {
+//        String salt = "Oj3Cu4";
+//        String password = "P@ssw0rd";
+//        System.out.println(SaSecureUtil.aesEncrypt(salt,password));;
+//    }
+//}

+ 15 - 0
dtok-api/entity/entity.iml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4">
+  <component name="FacetManager">
+    <facet type="jpa" name="JPA">
+      <configuration>
+        <setting name="validation-enabled" value="true" />
+        <setting name="provider-name" value="Hibernate" />
+        <datasource-mapping>
+          <factory-entry name="entityManagerFactory" value="150fb651-f83e-421f-94c7-7a290165da30" />
+        </datasource-mapping>
+        <naming-strategy-map />
+      </configuration>
+    </facet>
+  </component>
+</module>

+ 27 - 0
dtok-api/entity/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dtok-api</artifactId>
+        <groupId>com.dtok</groupId>
+        <version>0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>entity</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel-core</artifactId>
+            <version>3.1.1</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+</project>

+ 115 - 0
dtok-api/entity/src/main/java/com/dtok/entity/Account.java

@@ -0,0 +1,115 @@
+package com.dtok.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-08 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="acc_account" )
+public class Account implements Serializable {
+
+	private static final long serialVersionUID =  8809453470721335304L;
+
+	public static final String FINAL_ROLE = "SuperAdmin";
+
+	/**
+	 * 用户ID自增
+	 */
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	@Column(name = "id" )
+	private Long id;
+
+	/**
+	 * 用户名
+	 */
+   	@Column(name = "username" )
+	private String username;
+
+	/**
+	 * 密码
+	 */
+   	@Column(name = "password" )
+	private String password;
+
+	/**
+	 * 加密盐
+	 */
+   	@Column(name = "salt" )
+	private String salt;
+
+	/**
+	 * 最大设备数量
+	 */
+	@Column(name = "max_devices" )
+	private String maxDevices;
+	/**
+	 * 手机号
+	 */
+   	@Column(name = "phone_number" )
+	private Long phoneNumber;
+
+	/**
+	 * 名称
+	 */
+   	@Column(name = "name" )
+	private String name;
+
+	/**
+	 * 1 正常 0 冻结
+
+	 */
+   	@Column(name = "status" )
+	private Boolean status;
+
+   	@Column(name = "is_super" )
+	private Boolean isSuper;
+
+   	@Column(name = "role_code" )
+	private String roleCode;
+
+
+	@OneToOne
+	@JoinColumn(name = "role_code", referencedColumnName = "code", insertable = false, updatable = false)
+	private AccountRole role;
+
+	/**
+	 * 最新更新时间
+	 */
+   	@Column(name = "last_modify_at" )
+	private Date lastModifyAt;
+
+	/**
+	 * 过期时间
+	 */
+	@DateTimeFormat(pattern = "yyyy-MM-dd")
+	@Column(name = "expire_at" )
+	private Date expireAt;
+
+	/**
+	 * 创建时间
+	 */
+   	@Column(name = "created_at" )
+	private Date createdAt;
+
+}

+ 34 - 0
dtok-api/entity/src/main/java/com/dtok/entity/AccountRole.java

@@ -0,0 +1,34 @@
+package com.dtok.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-08 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="acc_account_role" )
+public class AccountRole implements Serializable {
+
+	private static final long serialVersionUID =  8827139383389127607L;
+
+	@Id
+   	@Column(name = "code" )
+	private String code;
+
+   	@Column(name = "role_name" )
+	private String roleName;
+
+}

+ 40 - 0
dtok-api/entity/src/main/java/com/dtok/entity/AppInfo.java

@@ -0,0 +1,40 @@
+package com.dtok.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-09 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="app_info" )
+public class AppInfo  implements Serializable {
+
+	private static final long serialVersionUID =  3964102537237037449L;
+
+	/**
+	 * 包名
+	 */
+	@Id
+   	@Column(name = "package_name" )
+	private String packageName;
+
+   	@Column(name = "name" )
+	private String name;
+
+   	@Column(name = "support_version" )
+	private String supportVersion;
+
+}

+ 59 - 0
dtok-api/entity/src/main/java/com/dtok/entity/CommonItem.java

@@ -0,0 +1,59 @@
+package com.dtok.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @Description
+ * @Author C.J
+ * @Date 2024-03-09
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "common_item")
+public class CommonItem implements Serializable {
+
+    private static final long serialVersionUID = 7644588109681057010L;
+
+    @Id
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "app")
+    private String app;
+
+    @Column(name = "type")
+    private String type;
+
+    @Column(name = "content")
+    private String content;
+
+    /**
+     * 0,1
+     */
+    @Column(name = "is_default")
+    private Boolean isDefault;
+
+    @Column(name = "created_time")
+    private Date createdTime;
+
+
+    /**
+     * 创建
+     */
+    @Column(name = "created_at")
+    private Long createdAt;
+
+}

+ 92 - 0
dtok-api/entity/src/main/java/com/dtok/entity/Devices.java

@@ -0,0 +1,92 @@
+package com.dtok.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import java.util.Date;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-09 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="devices" )
+public class Devices  implements Serializable {
+
+	private static final long serialVersionUID =  7336812044556799572L;
+
+	/**
+	 * 自增ID
+
+	 */
+	@Id
+   	@Column(name = "uuid" )
+	private String uuid;
+
+	/**
+	 * 关联用户
+	 */
+   	@Column(name = "account" )
+	private Long account;
+
+	/**
+	 * 手机型号
+	 */
+   	@Column(name = "device_name" )
+	private String deviceName;
+
+	/**
+	 * 手机的系统版本
+	 */
+   	@Column(name = "device_version" )
+	private String deviceVersion;
+
+	/**
+	 * 手机品牌
+	 */
+   	@Column(name = "device_brand" )
+	private String deviceBrand;
+
+	/**
+	 * 最后连接时间
+	 */
+   	@Column(name = "last_connection_time" )
+	private Date lastConnectionTime;
+
+	/**
+	 * 抖音版本
+	 */
+   	@Column(name = "tiktok_version" )
+	private String tiktokVersion;
+
+	/**
+	 * ONLINE 在线
+OFFLINE 离线
+	 */
+   	@Column(name = "status" )
+	private String status;
+
+	/**
+	 * Android ID
+	 */
+   	@Column(name = "android_id" )
+	private String androidId;
+
+	/**
+	 * 最后登录IP
+
+	 */
+   	@Column(name = "last_connection_ip" )
+	private String lastConnectionIp;
+
+}

+ 56 - 0
dtok-api/entity/src/main/java/com/dtok/entity/LoginHistory.java

@@ -0,0 +1,56 @@
+package com.dtok.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @Description
+ * @Author C.J
+ * @Date 2024-03-09
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "login_history")
+public class LoginHistory implements Serializable {
+
+    private static final long serialVersionUID = 7745461238091119313L;
+
+    public static final String PC = "PC";
+    public static final String DEVICE = "DEVICE";
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @Column(name = "user")
+    private Long user;
+
+    @Column(name = "ip")
+    private String ip;
+
+    @Column(name = "happen_time")
+    private Date happenTime;
+
+    /**
+     * 发生动作1. 登录 0. 退出
+     */
+    @Column(name = "action_type")
+    private Integer actionType;
+
+    @Column(name = "username")
+    private String username;
+
+    @Column(name = "login_sys")
+    private String loginSys;
+
+}

+ 56 - 0
dtok-api/entity/src/main/java/com/dtok/entity/Permission.java

@@ -0,0 +1,56 @@
+package com.dtok.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.List;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-08 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="acc_permission" )
+public class Permission implements Serializable {
+
+	private static final long serialVersionUID =  8390331033213864704L;
+
+	@Id
+   	@Column(name = "code" )
+	private String code;
+
+   	@Column(name = "name" )
+	private String name;
+
+   	@Column(name = "is_active" )
+	private Integer isActive;
+
+   	@Column(name = "url" )
+	private String url;
+
+   	@Column(name = "icon" )
+	private String icon;
+
+   	@Column(name = "seq" )
+	private Long seq;
+
+   	@Column(name = "parent" )
+	private String parent;
+
+   	@Column(name = "level" )
+	private Long level;
+
+   	@Column(name = "is_menu" )
+	private Integer isMenu;
+
+	@Transient
+	private List<Permission> children;
+}

+ 35 - 0
dtok-api/entity/src/main/java/com/dtok/entity/RolePermission.java

@@ -0,0 +1,35 @@
+package com.dtok.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-08 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="acc_role_permission" )
+public class RolePermission implements Serializable {
+
+	private static final long serialVersionUID =  2764553074228468177L;
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+   	@Column(name = "id" )
+	private Long id;
+
+   	@Column(name = "role_code" )
+	private String roleCode;
+
+   	@Column(name = "pm_code" )
+	private String pmCode;
+
+}

+ 74 - 0
dtok-api/entity/src/main/java/com/dtok/entity/Script.java

@@ -0,0 +1,74 @@
+package com.dtok.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @Description
+ * @Author C.J
+ * @Date 2024-03-09
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table(name = "script")
+public class Script implements Serializable {
+
+    private static final long serialVersionUID = 7878805062919342891L;
+
+    @Id
+    @Column(name = "uuid")
+    private String uuid;
+
+    /**
+     * APP
+     */
+    @Column(name = "app")
+    private String app;
+
+    /**
+     * 模块
+     */
+    @Column(name = "module")
+    private String module;
+
+    @Column(name = "version")
+    private Long version;
+
+    /**
+     * 脚本内容
+     */
+    @Column(name = "script_content")
+    private String scriptContent;
+
+    /**
+     * 1 生效
+     * 0 失效
+     */
+    @Column(name = "status")
+    private Integer status;
+
+    /**
+     * 调用次数
+     */
+    @Column(name = "call_count")
+    private Long callCount;
+
+    @Column(name = "encrypt")
+    private Boolean encrypt;
+
+    @Column(name = "created_at")
+    private Date createdAt;
+
+}

+ 53 - 0
dtok-api/entity/src/main/java/com/dtok/entity/ScriptHistory.java

@@ -0,0 +1,53 @@
+package com.dtok.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import java.util.Date;
+
+/**
+ * @Description  
+ * @Author  C.J
+ * @Date 2024-03-09 
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Table ( name ="script_history" )
+public class ScriptHistory  implements Serializable {
+
+	private static final long serialVersionUID =  6852446363573994158L;
+
+	@Id
+   	@Column(name = "id" )
+	private Long id;
+
+   	@Column(name = "script_id" )
+	private String scriptId;
+
+   	@Column(name = "version" )
+	private Long version;
+
+	/**
+	 * 脚本内容
+	 */
+   	@Column(name = "script_content" )
+	private String scriptContent;
+
+   	@Column(name = "app" )
+	private String app;
+
+	/**
+	 * 创建时间
+	 */
+   	@Column(name = "created_at" )
+	private Date createdAt;
+
+}

+ 24 - 0
dtok-api/entity/src/main/java/com/dtok/entity/emum/LOGIN_DEVICE.java

@@ -0,0 +1,24 @@
+package com.dtok.entity.emum;
+
+import lombok.Data;
+
+public enum LOGIN_DEVICE {
+    DEVICE("DEVICE"),
+    PC("PC");
+
+    LOGIN_DEVICE(String type) {
+        this.type = type;
+    }
+
+
+    private String type;
+
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+}

+ 26 - 0
dtok-api/entity/src/main/java/com/dtok/entity/params/PermissionNode.java

@@ -0,0 +1,26 @@
+package com.dtok.entity.params;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class PermissionNode {
+
+
+    private String code;
+
+    private String name;
+
+    private Boolean isActive;
+
+    private String url;
+
+    private Long level;
+
+    private String icon;
+
+    private String parent;
+
+    List<PermissionNode> children;
+}

+ 16 - 0
dtok-api/entity/src/main/java/com/dtok/entity/params/UserResponse.java

@@ -0,0 +1,16 @@
+package com.dtok.entity.params;
+
+import com.dtok.entity.Account;
+import com.dtok.entity.AccountRole;
+import com.dtok.entity.Permission;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class UserResponse {
+    Account user;
+    String token;
+    AccountRole role;
+    List<Permission> permissions;
+}

binární
dtok-api/entity/target/classes/com/dtok/entity/Account.class


binární
dtok-api/entity/target/classes/com/dtok/entity/AccountRole.class


binární
dtok-api/entity/target/classes/com/dtok/entity/AppInfo.class


binární
dtok-api/entity/target/classes/com/dtok/entity/CommonItem.class


binární
dtok-api/entity/target/classes/com/dtok/entity/Devices.class


binární
dtok-api/entity/target/classes/com/dtok/entity/LoginHistory.class


binární
dtok-api/entity/target/classes/com/dtok/entity/Permission.class


binární
dtok-api/entity/target/classes/com/dtok/entity/RolePermission.class


binární
dtok-api/entity/target/classes/com/dtok/entity/Script.class


binární
dtok-api/entity/target/classes/com/dtok/entity/ScriptHistory.class


binární
dtok-api/entity/target/classes/com/dtok/entity/emum/LOGIN_DEVICE.class


binární
dtok-api/entity/target/classes/com/dtok/entity/params/PermissionNode.class


binární
dtok-api/entity/target/classes/com/dtok/entity/params/UserResponse.class


binární
dtok-api/entity/target/entity-0.1.jar


+ 5 - 0
dtok-api/entity/target/maven-archiver/pom.properties

@@ -0,0 +1,5 @@
+#Generated by Maven
+#Sun Feb 12 10:26:00 CST 2023
+version=0.1
+groupId=com.ciemis
+artifactId=entity

+ 25 - 0
dtok-api/entity/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

@@ -0,0 +1,25 @@
+com\ciemis\entity\postgres\OpcImData.class
+com\ciemis\entity\Role.class
+com\ciemis\entity\BaseCraftProcess.class
+com\ciemis\entity\Permission.class
+com\ciemis\entity\param\BaseMachineForm.class
+com\ciemis\entity\UserCompany.class
+com\ciemis\entity\MqAccount.class
+com\ciemis\entity\ChartUser.class
+com\ciemis\entity\postgres\OpcImWarningRecord.class
+com\ciemis\entity\MqAccountUpdate.class
+com\ciemis\entity\RolePermission.class
+com\ciemis\entity\Company.class
+com\ciemis\entity\Dict.class
+com\ciemis\entity\param\PermissionNode.class
+com\ciemis\entity\param\CompanyUserBalance.class
+com\ciemis\entity\ChartCompany.class
+com\ciemis\entity\param\ChartParam.class
+com\ciemis\entity\MqPermission.class
+com\ciemis\entity\BaseMachine.class
+com\ciemis\entity\Gateway.class
+com\ciemis\entity\User.class
+com\ciemis\entity\BaseChartSocketMapping.class
+com\ciemis\entity\BaseCraft.class
+com\ciemis\entity\param\KanbanNodeParent.class
+com\ciemis\entity\Chart.class

+ 25 - 0
dtok-api/entity/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@@ -0,0 +1,25 @@
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\MqAccountUpdate.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\Dict.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\param\KanbanNodeParent.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\Role.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\User.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\Gateway.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\BaseChartSocketMapping.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\Permission.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\param\BaseMachineForm.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\postgres\OpcImData.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\MqPermission.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\MqAccount.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\RolePermission.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\Company.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\param\CompanyUserBalance.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\UserCompany.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\Chart.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\param\ChartParam.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\BaseCraft.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\postgres\OpcImWarningRecord.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\BaseCraftProcess.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\ChartCompany.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\param\PermissionNode.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\ChartUser.java
+E:\Project\He3\MI\MI\ciemis-mi-api\entity\src\main\java\com\ciemis\entity\BaseMachine.java

+ 95 - 0
dtok-api/framework/pom.xml

@@ -0,0 +1,95 @@
+<?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">
+    <parent>
+        <artifactId>dtok-api</artifactId>
+        <groupId>com.dtok</groupId>
+        <version>0.1</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>framework</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>42.5.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.10.2</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
+        <dependency>
+            <groupId>commons-dbutils</groupId>
+            <artifactId>commons-dbutils</artifactId>
+            <version>1.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-spring-boot-starter</artifactId>
+        </dependency>
+        <!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-dao-redis</artifactId>
+            <version>1.25.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.dtok</groupId>
+            <artifactId>repository</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dtok</groupId>
+            <artifactId>entity</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.openservices</groupId>
+            <artifactId>ons-client</artifactId>
+            <version>1.7.9.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-onsmqtt</artifactId>
+            <version>1.0.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.5.0</version>
+        </dependency>
+
+    </dependencies>
+</project>

+ 100 - 0
dtok-api/framework/src/main/java/com/dtok/framework/aop/GlobalExceptionHandler.java

@@ -0,0 +1,100 @@
+package com.dtok.framework.aop;
+
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.exception.NotRoleException;
+import com.alibaba.fastjson.JSONException;
+import com.dtok.framework.exception.AuthenticateException;
+import com.dtok.framework.exception.BusinessException;
+import com.dtok.framework.response.ErrorResponseData;
+import com.dtok.framework.util.IpUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.http.HttpServletRequest;
+
+@ControllerAdvice
+@Order(-1)
+public class GlobalExceptionHandler {
+
+    private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 拦截业务异常
+     */
+    @ExceptionHandler(BusinessException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ResponseBody
+    public ErrorResponseData business(BusinessException e) {
+        log.error("业务异常:", e);
+        return new ErrorResponseData(e.getCode(), e.getMessage());
+    }
+
+    @ExceptionHandler(NotRoleException.class)
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ResponseBody
+    public ErrorResponseData exception(NotRoleException e) {
+        return new ErrorResponseData("无角色权限");
+    }
+    /**
+     * 拦截业务异常
+     */
+    @ExceptionHandler(Exception.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ResponseBody
+    public ErrorResponseData exception(Exception e) {
+        log.error("业务异常:", e);
+        return new ErrorResponseData(e.getMessage());
+    }
+
+    @ExceptionHandler(JSONException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ResponseBody
+    public ErrorResponseData jsonException(JSONException e) {
+        log.error("JSON异常:  " + e.getMessage());
+        return new ErrorResponseData("服务异常!");
+    }
+
+    @ExceptionHandler(NotLoginException.class)
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ResponseBody
+    public ErrorResponseData AuthenticatorException(NotLoginException nle, HttpServletRequest request) {
+        log.error("未登录:" + IpUtil.getRequestIp(request));
+        String message = "";
+        switch (nle.getType()) {
+            case NotLoginException.NOT_TOKEN:
+                message = "未提供token";
+                break;
+            case NotLoginException.INVALID_TOKEN:
+                message = "token无效";
+                break;
+            case NotLoginException.TOKEN_TIMEOUT:
+                message = "token已过期";
+                break;
+            case NotLoginException.BE_REPLACED:
+                message = "token已被顶下线";
+                break;
+            case NotLoginException.KICK_OUT:
+                message = "token已被踢下线";
+                break;
+            default:
+                message = "当前会话未登录";
+                break;
+        }
+        return new ErrorResponseData(401, message);
+    }
+
+    @ExceptionHandler(AuthenticateException.class)
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ResponseBody
+    public ErrorResponseData AuthenticatorException(AuthenticateException authenticateException) {
+        return new ErrorResponseData(401, authenticateException.getErrorMessage());
+    }
+
+
+}

+ 40 - 0
dtok-api/framework/src/main/java/com/dtok/framework/authenticate/StpInterfaceImpl.java

@@ -0,0 +1,40 @@
+package com.dtok.framework.authenticate;
+
+import cn.dev33.satoken.stp.StpInterface;
+import com.dtok.entity.Account;
+import com.dtok.entity.Permission;
+import com.dtok.repository.AccountRepository;
+import com.dtok.repository.PermissionRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class StpInterfaceImpl implements StpInterface {
+
+    @Autowired
+    AccountRepository userRepository;
+
+    @Autowired
+    PermissionRepository permissionRepository;
+
+    private static final Logger LOGIN_LOG = LoggerFactory.getLogger("LoginLog");
+
+    @Override
+    public List<String> getPermissionList(Object o, String s) {
+        List<Permission> permissions = permissionRepository.findPermissionByUsername(((Account) o).getUsername());
+        return permissions.stream().map(Permission::getCode).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<String> getRoleList(Object o, String s) {
+        List<String> role = new ArrayList<>();
+        role.add(((Account)o).getRoleCode());
+        return role;
+    }
+}

+ 189 - 0
dtok-api/framework/src/main/java/com/dtok/framework/base/BaseController.java

@@ -0,0 +1,189 @@
+package com.dtok.framework.base;
+
+
+import cn.hutool.core.date.DateUtil;
+import com.aliyun.oss.OSSClient;
+import com.dtok.framework.exception.BizExceptionEnum;
+import com.dtok.framework.exception.CoreExceptionEnum;
+import com.dtok.framework.exception.ServiceException;
+import com.dtok.framework.response.SuccessResponseData;
+import com.dtok.framework.util.FileUtils;
+import com.dtok.framework.util.HttpContext;
+import com.dtok.framework.util.UploadUtils;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.*;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Objects;
+import java.util.UUID;
+
+public class BaseController {
+    protected static SuccessResponseData SUCCESS_TIP = new SuccessResponseData();
+
+    protected HttpServletRequest getHttpServletRequest() {
+        return HttpContext.getRequest();
+    }
+
+    protected HttpServletResponse getHttpServletResponse() {
+        return HttpContext.getResponse();
+    }
+
+    protected HttpSession getSession() {
+        return Objects.requireNonNull(HttpContext.getRequest()).getSession();
+    }
+
+    protected HttpSession getSession(Boolean flag) {
+        return Objects.requireNonNull(HttpContext.getRequest()).getSession(flag);
+    }
+
+    protected String getPara(String name) {
+        return Objects.requireNonNull(HttpContext.getRequest()).getParameter(name);
+    }
+
+    protected void setAttr(String name, Object value) {
+        Objects.requireNonNull(HttpContext.getRequest()).setAttribute(name, value);
+    }
+
+    protected File saveFile(MultipartFile file) {
+        String name = file.getOriginalFilename();
+        String fileSavePath = UploadUtils.getExcelDirFile();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
+        String str = sdf.format(new Date());
+        File newFile = new File(fileSavePath + "/" + UUID.randomUUID() + "_" + str + name.substring(name.lastIndexOf(".")));
+        try {
+            file.transferTo(newFile);
+        } catch (Exception e) {
+            throw new ServiceException(BizExceptionEnum.UPLOAD_ERROR);
+        }
+        return newFile;
+    }
+
+
+    public String getObjectName(String dirPrefix, MultipartFile file) {
+        // 文件后缀
+        String suffixName = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
+        String fileName = UUID.randomUUID() + suffixName;
+        // 文件类型:1-图片,2-音频,3-视频
+        String fileType = FileUtils.getFileType(suffixName);
+        // 完整路径
+        String objectName = "";
+        switch (fileType) {
+            case "1":
+                objectName = dirPrefix + "images/" + DateUtil.today() + "/" + fileName;
+                break;
+            case "2":
+
+                objectName = dirPrefix + "audio/" + DateUtil.today() + "/" + fileName;
+                break;
+            case "3":
+                objectName = dirPrefix + "videos/" + DateUtil.today() + "/" + fileName;
+                break;
+            default:
+                break;
+        }
+        return objectName;
+    }
+
+
+    protected File saveFile(MultipartFile file, String type) {
+        String name = file.getOriginalFilename();
+        String fileSavePath = UploadUtils.getExcelDirFile();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
+        String str = sdf.format(new Date());
+        File newFile = new File(fileSavePath + "/" + type + "/" + UUID.randomUUID() + "_" + str + name.substring(name.lastIndexOf(".")));
+        if (!newFile.exists()) {
+            newFile.mkdirs();
+        }
+        try {
+            file.transferTo(newFile);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ServiceException(BizExceptionEnum.UPLOAD_ERROR);
+        }
+        return newFile;
+    }
+
+
+    /**
+     * 删除cookie
+     */
+    protected void deleteCookieByName(String cookieName) {
+        Cookie[] cookies = this.getHttpServletRequest().getCookies();
+        for (Cookie cookie : cookies) {
+            if (cookie.getName().equals(cookieName)) {
+                Cookie temp = new Cookie(cookie.getName(), "");
+                temp.setMaxAge(0);
+                this.getHttpServletResponse().addCookie(temp);
+            }
+        }
+    }
+
+    /**
+     * 删除所有cookie
+     */
+    protected void deleteAllCookie() {
+        Cookie[] cookies = this.getHttpServletRequest().getCookies();
+        for (Cookie cookie : cookies) {
+            Cookie temp = new Cookie(cookie.getName(), "");
+            temp.setMaxAge(0);
+            this.getHttpServletResponse().addCookie(temp);
+        }
+    }
+
+    /**
+     * 返回前台文件流
+     *
+     * @author fengshuonan
+     * @date 2017年2月28日 下午2:53:19
+     */
+    protected ResponseEntity<InputStreamResource> renderFile(String fileName, String filePath) {
+        try {
+            final FileInputStream inputStream = new FileInputStream(filePath);
+            return renderFile(fileName, inputStream);
+        } catch (FileNotFoundException e) {
+            throw new ServiceException(CoreExceptionEnum.FILE_READING_ERROR);
+        }
+    }
+
+    /**
+     * 返回前台文件流
+     *
+     * @author fengshuonan
+     * @date 2017年2月28日 下午2:53:19
+     */
+    protected ResponseEntity<InputStreamResource> renderFile(String fileName, byte[] fileBytes) {
+        return renderFile(fileName, new ByteArrayInputStream(fileBytes));
+    }
+
+    /**
+     * 返回前台文件流
+     *
+     * @param fileName    文件名
+     * @param inputStream 输入流
+     * @return
+     * @author 0x0001
+     */
+    protected ResponseEntity<InputStreamResource> renderFile(String fileName, InputStream inputStream) {
+        InputStreamResource resource = new InputStreamResource(inputStream);
+        String dfileName = null;
+        try {
+            dfileName = new String(fileName.getBytes("gb2312"), "iso8859-1");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
+        headers.setContentDispositionFormData("attachment", dfileName);
+        return new ResponseEntity<>(resource, headers, HttpStatus.CREATED);
+    }
+}

+ 52 - 0
dtok-api/framework/src/main/java/com/dtok/framework/configure/RedisConfig.java

@@ -0,0 +1,52 @@
+package com.dtok.framework.configure;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+@Configuration
+@PropertySource("classpath:redis.properties")
+@Slf4j
+public class RedisConfig {
+
+    @Value("${spring.redis.host}")
+    private String host;
+
+    @Value("${spring.redis.port}")
+    private int port;
+
+    @Value("${spring.redis.timeout}")
+    private int timeout;
+
+    @Value("${spring.redis.jedis.pool.max-idle}")
+    private int maxIdle;
+
+    @Value("${spring.redis.jedis.pool.max-wait}")
+    private long maxWaitMillis;
+
+    @Value("${spring.redis.password}")
+    private String password;
+
+    @Value("${spring.redis.block-when-exhausted}")
+    private boolean  blockWhenExhausted;
+
+    @Bean
+    public JedisPool redisPoolFactory()  throws Exception{
+        log.info("JedisPool注入成功!!");
+        log.info("redis地址:" + host + ":" + port);
+        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
+        jedisPoolConfig.setMaxIdle(maxIdle);
+        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
+        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
+        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
+        // 是否启用pool的jmx管理功能, 默认true
+        jedisPoolConfig.setJmxEnabled(true);
+        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
+        return jedisPool;
+    }
+
+}

+ 32 - 0
dtok-api/framework/src/main/java/com/dtok/framework/configure/SaTokenConfigure.java

@@ -0,0 +1,32 @@
+//package com.dtok.framework.configure;
+//
+//import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
+//import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+//import cn.dev33.satoken.router.SaRouter;
+//import cn.dev33.satoken.stp.StpUtil;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+//
+//import java.util.Arrays;
+//import java.util.Collections;
+//
+//@Configuration
+//public class SaTokenConfigure implements WebMvcConfigurer {
+//    // 注册拦截器
+//    @Override
+//    public void addInterceptors(InterceptorRegistry registry) {
+//        // 注册 Sa-Token 的路由拦截器
+//        registry.addInterceptor(new SaRouteInterceptor())
+//                .addPathPatterns("/**")
+//                .excludePathPatterns("/login","/logout","/static/**");
+//    }
+//
+//
+//    @Override
+//    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+//        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
+//        registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
+//    }
+//}

+ 33 - 0
dtok-api/framework/src/main/java/com/dtok/framework/configure/ServerConfig.java

@@ -0,0 +1,33 @@
+package com.dtok.framework.configure;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+@Component
+@Slf4j
+public class ServerConfig  implements ApplicationListener<WebServerInitializedEvent> {
+
+    private int serverPort;
+
+    public int getPort() {
+        return this.serverPort;
+    }
+
+    @Override
+    public void onApplicationEvent(WebServerInitializedEvent event) {
+        try {
+            InetAddress inetAddress = Inet4Address.getLocalHost();
+            this.serverPort = event.getWebServer().getPort();
+            log.info("项目启动启动成功!接口文档地址: http://"+inetAddress.getHostAddress()+":"+serverPort+"/swagger-ui.html");
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+    }
+
+}

+ 48 - 0
dtok-api/framework/src/main/java/com/dtok/framework/configure/SwaggerConfig.java

@@ -0,0 +1,48 @@
+package com.dtok.framework.configure;
+
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+
+    @Bean
+    public Docket createRestApi(){
+        ParameterBuilder ticketPar = new ParameterBuilder();
+        List<Parameter> pars = new ArrayList<Parameter>();
+        ticketPar.name("satoken").description("密钥").defaultValue("")//Token 以及Authorization 为自定义的参数,session保存的名字是哪个就可以写成那个
+                .modelRef(new ModelRef("string")).parameterType("header").defaultValue("Bearer ")
+                .required(false).build(); // header中的ticket参数非必填,传空也可以
+        pars.add(ticketPar.build());    // 根据每个方法名也知道当前方法在设置什么参数
+
+        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.any())
+                .paths(PathSelectors.any()).build()
+                .globalOperationParameters(pars);
+    }
+
+    private ApiInfo apiInfo(){
+        return new ApiInfoBuilder()
+                .title("DTok (DMS)")
+                .description("DTok (DMS) API 文档")
+                .version("1.0")
+                .build();
+    }
+}

+ 37 - 0
dtok-api/framework/src/main/java/com/dtok/framework/configure/WebConfigurer.java

@@ -0,0 +1,37 @@
+package com.dtok.framework.configure;
+
+import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+import com.dtok.framework.util.UploadUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.expression.ParseException;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@Configuration
+public class WebConfigurer implements WebMvcConfigurer {
+
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/static/**").addResourceLocations("file:///" + UploadUtils.getExcelDirFile() + "/");
+    }
+
+    //注册拦截器
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 注册 Sa-Token 的路由拦截器
+        registry.addInterceptor(new SaRouteInterceptor())
+                .addPathPatterns("/**").excludePathPatterns("/login");
+    }
+
+
+}

+ 7 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/AbstractBaseExceptionEnum.java

@@ -0,0 +1,7 @@
+package com.dtok.framework.exception;
+
+public interface AbstractBaseExceptionEnum {
+    Integer getCode();
+
+    String getMessage();
+}

+ 34 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/AuthenticateException.java

@@ -0,0 +1,34 @@
+package com.dtok.framework.exception;
+
+public class AuthenticateException extends RuntimeException{
+    private Integer code;
+    private String errorMessage;
+
+    public AuthenticateException(Integer code, String errorMessage) {
+        super(errorMessage);
+        this.code = code;
+        this.errorMessage = errorMessage;
+    }
+
+    public AuthenticateException(AbstractBaseExceptionEnum exception) {
+        super(exception.getMessage());
+        this.code = exception.getCode();
+        this.errorMessage = exception.getMessage();
+    }
+
+    public Integer getCode() {
+        return this.code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getErrorMessage() {
+        return this.errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+}

+ 127 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/BizExceptionEnum.java

@@ -0,0 +1,127 @@
+/**
+ * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng)
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dtok.framework.exception;
+
+/**
+ * @author fengshuonan
+ * @Description 所有业务异常的枚举
+ * @date 2016年11月12日 下午5:04:51
+ */
+public enum BizExceptionEnum implements AbstractBaseExceptionEnum {
+
+    /**
+     * 字典
+     */
+    DICT_EXISTED(400, "字典已经存在"),
+    ERROR_CREATE_DICT(500, "创建字典失败"),
+    ERROR_WRAPPER_FIELD(500, "包装字典属性失败"),
+    ERROR_CODE_EMPTY(500, "字典类型不能为空"),
+
+    /**
+     * 文件上传
+     */
+    FILE_READING_ERROR(400, "FILE_READING_ERROR!"),
+    FILE_NOT_FOUND(400, "FILE_NOT_FOUND!"),
+    UPLOAD_ERROR(500, "上传图片出错"),
+
+    /**
+     * 权限和数据问题
+     */
+    DB_RESOURCE_NULL(400, "数据库中没有该资源"),
+    NO_PERMITION(405, "权限异常"),
+    REQUEST_INVALIDATE(400, "请求数据格式不正确"),
+    INVALID_KAPTCHA(400, "验证码不正确"),
+    CANT_DELETE_ADMIN(600, "不能删除超级管理员"),
+    CANT_FREEZE_ADMIN(600, "不能冻结超级管理员"),
+    CANT_CHANGE_ADMIN(600, "不能修改超级管理员角色"),
+
+    /**
+     * 账户问题
+     */
+    NOT_LOGIN(401, "当前用户未登录"),
+    USER_ALREADY_REG(401, "该用户已经注册"),
+    NO_THIS_USER(400, "没有此用户"),
+    USER_NOT_EXISTED(400, "没有此用户"),
+    ACCOUNT_FREEZED(401, "账号被冻结"),
+    OLD_PWD_NOT_RIGHT(402, "原密码不正确"),
+    TWO_PWD_NOT_MATCH(405, "两次输入密码不一致"),
+    NOT_ROLE_EXCEPTION(400, "该用户没有角色,请配置"),
+    SYS_NO_PERMISSION(400, "没有%s系统的权限"),
+    ROLE_ERROR(400, "用户角色异常"),
+    NO_PERMISSION(501, "没有权限操作"),
+    CREATE_USER_ERROR(500, "创建用户失败"),
+    CANT_HAVE_MORE_COMPANY(500, "公司授权异常"),
+    USER_COUNT_OVERFLOW(500, "用户数已达上限"),
+
+    /**
+     * 错误的请求
+     */
+    MENU_PCODE_COINCIDENCE(400, "菜单编号和副编号不能一致"),
+    NOT_DELETE_DEFAULT_MENU_PERMISSION(400, "不能删除预设菜单权限"),
+    EXISTED_THE_MENU(400, "菜单编号重复,不能添加"),
+    DICT_MUST_BE_NUMBER(400, "字典的值必须为数字"),
+    REQUEST_NULL(400, "请求有错误"),
+    SESSION_TIMEOUT(400, "会话超时"),
+    SERVER_ERROR(500, "服务器异常"),
+
+    /**
+     * token异常
+     */
+    TOKEN_EXPIRED(700, "token过期"),
+    TOKEN_ERROR(700, "token验证失败"),
+
+    /**
+     * 签名异常
+     */
+    SIGN_ERROR(700, "签名验证失败"),
+
+    /**
+     * 其他
+     */
+    AUTH_REQUEST_ERROR(400, "账号密码错误"),
+    USER_ALREADY(400, "用户名重复"),
+
+    NOT_FIND_COMPANY(404, "没有找到公司"),
+
+    NO_COMPANY_PERMISSION(403, "没有该公司权限");
+
+    BizExceptionEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    private Integer code;
+
+    private String message;
+
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 34 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/BusinessException.java

@@ -0,0 +1,34 @@
+package com.dtok.framework.exception;
+
+public class BusinessException extends RuntimeException {
+    private Integer code;
+    private String errorMessage;
+
+    public BusinessException(Integer code, String errorMessage) {
+        super(errorMessage);
+        this.code = code;
+        this.errorMessage = errorMessage;
+    }
+
+    public BusinessException(AbstractBaseExceptionEnum exception) {
+        super(exception.getMessage());
+        this.code = exception.getCode();
+        this.errorMessage = exception.getMessage();
+    }
+
+    public Integer getCode() {
+        return this.code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getErrorMessage() {
+        return this.errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+}

+ 34 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/ConnectionAlreadyExist.java

@@ -0,0 +1,34 @@
+package com.dtok.framework.exception;
+
+public class ConnectionAlreadyExist  extends RuntimeException {
+    private Integer code;
+    private String errorMessage;
+
+    public ConnectionAlreadyExist(Integer code, String errorMessage) {
+        super(errorMessage);
+        this.code = code;
+        this.errorMessage = errorMessage;
+    }
+
+    public ConnectionAlreadyExist(AbstractBaseExceptionEnum exception) {
+        super(exception.getMessage());
+        this.code = exception.getCode();
+        this.errorMessage = exception.getMessage();
+    }
+
+    public Integer getCode() {
+        return this.code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getErrorMessage() {
+        return this.errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+}

+ 84 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/CoreExceptionEnum.java

@@ -0,0 +1,84 @@
+/**
+ * Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dtok.framework.exception;
+
+
+
+/**
+ * core模块的异常集合
+ *
+ * @author stylefeng
+ * @Date 2018/1/4 22:40
+ */
+public enum CoreExceptionEnum implements AbstractBaseExceptionEnum {
+
+    /**
+     * 其他
+     */
+    INVLIDE_DATE_STRING(400, "输入日期格式不对"),
+
+    /**
+     * 初始化数据库的异常
+     */
+    NO_CURRENT_USER(700, "当前没有登录的用户"),
+    INIT_TABLE_EMPTY_PARAMS(701, "初始化数据库,存在为空的字段"),
+
+    /**
+     * 其他
+     */
+    WRITE_ERROR(500, "渲染界面错误"),
+    ENCRYPT_ERROR(600, "加解密错误"),
+
+    /**
+     * 文件上传
+     */
+    FILE_READING_ERROR(400, "FILE_READING_ERROR!"),
+    FILE_NOT_FOUND(400, "FILE_NOT_FOUND!"),
+
+    /**
+     * 数据库字段与实体字段不一致
+     */
+    FIELD_VALIDATE_ERROR(700, "数据库字段与实体字段不一致!"),
+
+    /**
+     * 错误的请求
+     */
+    PAGE_NULL(404, "请求页面不存在"),
+    IO_ERROR(500, "流读取异常"),
+    SERVICE_ERROR(500, "服务器异常"),
+    REMOTE_SERVICE_NULL(404, "远程服务不存在"),
+    ASYNC_ERROR(5000, "数据在被别人修改,请稍后重试");
+
+    CoreExceptionEnum(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    private Integer code;
+
+    private String message;
+
+    @Override
+    public Integer getCode() {
+        return code;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+}

+ 34 - 0
dtok-api/framework/src/main/java/com/dtok/framework/exception/ServiceException.java

@@ -0,0 +1,34 @@
+package com.dtok.framework.exception;
+
+public class ServiceException extends RuntimeException {
+    private Integer code;
+    private String errorMessage;
+
+    public ServiceException(Integer code, String errorMessage) {
+        super(errorMessage);
+        this.code = code;
+        this.errorMessage = errorMessage;
+    }
+
+    public ServiceException(AbstractBaseExceptionEnum exception) {
+        super(exception.getMessage());
+        this.code = exception.getCode();
+        this.errorMessage = exception.getMessage();
+    }
+
+    public Integer getCode() {
+        return this.code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getErrorMessage() {
+        return this.errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+}

+ 51 - 0
dtok-api/framework/src/main/java/com/dtok/framework/http/LoggingInterceptor.java

@@ -0,0 +1,51 @@
+package com.dtok.framework.http;
+
+
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+@Slf4j
+public class LoggingInterceptor implements Interceptor {
+
+    private static final Logger WMS_LOG = LoggerFactory.getLogger("WmsLog");
+
+    public Response intercept(Chain chain) throws IOException {
+        // 这个chain里面包含了request和response,所以你要什么都可以从这里拿
+        Request request = chain.request();
+
+        long t1 = System.nanoTime();// 请求发起的时间
+        WMS_LOG.info(String.format("发送请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
+        log.info(String.format("发送请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
+//            WMS_LOG.info("请求参数:{\n +" + request.body().writeTo(); + "\n}");
+        StringBuilder bodyLog = new StringBuilder();
+        if (request.body() instanceof FormBody) {
+            FormBody body = (FormBody) request.body();
+            for (int i = 0; i < body.size(); i++) {
+                bodyLog.append(body.encodedName(i)).append("=").append(body.encodedValue(i)).append(",");
+            }
+            WMS_LOG.info("请求参数:" + bodyLog.toString());
+            log.info("请求参数:" + bodyLog.toString());
+        }
+//		System.out.println(String.format("发送请求 %s on %s%n%s", request.url(), chain.connection(), request.headers()));
+        Response response = chain.proceed(request);
+
+        long t2 = System.nanoTime();// 收到响应的时间
+
+        // 这里不能直接使用response.body().string()的方式输出日志
+        // 因为response.body().string()之后,response中的流会被关闭,程序会报错,我们需要创建出一
+        // 个新的response给应用层处理
+        ResponseBody responseBody = response.peekBody(1024 * 1024);
+        String respStr = responseBody.string();
+        WMS_LOG.info(String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s", response.request().url(),
+                respStr, (t2 - t1) / 1e6d, response.headers()));
+        log.info(String.format("接收响应: [%s] %n返回json:【%s】 %.1fms%n%s", response.request().url(),
+                respStr, (t2 - t1) / 1e6d, response.headers()));
+        return response;
+
+    }
+
+}

+ 149 - 0
dtok-api/framework/src/main/java/com/dtok/framework/http/OkHttpUtil.java

@@ -0,0 +1,149 @@
+package com.dtok.framework.http;
+
+import com.dtok.framework.util.MD5Util;
+import com.mashape.unirest.http.HttpResponse;
+import com.mashape.unirest.http.Unirest;
+import com.mashape.unirest.http.exceptions.UnirestException;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Component
+@Slf4j
+public class OkHttpUtil {
+
+
+    private static final OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new LoggingInterceptor()).build();
+
+    public static Response sendPostRequest(String url, Map<String, String> params) throws IOException {
+        //动态添加参数
+        FormBody.Builder formBody = new FormBody.Builder();
+        //遍历参数,KV对应。
+        for (Map.Entry<String, String> mapping : params.entrySet()) {
+            formBody.add(mapping.getKey(), String.valueOf(mapping.getValue()));
+        }
+
+        Request request = new Request.Builder()
+                .url(url)
+                .post(formBody.build())
+                .build();
+        return okHttpClient.newCall(request).execute();
+    }
+
+    public static Response post(String url) throws IOException {
+        //动态添加参数
+        FormBody.Builder formBody = new FormBody.Builder();
+        //遍历参数,KV对应
+
+        Request request = new Request.Builder()
+                .url(url)
+                .post(formBody.build())
+                .build();
+        return okHttpClient.newCall(request).execute();
+    }
+
+
+    public static void encodingRequestBody(Map<String, String> params) {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("he3yun.com-");
+        Map<String, String> newMap = params.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
+                stringStringEntry -> stringStringEntry.getValue().toLowerCase(Locale.ROOT)));
+
+        Map<String, String> sortedParams = newMap.entrySet().stream().sorted(Map.Entry.comparingByValue())
+                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
+                (oldValue, newValue) -> oldValue, LinkedHashMap::new));
+
+        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
+            stringBuilder.append(params.get(entry.getKey())).append("-");
+        }
+        String timestamp = String.valueOf(new Date().getTime());
+        stringBuilder.append(timestamp);
+        System.out.println("HASH: =>" + stringBuilder);
+        System.out.println(MD5Util.stringToMD5(stringBuilder.toString()));
+        params.put("timestamp", timestamp);
+        params.put("hashCode", MD5Util.stringToMD5(stringBuilder.toString()));
+    }
+
+    public static Response get(String url, Map<String, String> params) throws IOException {
+        HttpUrl.Builder httpBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+        for (Map.Entry<String, String> param : params.entrySet()) {
+            httpBuilder.addQueryParameter(param.getKey(), param.getValue());
+            log.info(String.format("K: %s - V: %s", param.getKey(), param.getValue()));
+        }
+
+        Request request = new Request.Builder().url(httpBuilder.build())
+
+
+                .build();
+        return okHttpClient.newCall(request).execute();
+    }
+
+    public static Response get(String url) throws IOException {
+        HttpUrl.Builder httpBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+        Request request = new Request.Builder().url(httpBuilder.build())
+                .build();
+        return okHttpClient.newCall(request).execute();
+    }
+
+    public static Response get(String url, Map<String, String> params, Map<String, String> extraParam) throws IOException {
+        for (Map.Entry<String, String> entry : extraParam.entrySet()) {
+            params.put(entry.getKey(), entry.getValue());
+        }
+        HttpUrl.Builder httpBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+        for (Map.Entry<String, String> param : params.entrySet()) {
+            httpBuilder.addQueryParameter(param.getKey(), param.getValue());
+            log.info(String.format("K: %s - V: %s", param.getKey(), param.getValue()));
+        }
+
+        Request request = new Request.Builder().url(httpBuilder.build())
+
+
+                .build();
+        return okHttpClient.newCall(request).execute();
+    }
+
+    public static Response get(String url, Map<String, String> params, String checkListDetail, String remark) throws IOException {
+
+        HttpUrl.Builder httpBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+        for (Map.Entry<String, String> param : params.entrySet()) {
+            httpBuilder.addQueryParameter(param.getKey(), param.getValue());
+            log.info(String.format("K: %s - V: %s", param.getKey(), param.getValue()));
+        }
+        RequestBody requestBody = new FormBody.Builder()
+                .add("checkListDetail", checkListDetail)
+                .build();
+        Request request = new Request.Builder().url(httpBuilder.build())
+                .post(requestBody)
+                .build();
+        return okHttpClient.newCall(request).execute();
+    }
+
+    public static String upload(String url, Map<String, String> params, File file, Map<String, String> extraParam) throws IOException, UnirestException {
+        for (Map.Entry<String, String> entry : extraParam.entrySet()) {
+            params.put(entry.getKey(), entry.getValue());
+        }
+        log.info(String.format("upload... %s", file.getName()));
+        HttpUrl.Builder httpBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
+        for (Map.Entry<String, String> param : params.entrySet()) {
+            httpBuilder.addQueryParameter(param.getKey(), param.getValue());
+            log.info(String.format("K: %s - V: %s", param.getKey(), param.getValue()));
+        }
+
+        Request request = new Request.Builder().url(httpBuilder.build()).build();
+        System.out.println(file.getName());
+
+        System.out.println(String.valueOf(request.url()));
+        HttpResponse<String> response =
+                Unirest.post(String.valueOf(request.url()))
+                        .field("fileData", file)
+                        .asString();
+        return response.getBody();
+    }
+
+
+}

+ 85 - 0
dtok-api/framework/src/main/java/com/dtok/framework/listener/MySaTokenListener.java

@@ -0,0 +1,85 @@
+package com.dtok.framework.listener;
+
+import cn.dev33.satoken.listener.SaTokenListener;
+import cn.dev33.satoken.stp.SaLoginModel;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * 自定义侦听器的实现
+ */
+@Component
+@Slf4j
+public class MySaTokenListener implements SaTokenListener {
+
+    private static final Logger LOGGER= LoggerFactory.getLogger("loginLog");
+
+    /**
+     * 每次登录时触发
+     */
+    @Override
+    public void doLogin(String loginType, Object loginId, SaLoginModel loginModel) {
+        LOGGER.info(String.format("登录 : %s\t%s\t%s\t", loginType, loginId, loginModel.getDevice()));
+        // ...
+    }
+
+    /**
+     * 每次注销时触发
+     */
+    @Override
+    public void doLogout(String loginType, Object loginId, String tokenValue) {
+        // ...
+    }
+
+    /**
+     * 每次被踢下线时触发
+     */
+    @Override
+    public void doLogoutByLoginId(String loginType, Object loginId, String tokenValue, String device) {
+        // ...
+    }
+
+    /**
+     * 每次被顶下线时触发
+     */
+    @Override
+    public void doReplaced(String loginType, Object loginId, String tokenValue, String device) {
+        // ...
+    }
+
+    /**
+     * 每次被封禁时触发
+     */
+    @Override
+    public void doDisable(String loginType, Object loginId, long disableTime) {
+        // ...
+    }
+
+    /**
+     * 每次被解封时触发
+     */
+    @Override
+    public void doUntieDisable(String loginType, Object loginId) {
+        // ...
+    }
+
+    /**
+     * 每次创建Session时触发
+     */
+    @Override
+    public void doCreateSession(String id) {
+        LOGGER.info(String.format("create session %s", id));
+        // ...
+    }
+
+    /**
+     * 每次注销Session时触发
+     */
+    @Override
+    public void doLogoutSession(String id) {
+        // ...
+    }
+
+}

+ 46 - 0
dtok-api/framework/src/main/java/com/dtok/framework/response/ErrorResponseData.java

@@ -0,0 +1,46 @@
+/**
+ * Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dtok.framework.response;
+
+
+import lombok.Data;
+
+/**
+ * 请求失败的返回
+ *
+ * @author stylefeng
+ * @Date 2018/1/4 22:39
+ */
+@Data
+public class ErrorResponseData extends ResponseData {
+
+    /**
+     * 异常的具体类名称
+     */
+    private String exceptionClazz;
+
+    public ErrorResponseData(String message) {
+        super(false, ResponseData.DEFAULT_ERROR_CODE, message, null);
+    }
+
+    public ErrorResponseData(Integer code, String message) {
+        super(false, code, message, null);
+    }
+
+    public ErrorResponseData(Integer code, String message, Object object) {
+        super(false, code, message, object);
+    }
+}

+ 95 - 0
dtok-api/framework/src/main/java/com/dtok/framework/response/ResponseData.java

@@ -0,0 +1,95 @@
+/**
+ * Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dtok.framework.response;
+
+
+import lombok.Data;
+
+/**
+ * 返回给前台的通用包装
+ *
+ * @author stylefeng
+ * @Date 2018/1/4 22:37
+ */
+@Data
+public class ResponseData {
+
+    public static final String DEFAULT_SUCCESS_MESSAGE = "请求成功";
+
+    public static final String DEFAULT_ERROR_MESSAGE = "网络异常";
+
+    public static final Integer DEFAULT_SUCCESS_CODE = 200;
+
+    public static final Integer DEFAULT_ERROR_CODE = 500;
+
+    /**
+     * 请求是否成功
+     */
+    private Boolean success;
+
+    /**
+     * 响应状态码
+     */
+    private Integer code;
+
+    /**
+     * 响应信息
+     */
+    private String message;
+
+    /**
+     * 响应对象
+     */
+    private Object data;
+
+    public ResponseData() {
+    }
+
+    public ResponseData(Boolean success, Integer code, String message, Object data) {
+        this.success = success;
+        this.code = code;
+        this.message = message;
+        this.data = data;
+    }
+
+    public static SuccessResponseData success() {
+        return new SuccessResponseData();
+    }
+
+    public static SuccessResponseData success(Object object) {
+        return new SuccessResponseData(object);
+    }
+
+    public static SuccessResponseData success(String message) {
+        return new SuccessResponseData(message);
+    }
+
+    public static SuccessResponseData success(Integer code, String message, Object object) {
+        return new SuccessResponseData(code, message, object);
+    }
+
+    public static ErrorResponseData error(String message) {
+        return new ErrorResponseData(message);
+    }
+
+    public static ErrorResponseData error(Integer code, String message) {
+        return new ErrorResponseData(code, message);
+    }
+
+    public static ErrorResponseData error(Integer code, String message, Object object) {
+        return new ErrorResponseData(code, message, object);
+    }
+}

+ 41 - 0
dtok-api/framework/src/main/java/com/dtok/framework/response/SuccessResponseData.java

@@ -0,0 +1,41 @@
+/**
+ * Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dtok.framework.response;
+
+/**
+ * 请求成功的返回
+ *
+ * @author stylefeng
+ * @Date 2018/1/4 22:38
+ */
+public class SuccessResponseData extends ResponseData {
+
+    public SuccessResponseData() {
+        super(true, DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, null);
+    }
+
+    public SuccessResponseData(Object object) {
+        super(true, DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, object);
+    }
+
+    public SuccessResponseData(String message) {
+        super(true, DEFAULT_SUCCESS_CODE, message, null);
+    }
+
+    public SuccessResponseData(Integer code, String message, Object object) {
+        super(true, code, message, object);
+    }
+}

+ 21 - 0
dtok-api/framework/src/main/java/com/dtok/framework/sql/SqlServerDialect.java

@@ -0,0 +1,21 @@
+package com.dtok.framework.sql;
+
+import org.hibernate.dialect.SQLServer2012Dialect;
+import org.hibernate.type.StandardBasicTypes;
+
+import java.sql.Types;
+
+public class SqlServerDialect extends SQLServer2012Dialect {
+
+    /**
+     * 设置sql server 数据库方言转换
+     */
+    public SqlServerDialect() {
+        registerHibernateType(Types.NCHAR, StandardBasicTypes.CHARACTER.getName());
+        registerHibernateType(Types.NCHAR, 1, StandardBasicTypes.CHARACTER.getName());
+        registerHibernateType(Types.NCHAR, 255, StandardBasicTypes.STRING.getName());
+        registerHibernateType(Types.NVARCHAR, StandardBasicTypes.STRING.getName());
+        registerHibernateType(Types.LONGNVARCHAR, StandardBasicTypes.TEXT.getName());
+        registerHibernateType(Types.NCLOB, StandardBasicTypes.CLOB.getName());
+    }
+}

+ 15 - 0
dtok-api/framework/src/main/java/com/dtok/framework/sql/UpperTableStrategy.java

@@ -0,0 +1,15 @@
+package com.dtok.framework.sql;
+
+import org.hibernate.boot.model.naming.Identifier;
+import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
+import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
+
+public class UpperTableStrategy extends PhysicalNamingStrategyStandardImpl {
+    private static final long serialVersionUID = 1383021413247872469L;
+
+    @Override
+    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
+        String tableName = name.getText().toUpperCase();
+        return Identifier.toIdentifier(tableName);
+    }
+}

+ 261 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/ConnectionOptionWrapper.java

@@ -0,0 +1,261 @@
+//package com.dtok.framework.util;
+//
+//import java.io.File;
+//import java.io.FileInputStream;
+//import java.io.FileNotFoundException;
+//import java.io.FileReader;
+//import java.io.IOException;
+//import java.security.InvalidKeyException;
+//import java.security.KeyFactory;
+//import java.security.KeyStore;
+//import java.security.NoSuchAlgorithmException;
+//import java.security.PrivateKey;
+//import java.security.SecureRandom;
+//import java.security.cert.Certificate;
+//import java.security.cert.CertificateFactory;
+//import java.security.cert.X509Certificate;
+//import java.security.interfaces.ECPrivateKey;
+//import java.security.spec.ECPrivateKeySpec;
+//import java.security.spec.InvalidKeySpecException;
+//import java.security.spec.PKCS8EncodedKeySpec;
+//import java.security.spec.RSAPrivateKeySpec;
+//import java.util.Collection;
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//import javax.net.ssl.KeyManager;
+//import javax.net.ssl.KeyManagerFactory;
+//import javax.net.ssl.SSLContext;
+//import javax.net.ssl.TrustManager;
+//import javax.net.ssl.TrustManagerFactory;
+//
+//import org.bouncycastle.util.io.pem.PemObject;
+//import org.bouncycastle.util.io.pem.PemReader;
+//import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
+//import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+//import sun.security.ssl.SSLContextImpl;
+//
+//import static org.eclipse.paho.client.mqttv3.MqttConnectOptions.MQTT_VERSION_3_1_1;
+//
+///**
+// * 工具类:负责封装 MQ4IOT 客户端的初始化参数设置
+// */
+//public class ConnectionOptionWrapper {
+//    /**
+//     * 内部连接参数
+//     */
+//    private MqttConnectOptions mqttConnectOptions;
+//    /**
+//     * MQ4IOT 实例 ID,购买后控制台获取
+//     */
+//    private String instanceId;
+//    /**
+//     * 账号 accesskey,从账号系统控制台获取
+//     */
+//    private String accessKey;
+//    /**
+//     * 账号 secretKey,从账号系统控制台获取,仅在Signature鉴权模式下需要设置
+//     */
+//    private String secretKey;
+//    /**
+//     * MQ4IOT clientId,由业务系统分配,需要保证每个 tcp 连接都不一样,保证全局唯一,如果不同的客户端对象(tcp 连接)使用了相同的 clientId 会导致连接异常断开。
+//     * clientId 由两部分组成,格式为 GroupID@@@DeviceId,其中 groupId 在 MQ4IOT 控制台申请,DeviceId 由业务方自己设置,clientId 总长度不得超过64个字符。
+//     */
+//    private String clientId;
+//    /**
+//     * 客户端使用的 Token 参数,仅在 Token 鉴权模式下需要设置,Key 为 token 类型,一个客户端最多存在三种类型,R,W,RW,Value 是 token内容。
+//     * 应用需要保证 token 在过期及时更新。否则会导致连接异常。
+//     */
+//    private Map<String, String> tokenData = new ConcurrentHashMap<String, String>();
+//
+//    /**
+//     * Token 鉴权模式下构造方法
+//     *
+//     * @param instanceId MQ4IOT 实例 ID,购买后控制台获取
+//     * @param accessKey 账号 accesskey,从账号系统控制台获取
+//     * @param clientId MQ4IOT clientId,由业务系统分配
+//     * @param tokenData 客户端使用的 Token 参数,仅在 Token 鉴权模式下需要设置
+//     */
+//    public ConnectionOptionWrapper(String instanceId, String accessKey, String clientId,
+//                                   Map<String, String> tokenData) {
+//        this.instanceId = instanceId;
+//        this.accessKey = accessKey;
+//        this.clientId = clientId;
+//        if (tokenData != null) {
+//            this.tokenData.putAll(tokenData);
+//        }
+//        mqttConnectOptions = new MqttConnectOptions();
+//        mqttConnectOptions.setUserName("Token|" + accessKey + "|" + instanceId);
+//        StringBuilder builder = new StringBuilder();
+//        for (Map.Entry<String, String> entry : tokenData.entrySet()) {
+//            builder.append(entry.getKey()).append("|").append(entry.getValue()).append("|");
+//        }
+//        if (builder.length() > 0) {
+//            builder.setLength(builder.length() - 1);
+//        }
+//        mqttConnectOptions.setPassword(builder.toString().toCharArray());
+//        mqttConnectOptions.setCleanSession(true);
+//        mqttConnectOptions.setKeepAliveInterval(90);
+//        mqttConnectOptions.setAutomaticReconnect(true);
+//        mqttConnectOptions.setMqttVersion(MQTT_VERSION_3_1_1);
+//        mqttConnectOptions.setConnectionTimeout(5000);
+//    }
+//
+//    /**
+//     * Signature 鉴权模式下构造方法
+//     *
+//     * @param instanceId MQ4IOT 实例 ID,购买后控制台获取
+//     * @param accessKey 账号 accesskey,从账号系统控制台获取
+//     * @param clientId MQ4IOT clientId,由业务系统分配
+//     * @param secretKey 账号 secretKey,从账号系统控制台获取
+//     */
+//    public ConnectionOptionWrapper(String instanceId, String accessKey, String secretKey,
+//                                   String clientId) throws NoSuchAlgorithmException, InvalidKeyException {
+//        this.instanceId = instanceId;
+//        this.accessKey = accessKey;
+//        this.secretKey = secretKey;
+//        this.clientId = clientId;
+//        mqttConnectOptions = new MqttConnectOptions();
+//        mqttConnectOptions.setUserName("Signature|" + accessKey + "|" + instanceId);
+//        mqttConnectOptions.setPassword(Tools.macSignature(clientId, secretKey).toCharArray());
+//        mqttConnectOptions.setCleanSession(false);
+//        mqttConnectOptions.setKeepAliveInterval(90);
+//        mqttConnectOptions.setAutomaticReconnect(true);
+//        mqttConnectOptions.setMqttVersion(MQTT_VERSION_3_1_1);
+//        mqttConnectOptions.setConnectionTimeout(5000);
+//    }
+//
+//    public ConnectionOptionWrapper(String instanceId, String accessKey, String secretKey,
+//                                   String clientId, String rootCAPath, String deviceCrtPath, String deviceKeyPath,
+//                                   String passwd) throws Exception {
+//        this.instanceId = instanceId;
+//        this.accessKey = accessKey;
+//        this.secretKey = secretKey;
+//        this.clientId = clientId;
+//        mqttConnectOptions = new MqttConnectOptions();
+//        mqttConnectOptions.setCleanSession(false);
+//        mqttConnectOptions.setKeepAliveInterval(90);
+//        mqttConnectOptions.setAutomaticReconnect(true);
+//        mqttConnectOptions.setMqttVersion(MQTT_VERSION_3_1_1);
+//        mqttConnectOptions.setConnectionTimeout(5000);
+//
+//        SSLContext ctx = getSSLContext(rootCAPath, deviceCrtPath, deviceKeyPath, passwd);
+//        mqttConnectOptions.setSocketFactory(ctx.getSocketFactory());
+//    }
+//
+//    public SSLContext getSSLContext(String caPath, String crtPath, String keyPath, String password) throws Exception {
+//        /*
+//         * CA证书是用来认证服务端的,这里的CA就是一个公认的认证证书
+//         * TrustManagerFactory 管理的是授信的CA证书,所以KeyStore里面存放的不需要私钥信息,通常也不可能有
+//         */
+//        CertificateFactory cAf = CertificateFactory.getInstance("X.509");
+//        FileInputStream caIn = new FileInputStream(caPath);
+//        X509Certificate ca = (X509Certificate) cAf.generateCertificate(caIn);
+//        KeyStore caKs = KeyStore.getInstance("JKS");
+//        caKs.load(null, password.toCharArray());
+//        caKs.setCertificateEntry("ca1", ca); //可以通过设置alias不同,配置多个ca实例,即配置多个可信的root CA。
+//        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+//        tmf.init(caKs);
+//        caIn.close();
+//
+//        //这个客户端证书,是用来发送给服务端的,准备做双向验证用的。
+//        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+//        FileInputStream crtIn = new FileInputStream(crtPath);
+//        Collection<? extends Certificate> certs = cf.generateCertificates(crtIn);
+//        X509Certificate[] x509Certs = new X509Certificate[certs.size()];
+//        int i=0;
+//        for(Certificate cert: certs) {
+//            x509Certs[i++] = (X509Certificate) cert;
+//        }
+//        crtIn.close();
+//
+//        //客户端私钥,是用来处理双向SSL验证中服务端用客户端证书加密的数据的解密(解析签名)工具
+//        KeyStore ks = KeyStore.getInstance("JKS");
+//        ks.load(null, password.toCharArray());
+//        ks.setCertificateEntry("certificate3", x509Certs[0]);
+//
+//        PrivateKey privateKey = getPrivateKey(new File(keyPath));
+//        /*
+//         * 注意:下面这行代码中非常重要的一点是:
+//         * setKeyEntry这个函数的第二个参数 password,他不是指私钥的加密密码,只是KeyStore对这个私钥进行管理设置的密码
+//         *
+//         * setKeyEntry中最后一个参数,chain的顺序是证书链中越靠近当前privateKey节点的证书,越靠近数字下标0的位置。
+//         */
+//        ks.setKeyEntry("private-key", privateKey, password.toCharArray(), x509Certs);
+//        /*
+//         * KeyManagerFactory必须是证书和私钥配对使用,即KeyStore里面装载客户端证书以及对应的私钥,双向SSL验证需要。
+//         */
+//        KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");
+//        kmf.init(ks, password.toCharArray());
+//
+//        /*
+//         * 最后创建SSL套接字工厂 SSLSocketFactory
+//         * 注意:这里,SSLContext不支持TLSv2创建
+//         */
+//        SSLContext context = SSLContext.getInstance("TLSv1.2");
+//        KeyManager[] kms = kmf.getKeyManagers();
+//        TrustManager[] tms = tmf.getTrustManagers();
+//        context.init(kms, tms, new SecureRandom());
+//        return context;
+//    }
+//
+//    public PrivateKey getPrivateKey(File file) {
+//        if (file == null) {
+//            return null;
+//        }
+//        PrivateKey privKey = null;
+//        PemReader pemReader = null;
+//        try {
+//            pemReader = new PemReader(new FileReader(file));
+//            PemObject pemObject = pemReader.readPemObject();
+//            byte[] pemContent = pemObject.getContent();
+//            //支持从PKCS#1或PKCS#8 格式的私钥文件中提取私钥
+//            if (pemObject.getType().endsWith("RSA PRIVATE KEY")) {
+//                /*
+//                 * 取得私钥  for PKCS#1
+//                 * openssl genrsa 默认生成的私钥就是PKCS1的编码
+//                 */
+//                RSAPrivateKey asn1PrivKey = RSAPrivateKey.getInstance(pemContent);
+//                RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());
+//                KeyFactory keyFactory= KeyFactory.getInstance("rsa");
+//                privKey= keyFactory.generatePrivate(rsaPrivKeySpec);
+//            } else if (pemObject.getType().endsWith("PRIVATE KEY")) {
+//                /*
+//                 * 通过openssl pkcs8 -topk8转换为pkcs8,例如(-nocrypt不做额外加密操作):
+//                 * openssl pkcs8 -topk8 -in pri.key -out pri8.key -nocrypt
+//                 *
+//                 * 取得私钥 for PKCS#8
+//                 */
+//                PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(pemContent);
+//                KeyFactory kf = KeyFactory.getInstance("rsa");
+//                privKey = kf.generatePrivate(privKeySpec);
+//            }
+//
+////            else if (pemObject.getType().endsWith("EC PARAMETERS")) {
+////                KeyFactory kf = KeyFactory.getInstance("EC");
+////                // decode private key
+////                PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(pemContent);
+////                privKey = kf.generatePrivate(privSpec);
+////            }
+//        } catch (FileNotFoundException e) {
+//            System.out.println("read private key fail,the reason is the file not exist");
+//            e.printStackTrace();
+//        } catch (IOException | InvalidKeySpecException | NoSuchAlgorithmException e) {
+//            System.out.println("read private key fail,the reason is :"+e.getMessage());
+//            e.printStackTrace();
+//        } finally {
+//            try {
+//                if (pemReader != null) {
+//                    pemReader.close();
+//                }
+//            } catch (IOException e) {
+//                System.out.println(e.getMessage());
+//            }
+//        }
+//        return privKey;
+//    }
+//
+//    public MqttConnectOptions getMqttConnectOptions() {
+//        return mqttConnectOptions;
+//    }
+//
+//}

+ 68 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/FileUtils.java

@@ -0,0 +1,68 @@
+package com.dtok.framework.util;
+
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+
+@Component
+public class FileUtils {
+
+    public static final String TYPE_JPG = ".jpg";
+
+    public static final String TYPE_GIF = ".gif";
+
+    public static final String TYPE_PNG = ".png";
+
+    public static final String TYPE_BMP = ".bmp";
+
+    public static final String TYPE_MP3 = ".mp3";
+
+    public static final String TYPE_WAV = ".wav";
+
+    public static final String TYPE_M4A = ".m4a";
+
+    public static final String TYPE_MP4 = ".mp4";
+
+    public static final String TYPE_UNKNOWN = "unknown";
+
+
+    public static boolean delFile(File file) {
+        if (file.exists()) {
+            String name = file.getName();
+            file.delete();
+            System.out.println("文件 [" + name + "] 已经删除!");
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 获取文件类型
+     * type:1-图片,2-音频,3-视频
+     *
+     * @return {@link String}
+     */
+    public static String getFileType(String suffixName) {
+        String type = null;
+        switch (suffixName) {
+            case TYPE_JPG:
+            case TYPE_GIF:
+            case TYPE_PNG:
+            case TYPE_BMP:
+                type = "1";
+                break;
+            case TYPE_MP3:
+            case TYPE_WAV:
+            case TYPE_M4A:
+                type = "2";
+                break;
+            case TYPE_MP4:
+                type = "3";
+                break;
+            default:
+                break;
+        }
+        return type;
+    }
+
+}

+ 81 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/HttpContext.java

@@ -0,0 +1,81 @@
+package com.dtok.framework.util;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpContext {
+
+
+    /**
+     * 获取请求的ip地址
+     *
+     * @author fengshuonan
+     * @Date 2018/7/23 下午3:44
+     */
+    public static String getIp() {
+        HttpServletRequest request = HttpContext.getRequest();
+        if (request == null) {
+            return "127.0.0.1";
+        } else {
+            return request.getRemoteHost();
+        }
+    }
+
+    /**
+     * 获取当前请求的Request对象
+     *
+     * @author fengshuonan
+     * @Date 2018/7/23 下午3:44
+     */
+    public static HttpServletRequest getRequest() {
+        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (requestAttributes == null) {
+            return null;
+        } else {
+            return requestAttributes.getRequest();
+        }
+    }
+
+    /**
+     * 获取当前请求的Response对象
+     *
+     * @author fengshuonan
+     * @Date 2018/7/23 下午3:44
+     */
+    public static HttpServletResponse getResponse() {
+        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (requestAttributes == null) {
+            return null;
+        } else {
+            return requestAttributes.getResponse();
+        }
+    }
+
+    /**
+     * 获取所有请求的值
+     *
+     * @author fengshuonan
+     * @Date 2018/7/23 下午3:44
+     */
+    public static Map<String, String> getRequestParameters() {
+        HashMap<String, String> values = new HashMap<>();
+        HttpServletRequest request = HttpContext.getRequest();
+        if (request == null) {
+            return values;
+        }
+        Enumeration enums = request.getParameterNames();
+        while (enums.hasMoreElements()) {
+            String paramName = (String) enums.nextElement();
+            String paramValue = request.getParameter(paramName);
+            values.put(paramName, paramValue);
+        }
+        return values;
+    }
+
+}

+ 81 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/IpUtil.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright 2019-2029 geekidea(https://github.com/geekidea)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.dtok.framework.util;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * 获取IP地址工具类
+ * @author geekidea
+ * @date 2018-11-08
+ */
+public final class IpUtil {
+
+    private static final String UNKNOWN = "unknown";
+    private static final String IPV6_LOCAL = "0:0:0:0:0:0:0:1";
+
+    private IpUtil(){
+        throw new AssertionError();
+    }
+
+    /**
+     * 获取请求用户的IP地址
+     * @return
+     */
+    public static String getRequestIp() {
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = attributes.getRequest();
+        return getRequestIp(request);
+    }
+
+    /**
+     * 获取请求用户的IP地址
+     * @param request
+     * @return
+     */
+    public static String getRequestIp(HttpServletRequest request) {
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+
+        if (IPV6_LOCAL.equals(ip)){
+            ip = getLocalhostIp();
+        }
+        return ip;
+    }
+
+    public static String getLocalhostIp(){
+        try {
+            return InetAddress.getLocalHost().getHostAddress();
+        } catch (UnknownHostException e) {
+        }
+        return null;
+    }
+
+}

+ 36 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/MD5Util.java

@@ -0,0 +1,36 @@
+package com.dtok.framework.util;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class MD5Util {
+
+    /**
+     * 将字符串转成MD5值
+     *
+     * @param string 需要转换的字符串
+     * @return 字符串的MD5值
+     */
+    public static String stringToMD5(String string) {
+        byte[] hash;
+
+        try {
+            hash = MessageDigest.getInstance("MD5").digest(string.getBytes(StandardCharsets.UTF_8));
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            return null;
+        }
+
+        StringBuilder hex = new StringBuilder(hash.length * 2);
+        for (byte b : hash) {
+            if ((b & 0xFF) < 0x10)
+                hex.append("0");
+            hex.append(Integer.toHexString(b & 0xFF));
+        }
+
+        return hex.toString();
+    }
+
+}

+ 54 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/PasswordUtil.java

@@ -0,0 +1,54 @@
+package com.dtok.framework.util;
+
+import org.springframework.util.DigestUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
+
+public class PasswordUtil {
+
+    // 固定随机盐
+    public static final String SECRET = "z3g8r3h4bS8DFG0R";
+
+    /**
+     * md5+salt 加密算法 (推荐)
+     *
+     * @author chenlirun
+     * @date 2021/7/8 17:09
+     */
+    public static String getMD5Encryption(String password, String salt) {
+        //密码md5+随机盐加密
+        return DigestUtils.md5DigestAsHex((password + salt).getBytes(StandardCharsets.UTF_8));
+    }
+
+    /**
+     * md5+salt 加密算法
+     *
+     * @author chenlirun
+     * @date 2021/7/9 8:56
+     */
+    public static String getMd5Encryption(String password) {
+        return DigestUtils.md5DigestAsHex((password + SECRET).getBytes(StandardCharsets.UTF_8));
+    }
+
+    /**
+     * 生成随机盐
+     *
+     * @author chenlirun
+     * @date 2021/7/8 15:56
+     */
+    public static String getSalt() {
+        String str = "zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP1234567890,.<>:?";
+        Random random = new Random();
+        StringBuffer stringBuffer = new StringBuffer();
+        //循环16次,共取出16个随机字符
+        for (int i = 0; i < 16; i++) {
+            //每次生成一个67以内的随机数
+            int number = random.nextInt(68);
+            //生成的随机数作为 str 字符串的下标;从 str 中取出随机字符后追加到 stringBuffer
+            stringBuffer.append(str.charAt(number));
+        }
+        return stringBuffer.toString();
+    }
+}
+

+ 54 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/RedisConstants.java

@@ -0,0 +1,54 @@
+package com.dtok.framework.util;
+
+
+public class RedisConstants {
+	
+	public static final String spilt=":";
+
+	/**
+	 * redis库1  保存档案树
+	 */
+	public static final Integer datebase1=1;
+
+	/**
+	 * 1.redis库2 保存档案表格
+	 * 2.保存分页码
+	 */
+	public static final Integer datebase2=2;
+
+	/**
+	 * redis库3 保存档案image url
+	 */
+	public static final Integer datebase3=3;
+
+	/**
+	 * 1.redis库4 保存手机验证码
+	 *
+	 */
+	public static final Integer datebase4=4;
+
+	/**
+	 * redis库5 保存身份认证信息
+	 */
+	public static final Integer datebase5=5;
+
+	/**
+	 * redis库6 记录身份认证次数
+	 */
+	public static final Integer datebase6=6;
+
+	/**
+	 * redis库7 记录重发次数
+	 */
+	public static final Integer datebase7=7;
+
+	/**
+	 * redis库8 记录任务参数
+	 */
+	public static final Integer datebase8=8;
+
+	
+	public RedisConstants() {
+
+	}
+}

+ 2307 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/RedisUtil.java

@@ -0,0 +1,2307 @@
+package com.dtok.framework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.ListPosition;
+import redis.clients.jedis.SortingParams;
+
+@Component
+@Slf4j
+public class RedisUtil{
+
+	@Autowired
+	private JedisPool jedisPool;
+
+	/**
+	 * <p>
+	 * 通过key获取储存在redis中的value
+	 * </p>
+	 * <p>
+	 * 并释放连接
+	 * </p>
+	 *
+	 * @param key
+	 * @param indexdb 选择redis库 0-15
+	 * @return 成功返回value 失败返回null
+	 */
+	public String get(String key,int indexdb) {
+		Jedis jedis = null;
+		String value = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			value = jedis.get(key);
+			log.info(value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return value;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取储存在redis中的value
+	 * </p>
+	 * <p>
+	 * 并释放连接
+	 * </p>
+	 *
+	 * @param key
+	 * @param indexdb 选择redis库 0-15
+	 * @return 成功返回value 失败返回null
+	 */
+	public byte[] get(byte[] key,int indexdb) {
+		Jedis jedis = null;
+		byte[] value = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			value = jedis.get(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return value;
+	}
+	/**
+	 * <p>
+	 * 向redis存入key和value,并释放连接资源
+	 * </p>
+	 * <p>
+	 * 如果key已经存在 则覆盖
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @param indexdb 选择redis库 0-15
+	 * @return 成功 返回OK 失败返回 0
+	 */
+	public String set(String key, String value,int indexdb) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			return jedis.set(key, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return "0";
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+	/**
+	 * <p>
+	 * 向redis存入key和value,并释放连接资源
+	 * </p>
+	 * <p>
+	 * 如果key已经存在 则覆盖
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @param indexdb 选择redis库 0-15
+	 * @return 成功 返回OK 失败返回 0
+	 */
+	public String set(byte[] key, byte[] value,int indexdb) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			return jedis.set(key, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return "0";
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+	/**
+	 * <p>
+	 * 删除指定的key,也可以传入一个包含key的数组
+	 * </p>
+	 *
+	 * @param keys 一个key 也可以使 string 数组
+	 * @return 返回删除成功的个数
+	 */
+	public Long del(String... keys) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.del(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+	/**
+	 * <p>
+	 * 删除指定的key,也可以传入一个包含key的数组
+	 * </p>
+	 * @param indexdb 选择redis库 0-15
+	 * @param keys 一个key 也可以使 string 数组
+	 * @return 返回删除成功的个数
+	 */
+	public Long del(int indexdb,String... keys) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			return jedis.del(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+	/**
+	 * <p>
+	 * 删除指定的key,也可以传入一个包含key的数组
+	 * </p>
+	 * @param indexdb 选择redis库 0-15
+	 * @param keys 一个key 也可以使 string 数组
+	 * @return 返回删除成功的个数
+	 */
+	public Long del(int indexdb,byte[]... keys) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			return jedis.del(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+	/**
+	 * <p>
+	 * 通过key向指定的value值追加值
+	 * </p>
+	 *
+	 * @param key
+	 * @param str
+	 * @return 成功返回 添加后value的长度 失败 返回 添加的 value 的长度 异常返回0L
+	 */
+	public Long append(String key, String str) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.append(key, str);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 判断key是否存在
+	 * </p>
+	 *
+	 * @param key
+	 * @return true OR false
+	 */
+	public Boolean exists(String key) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.exists(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return false;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+
+	/**
+	 * <p>
+	 * 清空当前数据库中的所有 key,此命令从不失败。
+	 * </p>
+	 *
+	 * @return 总是返回 OK
+	 */
+	public String flushDB() {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.flushDB();
+		} catch (Exception e) {
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 *            过期时间,单位:秒
+	 * @return 成功返回1 如果存在 和 发生异常 返回 0
+	 */
+	public Long expire(String key, int value, int indexdb) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			return jedis.expire(key, value);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+
+	/**
+	 * <p>
+	 * 以秒为单位,返回给定 key 的剩余生存时间
+	 * </p>
+	 *
+	 * @param key
+	 * @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key
+	 *         的剩余生存时间。 发生异常 返回 0
+	 */
+	public Long ttl(String key,int indexdb) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			return jedis.ttl(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+
+	/**
+	 * <p>
+	 * 移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )
+	 * </p>
+	 *
+	 * @param key
+	 * @return 当生存时间移除成功时,返回 1 .如果 key 不存在或 key 没有设置生存时间,返回 0 , 发生异常 返回 -1
+	 */
+	public Long persist(String key) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.persist(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return -1L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+
+	/**
+	 * <p>
+	 * 新增key,并将 key 的生存时间 (以秒为单位)
+	 * </p>
+	 *
+	 * @param key
+	 * @param seconds
+	 *            生存时间 单位:秒
+	 * @param value
+	 * @return 设置成功时返回 OK 。当 seconds 参数不合法时,返回一个错误。
+	 */
+	public String setex(String key, int seconds, String value) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.setex(key, seconds, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 设置key value,如果key已经存在则返回0,nx==> not exist
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @return 成功返回1 如果存在 和 发生异常 返回 0
+	 */
+	public Long setnx(String key, String value) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.setnx(key, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+
+	/**
+	 * <p>
+	 * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
+	 * </p>
+	 * <p>
+	 * 当 key 存在但不是字符串类型时,返回一个错误。
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @return 返回给定 key 的旧值。当 key 没有旧值时,也即是, key 不存在时,返回 nil
+	 */
+	public String getSet(String key, String value) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.getSet(key, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 设置key value并制定这个键值的有效期
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @param seconds
+	 *            单位:秒
+	 * @return 成功返回OK 失败和异常返回null
+	 */
+	public String setex(String key, String value, int seconds) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.setex(key, seconds, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key 和offset 从指定的位置开始将原先value替换
+	 * </p>
+	 * <p>
+	 * 下标从0开始,offset表示从offset下标开始替换
+	 * </p>
+	 * <p>
+	 * 如果替换的字符串长度过小则会这样
+	 * </p>
+	 * <p>
+	 * example:
+	 * </p>
+	 * <p>
+	 * value : bigsea@zto.cn
+	 * </p>
+	 * <p>
+	 * str : abc
+	 * </p>
+	 * <P>
+	 * 从下标7开始替换 则结果为
+	 * </p>
+	 * <p>
+	 * RES : bigsea.abc.cn
+	 * </p>
+	 *
+	 * @param key
+	 * @param str
+	 * @param offset
+	 *            下标位置
+	 * @return 返回替换后 value 的长度
+	 */
+	public Long setrange(String key, String str, int offset) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.setrange(key, offset, str);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+	}
+
+	/**
+	 * <p>
+	 * 通过批量的key获取批量的value
+	 * </p>
+	 *
+	 * @param keys
+	 *            string数组 也可以是一个key
+	 * @return 成功返回value的集合, 失败返回null的集合 ,异常返回空
+	 */
+	public List<String> mget(String... keys) {
+		Jedis jedis = null;
+		List<String> values = null;
+		try {
+			jedis = jedisPool.getResource();
+			values = jedis.mget(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return values;
+	}
+
+	/**
+	 * <p>
+	 * 批量的设置key:value,可以一个
+	 * </p>
+	 * <p>
+	 * example:
+	 * </p>
+	 * <p>
+	 * obj.mset(new String[]{"key2","value1","key2","value2"})
+	 * </p>
+	 *
+	 * @param keysvalues
+	 * @return 成功返回OK 失败 异常 返回 null
+	 *
+	 */
+	public String mset(String... keysvalues) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.mset(keysvalues);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 批量的设置key:value,可以一个,如果key已经存在则会失败,操作会回滚
+	 * </p>
+	 * <p>
+	 * example:
+	 * </p>
+	 * <p>
+	 * obj.msetnx(new String[]{"key2","value1","key2","value2"})
+	 * </p>
+	 *
+	 * @param keysvalues
+	 * @return 成功返回1 失败返回0
+	 */
+	public Long msetnx(String... keysvalues) {
+		Jedis jedis = null;
+		Long res = 0L;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.msetnx(keysvalues);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 设置key的值,并返回一个旧值
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @return 旧值 如果key不存在 则返回null
+	 */
+	public String getset(String key, String value) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.getSet(key, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过下标 和key 获取指定下标位置的 value
+	 * </p>
+	 *
+	 * @param key
+	 * @param startOffset
+	 *            开始位置 从0 开始 负数表示从右边开始截取
+	 * @param endOffset
+	 * @return 如果没有返回null
+	 */
+	public String getrange(String key, int startOffset, int endOffset) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.getrange(key, startOffset, endOffset);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key 对value进行加值+1操作,当value不是int类型时会返回错误,当key不存在是则value为1
+	 * </p>
+	 *
+	 * @param key
+	 * @return 加值后的结果
+	 */
+	public Long incr(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.incr(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key给指定的value加值,如果key不存在,则这是value为该值
+	 * </p>
+	 *
+	 * @param key
+	 * @param integer
+	 * @return
+	 */
+	public Long incrBy(String key, Long integer) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.incrBy(key, integer);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 对key的值做减减操作,如果key不存在,则设置key为-1
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long decr(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.decr(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 减去指定的值
+	 * </p>
+	 *
+	 * @param key
+	 * @param integer
+	 * @return
+	 */
+	public Long decrBy(String key, Long integer) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.decrBy(key, integer);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取value值的长度
+	 * </p>
+	 *
+	 * @param key
+	 * @return 失败返回null
+	 */
+	public Long serlen(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.strlen(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key给field设置指定的值,如果key不存在,则先创建
+	 * </p>
+	 *
+	 * @param key
+	 * @param field
+	 *            字段
+	 * @param value
+	 * @return 如果存在返回0 异常返回null
+	 */
+	public Long hset(String key, String field, String value) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hset(key, field, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key给field设置指定的值,如果key不存在则先创建,如果field已经存在,返回0
+	 * </p>
+	 *
+	 * @param key
+	 * @param field
+	 * @param value
+	 * @return
+	 */
+	public Long hsetnx(String key, String field, String value) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hsetnx(key, field, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key同时设置 hash的多个field
+	 * </p>
+	 *
+	 * @param key
+	 * @param hash
+	 * @return 返回OK 异常返回null
+	 */
+	public String hmset(String key, Map<String, String> hash, int indexdb) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.hmset(key, hash);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key 和 field 获取指定的 value
+	 * </p>
+	 *
+	 * @param key
+	 * @param field
+	 * @return 没有返回null
+	 */
+	public String hget(String key, String field) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hget(key, field);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key 和 fields 获取指定的value 如果没有对应的value则返回null
+	 * </p>
+	 *
+	 * @param key
+	 * @param fields
+	 *            可以使 一个String 也可以是 String数组
+	 * @return
+	 */
+	public List<String> hmget(String key, int indexdb, String... fields) {
+		Jedis jedis = null;
+		List<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.hmget(key, fields);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key给指定的field的value加上给定的值
+	 * </p>
+	 *
+	 * @param key
+	 * @param field
+	 * @param value
+	 * @return
+	 */
+	public Long hincrby(String key, String field, Long value) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hincrBy(key, field, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key和field判断是否有指定的value存在
+	 * </p>
+	 *
+	 * @param key
+	 * @param field
+	 * @return
+	 */
+	public Boolean hexists(String key, String field) {
+		Jedis jedis = null;
+		Boolean res = false;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hexists(key, field);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回field的数量
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long hlen(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hlen(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+
+	}
+
+	/**
+	 * <p>
+	 * 通过key 删除指定的 field
+	 * </p>
+	 *
+	 * @param key
+	 * @param fields
+	 *            可以是 一个 field 也可以是 一个数组
+	 * @return
+	 */
+	public Long hdel(String key, String... fields) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hdel(key, fields);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回所有的field
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Set<String> hkeys(String key) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hkeys(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回所有和key有关的value
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public List<String> hvals(String key) {
+		Jedis jedis = null;
+		List<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.hvals(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取所有的field和value
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Map<String, String> hgetall(String key, int indexdb) {
+		Jedis jedis = null;
+		Map<String, String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.hgetAll(key);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key向list头部添加字符串
+	 * </p>
+	 *
+	 * @param key
+	 * @param strs
+	 *            可以使一个string 也可以使string数组
+	 * @return 返回list的value个数
+	 */
+	public Long lpush(int indexdb, String key, String... strs) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.lpush(key, strs);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key向list尾部添加字符串
+	 * </p>
+	 *
+	 * @param key
+	 * @param strs
+	 *            可以使一个string 也可以使string数组
+	 * @return 返回list的value个数
+	 */
+	public Long rpush(String key, String... strs) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.rpush(key, strs);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key在list指定的位置之前或者之后 添加字符串元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param where
+	 *            LIST_POSITION枚举类型
+	 * @param pivot
+	 *            list里面的value
+	 * @param value
+	 *            添加的value
+	 * @return
+	 */
+	public Long linsert(String key, ListPosition where, String pivot,
+						String value) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.linsert(key, where, pivot, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key设置list指定下标位置的value
+	 * </p>
+	 * <p>
+	 * 如果下标超过list里面value的个数则报错
+	 * </p>
+	 *
+	 * @param key
+	 * @param index
+	 *            从0开始
+	 * @param value
+	 * @return 成功返回OK
+	 */
+	public String lset(String key, Long index, String value) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.lset(key, index, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key从对应的list中删除指定的count个 和 value相同的元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param count
+	 *            当count为0时删除全部
+	 * @param value
+	 * @return 返回被删除的个数
+	 */
+	public Long lrem(String key, long count, String value) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.lrem(key, count, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key保留list中从strat下标开始到end下标结束的value值
+	 * </p>
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return 成功返回OK
+	 */
+	public String ltrim(String key, long start, long end) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.ltrim(key, start, end);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key从list的头部删除一个value,并返回该value
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	synchronized public String lpop(String key) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.lpop(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key从list尾部删除一个value,并返回该元素
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	synchronized public String rpop(String key, int indexdb) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.rpop(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key从一个list的尾部删除一个value并添加到另一个list的头部,并返回该value
+	 * </p>
+	 * <p>
+	 * 如果第一个list为空或者不存在则返回null
+	 * </p>
+	 *
+	 * @param srckey
+	 * @param dstkey
+	 * @return
+	 */
+	public String rpoplpush(String srckey, String dstkey, int indexdb) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.rpoplpush(srckey, dstkey);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取list中指定下标位置的value
+	 * </p>
+	 *
+	 * @param key
+	 * @param index
+	 * @return 如果没有返回null
+	 */
+	public String lindex(String key, long index) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.lindex(key, index);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回list的长度
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long llen(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.llen(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取list指定下标位置的value
+	 * </p>
+	 * <p>
+	 * 如果start 为 0 end 为 -1 则返回全部的list中的value
+	 * </p>
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public List<String> lrange(String key, long start, long end, int indexdb) {
+		Jedis jedis = null;
+		List<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(indexdb);
+			res = jedis.lrange(key, start, end);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 将列表 key 下标为 index 的元素的值设置为 value
+	 * </p>
+	 *
+	 * @param key
+	 * @param index
+	 * @param value
+	 * @return 操作成功返回 ok ,否则返回错误信息
+	 */
+	public String lset(String key, long index, String value) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.lset(key, index, value);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 返回给定排序后的结果
+	 * </p>
+	 *
+	 * @param key
+	 * @param sortingParameters
+	 * @return 返回列表形式的排序结果
+	 */
+	public List<String> sort(String key, SortingParams sortingParameters) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.sort(key, sortingParameters);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 返回排序后的结果,排序默认以数字作为对象,值被解释为双精度浮点数,然后进行比较。
+	 * </p>
+	 *
+	 * @param key
+	 * @return 返回列表形式的排序结果
+	 */
+	public List<String> sort(String key) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.sort(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 通过key向指定的set中添加value
+	 * </p>
+	 *
+	 * @param key
+	 * @param members
+	 *            可以是一个String 也可以是一个String数组
+	 * @return 添加成功的个数
+	 */
+	public Long sadd(String key, String... members) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sadd(key, members);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key删除set中对应的value值
+	 * </p>
+	 *
+	 * @param key
+	 * @param members
+	 *            可以是一个String 也可以是一个String数组
+	 * @return 删除的个数
+	 */
+	public Long srem(String key, String... members) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.srem(key, members);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key随机删除一个set中的value并返回该值
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public String spop(String key) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.spop(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取set中的差集
+	 * </p>
+	 * <p>
+	 * 以第一个set为标准
+	 * </p>
+	 *
+	 * @param keys
+	 *            可以使一个string 则返回set中所有的value 也可以是string数组
+	 * @return
+	 */
+	public Set<String> sdiff(String... keys) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sdiff(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取set中的差集并存入到另一个key中
+	 * </p>
+	 * <p>
+	 * 以第一个set为标准
+	 * </p>
+	 *
+	 * @param dstkey
+	 *            差集存入的key
+	 * @param keys
+	 *            可以使一个string 则返回set中所有的value 也可以是string数组
+	 * @return
+	 */
+	public Long sdiffstore(String dstkey, String... keys) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sdiffstore(dstkey, keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取指定set中的交集
+	 * </p>
+	 *
+	 * @param keys
+	 *            可以使一个string 也可以是一个string数组
+	 * @return
+	 */
+	public Set<String> sinter(String... keys) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sinter(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取指定set中的交集 并将结果存入新的set中
+	 * </p>
+	 *
+	 * @param dstkey
+	 * @param keys
+	 *            可以使一个string 也可以是一个string数组
+	 * @return
+	 */
+	public Long sinterstore(String dstkey, String... keys) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sinterstore(dstkey, keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回所有set的并集
+	 * </p>
+	 *
+	 * @param keys
+	 *            可以使一个string 也可以是一个string数组
+	 * @return
+	 */
+	public Set<String> sunion(String... keys) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sunion(keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回所有set的并集,并存入到新的set中
+	 * </p>
+	 *
+	 * @param dstkey
+	 * @param keys
+	 *            可以使一个string 也可以是一个string数组
+	 * @return
+	 */
+	public Long sunionstore(String dstkey, String... keys) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sunionstore(dstkey, keys);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key将set中的value移除并添加到第二个set中
+	 * </p>
+	 *
+	 * @param srckey
+	 *            需要移除的
+	 * @param dstkey
+	 *            添加的
+	 * @param member
+	 *            set中的value
+	 * @return
+	 */
+	public Long smove(String srckey, String dstkey, String member) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.smove(srckey, dstkey, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取set中value的个数
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long scard(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.scard(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key判断value是否是set中的元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param member
+	 * @return
+	 */
+	public Boolean sismember(String key, String member) {
+		Jedis jedis = null;
+		Boolean res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.sismember(key, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取set中随机的value,不删除元素
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public String srandmember(String key) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.srandmember(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取set中所有的value
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Set<String> smembers(String key) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.smembers(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key向zset中添加value,score,其中score就是用来排序的
+	 * </p>
+	 * <p>
+	 * 如果该value已经存在则根据score更新元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param score
+	 * @param member
+	 * @return
+	 */
+	public Long zadd(String key, double score, String member) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zadd(key, score, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 返回有序集 key 中,指定区间内的成员。min=0,max=-1代表所有元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return 指定区间内的有序集成员的列表。
+	 */
+	public Set<String> zrange(String key, long min, long max) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.zrange(key, min, max);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return null;
+	}
+
+	/**
+	 * <p>
+	 * 统计有序集 key 中,值在 min 和 max 之间的成员的数量
+	 * </p>
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return 值在 min 和 max 之间的成员的数量。异常返回0
+	 */
+	public Long zcount(String key, double min, double max) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.zcount(key, min, max);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+
+	}
+
+	/**
+	 * <p>
+	 * 为哈希表 key 中的域 field 的值加上增量 increment 。增量也可以为负数,相当于对给定域进行减法操作。 如果 key
+	 * 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。
+	 * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。本操作的值被限制在 64 位(bit)有符号数字表示之内。
+	 * </p>
+	 * <p>
+	 * 将名称为key的hash中field的value增加integer
+	 * </p>
+	 *
+	 * @param key
+	 * @param value
+	 * @param increment
+	 * @return 执行 HINCRBY 命令之后,哈希表 key 中域 field的值。异常返回0
+	 */
+	public Long hincrBy(String key, String value, long increment) {
+		Jedis jedis = null;
+		try {
+			jedis = jedisPool.getResource();
+			return jedis.hincrBy(key, value, increment);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			return 0L;
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+
+	}
+
+	/**
+	 * <p>
+	 * 通过key删除在zset中指定的value
+	 * </p>
+	 *
+	 * @param key
+	 * @param members
+	 *            可以使一个string 也可以是一个string数组
+	 * @return
+	 */
+	public Long zrem(String key, String... members) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zrem(key, members);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key增加该zset中value的score的值
+	 * </p>
+	 *
+	 * @param key
+	 * @param score
+	 * @param member
+	 * @return
+	 */
+	public Double zincrby(String key, double score, String member) {
+		Jedis jedis = null;
+		Double res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zincrby(key, score, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回zset中value的排名
+	 * </p>
+	 * <p>
+	 * 下标从小到大排序
+	 * </p>
+	 *
+	 * @param key
+	 * @param member
+	 * @return
+	 */
+	public Long zrank(String key, String member) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zrank(key, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回zset中value的排名
+	 * </p>
+	 * <p>
+	 * 下标从大到小排序
+	 * </p>
+	 *
+	 * @param key
+	 * @param member
+	 * @return
+	 */
+	public Long zrevrank(String key, String member) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zrevrank(key, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key将获取score从start到end中zset的value
+	 * </p>
+	 * <p>
+	 * socre从大到小排序
+	 * </p>
+	 * <p>
+	 * 当start为0 end为-1时返回全部
+	 * </p>
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Set<String> zrevrange(String key, long start, long end) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zrevrange(key, start, end);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回指定score内zset中的value
+	 * </p>
+	 *
+	 * @param key
+	 * @param max
+	 * @param min
+	 * @return
+	 */
+	public Set<String> zrangebyscore(String key, String max, String min) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zrevrangeByScore(key, max, min);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回指定score内zset中的value
+	 * </p>
+	 *
+	 * @param key
+	 * @param max
+	 * @param min
+	 * @return
+	 */
+	public Set<String> zrangeByScore(String key, double max, double min) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zrevrangeByScore(key, max, min);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 返回指定区间内zset中value的数量
+	 * </p>
+	 *
+	 * @param key
+	 * @param min
+	 * @param max
+	 * @return
+	 */
+	public Long zcount(String key, String min, String max) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zcount(key, min, max);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key返回zset中的value个数
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public Long zcard(String key) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zcard(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key获取zset中value的score值
+	 * </p>
+	 *
+	 * @param key
+	 * @param member
+	 * @return
+	 */
+	public Double zscore(String key, String member) {
+		Jedis jedis = null;
+		Double res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zscore(key, member);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key删除给定区间内的元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Long zremrangeByRank(String key, long start, long end) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zremrangeByRank(key, start, end);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 通过key删除指定score内的元素
+	 * </p>
+	 *
+	 * @param key
+	 * @param start
+	 * @param end
+	 * @return
+	 */
+	public Long zremrangeByScore(String key, double start, double end) {
+		Jedis jedis = null;
+		Long res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.zremrangeByScore(key, start, end);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * <p>
+	 * 返回满足pattern表达式的所有key
+	 * </p>
+	 * <p>
+	 * keys(*)
+	 * </p>
+	 * <p>
+	 * 返回所有的key
+	 * </p>
+	 *
+	 * @param pattern
+	 * @return
+	 */
+	public Set<String> keys(String pattern) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.keys(pattern);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	public Set<String> keysBySelect(String pattern,int database) {
+		Jedis jedis = null;
+		Set<String> res = null;
+		try {
+			jedis = jedisPool.getResource();
+			jedis.select(database);
+			res = jedis.keys(pattern);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+
+	/**
+	 * <p>
+	 * 通过key判断值得类型
+	 * </p>
+	 *
+	 * @param key
+	 * @return
+	 */
+	public String type(String key) {
+		Jedis jedis = null;
+		String res = null;
+		try {
+			jedis = jedisPool.getResource();
+			res = jedis.type(key);
+		} catch (Exception e) {
+
+			log.error(e.getMessage());
+		} finally {
+			returnResource(jedisPool, jedis);
+		}
+		return res;
+	}
+
+	/**
+	 * 序列化对象
+	 * @param obj
+	 * @return
+	 * 对象需实现Serializable接口
+	 */
+	public static byte[] ObjTOSerialize(Object obj) {
+		ObjectOutputStream oos = null;
+		ByteArrayOutputStream byteOut = null;
+		try {
+			byteOut = new ByteArrayOutputStream();
+			oos = new ObjectOutputStream(byteOut);
+			oos.writeObject(obj);
+			byte[] bytes = byteOut.toByteArray();
+			return bytes;
+		} catch (Exception e) {
+		}
+		return null;
+	}
+
+	/**
+	 * 反序列化对象
+	 * @param bytes
+	 * @return
+	 * 对象需实现Serializable接口
+	 */
+	public static Object unserialize(byte[] bytes) {
+		ByteArrayInputStream bais = null;
+		try {
+			//反序列化
+			bais = new ByteArrayInputStream(bytes);
+			ObjectInputStream ois = new ObjectInputStream(bais);
+			return ois.readObject();
+		} catch (Exception e) {
+		}
+		return null;
+	}
+
+	/**
+	 * 返还到连接池
+	 *
+	 * @param jedisPool
+	 * @param jedis
+	 */
+	public static void returnResource(JedisPool jedisPool, Jedis jedis) {
+		if (jedis != null) {
+			jedisPool.returnResource(jedis);
+		}
+	}
+
+	// public static RedisUtil getRu() {
+	// return ru;
+	// }
+	//
+	// public static void setRu(RedisUtil ru) {
+	// RedisUtil.ru = ru;
+	// }
+
+	public static void main(String[] args) {
+		/*JedisPool jedisPool = new JedisPool(null,"localhost",6379,100,"123456");
+		Jedis jedis = jedisPool.getResource();
+		//r.get("", RedisConstants.datebase4);
+		jedis.select(RedisConstants.datebase4);
+		Set<String> str =  jedis.keys("*");
+		for (String string : str) {
+			System.out.println(string);
+		}*/
+	}
+}

+ 22 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/RenderUtil.java

@@ -0,0 +1,22 @@
+package com.dtok.framework.util;
+
+import com.alibaba.fastjson.JSON;
+import com.dtok.framework.exception.CoreExceptionEnum;
+import com.dtok.framework.exception.ServiceException;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class RenderUtil {
+    public static void renderJson(HttpServletResponse response, Object jsonObject) {
+        try {
+            response.setContentType("application/json");
+            response.setCharacterEncoding("UTF-8");
+            PrintWriter writer = response.getWriter();
+            writer.write(JSON.toJSONString(jsonObject));
+        } catch (IOException e) {
+            throw new ServiceException(CoreExceptionEnum.WRITE_ERROR);
+        }
+    }
+}

+ 43 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/SerializeUtil.java

@@ -0,0 +1,43 @@
+package com.dtok.framework.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * @ClassName: SerializeUtil
+ * @Auther: zhangyingqi
+ * @Date: 2018/10/17 17:54
+ * @Description: 序列化工具
+ */
+public class SerializeUtil {
+
+    public static byte[] serialize(Object object) {
+        ObjectOutputStream oos = null;
+        ByteArrayOutputStream baos = null;
+        try {
+//序列化
+            baos = new ByteArrayOutputStream();
+            oos = new ObjectOutputStream(baos);
+            oos.writeObject(object);
+            byte[] bytes = baos.toByteArray();
+            return bytes;
+        } catch (Exception e) {
+        }
+        return null;
+    }
+
+    public static Object unserialize(byte[] bytes) {
+        ByteArrayInputStream bais = null;
+        try {
+//反序列化
+            bais = new ByteArrayInputStream(bytes);
+            ObjectInputStream ois = new ObjectInputStream(bais);
+            return ois.readObject();
+        } catch (Exception e) {
+        }
+        return null;
+    }
+
+}

+ 9 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/StateParameter.java

@@ -0,0 +1,9 @@
+package com.dtok.framework.util;
+
+public class StateParameter {
+	public final static String SUCCESS="1";
+	public final  static String  FAULT="0";
+	public final static String DATA="data";
+	public final static String STATE="state";
+	
+}

+ 286 - 0
dtok-api/framework/src/main/java/com/dtok/framework/util/ToolUtil.java

@@ -0,0 +1,286 @@
+package com.dtok.framework.util;
+
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.date.DateUtil;
+import com.dtok.framework.exception.CoreExceptionEnum;
+import com.dtok.framework.exception.ServiceException;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.net.*;
+import java.security.MessageDigest;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Random;
+
+public class ToolUtil extends ValidateUtil {
+
+    /**
+     * 默认密码盐长度
+     */
+    public static final int SALT_LENGTH = 6;
+
+    /**
+     * 获取随机字符,自定义长度
+     *
+     * @author fengshuonan
+     * @Date 2018/3/18 21:55
+     */
+    public static String getRandomString(int length) {
+        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
+        Random random = new Random();
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            int number = random.nextInt(base.length());
+            sb.append(base.charAt(number));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * md5加密(加盐)
+     *
+     * @author fengshuonan
+     * @Date 2018/3/18 21:56
+     */
+    public static String md5Hex(String password, String salt) {
+        return md5Hex(password + salt);
+    }
+
+    /**
+     * md5加密(不加盐)
+     *
+     * @author fengshuonan
+     * @Date 2018/3/18 21:56
+     */
+    public static String md5Hex(String str) {
+        try {
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            byte[] bs = md5.digest(str.getBytes());
+            StringBuffer md5StrBuff = new StringBuffer();
+            for (int i = 0; i < bs.length; i++) {
+                if (Integer.toHexString(0xFF & bs[i]).length() == 1)
+                    md5StrBuff.append("0").append(Integer.toHexString(0xFF & bs[i]));
+                else
+                    md5StrBuff.append(Integer.toHexString(0xFF & bs[i]));
+            }
+            return md5StrBuff.toString();
+        } catch (Exception e) {
+            throw new ServiceException(CoreExceptionEnum.ENCRYPT_ERROR);
+        }
+    }
+
+    /**
+     * 过滤掉掉字符串中的空白
+     *
+     * @author fengshuonan
+     * @Date 2018/3/22 15:16
+     */
+    public static String removeWhiteSpace(String value) {
+        if (isEmpty(value)) {
+            return "";
+        } else {
+            return value.replaceAll("\\s*", "");
+        }
+    }
+
+    /**
+     * 获取某个时间间隔以前的时间 时间格式:yyyy-MM-dd HH:mm:ss
+     *
+     * @author stylefeng
+     * @Date 2018/5/8 22:05
+     */
+    public static String getCreateTimeBefore(int seconds) {
+        long currentTimeInMillis = Calendar.getInstance().getTimeInMillis();
+        Date date = new Date(currentTimeInMillis - seconds * 1000);
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return sdf.format(date);
+    }
+
+    /**
+     * 获取异常的具体信息
+     *
+     * @author fengshuonan
+     * @Date 2017/3/30 9:21
+     * @version 2.0
+     */
+    public static String getExceptionMsg(Throwable e) {
+        StringWriter sw = new StringWriter();
+        try {
+            e.printStackTrace(new PrintWriter(sw));
+        } finally {
+            try {
+                sw.close();
+            } catch (IOException e1) {
+                e1.printStackTrace();
+            }
+        }
+        return sw.getBuffer().toString().replaceAll("\\$", "T");
+    }
+
+
+    /**
+     * 获取ip地址
+     *
+     * @author fengshuonan
+     * @Date 2018/5/15 下午6:36
+     */
+    public static String getIP() {
+        try {
+            StringBuilder IFCONFIG = new StringBuilder();
+            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
+                NetworkInterface intf = en.nextElement();
+                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+                    InetAddress inetAddress = enumIpAddr.nextElement();
+                    if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) {
+                        IFCONFIG.append(inetAddress.getHostAddress().toString() + "\n");
+                    }
+
+                }
+            }
+            return IFCONFIG.toString();
+
+        } catch (SocketException ex) {
+            ex.printStackTrace();
+        }
+        try {
+            return InetAddress.getLocalHost().getHostAddress();
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 拷贝属性,为null的不拷贝
+     *
+     * @author fengshuonan
+     * @Date 2018/7/25 下午4:41
+     */
+    public static void copyProperties(Object source, Object target) {
+        BeanUtil.copyProperties(source, target, CopyOptions.create().setIgnoreNullValue(true));
+    }
+
+    /**
+     * 判断是否是windows操作系统
+     *
+     * @author stylefeng
+     * @Date 2017/5/24 22:34
+     */
+    public static Boolean isWinOs() {
+        String os = System.getProperty("os.name");
+        if (os.toLowerCase().startsWith("win")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 获取临时目录
+     *
+     * @author stylefeng
+     * @Date 2017/5/24 22:35
+     */
+    public static String getTempPath() {
+        return System.getProperty("java.io.tmpdir");
+    }
+
+    /**
+     * 把一个数转化为int
+     *
+     * @author fengshuonan
+     * @Date 2017/11/15 下午11:10
+     */
+    public static Integer toInt(Object val) {
+        if (val instanceof Double) {
+            BigDecimal bigDecimal = new BigDecimal((Double) val);
+            return bigDecimal.intValue();
+        } else {
+            return Integer.valueOf(val.toString());
+        }
+
+    }
+
+    /**
+     * 是否为数字
+     *
+     * @author fengshuonan
+     * @Date 2017/11/15 下午11:10
+     */
+    public static boolean isNum(Object obj) {
+        try {
+            Integer.parseInt(obj.toString());
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 获取项目路径
+     *
+     * @author fengshuonan
+     * @Date 2017/11/15 下午11:10
+     */
+    public static String getWebRootPath(String filePath) {
+        try {
+            String path = ToolUtil.class.getClassLoader().getResource("").toURI().getPath();
+            path = path.replace("/WEB-INF/classes/", "");
+            path = path.replace("/target/classes/", "");
+            path = path.replace("file:/", "");
+            if (ToolUtil.isEmpty(filePath)) {
+                return path;
+            } else {
+                return path + "/" + filePath;
+            }
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 获取文件后缀名 不包含点
+     *
+     * @author fengshuonan
+     * @Date 2017/11/15 下午11:10
+     */
+    public static String getFileSuffix(String fileWholeName) {
+        if (ToolUtil.isEmpty(fileWholeName)) {
+            return "none";
+        }
+        int lastIndexOf = fileWholeName.lastIndexOf(".");
+        return fileWholeName.substring(lastIndexOf + 1);
+    }
+
+    /**
+     * 判断一个对象是否是时间类型
+     *
+     * @author stylefeng
+     * @Date 2017/4/18 12:55
+     */
+    public static String dateType(Object o) {
+        if (o instanceof Date) {
+            return DateUtil.formatDate((Date) o);
+        } else {
+            return o.toString();
+        }
+    }
+
+    /**
+     * 当前时间
+     *
+     * @author stylefeng
+     * @Date 2017/5/7 21:56
+     */
+    public static String currentTime() {
+        return DateUtil.formatDateTime(new Date());
+    }
+
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů