1811872455@163.com vor 2 Wochen
Ursprung
Commit
d4db460d0c
100 geänderte Dateien mit 5313 neuen und 247 gelöschten Zeilen
  1. 6 0
      .idea/compiler.xml
  2. 4 0
      .idea/encodings.xml
  3. 1 0
      .idea/misc.xml
  4. 124 0
      .idea/uiDesigner.xml
  5. 2 0
      pom.xml
  6. 4 1
      storlead-centre-api/pom.xml
  7. 4 4
      storlead-centre-api/src/main/java/com/storlead/centre/ChenkqGeneratorCodeConfig.java
  8. 117 0
      storlead-centre-api/src/main/java/com/storlead/centre/app/AppManageApiController.java
  9. 144 0
      storlead-centre-api/src/main/java/com/storlead/centre/util/CryptoZipUtil.java
  10. 59 0
      storlead-centre-api/src/main/java/com/storlead/centre/util/HttpSecurityCheckUtil.java
  11. 197 0
      storlead-centre-api/src/main/resources/application-dev.yml
  12. 160 0
      storlead-centre-api/src/main/resources/application-prod.yml
  13. 172 0
      storlead-centre-api/src/main/resources/application-test.yml
  14. 87 0
      storlead-centre-api/src/main/resources/application.yml
  15. 5 0
      storlead-centre-service/pom.xml
  16. 0 48
      storlead-centre-service/src/main/java/com/storlead/centre/controller/SysAppInfoController.java
  17. 1 1
      storlead-centre-service/src/main/java/com/storlead/centre/mapper/SysAppInfoMapper.java
  18. 1 1
      storlead-centre-service/src/main/java/com/storlead/centre/mapper/xml/SysAppInfoMapper.xml
  19. 14 0
      storlead-centre-service/src/main/java/com/storlead/centre/pojo/dto/SysAppInfoJumpDTO.java
  20. 16 0
      storlead-centre-service/src/main/java/com/storlead/centre/pojo/dto/SysAppInfoQuery.java
  21. 1 1
      storlead-centre-service/src/main/java/com/storlead/centre/pojo/entity/SysAppInfoEntity.java
  22. 1 1
      storlead-centre-service/src/main/java/com/storlead/centre/service/SysAppInfoService.java
  23. 1 1
      storlead-centre-service/src/main/java/com/storlead/centre/service/impl/SysAppInfoServiceImpl.java
  24. 7 7
      storlead-centre-service/src/main/resources/mapper/SysAppInfoMapper.xml
  25. 28 1
      storlead-dependencies/pom.xml
  26. 0 1
      storlead-framework/storlead-auth/pom.xml
  27. 39 0
      storlead-framework/storlead-auth/src/main/java/com/storlead/framework/util/LoginUserUtil.java
  28. 712 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/ecode/BCrypt.java
  29. 159 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/ecode/BCryptPasswordEncoder.java
  30. 19 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/ecode/PasswordEncoder.java
  31. 88 0
      storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/thread/ThreadPoolUtil.java
  32. 0 115
      storlead-framework/storlead-core/src/main/java/com/storlead/framework/core/Page.java
  33. 6 0
      storlead-framework/storlead-redis/pom.xml
  34. 3 2
      storlead-framework/storlead-web/src/main/java/com/storlead/framework/web/assemble/QueryBaseDTO.java
  35. 0 63
      storlead-framework/storlead-web/src/main/java/com/storlead/framework/web/message/PageResp.java
  36. 79 0
      storlead-user/pom.xml
  37. 37 0
      storlead-user/src/main/java/com/storlead/user/constant/JurisdictionConstant.java
  38. 17 0
      storlead-user/src/main/java/com/storlead/user/mapper/CompanyMapper.java
  39. 42 0
      storlead-user/src/main/java/com/storlead/user/mapper/DeptMapper.java
  40. 16 0
      storlead-user/src/main/java/com/storlead/user/mapper/HrmcompanyMapper.java
  41. 16 0
      storlead-user/src/main/java/com/storlead/user/mapper/HrmdepartmentMapper.java
  42. 16 0
      storlead-user/src/main/java/com/storlead/user/mapper/HrmdepartmentdefinedMapper.java
  43. 16 0
      storlead-user/src/main/java/com/storlead/user/mapper/HrmjobtitlesMapper.java
  44. 46 0
      storlead-user/src/main/java/com/storlead/user/mapper/HrmresourceMapper.java
  45. 15 0
      storlead-user/src/main/java/com/storlead/user/mapper/HrmsubcompanyMapper.java
  46. 8 0
      storlead-user/src/main/java/com/storlead/user/mapper/JobMapper.java
  47. 15 0
      storlead-user/src/main/java/com/storlead/user/mapper/SubCompanyMapper.java
  48. 69 0
      storlead-user/src/main/java/com/storlead/user/mapper/UserMapper.java
  49. 91 0
      storlead-user/src/main/java/com/storlead/user/model/DepartIdModel.java
  50. 187 0
      storlead-user/src/main/java/com/storlead/user/model/DeptTreeModel.java
  51. 24 0
      storlead-user/src/main/java/com/storlead/user/model/SysLoginModel.java
  52. 29 0
      storlead-user/src/main/java/com/storlead/user/model/TreeSelectModel.java
  53. 37 0
      storlead-user/src/main/java/com/storlead/user/model/UserBaseInfo.java
  54. 68 0
      storlead-user/src/main/java/com/storlead/user/model/UserInfo.java
  55. 21 0
      storlead-user/src/main/java/com/storlead/user/model/UserQueryModel.java
  56. 15 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/CompanyDTO.java
  57. 48 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/DepartmentParam.java
  58. 16 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/DeptParam.java
  59. 27 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/EmployeeParam.java
  60. 22 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/JobDTO.java
  61. 20 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/MenuParam.java
  62. 34 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/MenuTreeParam.java
  63. 52 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/RoleParam.java
  64. 78 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/SetUserDetailDTO.java
  65. 27 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/UserLoginDTO.java
  66. 33 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/UserLoginParam.java
  67. 64 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/UserParam.java
  68. 35 0
      storlead-user/src/main/java/com/storlead/user/pojo/dto/UserRoleParam.java
  69. 39 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/CompanyEntity.java
  70. 92 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/DeptEntity.java
  71. 45 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmcompany.java
  72. 101 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmdepartment.java
  73. 56 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmdepartmentdefined.java
  74. 79 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmjobtitles.java
  75. 416 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmresource.java
  76. 83 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmsubcompany.java
  77. 38 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/JobEntity.java
  78. 47 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/SubCompanyEntity.java
  79. 137 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/UserEntity.java
  80. 29 0
      storlead-user/src/main/java/com/storlead/user/pojo/entity/UserForm.java
  81. 20 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/ApiDataQuery.java
  82. 35 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/AppServiceVO.java
  83. 22 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/DateInfoVO.java
  84. 141 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/DepartmentTree.java
  85. 26 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/DeptTreeVO.java
  86. 35 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/DeptWxVo.java
  87. 33 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/MenuResTreeVo.java
  88. 52 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/SetUserDetailVo.java
  89. 42 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/UserVo.java
  90. 13 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/WeChatPhone.java
  91. 15 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/WeChatPhoneInfo.java
  92. 39 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/WxExcelOrgVo.java
  93. 21 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/WxUserInfo.java
  94. 22 0
      storlead-user/src/main/java/com/storlead/user/pojo/vo/WxUserVO.java
  95. 21 0
      storlead-user/src/main/java/com/storlead/user/property/UserSystemConfigProperties.java
  96. 9 0
      storlead-user/src/main/java/com/storlead/user/service/ICompanyService.java
  97. 79 0
      storlead-user/src/main/java/com/storlead/user/service/IDepartService.java
  98. 8 0
      storlead-user/src/main/java/com/storlead/user/service/IHrmcompanyService.java
  99. 8 0
      storlead-user/src/main/java/com/storlead/user/service/IHrmdepartmentService.java
  100. 8 0
      storlead-user/src/main/java/com/storlead/user/service/IHrmdepartmentdefinedService.java

+ 6 - 0
.idea/compiler.xml

@@ -13,11 +13,14 @@
         <module name="storlead-redis" />
         <module name="storlead-centre-service" />
         <module name="storlead-web" />
+        <module name="storlead-user" />
+        <module name="storlead-wx" />
         <module name="storlead-mybatis" />
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel>
       <module name="storlead-ai-api" target="17" />
+      <module name="storlead-centre-wx" target="17" />
       <module name="storlead-platform" target="17" />
     </bytecodeTargetLevel>
   </component>
@@ -27,11 +30,14 @@
       <module name="storlead-auth" options="-parameters" />
       <module name="storlead-centre-api" options="-parameters" />
       <module name="storlead-centre-service" options="-parameters" />
+      <module name="storlead-centre-wx" options="-parameters" />
       <module name="storlead-common" options="-parameters" />
       <module name="storlead-core" options="-parameters" />
       <module name="storlead-mybatis" options="-parameters" />
       <module name="storlead-redis" options="-parameters" />
+      <module name="storlead-user" options="-parameters" />
       <module name="storlead-web" options="-parameters" />
+      <module name="storlead-wx" options="-parameters" />
     </option>
   </component>
 </project>

+ 4 - 0
.idea/encodings.xml

@@ -6,6 +6,7 @@
     <file url="file://$PROJECT_DIR$/storlead-centre-api/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-centre-api/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-centre-service/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-centre-wx/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-dependencies/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-dependencies/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-framework/src/main/java" charset="UTF-8" />
@@ -18,5 +19,8 @@
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-redis/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-redis/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/storlead-framework/storlead-web/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-user/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-wx/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/storlead-wx/src/main/resources" charset="UTF-8" />
   </component>
 </project>

+ 1 - 0
.idea/misc.xml

@@ -7,6 +7,7 @@
         <option value="$PROJECT_DIR$/storlead-dependencies/pom.xml" />
         <option value="$PROJECT_DIR$/storlead-framework/pom.xml" />
         <option value="$PROJECT_DIR$/pom.xml" />
+        <option value="$PROJECT_DIR$/storlead-wx/pom.xml" />
       </list>
     </option>
   </component>

+ 124 - 0
.idea/uiDesigner.xml

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

+ 2 - 0
pom.xml

@@ -21,6 +21,8 @@
         <module>storlead-framework</module>
         <module>storlead-centre-api</module>
         <module>storlead-centre-service</module>
+        <module>storlead-wx</module>
+        <module>storlead-user</module>
     </modules>
 
     <properties>

+ 4 - 1
storlead-centre-api/pom.xml

@@ -34,7 +34,10 @@
             <artifactId>storlead-common</artifactId>
         </dependency>
 
-
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-centre-service</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>com.alibaba</groupId>

+ 4 - 4
storlead-centre-api/src/main/java/com/storlead/centre/ChenkqGeneratorCodeConfig.java

@@ -128,15 +128,15 @@ public class ChenkqGeneratorCodeConfig {
         strategy.setColumnNaming(NamingStrategy.underline_to_camel);
 
         // 公共父类
-        strategy.setSuperEntityClass("com.storlead.frame.mybatis.entity.SysBaseField");
+        strategy.setSuperEntityClass("com.storlead.frameworkmybatis.entity.SysBaseField");
         // 写于父类中的公共字段
         strategy.setSuperEntityColumns("create_by","update_by","create_time","update_time","is_delete","enabled","owner_by","sort");
         strategy.setControllerMappingHyphenStyle(true);
         strategy.setEntityTableFieldAnnotationEnable(true);
 
-        strategy.setSuperMapperClass("com.storlead.frame.mybatis.mapper.MyBaseMapper");
-        strategy.setSuperServiceClass("com.storlead.frame.mybatis.service.MyBaseService");
-        strategy.setSuperServiceImplClass("com.storlead.frame.mybatis.service.impl.MyBaseServiceImpl");
+        strategy.setSuperMapperClass("com.storlead.frameworkmybatis.mapper.MyBaseMapper");
+        strategy.setSuperServiceClass("com.storlead.frameworkmybatis.service.MyBaseService");
+        strategy.setSuperServiceImplClass("com.storlead.frameworkmybatis.service.impl.MyBaseServiceImpl");
         strategy.setEntityLombokModel(true);
         // 公共父类
 //        strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");

+ 117 - 0
storlead-centre-api/src/main/java/com/storlead/centre/app/AppManageApiController.java

@@ -0,0 +1,117 @@
+package com.storlead.centre.app;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.storlead.centre.pojo.dto.SysAppInfoQuery;
+import com.storlead.centre.pojo.entity.SysAppInfoEntity;
+import com.storlead.centre.service.SysAppInfoService;
+import com.storlead.centre.util.CryptoZipUtil;
+import com.storlead.centre.util.HttpSecurityCheckUtil;
+import com.storlead.framework.common.util.MD5Util;
+import com.storlead.framework.util.LoginUserUtil;
+import com.storlead.framework.web.assemble.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @program: storlead-centre-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-11-21 12:06
+ */
+@RestController
+@RequestMapping("/app/manage")
+@Api(tags = "1.应用管理")
+public class AppManageApiController {
+
+    @Resource
+    private SysAppInfoService sysAppInfoService;
+
+    private static final String SALT_KEY = "G4YfTqX6Kh8cHQy5";
+
+    @PostMapping(value = "/save")
+    @ApiOperation(value = "应用管理--新增/编辑", notes = "应用管理-新增/编辑")
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<?> save(@RequestBody SysAppInfoEntity info) {
+        sysAppInfoService.save(info);
+        return Result.ok();
+    }
+
+    @PostMapping(value = "/pagelist")
+    @ApiOperation(value = "应用管理-分页查询", notes = "应用管理-分页查询")
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<?> pagelist(@RequestBody SysAppInfoQuery query) {
+
+        IPage<SysAppInfoEntity> page = new Page<>(query.getPageIndex(),query.getPageSize());
+        IPage<SysAppInfoEntity> infos = sysAppInfoService.page(page);
+        return Result.result(infos);
+    }
+
+    @ApiOperation("启用禁用部门")
+    @PostMapping("enable")
+    public Result setEnable(Long id,Boolean enable) {
+        if (enable) {
+            sysAppInfoService.enable(id);
+        } else {
+            sysAppInfoService.disable(id);
+        }
+        return Result.ok();
+    }
+
+    @PostMapping(value = "/jumpToApp")
+    @ApiOperation(value = "应用管理-分页查询", notes = "应用管理-分页查询")
+    @Transactional(rollbackFor = Throwable.class)
+    public Result<?> jumpToApp(Long appId) {
+        SysAppInfoEntity info = sysAppInfoService.getById(appId);
+
+        LoginUserUtil.getLoginUser();
+        Map<String,String> argMap = new HashMap<>();
+        Long dt = System.currentTimeMillis() / 1000 % HttpSecurityCheckUtil.divisor;
+        argMap.put("dt",dt.toString());
+        argMap.put("redirect",info.getRedirectUri());
+        argMap.put("appSecret",info.getAppSecret());
+        argMap.put("token","ouunwqlkeklnkljm23jk3nywwqk");
+        argMap.put("account","ouunwqlkeklnkljm23jk3nywwqk");
+        String sign = MD5Util.MD5Encode(HttpSecurityCheckUtil.makeSign(argMap),"UTF-8");
+
+        argMap.put("sign",sign);
+        String urlParam =  HttpSecurityCheckUtil.buildUrlParams(argMap);
+        String requestUrl = info.getHomepageUrl()+"?"+urlParam;
+        return Result.result(requestUrl);
+    }
+
+    public static void main(String[] args) {
+
+        Map<String,String> argMap = new HashMap<>();
+        Long dt = System.currentTimeMillis() / 1000 % HttpSecurityCheckUtil.divisor;
+        argMap.put("dt",dt.toString());
+        argMap.put("redirect","/home");
+        argMap.put("appSecret","ddddddd");
+        argMap.put("account","18118724055");
+        argMap.put("token","ouunwqlkeklnkljm23jk3nywwqk");
+        String sign = MD5Util.MD5Encode(HttpSecurityCheckUtil.makeSign(argMap),"UTF-8").toLowerCase();
+        argMap.put("sign",sign);
+        String urlParam =  HttpSecurityCheckUtil.buildUrlParams(argMap);
+        String requestUrl = "http://127.0.0.1:8080/ssoredirect?ticket="+urlParam;
+
+        System.out.println("urlParam = "+urlParam);
+        System.out.println("requestUrl = "+requestUrl);
+        String encrypted = CryptoZipUtil.encryptParams(argMap,SALT_KEY);
+        System.out.println("加密后的 URL 参数:" + encrypted);
+        System.out.println("加密后的 URL  http://127.0.0.1:8080/ssoredirect?ticket="+encrypted);
+
+        Map<String, String> map = CryptoZipUtil.decryptParams(encrypted, SALT_KEY);
+
+        System.out.println("解密后的 参数:" + map);
+
+    }
+}

+ 144 - 0
storlead-centre-api/src/main/java/com/storlead/centre/util/CryptoZipUtil.java

@@ -0,0 +1,144 @@
+package com.storlead.centre.util;
+
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.zip.GZIPOutputStream;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * @program: storlead-centre-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-11-21 16:03
+ */
+public class CryptoZipUtil {
+
+    private static final String AES_CIPHER = "AES/CBC/PKCS5Padding";
+    private static final String IV = "1234567890abcdef"; // 16字节固定 IV
+
+
+
+    // ====================================
+    // Map → URL 参数 → GZIP → AES → Base64
+    // ====================================
+    public static String encryptParams(Map<String, String> params, String key) {
+        StringBuilder sb = new StringBuilder();
+        params.forEach((k, v) -> {
+            try {
+                sb.append(URLEncoder.encode(k, "UTF-8"))
+                        .append("=")
+                        .append(URLEncoder.encode(v, "UTF-8"))
+                        .append("&");
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        String paramString = sb.substring(0, sb.length() - 1);
+
+        // 1. GZIP 压缩
+        byte[] gzipData = gzip(paramString.getBytes(StandardCharsets.UTF_8));
+
+        // 2. AES 加密
+        byte[] encryptedBytes = aesEncrypt(gzipData, key);
+
+        // 3. Base64 URL 安全编码
+        return Base64.getUrlEncoder().encodeToString(encryptedBytes);
+    }
+
+    // ====================================
+    // Base64 → AES 解密 → GZIP 解压 → Map
+    // ====================================
+    public static Map<String, String> decryptParams(String encrypted, String key) {
+        try {
+            byte[] encryptedBytes = Base64.getUrlDecoder().decode(encrypted);
+
+            // 1. AES 解密
+            byte[] gzipBytes = aesDecrypt(encryptedBytes, key);
+
+            // 2. GZIP 解压
+            String decrypted = new String(gunzip(gzipBytes), StandardCharsets.UTF_8);
+
+            // 3. URL 参数解析
+            Map<String, String> map = new HashMap<>();
+            for (String pair : decrypted.split("&")) {
+                String[] kv = pair.split("=");
+                if (kv.length == 2) {
+                    map.put(
+                            URLDecoder.decode(kv[0], "UTF-8"),
+                            URLDecoder.decode(kv[1], "UTF-8")
+                    );
+                }
+            }
+            return map;
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // GZIP 压缩
+    private static byte[] gzip(byte[] data) {
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            try (GZIPOutputStream gzip = new GZIPOutputStream(bos)) {
+                gzip.write(data);
+            }
+            return bos.toByteArray();
+        } catch (Exception e) {
+            throw new RuntimeException("GZIP 压缩失败", e);
+        }
+    }
+
+    // GZIP 解压
+    private static byte[] gunzip(byte[] data) {
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            GZIPInputStream gis = new GZIPInputStream(new java.io.ByteArrayInputStream(data));
+            byte[] buffer = new byte[1024];
+            int len;
+            while ((len = gis.read(buffer)) > 0) {
+                bos.write(buffer, 0, len);
+            }
+            return bos.toByteArray();
+        } catch (Exception e) {
+            throw new RuntimeException("GZIP 解压失败", e);
+        }
+    }
+
+    // AES 加密
+    private static byte[] aesEncrypt(byte[] content, String key) {
+        try {
+            Cipher cipher = Cipher.getInstance(AES_CIPHER);
+            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
+            IvParameterSpec iv = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8));
+            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+            return cipher.doFinal(content);
+        } catch (Exception e) {
+            throw new RuntimeException("AES 加密失败", e);
+        }
+    }
+
+    // AES 解密
+    private static byte[] aesDecrypt(byte[] encrypted, String key) {
+        try {
+            Cipher cipher = Cipher.getInstance(AES_CIPHER);
+            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
+            IvParameterSpec iv = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8));
+            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
+            return cipher.doFinal(encrypted);
+        } catch (Exception e) {
+            throw new RuntimeException("AES 解密失败", e);
+        }
+    }
+}
+

+ 59 - 0
storlead-centre-api/src/main/java/com/storlead/centre/util/HttpSecurityCheckUtil.java

@@ -0,0 +1,59 @@
+package com.storlead.centre.util;
+
+import com.storlead.framework.common.util.encryptor.AccessKeyEncryptor;
+import lombok.Data;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @program: storlead-centre-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-11-21 15:01
+ */
+public class HttpSecurityCheckUtil {
+
+    private static final String SALT_KEY = "G4YfTqX6Kh8cHQy5";
+    /**
+     * 除数
+     */
+    public static long divisor = 100861;
+
+    public static String makeSign(Map<String, String> sginArgMap) {
+        List<Map.Entry<String, String>> entryList = new ArrayList<>(sginArgMap.entrySet());
+        entryList.sort(Map.Entry.comparingByKey());
+        /**
+         * 构建字符串
+         */
+        StringBuilder sb = new StringBuilder();
+        for (Map.Entry<String, String> entry : entryList) {
+            sb.append(entry.getKey()).append("=").append(entry.getValue());
+        }
+        String dataToEncrypt = sb.toString();
+        String sign = AccessKeyEncryptor.getAccessKeyEncryptor(SALT_KEY).encrypt(dataToEncrypt);
+        return  sign;
+    }
+
+    public static String buildUrlParams(Map<String, String> paramMap) {
+        if (paramMap == null || paramMap.isEmpty()) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+            if (entry.getValue() == null) continue; // 忽略 null
+            if (sb.length() > 0) sb.append("&");
+
+            sb.append(entry.getKey())
+                    .append("=")
+                    .append(entry.getValue());
+        }
+
+        return sb.toString();
+    }
+}

+ 197 - 0
storlead-centre-api/src/main/resources/application-dev.yml

@@ -0,0 +1,197 @@
+server:
+  port: 18090
+  tomcat:
+    max-swallow-size: -1
+    max-upload-size: 200MB
+    basedir: /app/centre/temp
+
+
+  compression:
+    enabled: true
+    min-response-size: 1024
+    mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
+
+management:
+  endpoints:
+    web:
+      exposure:
+        include: metrics,httptrace
+
+spring:
+  servlet:
+    multipart:
+      max-file-size: 200MB
+      max-request-size: 200MB
+  ## quartz定时任务,采用数据库方式
+  #  quartz:
+  #    job-store-type: jdbc
+  #json 时间戳统一转换
+  jackson:
+    date-format:   yyyy-MM-dd HH:mm:ss
+    time-zone:   GMT+8
+  aop:
+    proxy-target-class: true
+  #配置freemarker
+  freemarker:
+    # 设置模板后缀名
+    suffix: .ftl
+    # 设置文档类型
+    content-type: text/html
+    # 设置页面编码格式
+    charset: UTF-8
+    # 设置页面缓存
+    cache: false
+    prefer-file-system-access: false
+    # 设置ftl文件路径
+    template-loader-path:
+      - classpath:/templates
+  # 设置静态文件路径,js,css等  #redis 配置
+#  cloud:
+#    nacos:
+#      discovery:
+#        server-addr: http://192.168.1.93:8848
+#        group: DEV
+#        namespace: 1b26d8af-529f-4118-9519-47b6a4aaaa4e
+#        username: nacos
+#        password: nacos
+
+  redis:
+    host: test1.storlead.com
+    port: 59394
+    database: 8
+    lettuce:
+      pool:
+        max-wait: 100000
+        max-idle: 10
+        max-active: 100
+    timeout: 5000
+    password: bnoCWkyDqYA*ecT7FoL7
+
+  mvc:
+    static-path-pattern: /**
+  resource:
+    static-locations: classpath:/static/,classpath:/public/
+  autoconfigure:
+    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+  datasource:
+    dynamic:
+      druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
+        # 连接池的配置信息
+        # 初始化大小,最小,最大
+        initial-size: 5
+        min-idle: 5
+        maxActive: 20
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        # 打开PSCache,并且指定每个连接上PSCache的大小
+        poolPreparedStatements: true
+        maxPoolPreparedStatementPerConnectionSize: 20
+        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+        filters: stat,wall,slf4j
+        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
+        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
+      datasource:
+        master:
+#          driver-class-name: com.mysql.jdbc.Driver
+#          url: jdbc:mysql://192.168.1.69:3306/sp_sales_dev?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
+#          username: storlead
+#          password: DW8YRN*5!6u&Agt7N
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://mysql.test.storlead.com:39091/sp_unified_service_test?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
+          username: root
+          password: rCgRgLjH99Xvg5BN
+
+#          driver-class-name: com.mysql.jdbc.Driver
+#          url: jdbc:mysql://139.159.206.64:65369/sp_sales_system_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&rewriteBatchedStatements=true
+#          username: sp_sales_prod
+#          password: MsKLJue01MLIYnd2*0ReMQ
+        management:
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://mysql.test.storlead.com:39091/storlead_test?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&noDatetimeStringSync=true&serverTimezone=Asia/Shanghai
+          username: root
+          password: rCgRgLjH99Xvg5BN
+
+#          driver-class-name: com.mysql.jdbc.Driver
+#          url: jdbc:mysql://139.159.206.64:65369/storlead_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&rewriteBatchedStatements=true
+#          username: storlead_platform
+#          password: QkfgG7Cw6E&*PlvYYw==oBfjSf2zw
+        oa:
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://139.159.206.64:65369/storlead_ecology_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
+          username: storlead_ecology
+          password: 3raNoDvbo7jqbwtedQGQ
+#mybatis plus 设置
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*/*Mapper.xml
+  # 实体扫描,多个 package 用逗号或者分号分隔
+  type-aliases-package: com.storlead.sales.modules.*.pojo.entity
+  typeEnumsPackage: com.storlead.sales.modules.console.enums;com.storlead.sales.modules.perform.enums
+#  configuration:
+  #配置显示查询SQL
+  #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+#    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
+  global-config:
+    # 关闭MP3.0自带的banner
+    banner: false
+    db-config:
+      #主键类型  0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";
+      id-type: 4
+      # 默认数据库表下划线命名
+      table-underline: true
+    #configuration:
+    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
+    #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+message:
+  task:
+    enable : false
+  send:
+    enable : true
+storlead:
+  project:
+    baseUrl: http://127.0.0.1:8101/sp-project
+
+#Mybatis输出sql日志
+logging:
+  file:
+    # 日志存放目录
+    path: /app/sp/${spring.application.name}/log
+  level:
+    root: info
+    io:
+      swagger:
+        models:
+          parameters:
+            AbstractSerializableParameter: error
+    c:
+      a:
+        icatch:
+          provider:
+            imp:
+              AssemblerImp: debug
+    o:
+      s:
+        h:
+          c:
+            j:
+              Jackson2ObjectMapperBuilder: off # 禁止okhttp4 打印警告日志 For Jackson Kotlin classes support please add "com.fasterxml.jackson.module:jackson-module-kotlin" to the classpath
+    com:
+      storlead: debug
+
+
+# 企业微信
+#corp-wechat:
+#  corpId: ww5323bd8ab4394132
+#  # 这个是通讯录secret只能用来调用通讯录相关API使用
+#  corpAddressSecret: FE-ofiE08oeT8DsccbigqPFWl6Nk8LRKBFffpL76Z-M
+#  corpAgentId: 1000024
+#  corpAgentSecret: T2N9RAs0ATGrgUEedAovo80a1Z4wpepO9eKn-_5qsBo
+

+ 160 - 0
storlead-centre-api/src/main/resources/application-prod.yml

@@ -0,0 +1,160 @@
+#开发模式
+debug: false
+server:
+  port: 18094
+  tomcat:
+    max-swallow-size: -1
+    max-upload-size: 200MB
+    basedir: /mnt/vdb/storlead/sales/temp
+  compression:
+    enabled: true
+    min-response-size: 1024
+    mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
+
+management:
+  endpoints:
+    web:
+      exposure:
+        include: metrics,httptrace
+
+spring:
+  servlet:
+    multipart:
+      max-file-size: 200MB
+      max-request-size: 200MB
+  ## quartz定时任务,采用数据库方式
+  #  quartz:
+  #    job-store-type: jdbc
+  #json 时间戳统一转换
+  jackson:
+    date-format:   yyyy-MM-dd HH:mm:ss
+    time-zone:   GMT+8
+  aop:
+    proxy-target-class: true
+  #配置freemarker
+  freemarker:
+    # 设置模板后缀名
+    suffix: .ftl
+    # 设置文档类型
+    content-type: text/html
+    # 设置页面编码格式
+    charset: UTF-8
+    # 设置页面缓存
+    cache: false
+    prefer-file-system-access: false
+    # 设置ftl文件路径
+    template-loader-path:
+      - classpath:/templates
+  # 设置静态文件路径,js,css等  #redis 配置
+  redis:
+    database: 14
+    host: 192.168.0.210
+    lettuce:
+      pool:
+        max-active: 8   #最大连接数据库连接数,设 0 为没有限制
+        max-idle: 8     #最大等待连接中的数量,设 0 为没有限制
+        max-wait: -1ms  #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
+        min-idle: 0     #最小等待连接中的数量,设 0 为没有限制
+      shutdown-timeout: 100ms
+    password: 'B3f@NT4y%etekQaDkufd'
+    port: 56379
+  mvc:
+    static-path-pattern: /**
+  resource:
+    static-locations: classpath:/static/,classpath:/public/
+  autoconfigure:
+    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+  datasource:
+    dynamic:
+      druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
+        # 连接池的配置信息
+        # 初始化大小,最小,最大
+        initial-size: 5
+        min-idle: 5
+        maxActive: 20
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        # 打开PSCache,并且指定每个连接上PSCache的大小
+        poolPreparedStatements: true
+        maxPoolPreparedStatementPerConnectionSize: 20
+        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+        filters: stat,wall,slf4j
+        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
+        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
+      datasource:
+        master:
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://storlead.internal.cn-south-1.mysql.rds.myhuaweicloud.com:65369/sp_unified_service_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&rewriteBatchedStatements=true
+          username: sp_sales_prod
+          password: MsKLJue01MLIYnd2*0ReMQ
+        oa:
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://storlead.internal.cn-south-1.mysql.rds.myhuaweicloud.com:65369/storlead_ecology_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
+          username: storlead_ecology
+          password: 3raNoDvbo7jqbwtedQGQ
+#mybatis plus 设置
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*/*Mapper.xml
+  # 实体扫描,多个 package 用逗号或者分号分隔
+#  type-aliases-package: com.storlead.sales.modules.*.entity
+#  type-enums-package: com.storlead.sales.modules.console.enums;com.storlead.sales.modules.perform.enums;com.storlead.sales.modules.project.enums
+    #  configuration:
+  #配置显示查询SQL
+  #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  #    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
+  global-config:
+    # 关闭MP3.0自带的banner
+    banner: false
+    db-config:
+      #主键类型  0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";
+      id-type: 4
+      # 默认数据库表下划线命名
+      table-underline: true
+    #configuration:
+    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
+    #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+#Mybatis输出sql日志
+logging:
+  file:
+    # 日志存放目录
+    path: /mnt/vdb/storlead/sales/log/
+  level:
+    root: info
+    io:
+      swagger:
+        models:
+          parameters:
+            AbstractSerializableParameter: error
+    c:
+      a:
+        icatch:
+          provider:
+            imp:
+              AssemblerImp: debug
+    o:
+      s:
+        h:
+          c:
+            j:
+              Jackson2ObjectMapperBuilder: off # 禁止okhttp4 打印警告日志 For Jackson Kotlin classes support please add "com.fasterxml.jackson.module:jackson-module-kotlin" to the classpath
+    com:
+      storlead: error
+
+
+# 企业微信
+corp-wechat:
+  corpId: ww5323bd8ab4394132
+  # 这个是通讯录secret只能用来调用通讯录相关API使用
+  corpAddressSecret: FE-ofiE08oeT8DsccbigqPFWl6Nk8LRKBFffpL76Z-M
+  corpAgentId: 1000025
+  corpAgentSecret: MqG2_t0HB4L2KN6MsOVdpL48XFB26VkUyTsKHT0T6y0
+

+ 172 - 0
storlead-centre-api/src/main/resources/application-test.yml

@@ -0,0 +1,172 @@
+server:
+  port: 18090
+  tomcat:
+    max-swallow-size: -1
+    max-upload-size: 200MB
+    basedir: /mnt/vdb/storlead/sales/temp/${spring.profiles.active}
+  servlet:
+    context-path: /sales
+  compression:
+    enabled: true
+    min-response-size: 1024
+    mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
+
+management:
+  endpoints:
+    web:
+      exposure:
+        include: metrics,httptrace
+
+spring:
+  servlet:
+    multipart:
+      max-file-size: 200MB
+      max-request-size: 200MB
+  ## quartz定时任务,采用数据库方式
+  #  quartz:
+  #    job-store-type: jdbc
+  #json 时间戳统一转换
+  jackson:
+    date-format:   yyyy-MM-dd HH:mm:ss
+    time-zone:   GMT+8
+  aop:
+    proxy-target-class: true
+  #配置freemarker
+  freemarker:
+    # 设置模板后缀名
+    suffix: .ftl
+    # 设置文档类型
+    content-type: text/html
+    # 设置页面编码格式
+    charset: UTF-8
+    # 设置页面缓存
+    cache: false
+    prefer-file-system-access: false
+    # 设置ftl文件路径
+    template-loader-path:
+      - classpath:/templates
+  # 设置静态文件路径,js,css等  #redis 配置
+#  cloud:
+#    nacos:
+#      config:
+#        name: sp-project-management
+#        username: nacos
+#        password: nacos
+#      discovery:
+#        server-addr: http://172.18.194.168:8848
+#        group: TEST
+#        namespace: 76d9e9c9-e012-4845-a0a6-c6ba7818b727
+#        username: nacos
+#        password: nacos
+#        ip: 172.18.194.168
+
+  redis:
+    host: test1.storlead.com
+    port: 59394
+    database: 15
+    lettuce:
+      pool:
+        max-wait: 100000
+        max-idle: 10
+        max-active: 100
+    timeout: 5000
+    password: bnoCWkyDqYA*ecT7FoL7
+
+  mvc:
+    static-path-pattern: /**
+  resource:
+    static-locations: classpath:/static/,classpath:/public/
+  autoconfigure:
+    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+  datasource:
+    dynamic:
+      druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
+        # 连接池的配置信息
+        # 初始化大小,最小,最大
+        initial-size: 5
+        min-idle: 5
+        maxActive: 20
+        # 配置获取连接等待超时的时间
+        maxWait: 60000
+        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        timeBetweenEvictionRunsMillis: 60000
+        # 配置一个连接在池中最小生存的时间,单位是毫秒
+        minEvictableIdleTimeMillis: 300000
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        # 打开PSCache,并且指定每个连接上PSCache的大小
+        poolPreparedStatements: true
+        maxPoolPreparedStatementPerConnectionSize: 20
+        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
+        filters: stat,wall,slf4j
+        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
+        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
+      datasource:
+        master:
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://mysql.test.storlead.com:39091/sp_unified_service_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
+          username: root
+          password: rCgRgLjH99Xvg5BN
+        oa:
+          driver-class-name: com.mysql.jdbc.Driver
+          url: jdbc:mysql://139.159.206.64:65369/storlead_ecology_prod?useSSL=false&useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
+          username: storlead_ecology
+          password: 3raNoDvbo7jqbwtedQGQ
+#mybatis plus 设置
+mybatis-plus:
+  mapper-locations: classpath:/mapper/*/*Mapper.xml
+  # 实体扫描,多个 package 用逗号或者分号分隔
+  type-aliases-package: com.storlead.sales.modules.*.entity
+  type-enums-package: com.storlead.sales.enums
+    #  configuration:
+  #配置显示查询SQL
+  #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  #    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
+  global-config:
+    # 关闭MP3.0自带的banner
+    banner: false
+    db-config:
+      #主键类型  0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";
+      id-type: 4
+      # 默认数据库表下划线命名
+      table-underline: true
+    #configuration:
+    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
+    #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
+#Mybatis输出sql日志
+logging:
+  file:
+    # 日志存放目录
+    path: /mnt/vdb/storlead/sales/log/${spring.profiles.active}/
+  level:
+    root: info
+    io:
+      swagger:
+        models:
+          parameters:
+            AbstractSerializableParameter: error
+    c:
+      a:
+        icatch:
+          provider:
+            imp:
+              AssemblerImp: INFO
+    o:
+      s:
+        h:
+          c:
+            j:
+              Jackson2ObjectMapperBuilder: off # 禁止okhttp4 打印警告日志 For Jackson Kotlin classes support please add "com.fasterxml.jackson.module:jackson-module-kotlin" to the classpath
+    com:
+      storlead: INFO
+
+# 企业微信
+corp-wechat:
+  corpId: ww5323bd8ab4394132
+  # 这个是通讯录secret只能用来调用通讯录相关API使用
+  corpAddressSecret: FE-ofiE08oeT8DsccbigqPFWl6Nk8LRKBFffpL76Z-M
+  corpAgentId: 1000024
+  corpAgentSecret: T2N9RAs0ATGrgUEedAovo80a1Z4wpepO9eKn-_5qsBo

+ 87 - 0
storlead-centre-api/src/main/resources/application.yml

@@ -0,0 +1,87 @@
+spring:
+  profiles:
+    active: dev
+  servlet:
+    context-path: /api
+    multipart:
+      max-file-size: 50MB
+      max-request-size: 200MB
+  tomcat:
+    max-upload-size: 200MB
+
+  mvc:
+    pathmatch:
+      matching-strategy: ant_path_matcher
+
+  application:
+    name: sp-sales
+  main:
+    allow-circular-references: true
+    allow-bean-definition-overriding: true
+  # 定时任务
+#  quartz:
+#    jdbc:
+#      initialize-schema: never
+#    job-store-type: jdbc
+#    properties:
+#      org:
+#        quartz:
+#          dataSource:
+#            myDS: # 设置数据源名称
+#              driver: com.mysql.jdbc.Driver
+#              URL: jdbc:mysql://192.168.1.93:39091/sp_sales_dev?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&noDatetimeStringSync=true&serverTimezone=Asia/Shanghai
+#              username: root
+#              password: DW8YRN*5!6u&Agt7N
+#          scheduler:
+#            instanceId: AUTO
+#            instanceName: quartzScheduler
+#          jobStore:
+#            useProperties: true
+#            isClustered: true
+#            maxMisfiresToHandleAtATime: 1
+#            tablePrefix: qrtz_
+#            dataSource: myDS
+##            class: org.quartz.impl.jdbcjobstore.LocalDataSourceJobStore
+#            class: org.quartz.impl.jdbcjobstore.JobStoreTX
+#            clusterCheckinInterval: 3600000
+#            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
+#          threadPool:
+#            threadCount: 10
+#            threadPriority: 5
+#            threadsInheritContextClassLoaderOfInitializingThread: true
+#            class: org.quartz.simpl.SimpleThreadPool
+  # 在上下文中没有Executor bean的情况下,Spring Boot会自动配置ThreadPoolTaskExecutor,并使用合理的默认值,这些默认值可以自动关联到异步任务执行(@EnableAsync)和Spring MVC异步请求处理。
+  #如果您已经在上下文中定义了一个自定义执行器,那么常规任务执行(即@EnableAsync)将透明地使用它,但是Spring MVC支持将不会被配置,因为它需要一个AsyncTaskExecutor实现(名为applicationTaskExecutor)。根据您的目标安排,您可以将执行程序更改为ThreadPoolTaskExecutor,或者定义一个ThreadPoolTaskExecutor和一个包装自定义执行程序的AsyncConfigurer。
+  task:
+    execution:
+      pool:
+        core-size: 10
+        max-size: 100
+        queue-capacity: 50
+
+swagger:
+  production: false
+  basic:
+    enable: false
+    username: lingcun
+    password: l123@.com
+
+fdfs:
+  so-timeout: 1501
+  connect-timeout:  601
+  thumb-image: # 缩略图
+      width: 60
+      height: 60
+  tracker-list: 113.106.164.42:22122
+
+weixin:
+  appid: wxe441c4feba0ca8dd
+  secret: 06f454271578d3ed1db2f970e5ef47fd
+
+gpt:
+  gptLength: 16000
+
+xh:
+  xhLength: 8000
+
+

+ 5 - 0
storlead-centre-service/pom.xml

@@ -24,6 +24,11 @@
             <artifactId>storlead-common</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-wx</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.storlead.boot</groupId>
             <artifactId>storlead-mybatis</artifactId>

+ 0 - 48
storlead-centre-service/src/main/java/com/storlead/centre/controller/SysAppInfoController.java

@@ -1,48 +0,0 @@
-package com.storlead.centre.controller;
-
-
-import com.storlead.centre.entity.SysAppInfoEntity;
-import com.storlead.centre.service.SysAppInfoService;
-import com.storlead.framework.web.assemble.Result;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-
-/**
- * <p>
- * 应用信息表 前端控制器
- * </p>
- *
- * @author chenkq
- * @since 2025-11-18
- */
-@RestController
-@RequestMapping("/sys/app/")
-public class SysAppInfoController {
-
-    @Resource
-    private SysAppInfoService sysAppInfoService;
-
-    @ResponseBody
-    @RequestMapping("save")
-    public Result save(SysAppInfoEntity info){
-        sysAppInfoService.save(info);
-        return Result.ok();
-    }
-
-    @ApiOperation("启用禁用部门")
-    @PostMapping("enable")
-    public Result setEnable(Long id,Boolean enable) {
-        if (enable) {
-            sysAppInfoService.enable(id);
-        } else {
-            sysAppInfoService.disable(id);
-        }
-        return Result.ok();
-    }
-}

+ 1 - 1
storlead-centre-service/src/main/java/com/storlead/centre/mapper/SysAppInfoMapper.java

@@ -1,6 +1,6 @@
 package com.storlead.centre.mapper;
 
-import com.storlead.centre.entity.SysAppInfoEntity;
+import com.storlead.centre.pojo.entity.SysAppInfoEntity;
 import com.storlead.framework.mybatis.mapper.MyBaseMapper;
 
 /**

+ 1 - 1
storlead-centre-service/src/main/java/com/storlead/centre/mapper/xml/SysAppInfoMapper.xml

@@ -3,7 +3,7 @@
 <mapper namespace="com.storlead.centre.mapper.SysAppInfoMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.storlead.centre.entity.SysAppInfoEntity">
+    <resultMap id="BaseResultMap" type="com.storlead.centre.pojo.entity.SysAppInfoEntity">
         <id column="id" property="id" />
     <result column="sort" property="sort" />
     <result column="enabled" property="enabled" />

+ 14 - 0
storlead-centre-service/src/main/java/com/storlead/centre/pojo/dto/SysAppInfoJumpDTO.java

@@ -0,0 +1,14 @@
+package com.storlead.centre.pojo.dto;
+
+import lombok.Data;
+
+/**
+ * @program: storlead-centre-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-11-21 14:30
+ */
+@Data
+public class SysAppInfoJumpDTO {
+    private  String appId;
+}

+ 16 - 0
storlead-centre-service/src/main/java/com/storlead/centre/pojo/dto/SysAppInfoQuery.java

@@ -0,0 +1,16 @@
+package com.storlead.centre.pojo.dto;
+
+import com.storlead.framework.mybatis.entity.Page;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @program: storlead-centre-platform
+ * @description:
+ * @author: chenkq
+ * @create: 2025-11-21 14:16
+ */
+@Data
+public class SysAppInfoQuery extends Page {
+}

+ 1 - 1
storlead-centre-service/src/main/java/com/storlead/centre/entity/SysAppInfoEntity.java → storlead-centre-service/src/main/java/com/storlead/centre/pojo/entity/SysAppInfoEntity.java

@@ -1,4 +1,4 @@
-package com.storlead.centre.entity;
+package com.storlead.centre.pojo.entity;
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.IdType;

+ 1 - 1
storlead-centre-service/src/main/java/com/storlead/centre/service/SysAppInfoService.java

@@ -1,6 +1,6 @@
 package com.storlead.centre.service;
 
-import com.storlead.centre.entity.SysAppInfoEntity;
+import com.storlead.centre.pojo.entity.SysAppInfoEntity;
 import com.storlead.framework.mybatis.service.MyBaseService;
 
 /**

+ 1 - 1
storlead-centre-service/src/main/java/com/storlead/centre/service/impl/SysAppInfoServiceImpl.java

@@ -1,8 +1,8 @@
 package com.storlead.centre.service.impl;
 
-import com.storlead.centre.entity.SysAppInfoEntity;
 import com.storlead.centre.mapper.SysAppInfoMapper;
 import com.storlead.centre.service.SysAppInfoService;
+import com.storlead.centre.pojo.entity.SysAppInfoEntity;
 import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
 import org.springframework.stereotype.Service;
 

+ 7 - 7
storlead-centre-service/src/main/resources/mapper/SysAppInfoMapper.xml

@@ -3,14 +3,14 @@
 <mapper namespace="com.storlead.centre.mapper.SysAppInfoMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.storlead.centre.entity.SysAppInfoEntity">
+    <resultMap id="BaseResultMap" type="com.storlead.centre.pojo.entity.SysAppInfoEntity">
         <id column="id" property="id" />
-    <result column="sort" property="sort" />
-    <result column="enabled" property="enabled" />
-    <result column="create_by" property="createBy" />
-    <result column="create_time" property="createTime" />
-    <result column="update_by" property="updateBy" />
-    <result column="update_time" property="updateTime" />
+        <result column="sort" property="sort" />
+        <result column="enabled" property="enabled" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="update_time" property="updateTime" />
         <result column="app_name" property="appName" />
         <result column="app_code" property="appCode" />
         <result column="app_secret" property="appSecret" />

+ 28 - 1
storlead-dependencies/pom.xml

@@ -36,7 +36,9 @@
         <swagger.version>3.0.0</swagger.version>
         <swagger.annotations.version>1.5.22</swagger.annotations.version>
         <spring.web.socket.version>1.5.3</spring.web.socket.version>
-
+        <!--  redis -->
+        <redisson.version>3.6.5</redisson.version>
+        <httpclient.version>4.5.3</httpclient.version>
         <!-- DB 相关 -->
         <druid.version>1.1.24</druid.version>
         <mybatis.version>3.5.17</mybatis.version>
@@ -112,6 +114,18 @@
                 <version>${revision}</version>
             </dependency>
 
+            <dependency>
+                <groupId>com.storlead.boot</groupId>
+                <artifactId>storlead-wx</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.storlead.boot</groupId>
+                <artifactId>storlead-centre-service</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
 <!--            &lt;!&ndash;swagger&ndash;&gt;-->
             <dependency>
                 <groupId>io.springfox</groupId>
@@ -163,12 +177,25 @@
                 <version>${hutool.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.redisson</groupId>
+                <artifactId>redisson</artifactId>
+                <version>${redisson.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-dependencies</artifactId>
                 <version>${spring.boot.version}</version>
             </dependency>
 
+            <!--HttpClient-->
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpclient</artifactId>
+                <version>${httpclient.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>com.github.xiaoymin</groupId>
                 <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>

+ 0 - 1
storlead-framework/storlead-auth/pom.xml

@@ -13,7 +13,6 @@
     <packaging>jar</packaging>
     <name>${project.artifactId}</name>
 
-
     <dependencies>
         <dependency>
             <groupId>com.storlead.boot</groupId>

+ 39 - 0
storlead-framework/storlead-auth/src/main/java/com/storlead/framework/util/LoginUserUtil.java

@@ -0,0 +1,39 @@
+package com.storlead.framework.util;
+
+import com.storlead.framework.auth.vo.LoginUser;
+import com.storlead.framework.common.constant.UserCacheKeyConstants;
+import com.storlead.framework.core.context.Context;
+import lombok.extern.log4j.Log4j2;
+
+/**
+ * @author chenkq
+ */
+@Log4j2
+public class LoginUserUtil {
+    /**
+     * 获取当前用户信息
+     * @return
+     */
+    public static LoginUser getLoginUser(){
+        try {
+            LoginUser loginUser = Context.getContext().getAttribute(UserCacheKeyConstants.LOGIN_USER_INFO_KEY, LoginUser.class);
+            return loginUser;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+    /**
+     * 获取当前用户信息
+     * @return
+     */
+    public static Long getCurrentUserId(){
+        try {
+            Long currentUserId = Context.getContext().getAttribute(UserCacheKeyConstants.LOGIN_USER_INFO_ID_KEY, Long.class);
+            return currentUserId;
+        } catch (Exception e) {
+            log.error("error - getCurrentUserId",e);
+            return null;
+        }
+    }
+
+}

+ 712 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/ecode/BCrypt.java

@@ -0,0 +1,712 @@
+package com.storlead.framework.common.ecode;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2021-10-25 18:54
+ */
+public class BCrypt {
+
+    // BCrypt parameters
+    private static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;
+
+    private static final int BCRYPT_SALT_LEN = 16;
+
+    // Blowfish parameters
+    private static final int BLOWFISH_NUM_ROUNDS = 16;
+
+    // Initial contents of key schedule
+    private static final int P_orig[] = { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+            0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
+            0xb5470917, 0x9216d5d9, 0x8979fb1b };
+
+    private static final int S_orig[] = { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
+            0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3,
+            0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+            0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1,
+            0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
+            0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16,
+            0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+            0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81,
+            0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
+            0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050,
+            0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+            0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724,
+            0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
+            0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb,
+            0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+            0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe,
+            0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
+            0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6,
+            0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+            0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada,
+            0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
+            0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191,
+            0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+            0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065,
+            0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
+            0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2,
+            0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+            0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521,
+            0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, 0x4b7a70e9, 0xb5b32944,
+            0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c,
+            0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+            0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f,
+            0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c,
+            0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58,
+            0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+            0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38,
+            0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,
+            0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc,
+            0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+            0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1,
+            0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1,
+            0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978,
+            0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+            0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef,
+            0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170,
+            0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b,
+            0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+            0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a,
+            0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263,
+            0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61,
+            0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+            0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2,
+            0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d,
+            0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1,
+            0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+            0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3,
+            0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,
+            0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e,
+            0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+            0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3,
+            0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900,
+            0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399,
+            0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+            0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a,
+            0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9,
+            0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f,
+            0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+            0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0,
+            0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd,
+            0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab,
+            0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+            0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88,
+            0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b,
+            0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8,
+            0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+            0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33,
+            0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,
+            0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79,
+            0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+            0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d,
+            0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa,
+            0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa,
+            0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+            0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578,
+            0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4,
+            0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 0xabc27737,
+            0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+            0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee,
+            0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+            0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550,
+            0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+            0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a,
+            0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+            0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44,
+            0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+            0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711,
+            0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+            0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd,
+            0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+            0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463,
+            0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+            0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b,
+            0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+            0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a,
+            0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+            0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065,
+            0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+            0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54,
+            0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
+            0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b,
+            0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+            0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c,
+            0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+            0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3,
+            0x3ac372e6 };
+
+    // bcrypt IV: "OrpheanBeholderScryDoubt"
+    static private final int bf_crypt_ciphertext[] = { 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944,
+            0x6f756274 };
+
+    // Table for Base64 encoding
+    static private final char base64_code[] = { '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
+            '2', '3', '4', '5', '6', '7', '8', '9' };
+
+    // Table for Base64 decoding
+    static private final byte index_64[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            0, 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+            12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32,
+            33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1 };
+    static final int MIN_LOG_ROUNDS = 4;
+    static final int MAX_LOG_ROUNDS = 31;
+
+    // Expanded Blowfish key
+    private int P[];
+
+    private int S[];
+
+    /**
+     * Encode a byte array using bcrypt's slightly-modified base64 encoding scheme. Note
+     * that this is <strong>not</strong> compatible with the standard MIME-base64
+     * encoding.
+     * @param d the byte array to encode
+     * @param len the number of bytes to encode
+     * @param rs the destination buffer for the base64-encoded string
+     * @exception IllegalArgumentException if the length is invalid
+     */
+    static void encode_base64(byte d[], int len, StringBuilder rs) throws IllegalArgumentException {
+        int off = 0;
+        int c1, c2;
+
+        if (len <= 0 || len > d.length) {
+            throw new IllegalArgumentException("Invalid len");
+        }
+
+        while (off < len) {
+            c1 = d[off++] & 0xff;
+            rs.append(base64_code[(c1 >> 2) & 0x3f]);
+            c1 = (c1 & 0x03) << 4;
+            if (off >= len) {
+                rs.append(base64_code[c1 & 0x3f]);
+                break;
+            }
+            c2 = d[off++] & 0xff;
+            c1 |= (c2 >> 4) & 0x0f;
+            rs.append(base64_code[c1 & 0x3f]);
+            c1 = (c2 & 0x0f) << 2;
+            if (off >= len) {
+                rs.append(base64_code[c1 & 0x3f]);
+                break;
+            }
+            c2 = d[off++] & 0xff;
+            c1 |= (c2 >> 6) & 0x03;
+            rs.append(base64_code[c1 & 0x3f]);
+            rs.append(base64_code[c2 & 0x3f]);
+        }
+    }
+
+    /**
+     * Look up the 3 bits base64-encoded by the specified character, range-checking againt
+     * conversion table
+     * @param x the base64-encoded value
+     * @return the decoded value of x
+     */
+    private static byte char64(char x) {
+        if (x < 0 || x >= index_64.length) {
+            return -1;
+        }
+        return index_64[x];
+    }
+
+    /**
+     * Decode a string encoded using bcrypt's base64 scheme to a byte array. Note that
+     * this is *not* compatible with the standard MIME-base64 encoding.
+     * @param s the string to decode
+     * @param maxolen the maximum number of bytes to decode
+     * @return an array containing the decoded bytes
+     * @throws IllegalArgumentException if maxolen is invalid
+     */
+    static byte[] decode_base64(String s, int maxolen) throws IllegalArgumentException {
+        StringBuilder rs = new StringBuilder();
+        int off = 0, slen = s.length(), olen = 0;
+        byte ret[];
+        byte c1, c2, c3, c4, o;
+
+        if (maxolen <= 0) {
+            throw new IllegalArgumentException("Invalid maxolen");
+        }
+
+        while (off < slen - 1 && olen < maxolen) {
+            c1 = char64(s.charAt(off++));
+            c2 = char64(s.charAt(off++));
+            if (c1 == -1 || c2 == -1) {
+                break;
+            }
+            o = (byte) (c1 << 2);
+            o |= (c2 & 0x30) >> 4;
+            rs.append((char) o);
+            if (++olen >= maxolen || off >= slen) {
+                break;
+            }
+            c3 = char64(s.charAt(off++));
+            if (c3 == -1) {
+                break;
+            }
+            o = (byte) ((c2 & 0x0f) << 4);
+            o |= (c3 & 0x3c) >> 2;
+            rs.append((char) o);
+            if (++olen >= maxolen || off >= slen) {
+                break;
+            }
+            c4 = char64(s.charAt(off++));
+            o = (byte) ((c3 & 0x03) << 6);
+            o |= c4;
+            rs.append((char) o);
+            ++olen;
+        }
+
+        ret = new byte[olen];
+        for (off = 0; off < olen; off++) {
+            ret[off] = (byte) rs.charAt(off);
+        }
+        return ret;
+    }
+
+    /**
+     * Blowfish encipher a single 64-bit block encoded as two 32-bit halves
+     * @param lr an array containing the two 32-bit half blocks
+     * @param off the position in the array of the blocks
+     */
+    private void encipher(int lr[], int off) {
+        int i, n, l = lr[off], r = lr[off + 1];
+
+        l ^= this.P[0];
+        for (i = 0; i <= BLOWFISH_NUM_ROUNDS - 2;) {
+            // Feistel substitution on left word
+            n = this.S[(l >> 24) & 0xff];
+            n += this.S[0x100 | ((l >> 16) & 0xff)];
+            n ^= this.S[0x200 | ((l >> 8) & 0xff)];
+            n += this.S[0x300 | (l & 0xff)];
+            r ^= n ^ this.P[++i];
+
+            // Feistel substitution on right word
+            n = this.S[(r >> 24) & 0xff];
+            n += this.S[0x100 | ((r >> 16) & 0xff)];
+            n ^= this.S[0x200 | ((r >> 8) & 0xff)];
+            n += this.S[0x300 | (r & 0xff)];
+            l ^= n ^ this.P[++i];
+        }
+        lr[off] = r ^ this.P[BLOWFISH_NUM_ROUNDS + 1];
+        lr[off + 1] = l;
+    }
+
+    /**
+     * Cycically extract a word of key material
+     * @param data the string to extract the data from
+     * @param offp a "pointer" (as a one-entry array) to the current offset into data
+     * @param signp a "pointer" (as a one-entry array) to the cumulative flag for
+     * non-benign sign extension
+     * @return correct and buggy next word of material from data as int[2]
+     */
+    private static int[] streamtowords(byte data[], int offp[], int signp[]) {
+        int i;
+        int words[] = { 0, 0 };
+        int off = offp[0];
+        int sign = signp[0];
+
+        for (i = 0; i < 4; i++) {
+            words[0] = (words[0] << 8) | (data[off] & 0xff);
+            words[1] = (words[1] << 8) | data[off]; // sign extension bug
+            if (i > 0) {
+                sign |= words[1] & 0x80;
+            }
+            off = (off + 1) % data.length;
+        }
+
+        offp[0] = off;
+        signp[0] = sign;
+        return words;
+    }
+
+    /**
+     * Cycically extract a word of key material
+     * @param data the string to extract the data from
+     * @param offp a "pointer" (as a one-entry array) to the current offset into data
+     * @return the next word of material from data
+     */
+    private static int streamtoword(byte data[], int offp[]) {
+        int signp[] = { 0 };
+        return streamtowords(data, offp, signp)[0];
+    }
+
+    /**
+     * Cycically extract a word of key material, with sign-extension bug
+     * @param data the string to extract the data from
+     * @param offp a "pointer" (as a one-entry array) to the current offset into data
+     * @return the next word of material from data
+     */
+    private static int streamtoword_bug(byte data[], int offp[]) {
+        int signp[] = { 0 };
+        return streamtowords(data, offp, signp)[1];
+    }
+
+    /**
+     * Initialise the Blowfish key schedule
+     */
+    private void init_key() {
+        this.P = P_orig.clone();
+        this.S = S_orig.clone();
+    }
+
+    /**
+     * Key the Blowfish cipher
+     * @param key an array containing the key
+     * @param sign_ext_bug true to implement the 2x bug
+     * @param safety bit 16 is set when the safety measure is requested
+     */
+    private void key(byte key[], boolean sign_ext_bug, int safety) {
+        int i;
+        int koffp[] = { 0 };
+        int lr[] = { 0, 0 };
+        int plen = this.P.length, slen = this.S.length;
+
+        for (i = 0; i < plen; i++) {
+            if (!sign_ext_bug) {
+                this.P[i] = this.P[i] ^ streamtoword(key, koffp);
+            }
+            else {
+                this.P[i] = this.P[i] ^ streamtoword_bug(key, koffp);
+            }
+        }
+
+        for (i = 0; i < plen; i += 2) {
+            encipher(lr, 0);
+            this.P[i] = lr[0];
+            this.P[i + 1] = lr[1];
+        }
+
+        for (i = 0; i < slen; i += 2) {
+            encipher(lr, 0);
+            this.S[i] = lr[0];
+            this.S[i + 1] = lr[1];
+        }
+    }
+
+    /**
+     * Perform the "enhanced key schedule" step described by Provos and Mazieres in "A
+     * Future-Adaptable Password Scheme" https://www.openbsd.org/papers/bcrypt-paper.ps
+     * @param data salt information
+     * @param key password information
+     * @param sign_ext_bug true to implement the 2x bug
+     * @param safety bit 16 is set when the safety measure is requested
+     */
+    private void ekskey(byte data[], byte key[], boolean sign_ext_bug, int safety) {
+        int i;
+        int koffp[] = { 0 }, doffp[] = { 0 };
+        int lr[] = { 0, 0 };
+        int plen = this.P.length, slen = this.S.length;
+        int signp[] = { 0 }; // non-benign sign-extension flag
+        int diff = 0; // zero iff correct and buggy are same
+
+        for (i = 0; i < plen; i++) {
+            int words[] = streamtowords(key, koffp, signp);
+            diff |= words[0] ^ words[1];
+            this.P[i] = this.P[i] ^ words[sign_ext_bug ? 1 : 0];
+        }
+
+        int sign = signp[0];
+
+        /*
+         * At this point, "diff" is zero iff the correct and buggy algorithms produced
+         * exactly the same result. If so and if "sign" is non-zero, which indicates that
+         * there was a non-benign sign extension, this means that we have a collision
+         * between the correctly computed hash for this password and a set of passwords
+         * that could be supplied to the buggy algorithm. Our safety measure is meant to
+         * protect from such many-buggy to one-correct collisions, by deviating from the
+         * correct algorithm in such cases. Let's check for this.
+         */
+        diff |= diff >> 16; /* still zero iff exact match */
+        diff &= 0xffff; /* ditto */
+        diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
+        sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
+        sign &= ~diff & safety; /* action needed? */
+
+        /*
+         * If we have determined that we need to deviate from the correct algorithm, flip
+         * bit 16 in initial expanded key. (The choice of 16 is arbitrary, but let's stick
+         * to it now. It came out of the approach we used above, and it's not any worse
+         * than any other choice we could make.)
+         *
+         * It is crucial that we don't do the same to the expanded key used in the main
+         * Eksblowfish loop. By doing it to only one of these two, we deviate from a state
+         * that could be directly specified by a password to the buggy algorithm (and to
+         * the fully correct one as well, but that's a side-effect).
+         */
+        this.P[0] ^= sign;
+
+        for (i = 0; i < plen; i += 2) {
+            lr[0] ^= streamtoword(data, doffp);
+            lr[1] ^= streamtoword(data, doffp);
+            encipher(lr, 0);
+            this.P[i] = lr[0];
+            this.P[i + 1] = lr[1];
+        }
+
+        for (i = 0; i < slen; i += 2) {
+            lr[0] ^= streamtoword(data, doffp);
+            lr[1] ^= streamtoword(data, doffp);
+            encipher(lr, 0);
+            this.S[i] = lr[0];
+            this.S[i + 1] = lr[1];
+        }
+    }
+
+    static long roundsForLogRounds(int log_rounds) {
+        if (log_rounds < 4 || log_rounds > 31) {
+            throw new IllegalArgumentException("Bad number of rounds");
+        }
+        return 1L << log_rounds;
+    }
+
+    /**
+     * Perform the central password hashing step in the bcrypt scheme
+     * @param password the password to hash
+     * @param salt the binary salt to hash with the password
+     * @param log_rounds the binary logarithm of the number of rounds of hashing to apply
+     * @param sign_ext_bug true to implement the 2x bug
+     * @param safety bit 16 is set when the safety measure is requested
+     * @return an array containing the binary hashed password
+     */
+    private byte[] crypt_raw(byte password[], byte salt[], int log_rounds, boolean sign_ext_bug, int safety) {
+        int rounds, i, j;
+        int cdata[] = bf_crypt_ciphertext.clone();
+        int clen = cdata.length;
+        byte ret[];
+
+        if (log_rounds < 4 || log_rounds > 31) {
+            throw new IllegalArgumentException("Bad number of rounds");
+        }
+        rounds = 1 << log_rounds;
+        if (salt.length != BCRYPT_SALT_LEN) {
+            throw new IllegalArgumentException("Bad salt length");
+        }
+
+        init_key();
+        ekskey(salt, password, sign_ext_bug, safety);
+        for (i = 0; i < rounds; i++) {
+            key(password, sign_ext_bug, safety);
+            key(salt, false, safety);
+        }
+
+        for (i = 0; i < 64; i++) {
+            for (j = 0; j < (clen >> 1); j++) {
+                encipher(cdata, j << 1);
+            }
+        }
+
+        ret = new byte[clen * 4];
+        for (i = 0, j = 0; i < clen; i++) {
+            ret[j++] = (byte) ((cdata[i] >> 24) & 0xff);
+            ret[j++] = (byte) ((cdata[i] >> 16) & 0xff);
+            ret[j++] = (byte) ((cdata[i] >> 8) & 0xff);
+            ret[j++] = (byte) (cdata[i] & 0xff);
+        }
+        return ret;
+    }
+
+    /**
+     * Hash a password using the OpenBSD bcrypt scheme
+     * @param password the password to hash
+     * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt)
+     * @return the hashed password
+     */
+    public static String hashpw(String password, String salt) {
+        byte passwordb[];
+
+        passwordb = password.getBytes(StandardCharsets.UTF_8);
+
+        return hashpw(passwordb, salt);
+    }
+
+    /**
+     * Hash a password using the OpenBSD bcrypt scheme
+     * @param passwordb the password to hash, as a byte array
+     * @param salt the salt to hash with (perhaps generated using BCrypt.gensalt)
+     * @return the hashed password
+     */
+    public static String hashpw(byte passwordb[], String salt) {
+        BCrypt B;
+        String real_salt;
+        byte saltb[], hashed[];
+        char minor = (char) 0;
+        int rounds, off;
+        StringBuilder rs = new StringBuilder();
+
+        if (salt == null) {
+            throw new IllegalArgumentException("salt cannot be null");
+        }
+
+        int saltLength = salt.length();
+
+        if (saltLength < 28) {
+            throw new IllegalArgumentException("Invalid salt");
+        }
+
+        if (salt.charAt(0) != '$' || salt.charAt(1) != '2') {
+            throw new IllegalArgumentException("Invalid salt version");
+        }
+        if (salt.charAt(2) == '$') {
+            off = 3;
+        }
+        else {
+            minor = salt.charAt(2);
+            if ((minor != 'a' && minor != 'x' && minor != 'y' && minor != 'b') || salt.charAt(3) != '$') {
+                throw new IllegalArgumentException("Invalid salt revision");
+            }
+            off = 4;
+        }
+
+        // Extract number of rounds
+        if (salt.charAt(off + 2) > '$') {
+            throw new IllegalArgumentException("Missing salt rounds");
+        }
+
+        if (off == 4 && saltLength < 29) {
+            throw new IllegalArgumentException("Invalid salt");
+        }
+        rounds = Integer.parseInt(salt.substring(off, off + 2));
+
+        real_salt = salt.substring(off + 3, off + 25);
+        saltb = decode_base64(real_salt, BCRYPT_SALT_LEN);
+
+        if (minor >= 'a') {
+            passwordb = Arrays.copyOf(passwordb, passwordb.length + 1);
+        }
+
+        B = new BCrypt();
+        hashed = B.crypt_raw(passwordb, saltb, rounds, minor == 'x', minor == 'a' ? 0x10000 : 0);
+
+        rs.append("$2");
+        if (minor >= 'a') {
+            rs.append(minor);
+        }
+        rs.append("$");
+        if (rounds < 10) {
+            rs.append("0");
+        }
+        rs.append(rounds);
+        rs.append("$");
+        encode_base64(saltb, saltb.length, rs);
+        encode_base64(hashed, bf_crypt_ciphertext.length * 4 - 1, rs);
+        return rs.toString();
+    }
+
+    /**
+     * Generate a salt for use with the BCrypt.hashpw() method
+     * @param prefix the prefix value (default $2a)
+     * @param log_rounds the log2 of the number of rounds of hashing to apply - the work
+     * factor therefore increases as 2**log_rounds.
+     * @param random an instance of SecureRandom to use
+     * @return an encoded salt value
+     * @exception IllegalArgumentException if prefix or log_rounds is invalid
+     */
+    public static String gensalt(String prefix, int log_rounds, SecureRandom random) throws IllegalArgumentException {
+        StringBuilder rs = new StringBuilder();
+        byte rnd[] = new byte[BCRYPT_SALT_LEN];
+
+        if (!prefix.startsWith("$2")
+                || (prefix.charAt(2) != 'a' && prefix.charAt(2) != 'y' && prefix.charAt(2) != 'b')) {
+            throw new IllegalArgumentException("Invalid prefix");
+        }
+        if (log_rounds < 4 || log_rounds > 31) {
+            throw new IllegalArgumentException("Invalid log_rounds");
+        }
+
+        random.nextBytes(rnd);
+
+        rs.append("$2");
+        rs.append(prefix.charAt(2));
+        rs.append("$");
+        if (log_rounds < 10) {
+            rs.append("0");
+        }
+        rs.append(log_rounds);
+        rs.append("$");
+        encode_base64(rnd, rnd.length, rs);
+        return rs.toString();
+    }
+
+    /**
+     * Generate a salt for use with the BCrypt.hashpw() method
+     * @param prefix the prefix value (default $2a)
+     * @param log_rounds the log2 of the number of rounds of hashing to apply - the work
+     * factor therefore increases as 2**log_rounds.
+     * @return an encoded salt value
+     * @exception IllegalArgumentException if prefix or log_rounds is invalid
+     */
+    public static String gensalt(String prefix, int log_rounds) throws IllegalArgumentException {
+        return gensalt(prefix, log_rounds, new SecureRandom());
+    }
+
+    /**
+     * Generate a salt for use with the BCrypt.hashpw() method
+     * @param log_rounds the log2 of the number of rounds of hashing to apply - the work
+     * factor therefore increases as 2**log_rounds.
+     * @param random an instance of SecureRandom to use
+     * @return an encoded salt value
+     * @exception IllegalArgumentException if log_rounds is invalid
+     */
+    public static String gensalt(int log_rounds, SecureRandom random) throws IllegalArgumentException {
+        return gensalt("$2a", log_rounds, random);
+    }
+
+    /**
+     * Generate a salt for use with the BCrypt.hashpw() method
+     * @param log_rounds the log2 of the number of rounds of hashing to apply - the work
+     * factor therefore increases as 2**log_rounds.
+     * @return an encoded salt value
+     * @exception IllegalArgumentException if log_rounds is invalid
+     */
+    public static String gensalt(int log_rounds) throws IllegalArgumentException {
+        return gensalt(log_rounds, new SecureRandom());
+    }
+
+    public static String gensalt(String prefix) {
+        return gensalt(prefix, GENSALT_DEFAULT_LOG2_ROUNDS);
+    }
+
+    /**
+     * Generate a salt for use with the BCrypt.hashpw() method, selecting a reasonable
+     * default for the number of hashing rounds to apply
+     * @return an encoded salt value
+     */
+    public static String gensalt() {
+        return gensalt(GENSALT_DEFAULT_LOG2_ROUNDS);
+    }
+
+    /**
+     * Check that a plaintext password matches a previously hashed one
+     * @param plaintext the plaintext password to verify
+     * @param hashed the previously-hashed password
+     * @return true if the passwords match, false otherwise
+     */
+    public static boolean checkpw(String plaintext, String hashed) {
+        return equalsNoEarlyReturn(hashed, hashpw(plaintext, hashed));
+    }
+
+    /**
+     * Check that a password (as a byte array) matches a previously hashed one
+     * @param passwordb the password to verify, as a byte array
+     * @param hashed the previously-hashed password
+     * @return true if the passwords match, false otherwise
+     * @since 5.3
+     */
+    public static boolean checkpw(byte[] passwordb, String hashed) {
+        return equalsNoEarlyReturn(hashed, hashpw(passwordb, hashed));
+    }
+
+    static boolean equalsNoEarlyReturn(String a, String b) {
+        return MessageDigest.isEqual(a.getBytes(StandardCharsets.UTF_8), b.getBytes(StandardCharsets.UTF_8));
+    }
+}

+ 159 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/ecode/BCryptPasswordEncoder.java

@@ -0,0 +1,159 @@
+package com.storlead.framework.common.ecode;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+
+import java.security.SecureRandom;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2021-10-25 18:50
+ */
+@Service
+@Primary
+public class BCryptPasswordEncoder implements PasswordEncoder {
+
+    private Pattern BCRYPT_PATTERN = Pattern.compile("\\A\\$2(a|y|b)?\\$(\\d\\d)\\$[./0-9A-Za-z]{53}");
+
+    private final Log logger = LogFactory.getLog(getClass());
+
+    private final int strength;
+
+    private final BCryptVersion version;
+
+    private final SecureRandom random;
+
+    public BCryptPasswordEncoder() {
+        this(-1);
+    }
+
+    /**
+     * @param strength the log rounds to use, between 4 and 31
+     */
+    public BCryptPasswordEncoder(int strength) {
+        this(strength, null);
+    }
+
+    /**
+     * @param version the version of bcrypt, can be 2a,2b,2y
+     */
+    public BCryptPasswordEncoder(BCryptVersion version) {
+        this(version, null);
+    }
+
+    /**
+     * @param version the version of bcrypt, can be 2a,2b,2y
+     * @param random the secure random instance to use
+     */
+    public BCryptPasswordEncoder(BCryptVersion version, SecureRandom random) {
+        this(version, -1, random);
+    }
+
+    /**
+     * @param strength the log rounds to use, between 4 and 31
+     * @param random the secure random instance to use
+     */
+    public BCryptPasswordEncoder(int strength, SecureRandom random) {
+        this(BCryptVersion.$2A, strength, random);
+    }
+
+    /**
+     * @param version the version of bcrypt, can be 2a,2b,2y
+     * @param strength the log rounds to use, between 4 and 31
+     */
+    public BCryptPasswordEncoder(BCryptVersion version, int strength) {
+        this(version, strength, null);
+    }
+
+    /**
+     * @param version the version of bcrypt, can be 2a,2b,2y
+     * @param strength the log rounds to use, between 4 and 31
+     * @param random the secure random instance to use
+     */
+    public BCryptPasswordEncoder(BCryptVersion version, int strength, SecureRandom random) {
+        if (strength != -1 && (strength < BCrypt.MIN_LOG_ROUNDS || strength > BCrypt.MAX_LOG_ROUNDS)) {
+            throw new IllegalArgumentException("Bad strength");
+        }
+        this.version = version;
+        this.strength = (strength == -1) ? 10 : strength;
+        this.random = random;
+    }
+
+    @Override
+    public String encode(CharSequence rawPassword) {
+        if (rawPassword == null) {
+            throw new IllegalArgumentException("rawPassword cannot be null");
+        }
+        String salt = getSalt();
+        return BCrypt.hashpw(rawPassword.toString(), salt);
+    }
+
+    private String getSalt() {
+        if (this.random != null) {
+            return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
+        }
+        return BCrypt.gensalt(this.version.getVersion(), this.strength);
+    }
+
+    @Override
+    public boolean matches(CharSequence rawPassword, String encodedPassword) {
+        if (rawPassword == null) {
+            throw new IllegalArgumentException("rawPassword cannot be null");
+        }
+        if (encodedPassword == null || encodedPassword.length() == 0) {
+            this.logger.warn("Empty encoded password");
+            return false;
+        }
+        if (!this.BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
+            this.logger.warn("Encoded password does not look like BCrypt");
+            return false;
+        }
+        return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
+    }
+
+    @Override
+    public boolean upgradeEncoding(String encodedPassword) {
+        if (encodedPassword == null || encodedPassword.length() == 0) {
+            this.logger.warn("Empty encoded password");
+            return false;
+        }
+        Matcher matcher = this.BCRYPT_PATTERN.matcher(encodedPassword);
+        if (!matcher.matches()) {
+            throw new IllegalArgumentException("Encoded password does not look like BCrypt: " + encodedPassword);
+        }
+        int strength = Integer.parseInt(matcher.group(2));
+        return strength < this.strength;
+    }
+
+    /**
+     * Stores the default bcrypt version for use in configuration.
+     *
+     * @author Lin Feng
+     */
+    public enum BCryptVersion {
+
+        $2A("$2a"),
+
+        $2Y("$2y"),
+
+        $2B("$2b");
+
+        private final String version;
+
+        BCryptVersion(String version) {
+            this.version = version;
+        }
+
+        public String getVersion() {
+            return this.version;
+        }
+
+    }
+}

+ 19 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/ecode/PasswordEncoder.java

@@ -0,0 +1,19 @@
+package com.storlead.framework.common.ecode;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2021-10-25 18:39
+ */
+
+public interface PasswordEncoder {
+
+    String encode(CharSequence var1);
+
+    boolean matches(CharSequence var1, String var2);
+
+    default boolean upgradeEncoding(String encodedPassword) {
+        return false;
+    }
+}

+ 88 - 0
storlead-framework/storlead-common/src/main/java/com/storlead/framework/common/thread/ThreadPoolUtil.java

@@ -0,0 +1,88 @@
+package com.storlead.framework.common.thread;
+
+
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * @program: sp-project-system
+ * @description: 线程池工具类
+ * @author: chenkq
+ * @create: 2021-09-13 08:55
+ */
+public class ThreadPoolUtil {
+    /**
+     * 核心线程池的数量,同时能够执行的线程数量
+     */
+    private final static int corePoolSize  = Runtime.getRuntime().availableProcessors() * 2 + 1;
+    /**
+     * 最大线程池数量,表示当缓冲队列满的时候能继续容纳的等待任务的数量
+     */
+    private final static int maxPoolSize  = corePoolSize;
+    /**
+     * 存活时间
+     */
+    private final static long keepAliveTime = 60L;
+    private final static TimeUnit unit = TimeUnit.SECONDS;
+
+    /**
+     * 线程等待队列
+     */
+    private static LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(2000);
+
+
+
+    /**
+     * 线程池对象
+     */
+    private static ThreadPoolExecutor threadExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize,
+            keepAliveTime, unit, queue, new ThreadPoolExecutor.AbortPolicy());
+
+    public static ThreadPoolExecutor getThreadExecutor() {
+        return threadExecutor;
+    }
+
+
+    /**
+     * 向线程池提交一个任务,返回线程结果
+     * @param r
+     * @return
+     */
+    public static Future<?> submit(Callable<?> r) {
+        return threadExecutor.submit(r);
+    }
+
+    /**
+     * 向线程池提交一个任务,返回线程结果
+     * @param rs
+     * @return
+     */
+    public static List<Future<?>> submits(List rs) {
+        try {
+            List list = threadExecutor.invokeAll(rs);
+            return list;
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 向线程池提交一个任务,不关心处理结果
+     * @param r
+     */
+    public static void execute(Runnable r) {
+        threadExecutor.execute(r);
+    }
+
+    /** 获取当前线程池线程数量 */
+    public static int getSize() {
+        return threadExecutor.getPoolSize();
+    }
+
+    /** 获取当前活动的线程数量 */
+    public static int getActiveCount() {
+        return threadExecutor.getActiveCount();
+    }
+}
+

+ 0 - 115
storlead-framework/storlead-core/src/main/java/com/storlead/framework/core/Page.java

@@ -1,115 +0,0 @@
-package com.storlead.framework.core;
-
-import java.io.Serializable;
-
-/**
- * @Author Created by chenkq on 2020/8/27
- */
-public class Page implements Serializable {
-
-    private static final long serialVersionUID = 1004386013084749956L;
-    /** 当前页 */
-    private int pageNo = 1;
-
-    private int page = 1;
-
-    /** 每页条数 默认20条 */
-    private int size = 20;
-    /**
-     * 页大小
-     */
-    private Integer pageSize;
-    /**
-     * 总行数
-     */
-    private  Integer totalRows;
-
-    /**
-     * 需要分页
-     */
-    private Boolean needPage;
-
-    /**
-     * 排序字段
-     */
-    private String sortby;
-
-    /**
-     * 排序字段方式,desc asc
-     */
-    private String order;
-
-    /**
-     * 需要总数
-     */
-    private Boolean needCount;
-    public Page() {
-        this.needCount=true;
-        this.needPage=true;
-    }
-
-    public Page(int page, int size) {
-        this.pageNo = page;
-        this.page = page;
-        this.size = size;
-    }
-
-    public int getPage() {
-        return pageNo;
-    }
-
-    public void setPage(int pageNo) {
-        this.page = pageNo <= 0 ? 1 : pageNo + 1;
-        this.pageNo = pageNo <= 0 ? 1 : pageNo + 1;
-    }
-
-    public int getSize() {
-        return size;
-    }
-
-    public void setSize(int size) {
-        this.size = size < 1 ? 20 : size;
-        this.pageSize=this.size;
-    }
-
-    public int getOffset() {
-        return this.size * (this.pageNo - 1);
-    }
-
-    public Integer getPageSize() {
-        return pageSize;
-    }
-
-    public Integer getPageNo() {
-        return pageNo;
-    }
-
-    public void setPageSize(Integer pageSize) {
-        this.pageSize = pageSize;
-    }
-
-    public Integer getTotalRows() {
-        return totalRows;
-    }
-
-    public void setTotalRows(Integer totalRows) {
-        this.totalRows = totalRows;
-    }
-
-    public Boolean getNeedPage() {
-        return needPage;
-    }
-
-    public void setNeedPage(Boolean needPage) {
-        this.needPage = needPage;
-    }
-
-    public Boolean getNeedCount() {
-        return needCount;
-    }
-
-    public void setNeedCount(Boolean needCount) {
-        this.needCount = needCount;
-    }
-
-}

+ 6 - 0
storlead-framework/storlead-redis/pom.xml

@@ -25,6 +25,12 @@
             <artifactId>storlead-common</artifactId>
             <version>${revision}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>

+ 3 - 2
storlead-framework/storlead-web/src/main/java/com/storlead/framework/web/assemble/QueryBaseDTO.java

@@ -1,12 +1,13 @@
 package com.storlead.framework.web.assemble;
 
-import com.storlead.framework.core.Page;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
+import java.io.Serializable;
+
 /**
  * @program: storlead-storlead-centre-platform
  * @description:
@@ -17,7 +18,7 @@ import lombok.extern.log4j.Log4j2;
 @AllArgsConstructor
 @Data
 @Log4j2
-public class QueryBaseDTO extends Page {
+public class QueryBaseDTO implements Serializable {
     @ApiModelProperty(value = "搜索参数")
     private String blurry;
 }

+ 0 - 63
storlead-framework/storlead-web/src/main/java/com/storlead/framework/web/message/PageResp.java

@@ -1,63 +0,0 @@
-package com.storlead.framework.web.message;
-
-import com.storlead.framework.core.Page;
-import lombok.Data;
-
-import java.util.Collection;
-
-@Data
-public class PageResp<T> {
-
-    private int page = 1;
-
-    private int pageSize = 20;
-    /**
-     * 总叶
-     */
-    private long totalPage;
-    /**
-     * 总行
-     */
-    private long totalCount;
-    /**
-     * 椰树
-     */
-    private int PageNo;
-
-    private Collection<T> datas;
-
-    public void setPageNo(int pageNo) {
-        PageNo = pageNo;
-        page = pageNo;
-    }
-
-    public void setDatas(Collection<T> datas) {
-        this.datas = datas;
-    }
-    public PageResp() {
-
-    }
-    /**
-     * 重写构造器,计算总页数
-     * @param data 查询的数据列表
-     * @param p 传入的分页参数
-     * @param totalRows 总条目书
-     */
-    public PageResp(Collection<T> data, Page p, long totalRows) {
-        this(data, p.getPage(), p.getPageSize(), totalRows);
-    }
-
-    public PageResp(Collection<T> datas, long page, long size, long totalCount) {
-
-        this.datas = datas;
-        this.page = (int)page;
-        this.pageSize = (int) size;
-        this.totalCount = totalCount;
-        /**
-         * 计算总页数
-         */
-        //this.totalPage = totalCount / size + ((totalCount % size == 0) ? 0 : 1);
-
-    }
-
-}

+ 79 - 0
storlead-user/pom.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.storlead.boot</groupId>
+        <artifactId>storlead-centre-platform</artifactId>
+        <version>1.0</version>
+    </parent>
+
+    <artifactId>storlead-user</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-common</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-wx</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.storlead.boot</groupId>
+            <artifactId>storlead-mybatis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <!-- 参数校验 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-ui</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Spring Boot WebSocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
+        <!-- Spring Boot WebFlux (响应式编程) -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 37 - 0
storlead-user/src/main/java/com/storlead/user/constant/JurisdictionConstant.java

@@ -0,0 +1,37 @@
+package com.storlead.user.constant;
+
+/**
+ * @program: 权限相关常量
+ * @description:
+ * @author: chenkq
+ * @create: 2022-04-20 17:06
+ */
+
+public class JurisdictionConstant {
+
+    /**
+     * 动态权限sql属性标记
+     */
+    public static final String SqlScriptProperty = "jurisdictionSql";
+
+    /**
+     * 权限按钮集合属性标记
+     */
+    public static final String BtnProperty = "jurisdictionBtns";
+
+    /**
+     * 字典缓存reis key
+     */
+    public static final String RedisDictKey = "redis-permission-dict-";
+
+    /**
+     * 缓存需要权限的资源
+     */
+    public static final String RedisApiCodeKey = "redis-permission-api-code-";
+
+    /**
+     *  记录是否需要权限
+     */
+    public static final String PermissionVerificationTrack = "context-permission-verification-track";
+
+}

+ 17 - 0
storlead-user/src/main/java/com/storlead/user/mapper/CompanyMapper.java

@@ -0,0 +1,17 @@
+package com.storlead.user.mapper;
+
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import com.storlead.user.pojo.entity.CompanyEntity;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+public interface CompanyMapper extends MyBaseMapper<CompanyEntity> {
+
+
+    @Select("select * from company")
+    List<CompanyEntity> projectCompanyList();
+
+    @Select("truncate table company")
+    void truncateTable();
+}

+ 42 - 0
storlead-user/src/main/java/com/storlead/user/mapper/DeptMapper.java

@@ -0,0 +1,42 @@
+package com.storlead.user.mapper;
+
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import com.storlead.user.pojo.entity.DeptEntity;
+import com.storlead.user.model.DeptTreeModel;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <p>
+ * 部门 Mapper 接口
+ * <p>
+ *
+ * @Author: Steve
+ * @Since:   2019-01-22
+ */
+public interface DeptMapper extends MyBaseMapper<DeptEntity> {
+
+    List<DeptTreeModel> queryDeptBySubList(Integer subCompanyId);
+
+    @Select("truncate table dept;")
+    Boolean truncateDept();
+
+    List<Long> queryDeptIdListByDeptId(Long deptId);
+
+    List<DeptEntity> findByPid(Long deptId);
+
+    /**
+     * 根据角色ID查询部门列表
+     *
+     * @param roleId 角色ID
+     * @return java.util.Set<com.storlead.web.model.entity.Dept>
+     * @author blank
+     * @date 2021-3-31 下午 5:14
+     */
+    Set<DeptEntity> findByRoleId(Long roleId);
+
+
+    List<DeptEntity> getDeptTreeIdsByDeptIds(Long deptId);
+}

+ 16 - 0
storlead-user/src/main/java/com/storlead/user/mapper/HrmcompanyMapper.java

@@ -0,0 +1,16 @@
+package com.storlead.user.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.Hrmcompany;
+
+/**
+ * Mapper 接口
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+//@DS(DSConstants.DATASOURCE_OA)
+public interface HrmcompanyMapper extends BaseMapper<Hrmcompany> {
+
+}

+ 16 - 0
storlead-user/src/main/java/com/storlead/user/mapper/HrmdepartmentMapper.java

@@ -0,0 +1,16 @@
+package com.storlead.user.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.Hrmdepartment;
+
+/**
+ * Mapper 接口
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+//@DS(DSConstants.DATASOURCE_OA)
+public interface HrmdepartmentMapper extends BaseMapper<Hrmdepartment> {
+
+}

+ 16 - 0
storlead-user/src/main/java/com/storlead/user/mapper/HrmdepartmentdefinedMapper.java

@@ -0,0 +1,16 @@
+package com.storlead.user.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.Hrmdepartmentdefined;
+
+/**
+ * Mapper 接口
+ *
+ * @author YPZ
+ * @since 2022-04-21
+ */
+//@DS(DSConstants.DATASOURCE_OA)
+public interface HrmdepartmentdefinedMapper extends BaseMapper<Hrmdepartmentdefined> {
+
+}

+ 16 - 0
storlead-user/src/main/java/com/storlead/user/mapper/HrmjobtitlesMapper.java

@@ -0,0 +1,16 @@
+package com.storlead.user.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.Hrmjobtitles;
+
+/**
+ *  Mapper 接口
+ *
+ * @author blank
+ * @since 2021-6-15
+ */
+//@DS(DSConstants.DATASOURCE_OA)
+public interface HrmjobtitlesMapper extends BaseMapper<Hrmjobtitles> {
+
+}

+ 46 - 0
storlead-user/src/main/java/com/storlead/user/mapper/HrmresourceMapper.java

@@ -0,0 +1,46 @@
+package com.storlead.user.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.Hrmresource;
+import com.storlead.user.pojo.entity.UserEntity;
+
+import java.util.List;
+
+/**
+ * Mapper 接口
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+//@DS(DSConstants.DATASOURCE_OA)
+public interface HrmresourceMapper extends BaseMapper<Hrmresource> {
+
+    /**
+     * 查询OA全部用户转成WEB user实体返回
+     *
+     * @return java.util.List<com.storlead.web.model.entity.User>
+     * @author blank
+     * @date 2021-3-9 上午 10:56
+     */
+    List<UserEntity> getUserList();
+
+    /**
+     * 同步OA流程中的转正日期到OA人力资源表中
+     * 离职日期使用 datefield1 字段
+     *
+     * @return java.lang.Long
+     * @author blank
+     * @date 2021-3-23 下午 4:31
+     */
+    Long updatePermanentDate();
+
+    /**
+     * 同步OA流程中的离职日期到OA人力资源表中
+     * 离职日期使用 datefield1 字段
+     *
+     * @return java.lang.Long
+     * @author blank
+     * @date 2021-3-23 下午 5:25
+     */
+    Long updateResignDate();
+}

+ 15 - 0
storlead-user/src/main/java/com/storlead/user/mapper/HrmsubcompanyMapper.java

@@ -0,0 +1,15 @@
+package com.storlead.user.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.Hrmsubcompany;
+
+/**
+ * Mapper 接口
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+//@DS(DSConstants.DATASOURCE_OA)
+public interface HrmsubcompanyMapper extends BaseMapper<Hrmsubcompany> {
+
+}

+ 8 - 0
storlead-user/src/main/java/com/storlead/user/mapper/JobMapper.java

@@ -0,0 +1,8 @@
+package com.storlead.user.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.JobEntity;
+
+public interface JobMapper extends BaseMapper<JobEntity> {
+
+}

+ 15 - 0
storlead-user/src/main/java/com/storlead/user/mapper/SubCompanyMapper.java

@@ -0,0 +1,15 @@
+package com.storlead.user.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.storlead.user.pojo.entity.SubCompanyEntity;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+public interface SubCompanyMapper extends BaseMapper<SubCompanyEntity> {
+
+    @Select("truncate table sub_company")
+    void truncateTable();
+
+    List<SubCompanyEntity> getHasSublist(Long roleId);
+}

+ 69 - 0
storlead-user/src/main/java/com/storlead/user/mapper/UserMapper.java

@@ -0,0 +1,69 @@
+package com.storlead.user.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.storlead.framework.auth.vo.LoginUser;
+import com.storlead.framework.mybatis.mapper.MyBaseMapper;
+import com.storlead.user.pojo.entity.UserEntity;
+import com.storlead.user.model.UserBaseInfo;
+import com.storlead.user.model.UserInfo;
+import com.storlead.user.model.UserQueryModel;
+import com.storlead.user.pojo.vo.UserVo;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+public interface UserMapper extends MyBaseMapper<UserEntity> {
+
+    @Select("select u.id,u.user_name,u.password,u.avatar,u.sex,u.nick_name,u.real_name,u.mobile,u.email,u.job_id," +
+            "u.dept_id,1 AS test,u.sub_company_id,u.company_id,u.enabled,u.status,u.is_leader,u.manager_id,u.managers,r.data_scope from user u left join user_role ur on ur.user_id = u.id left join role r on r.id = ur.role_id  where user_name = #{username} limit 1")
+    UserEntity getUserByName(String username);
+
+    @Select("select id,user_name,avatar,sex,nick_name,real_name,mobile,email,job_id,dept_id,sub_company_id,company_id,enabled,status from user")
+    List<UserEntity> getUserList();
+
+    UserBaseInfo queryByUserId(Long id);
+
+//    List<UserVo> list(IPage<UserVo> page, @Param(Constants.WRAPPER) Wrapper<UserVo> wrapper);
+
+    List<UserVo> searchHomeUserList(IPage<UserVo> page, @Param(Constants.WRAPPER) Wrapper<UserVo> wrapper);
+
+
+    List<UserBaseInfo> queryByUserIdList(@Param("ids") Collection<Long> ids);
+
+    List<UserInfo> queryList(@Param("query") UserQueryModel userQueryModel);
+
+    List<Long> getListByUserRole(LoginUser loginUser);
+
+    /**
+    * 获取所有下级id
+    * @Author: xiaojiawei
+    * @Date: 2022/5/7
+    */
+    List<Long> getAllSubordinate(@Param("currentUserId") Long currentUserId);
+
+    UserEntity getUserByMobile(String mobile);
+
+    UserVo getUserInfoById(@Param("userId") Long userId);
+
+    void addUserAvatar();
+
+    Set<Long> selectUserRoleIdsByApiUrl(@Param("userId") Long userId, @Param("apiUrl") String apiUrl);
+
+    Set<Long> selectUserRoleIdsByMenuId(@Param("userId") Long userId, @Param("menuId") String menuId);
+
+    Set<Long> selectUserRoleIdsByCommonScopeType(@Param("userId") Long userId, @Param("commonScopeType") String commonScopeType);
+
+    /**
+     * 根据部门id获取用户id
+     * @param deptIds
+     * @return
+     */
+    Set<Long> getUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds);
+
+    void updateLastFollowUpTime(@Param("ownerByIds") List<Long> ownerByIds);
+}

+ 91 - 0
storlead-user/src/main/java/com/storlead/user/model/DepartIdModel.java

@@ -0,0 +1,91 @@
+package com.storlead.user.model;
+
+import com.storlead.user.pojo.entity.DeptEntity;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 部门表 封装树结构的部门的名称的实体类
+ * <p>
+ *
+ * @Author Steve
+ * @Since 2019-01-22
+ *
+ */
+public class DepartIdModel implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    // 主键ID
+    private String key;
+
+    // 主键ID
+    private String value;
+
+    // 部门名称
+    private String title;
+
+    List<DepartIdModel> children = new ArrayList<>();
+
+    /**
+     * 将SysDepartTreeModel的部分数据放在该对象当中
+     * @param treeModel
+     * @return
+     */
+    public DepartIdModel convert(DeptTreeModel treeModel) {
+        this.key = treeModel.getId().toString();
+        this.value = treeModel.getId().toString();
+        this.title = treeModel.getName();
+        return this;
+    }
+    /**
+     * 该方法为用户部门的实现类所使用
+     * @param dept
+     * @return
+     */
+    public DepartIdModel convertByUserDepart(DeptEntity dept) {
+        this.key = String.valueOf(dept.getId());
+        this.value = String.valueOf(dept.getId());
+        this.title = dept.getName();
+        return this;
+    }
+
+    public List<DepartIdModel> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<DepartIdModel> children) {
+        this.children = children;
+    }
+
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+}

+ 187 - 0
storlead-user/src/main/java/com/storlead/user/model/DeptTreeModel.java

@@ -0,0 +1,187 @@
+package com.storlead.user.model;
+
+import com.storlead.user.pojo.entity.DeptEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * <p>
+ * 部门表 存储树结构数据的实体类
+ * <p>
+ *
+ * @Author Steve
+ * @Since 2019-01-22
+ */
+@ApiModel(value="部门tree对象", description="部门tree对象详细信息")
+public class DeptTreeModel implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 对应SysDepart中的id字段,前端数据树中的key*/
+    @ApiModelProperty(value = "对应dept中的id字段,前端数据树中的key")
+    private String key;
+
+    /** 对应SysDepart中的id字段,前端数据树中的value*/
+    @ApiModelProperty(value = "对应dept中的id字段,前端数据树中的value")
+    private String value;
+
+    /** 对应depart_name字段,前端数据树中的title*/
+    @ApiModelProperty(value = "对应dept中的name字段,前端数据树中的title")
+    private String title;
+
+    @ApiModelProperty(value = "部门名称")
+    private String name;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
+    @ApiModelProperty(value = "分公司ID")
+    private Long subCompanyId;
+
+    private boolean isLeaf;
+    // 以下所有字段均与SysDepart相同
+
+    @ApiModelProperty(value = "部门ID")
+    private Long id;
+
+    @ApiModelProperty(value = "上级部门ID")
+    private Long pid;
+
+    @ApiModelProperty(value = "是否启用(1:启用 2:禁用)")
+    private Integer enabled;
+
+    private List<DeptTreeModel> children = new ArrayList<>();
+
+
+    /**
+     * 将SysDepart对象转换成SysDepartTreeModel对象
+     * @param dept
+     */
+	public DeptTreeModel(DeptEntity dept) {
+		this.key = String.valueOf(dept.getId());
+        this.value = String.valueOf(dept.getId());
+        this.title = dept.getName();
+        this.id = dept.getId();
+        this.pid = dept.getPid();
+        this.enabled = dept.getEnabled() ? 1 : 0;
+        this.name = dept.getName();
+        this.sort = dept.getSort();
+        this.subCompanyId = dept.getSubCompanyId();
+    }
+
+    public boolean getIsLeaf() {
+        return isLeaf;
+    }
+
+    public void setIsLeaf(boolean isleaf) {
+         this.isLeaf = isleaf;
+    }
+
+    public String getKey() {
+		return key;
+	}
+
+
+	public void setKey(String key) {
+		this.key = key;
+	}
+
+
+    public String getName() {
+        return name;
+    }
+
+    public Integer getSort() {
+        return sort;
+    }
+
+    public Long getSubCompanyId() {
+        return subCompanyId;
+    }
+
+    public Long getPid() {
+        return pid;
+    }
+
+    public Integer getEnabled() {
+        return enabled;
+    }
+
+    public String getValue() {
+		return value;
+	}
+
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+
+
+	public String getTitle() {
+		return title;
+	}
+
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+
+	public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public List<DeptTreeModel> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<DeptTreeModel> children) {
+        if (children==null){
+            this.isLeaf=true;
+        }
+        this.children = children;
+    }
+
+    public DeptTreeModel() { }
+
+    /**
+     * 重写equals方法
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+			return true;
+		}
+        if (o == null || getClass() != o.getClass()) {
+			return false;
+		}
+        DeptTreeModel model = (DeptTreeModel) o;
+        return Objects.equals(id, model.id) &&
+                Objects.equals(pid, model.pid) &&
+                Objects.equals(sort, model.sort) &&
+                Objects.equals(name, model.name) &&
+                Objects.equals(subCompanyId, subCompanyId) &&
+                Objects.equals(enabled, enabled) &&
+                Objects.equals(children, model.children);
+    }
+
+    /**
+     * 重写hashCode方法
+     */
+    @Override
+    public int hashCode() {
+
+        return Objects.hash(id, pid, sort, name, subCompanyId, enabled,
+        		children);
+    }
+
+}

+ 24 - 0
storlead-user/src/main/java/com/storlead/user/model/SysLoginModel.java

@@ -0,0 +1,24 @@
+package com.storlead.user.model;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 登录表单
+ *
+ * @Author scott
+ * @since  2019-01-18
+ */
+@Data
+public class SysLoginModel {
+
+	@ApiModelProperty(value = "账号")
+    private String username;
+	@ApiModelProperty(value = "密码")
+    private String password;
+	@ApiModelProperty(value = "验证码")
+    private String captcha;
+	@ApiModelProperty(value = "验证码key")
+    private String checkKey;
+
+}

+ 29 - 0
storlead-user/src/main/java/com/storlead/user/model/TreeSelectModel.java

@@ -0,0 +1,29 @@
+package com.storlead.user.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+  * 树形下拉框
+ */
+@Data
+public class TreeSelectModel implements Serializable {
+
+	private static final long serialVersionUID = 9016390975325574747L;
+
+	private String key;
+
+	private String title;
+
+	private boolean isLeaf;
+
+	private String icon;
+
+	private String parentId;
+
+	private String value;
+
+	private String code;
+
+}

+ 37 - 0
storlead-user/src/main/java/com/storlead/user/model/UserBaseInfo.java

@@ -0,0 +1,37 @@
+package com.storlead.user.model;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class UserBaseInfo implements Serializable {
+
+    private Long deptId;
+
+    private String deptName;
+
+    private Long subCompanyId;
+
+    private String subCompanyName;
+
+    private Integer jobId;
+
+    private String jobName;
+
+    private Long companyId;
+
+    private String companyName;
+
+    private Integer isLeader;
+
+    @ApiModelProperty(value = "是否冻结: 1 冻结,0:未冻结")
+    private Integer isFreeze;
+
+    private Long createBy;
+
+    private String createName;
+
+    private String createPhoto;
+}

+ 68 - 0
storlead-user/src/main/java/com/storlead/user/model/UserInfo.java

@@ -0,0 +1,68 @@
+package com.storlead.user.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class UserInfo implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "用户ID")
+    private Long id;
+
+    @ApiModelProperty(value = "用户名")
+    private String username;
+
+    @ApiModelProperty(value = "头像")
+    private String avatar;
+
+    @ApiModelProperty(value = "性别")
+    private String sex;
+
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @ApiModelProperty(value = "姓名")
+    private String realName;
+
+    @ApiModelProperty(value = "姓名")
+    private String mobile;
+
+    @ApiModelProperty(value = "email")
+    private String email;
+
+    @ApiModelProperty(value = "岗位ID")
+    private Integer jobId;
+
+    @ApiModelProperty(value = "部门ID")
+    private Long deptId;
+
+    @ApiModelProperty(value = "分公司ID")
+    private Long subCompanyId;
+
+    @ApiModelProperty(value = "公司ID")
+    private Long companyId;
+
+    @ApiModelProperty(value = "公司名称")
+    private String companyName;
+
+    @ApiModelProperty(value = "状态 1:试用期 2:正式期 3:保护期 4:待岗 5:产假 6:离职流程")
+    private String status;
+
+    @ApiModelProperty(value = "职位名称")
+    private String jobName;
+
+    @ApiModelProperty(value = "子公司名称")
+    private String subCompanyName;
+
+    @ApiModelProperty(value = "部门名称")
+    private String deptName;
+
+    @ApiModelProperty(value = "是否冻结: 1 冻结,0:未冻结")
+    private Integer isFreeze;
+
+}

+ 21 - 0
storlead-user/src/main/java/com/storlead/user/model/UserQueryModel.java

@@ -0,0 +1,21 @@
+package com.storlead.user.model;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class UserQueryModel implements Serializable {
+
+
+    @ApiModelProperty(value = "关键字")
+    private String keyword;
+
+    @ApiModelProperty(value = "子公司ID")
+    private Long subCompanyId;
+
+    @ApiModelProperty(value = "部门ID")
+    private Long deptId;
+
+}

+ 15 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/CompanyDTO.java

@@ -0,0 +1,15 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.Page;
+import lombok.Data;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-06-29 17:37
+ */
+
+@Data
+public class CompanyDTO extends Page {
+}

+ 48 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/DepartmentParam.java

@@ -0,0 +1,48 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.Page;
+import lombok.Data;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-05-13 14:20
+ */
+@Data
+public class DepartmentParam extends Page {
+
+    /**
+     * 类型:10 集团,20:公司(分公司),30:部门,40:小组,50:雇员
+     */
+    private List<Integer> orgTypes;
+
+    private Integer reviewTag;
+
+    /**
+     * 上级id
+     */
+    private Long parentId;
+
+    /**
+     * 可选节点类型
+     */
+    private List<Integer> checkNodes = Arrays.asList(10,20,30,40,99);
+
+    /**
+     * 公司id
+     */
+    private Long subCompanyId;
+
+    /**
+     * 部门id
+     */
+    private Long deptId;
+
+    private String scopeMenuId;
+
+    private Integer enabled;
+}

+ 16 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/DeptParam.java

@@ -0,0 +1,16 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.user.pojo.entity.DeptEntity;
+import lombok.Data;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-06-29 09:25
+ */
+
+@Data
+public class DeptParam extends DeptEntity {
+
+}

+ 27 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/EmployeeParam.java

@@ -0,0 +1,27 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.Page;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.List;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-05-19 17:58
+ */
+public class EmployeeParam extends Page {
+
+    @ApiModelProperty("职位id")
+    private List<Long> jobIds;
+
+    @ApiModelProperty("组织")
+    private List<Long> orgIds;
+
+    @ApiModelProperty(value = "用户名")
+    private String username;
+
+    @ApiModelProperty(value = "手机号")
+    private String mobile;
+}

+ 22 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/JobDTO.java

@@ -0,0 +1,22 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.Page;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-05-24 11:08
+ */
+@Data
+public class JobDTO extends Page {
+
+    @ApiModelProperty(value = "角色ID")
+    private Long id;
+
+    @ApiModelProperty(value = "角色名称")
+    private String jobName;
+
+}

+ 20 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/MenuParam.java

@@ -0,0 +1,20 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.Page;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-06-29 17:22
+ */
+@Data
+public class MenuParam  extends Page {
+
+    @ApiModelProperty(value = "所属服务类型: 0:PC,1:移动")
+    private String serviceModeType;
+
+    private Long resourceId;
+}

+ 34 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/MenuTreeParam.java

@@ -0,0 +1,34 @@
+package com.storlead.user.pojo.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2021-11-23 10:29
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+public class MenuTreeParam implements Serializable {
+
+    @ApiModelProperty(value = "查询应用应用菜单")
+    private List<Long> appIds;
+
+    @ApiModelProperty(value = "角色")
+    private Long roleId;
+
+    @ApiModelProperty(value = "是否需要将应用作为顶级菜单,默认不需要")
+    private Boolean needService = false;
+
+    @ApiModelProperty(value = "查询应用应用菜单")
+    private Long appId;
+
+}

+ 52 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/RoleParam.java

@@ -0,0 +1,52 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.Page;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.util.Set;
+
+/**
+ * 角色参数
+ *
+ * @author blank
+ * @date 2021-1-7 上午 11:23
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "RoleParam对象", description = "角色请求参数对象")
+public class RoleParam extends Page {
+
+    private static final long serialVersionUID = 269890957793662474L;
+
+    @ApiModelProperty(value = "角色id")
+    private Long id;
+
+    @ApiModelProperty(value = "角色名称")
+    private String name;
+
+    @ApiModelProperty(value = "角色描述")
+    private String desc;
+
+    @ApiModelProperty(value = "权限范围(全部 本公司 自定义 自己,本部门)")
+    private String dataScope;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "菜单列表")
+    private Set<Long> menus;
+
+    @ApiModelProperty(value = "部门列表")
+    private Set<Long> depts;
+
+    @ApiModelProperty(value = "是否启用")
+    private Boolean enabled;
+
+    @ApiModelProperty(value = "是否移动端 1:是,0 :不是")
+    private Integer isApp;
+}

+ 78 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/SetUserDetailDTO.java

@@ -0,0 +1,78 @@
+package com.storlead.user.pojo.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-08-23 17:55
+ */
+@Data
+public class SetUserDetailDTO implements Serializable {
+
+    @ApiModelProperty(value = "用户名")
+    private String userName;
+
+    @ApiModelProperty(value = "头像")
+    private String avatar;
+
+    @ApiModelProperty(value = "岗位ID")
+    private Long jobId;
+
+    @ApiModelProperty(value = "部门ID")
+    private Long deptId;
+
+    @ApiModelProperty(value = "岗位ID")
+    private String jobName;
+
+    @ApiModelProperty(value = "部门")
+    private String deptName;
+
+    @ApiModelProperty(value = "手机号")
+    private String mobile;
+
+    @ApiModelProperty(value = "邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "部门岗位职责")
+    private String deptJobDes;
+
+    @ApiModelProperty(value = "岗位职责")
+    private String jobDes;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern="yyyy-MM-dd")
+    private LocalDate birthday;
+
+    @ApiModelProperty(value = "性别")
+    private String sex;
+
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @ApiModelProperty(value = "姓名")
+    private String realName;
+
+
+    @ApiModelProperty(value = "分公司ID")
+    private Long subCompanyId;
+
+    @ApiModelProperty(value = "公司ID")
+    private Long companyId;
+
+    @ApiModelProperty(value = "直接上级ID")
+    private Long managerId;
+
+    @ApiModelProperty(value = "领导路由")
+    private String managers;
+
+    private String idNum;
+    private String address;
+}

+ 27 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/UserLoginDTO.java

@@ -0,0 +1,27 @@
+package com.storlead.user.pojo.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-07-15 09:22
+ */
+@Data
+public class UserLoginDTO implements Serializable {
+    @ApiModelProperty(value = "登录账号")
+    private String account;
+
+    @ApiModelProperty(value = "密码")
+    private String password;
+
+    @ApiModelProperty(value = "微信登录code")
+    private String wxCode;
+
+    @ApiModelProperty(value = "短信验证码")
+    private String smsCode;
+}

+ 33 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/UserLoginParam.java

@@ -0,0 +1,33 @@
+package com.storlead.user.pojo.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @program: sp-cloud
+ * @description: 登录参数
+ * @author: chenkq
+ * @create: 2021-10-20 17:27
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "用户登录参数", description = "用户登录参数")
+public class UserLoginParam {
+
+    @ApiModelProperty(value = "登录账号")
+    private String account;
+
+    @ApiModelProperty(value = "密码")
+    private String password;
+
+    @ApiModelProperty(value = "微信登录code")
+    private String wxCode;
+
+    @ApiModelProperty(value = "短信验证码")
+    private String smsCode;
+
+}

+ 64 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/UserParam.java

@@ -0,0 +1,64 @@
+package com.storlead.user.pojo.dto;
+
+import com.storlead.common.object.QueryBaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import java.util.List;
+
+/**
+ * 用户相关参数
+ *
+ * @author blank
+ * @date 2020-12-31 下午 4:44
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "UserParam对象", description = "用户请求参数对象")
+public class UserParam  extends QueryBaseEntity {
+
+    private static final long serialVersionUID = -4911053849319957779L;
+
+    @ApiModelProperty(value = "用户id")
+    private Long id;
+
+    @ApiModelProperty(value = "组织路由")
+    private String orgRouteCode;
+
+    @ApiModelProperty(value = "用户名")
+    @NotBlank(message = "用户名不能为空")
+    @Length(min = 4, max = 20, message = "用户名长度为4-20位")
+    private String username;
+
+    @ApiModelProperty(value = "原密码")
+    @NotBlank(message = "原密码不能为空")
+    @Length(min = 6, max = 20, message = "原密码长度为6-20位")
+    private String password;
+
+    @ApiModelProperty(value = "新密码")
+    @NotBlank(message = "新密码不能为空")
+    @Length(min = 6, max = 20, message = "密码长度为6-20位")
+    private String newPass;
+
+    @ApiModelProperty(value = "手机号")
+    @NotBlank(message = "手机号不能为空")
+    @Length(min = 11, max = 11, message = "手机号11位")
+    @Pattern(regexp = "0?(13-9)[0-9]{9}", message = "手机号格式不正确")
+    private String mobile;
+
+    @ApiModelProperty(value = "角色ID列表")
+    private List<Long> roleIds;
+
+    @ApiModelProperty(value = "通用搜索条件")
+    private Integer status;
+
+    @ApiModelProperty(value = "查询离职人员:0 在职,1:在职 + 离职 ")
+    private Boolean isIncludeResign = false;
+}

+ 35 - 0
storlead-user/src/main/java/com/storlead/user/pojo/dto/UserRoleParam.java

@@ -0,0 +1,35 @@
+package com.storlead.user.pojo.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * 用户角色参数
+ *
+ * @author blank
+ * @date 2021-4-6 下午 7:50
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "RoleParam对象", description = "角色请求参数对象")
+public class UserRoleParam  implements Serializable {
+
+    private static final long serialVersionUID = 4270688918860415511L;
+
+    @ApiModelProperty(value = "用户id")
+    @NotNull(message = "用户id不能为空")
+    private Long userId;
+
+    @ApiModelProperty(value = "角色列表ID")
+    @NotNull(message = "角色id不能为空")
+    private Set<Long> roleIds;
+
+}

+ 39 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/CompanyEntity.java

@@ -0,0 +1,39 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="总公司对象", description="总公司对象详细信息")
+@TableName("company")
+public class CompanyEntity extends SysBaseField {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "公司ID")
+    @TableId(value = "id", type = IdType.INPUT)
+    private Long id;
+
+    @ApiModelProperty(value = "公司名称")
+    private String name;
+
+    @ApiModelProperty(value = "公司描述(全称)")
+    @TableField("`desc`")
+    private String desc;
+
+    @ApiModelProperty(value = "路由code")
+    private String routeCode;
+
+    @ApiModelProperty(value = "数据来源")
+    private Integer dataSource;
+}

+ 92 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/DeptEntity.java

@@ -0,0 +1,92 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Objects;
+
+/**
+ * <p>
+ * 部门表
+ * <p>
+ *
+ * @Author Steve
+ * @Since  2019-01-22
+ */
+@Data
+@TableName("dept")
+public class DeptEntity extends SysBaseField {
+    private static final long serialVersionUID = 1L;
+
+	/**ID*/
+	@TableId(type = IdType.INPUT)
+	private Long id;
+
+	@ApiModelProperty(value = "部门名称")
+	private String name;
+
+	@ApiModelProperty(value = "所属公司id")
+	private Long companyId;
+
+	@ApiModelProperty(value = "子公司")
+	private Long subCompanyId;
+
+	@ApiModelProperty(value = "父机构ID")
+	private Long pid;
+
+	@ApiModelProperty(value = "部门领导")
+	private Long managerId;
+
+	@ApiModelProperty(value = "部门分管领导")
+	private String subManagerIds;
+
+	@ApiModelProperty(value = "路由code")
+	private String routeCode;
+
+	@ApiModelProperty(value = "数据来源")
+	private Integer dataSource;
+
+	@ApiModelProperty(value = "部门负责人")
+	private String leaderName;
+
+	@ApiModelProperty(value = "部门路由名称")
+	private String deptNameRoute;
+
+	@ApiModelProperty(value = "部门岗位职责")
+	private String deptJobDes;
+
+	/**
+	 * 重写equals方法
+	 */
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+			return true;
+		}
+        if (o == null || getClass() != o.getClass()) {
+			return false;
+		}
+        if (!super.equals(o)) {
+			return false;
+		}
+        DeptEntity depart = (DeptEntity) o;
+        return Objects.equals(id, depart.id) &&
+                Objects.equals(pid, depart.pid) &&
+				Objects.equals(name, depart.name) &&
+				Objects.equals(subCompanyId, depart.subCompanyId);
+    }
+
+    /**
+     * 重写hashCode方法
+     */
+    @Override
+    public int hashCode() {
+
+        return Objects.hash(super.hashCode(), id, pid, name,
+				subCompanyId);
+    }
+}

+ 45 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmcompany.java

@@ -0,0 +1,45 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ *
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Hrmcompany对象", description="")
+public class Hrmcompany implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "ID", type = IdType.NONE)
+    private Integer id;
+
+    @TableField("COMPANYNAME")
+    private String companyname;
+
+    @TableField("COMPANYDESC")
+    private String companydesc;
+
+    @TableField("COMPANYWEB")
+    private String companyweb;
+
+    private LocalDateTime lastinittime;
+
+    private String uuid;
+
+
+}

+ 101 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmdepartment.java

@@ -0,0 +1,101 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ *
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Hrmdepartment对象", description="")
+public class Hrmdepartment implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @TableField("DEPARTMENTMARK")
+    private String departmentmark;
+
+    @TableField("DEPARTMENTNAME")
+    private String departmentname;
+
+    @TableField("SUBCOMPANYID1")
+    private Long subcompanyid1;
+
+    @TableField("SUPDEPID")
+    private Long supdepid;
+
+    @TableField("ALLSUPDEPID")
+    private String allsupdepid;
+
+    @TableField("CANCELED")
+    private String canceled;
+
+    @TableField("DEPARTMENTCODE")
+    private String departmentcode;
+
+    @TableField("COADJUTANT")
+    private Integer coadjutant;
+
+    @TableField("ZZJGBMFZR")
+    private String zzjgbmfzr;
+
+    @TableField("ZZJGBMFGLD")
+    private String zzjgbmfgld;
+
+    @TableField("JZGLBMFZR")
+    private String jzglbmfzr;
+
+    @TableField("JZGLBMFGLD")
+    private String jzglbmfgld;
+
+    @TableField("BMFZR")
+    private String bmfzr;
+
+    @TableField("BMFGLD")
+    private String bmfgld;
+
+    @TableField("OUTKEY")
+    private String outkey;
+
+    @TableField("BUDGETATUOMOVEORDER")
+    private Integer budgetatuomoveorder;
+
+    @TableField("ECOLOGY_PINYIN_SEARCH")
+    private String ecologyPinyinSearch;
+
+    @TableField("TLEVEL")
+    private Integer tlevel;
+
+    private LocalDateTime created;
+
+    private Integer creater;
+
+    private LocalDateTime modified;
+
+    private Integer modifier;
+
+    private String uuid;
+
+    private Double showorder;
+
+    @TableField("showOrderOfTree")
+    private Integer showorderoftree;
+
+
+}

+ 56 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmdepartmentdefined.java

@@ -0,0 +1,56 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ *
+ *
+ * @author YPZ
+ * @since 2022-04-21
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Hrmdepartmentdefined对象", description="OA部门负责人表")
+public class Hrmdepartmentdefined implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "ID", type = IdType.NONE)
+    private Integer id;
+
+    @TableField("DEPTID")
+    @ApiModelProperty(value = "部门ID")
+    private Integer deptId;
+
+    @TableField("BMFZR")
+    @ApiModelProperty(value = "部门负责人ID")
+    private String bmfzr;
+
+    @TableField("BMFGLD")
+    @ApiModelProperty(value = "部门分管领导,多领导用户逗号隔开")
+    private String bmfgld;
+
+    @TableField("ZZJGBMFZR")
+    private String zzjgbmfzr;
+
+    @TableField("ZZJGBMFGLD")
+    private String zzjgbmfgld;
+
+    @TableField("JZGLBMFZR")
+    private String jzglbmfzr;
+
+    @TableField("JZGLBMFGLD")
+    private String jzglbmfgld;
+
+
+}

+ 79 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmjobtitles.java

@@ -0,0 +1,79 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * OA人力资源岗位表
+ *
+ * @author blank
+ * @since 2021-6-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Hrmjobtitles对象", description="")
+public class Hrmjobtitles implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "自增主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @TableField("JOBTITLEMARK")
+    private String jobtitlemark;
+
+    @TableField("JOBTITLENAME")
+    private String jobtitlename;
+
+    @TableField("JOBTITLEREMARK")
+    private String jobtitleremark;
+
+    @TableField("JOBACTIVITYID")
+    private Integer jobactivityid;
+
+    @TableField("JOBDEPARTMENTID")
+    private Integer jobdepartmentid;
+
+    @TableField("JOBRESPONSIBILITY")
+    private String jobresponsibility;
+
+    @TableField("JOBCOMPETENCY")
+    private String jobcompetency;
+
+    @TableField("JOBDOC")
+    private Integer jobdoc;
+
+    @TableField("JOBTITLECODE")
+    private String jobtitlecode;
+
+    @TableField("OUTKEY")
+    private String outkey;
+
+    @TableField("ECOLOGY_PINYIN_SEARCH")
+    private String ecologyPinyinSearch;
+
+    private LocalDateTime created;
+
+    private Integer creater;
+
+    private LocalDateTime modified;
+
+    private Integer modifier;
+
+    private String uuid;
+
+    private String canceled;
+
+
+}

+ 416 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmresource.java

@@ -0,0 +1,416 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ *
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Hrmresource对象", description="")
+public class Hrmresource implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId("ID")
+    private Integer id;
+
+    @TableField("LOGINID")
+    private String loginid;
+
+    @TableField("PASSWORD")
+    private String password;
+
+    @TableField("LASTNAME")
+    private String lastname;
+
+    @TableField("SEX")
+    private String sex;
+
+    @TableField("BIRTHDAY")
+    private String birthday;
+
+    @TableField("NATIONALITY")
+    private Integer nationality;
+
+    @TableField("SYSTEMLANGUAGE")
+    private Integer systemlanguage;
+
+    @TableField("MARITALSTATUS")
+    private String maritalstatus;
+
+    @TableField("TELEPHONE")
+    private String telephone;
+
+    @TableField("MOBILE")
+    private String mobile;
+
+    @TableField("MOBILECALL")
+    private String mobilecall;
+
+    @TableField("EMAIL")
+    private String email;
+
+    @TableField("LOCATIONID")
+    private Integer locationid;
+
+    @TableField("WORKROOM")
+    private String workroom;
+
+    @TableField("HOMEADDRESS")
+    private String homeaddress;
+
+    @TableField("RESOURCETYPE")
+    private String resourcetype;
+
+    @TableField("STARTDATE")
+    private String startdate;
+
+    @TableField("ENDDATE")
+    private String enddate;
+
+    @TableField("JOBTITLE")
+    private Integer jobtitle;
+
+    @TableField("JOBACTIVITYDESC")
+    private String jobactivitydesc;
+
+    @TableField("JOBLEVEL")
+    private Integer joblevel;
+
+    @TableField("SECLEVEL")
+    private Integer seclevel;
+
+    @TableField("DEPARTMENTID")
+    private Integer departmentid;
+
+    @TableField("SUBCOMPANYID1")
+    private Long subcompanyid1;
+
+    @TableField("COSTCENTERID")
+    private Integer costcenterid;
+
+    @TableField("MANAGERID")
+    private Integer managerid;
+
+    @TableField("ASSISTANTID")
+    private Integer assistantid;
+
+    @TableField("BANKID1")
+    private Integer bankid1;
+
+    @TableField("ACCOUNTID1")
+    private String accountid1;
+
+    @TableField("RESOURCEIMAGEID")
+    private Integer resourceimageid;
+
+    @TableField("CREATERID")
+    private Integer createrid;
+
+    @TableField("CREATEDATE")
+    private String createdate;
+
+    @TableField("LASTMODID")
+    private Integer lastmodid;
+
+    @TableField("LASTMODDATE")
+    private String lastmoddate;
+
+    @TableField("LASTLOGINDATE")
+    private String lastlogindate;
+
+    @TableField("DATEFIELD1")
+    private String datefield1;
+
+    @TableField("DATEFIELD2")
+    private String datefield2;
+
+    @TableField("DATEFIELD3")
+    private String datefield3;
+
+    @TableField("DATEFIELD4")
+    private String datefield4;
+
+    @TableField("DATEFIELD5")
+    private String datefield5;
+
+    @TableField("NUMBERFIELD1")
+    private Double numberfield1;
+
+    @TableField("NUMBERFIELD2")
+    private Double numberfield2;
+
+    @TableField("NUMBERFIELD3")
+    private Double numberfield3;
+
+    @TableField("NUMBERFIELD4")
+    private Double numberfield4;
+
+    @TableField("NUMBERFIELD5")
+    private Double numberfield5;
+
+    @TableField("TEXTFIELD1")
+    private String textfield1;
+
+    @TableField("TEXTFIELD2")
+    private String textfield2;
+
+    @TableField("TEXTFIELD3")
+    private String textfield3;
+
+    @TableField("TEXTFIELD4")
+    private String textfield4;
+
+    @TableField("TEXTFIELD5")
+    private String textfield5;
+
+    @TableField("TINYINTFIELD1")
+    private Integer tinyintfield1;
+
+    @TableField("TINYINTFIELD2")
+    private Integer tinyintfield2;
+
+    @TableField("TINYINTFIELD3")
+    private Integer tinyintfield3;
+
+    @TableField("TINYINTFIELD4")
+    private Integer tinyintfield4;
+
+    @TableField("TINYINTFIELD5")
+    private Integer tinyintfield5;
+
+    @TableField("CERTIFICATENUM")
+    private String certificatenum;
+
+    @TableField("NATIVEPLACE")
+    private String nativeplace;
+
+    @TableField("EDUCATIONLEVEL")
+    private Integer educationlevel;
+
+    @TableField("BEMEMBERDATE")
+    private String bememberdate;
+
+    @TableField("BEPARTYDATE")
+    private String bepartydate;
+
+    @TableField("WORKCODE")
+    private String workcode;
+
+    @TableField("REGRESIDENTPLACE")
+    private String regresidentplace;
+
+    @TableField("HEALTHINFO")
+    private String healthinfo;
+
+    @TableField("RESIDENTPLACE")
+    private String residentplace;
+
+    @TableField("POLICY")
+    private String policy;
+
+    @TableField("DEGREE")
+    private String degree;
+
+    @TableField("HEIGHT")
+    private String height;
+
+    @TableField("USEKIND")
+    private Integer usekind;
+
+    @TableField("JOBCALL")
+    private Integer jobcall;
+
+    @TableField("ACCUMFUNDACCOUNT")
+    private String accumfundaccount;
+
+    @TableField("BIRTHPLACE")
+    private String birthplace;
+
+    @TableField("FOLK")
+    private String folk;
+
+    @TableField("RESIDENTPHONE")
+    private String residentphone;
+
+    @TableField("RESIDENTPOSTCODE")
+    private String residentpostcode;
+
+    @TableField("EXTPHONE")
+    private String extphone;
+
+    @TableField("MANAGERSTR")
+    private String managerstr;
+
+    @TableField("STATUS")
+    private Integer status;
+
+    @TableField("FAX")
+    private String fax;
+
+    @TableField("ISLABOUUNION")
+    private String islabouunion;
+
+    @TableField("WEIGHT")
+    private Integer weight;
+
+    @TableField("TEMPRESIDENTNUMBER")
+    private String tempresidentnumber;
+
+    @TableField("PROBATIONENDDATE")
+    private String probationenddate;
+
+    @TableField("COUNTRYID")
+    private Integer countryid;
+
+    @TableField("PASSWDCHGDATE")
+    private String passwdchgdate;
+
+    @TableField("NEEDUSB")
+    private Integer needusb;
+
+    @TableField("SERIAL")
+    private String serial;
+
+    @TableField("ACCOUNT")
+    private String account;
+
+    @TableField("LLOGINID")
+    private String lloginid;
+
+    @TableField("NEEDDYNAPASS")
+    private Integer needdynapass;
+
+    @TableField("DSPORDER")
+    private Double dsporder;
+
+    @TableField("PASSWORDSTATE")
+    private Integer passwordstate;
+
+    @TableField("ACCOUNTTYPE")
+    private Integer accounttype;
+
+    @TableField("BELONGTO")
+    private Integer belongto;
+
+    @TableField("DACTYLOGRAM")
+    private String dactylogram;
+
+    @TableField("ASSISTANTDACTYLOGRAM")
+    private String assistantdactylogram;
+
+    @TableField("PASSWORDLOCK")
+    private Integer passwordlock;
+
+    @TableField("SUMPASSWORDWRONG")
+    private Integer sumpasswordwrong;
+
+    @TableField("OLDPASSWORD1")
+    private String oldpassword1;
+
+    @TableField("OLDPASSWORD2")
+    private String oldpassword2;
+
+    @TableField("MSGSTYLE")
+    private String msgstyle;
+
+    @TableField("MESSAGERURL")
+    private String messagerurl;
+
+    private String pinyinlastname;
+
+    @TableField("TOKENKEY")
+    private String tokenkey;
+
+    @TableField("USERUSBTYPE")
+    private String userusbtype;
+
+    @TableField("OUTKEY")
+    private String outkey;
+
+    @TableField("ADSJGS")
+    private String adsjgs;
+
+    @TableField("ADGS")
+    private String adgs;
+
+    @TableField("ADBM")
+    private String adbm;
+
+    @TableField("MOBILESHOWTYPE")
+    private Integer mobileshowtype;
+
+    @TableField("USBSTATE")
+    private Integer usbstate;
+
+    @TableField("TOTALSPACE")
+    private Double totalspace;
+
+    @TableField("OCCUPYSPACE")
+    private Double occupyspace;
+
+    @TableField("ECOLOGY_PINYIN_SEARCH")
+    private String ecologyPinyinSearch;
+
+    @TableField("ISADACCOUNT")
+    private String isadaccount;
+
+    @TableField("ACCOUNTNAME")
+    private String accountname;
+
+    private String haschangepwd;
+
+    private LocalDateTime created;
+
+    private Integer creater;
+
+    private LocalDateTime modified;
+
+    private Integer modifier;
+
+    private LocalDateTime passwordlocktime;
+
+    private String mobilecaflag;
+
+    private String salt;
+
+    private String companystartdate;
+
+    private String workstartdate;
+
+    @TableField("secondaryPwd")
+    private String secondarypwd;
+
+    @TableField("useSecondaryPwd")
+    private Integer usesecondarypwd;
+
+    private String classification;
+
+    private String uuid;
+
+    @TableField("passwordLockReason")
+    private String passwordlockreason;
+
+    private BigDecimal companyworkyear;
+
+    private BigDecimal workyear;
+
+    @TableField("DISMISSDATE")
+    private String dismissdate;
+
+
+}

+ 83 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/Hrmsubcompany.java

@@ -0,0 +1,83 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ *
+ *
+ * @author blank
+ * @since 2021-03-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="Hrmsubcompany对象", description="")
+public class Hrmsubcompany implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @TableField("SUBCOMPANYNAME")
+    private String subcompanyname;
+
+    @TableField("SUBCOMPANYDESC")
+    private String subcompanydesc;
+
+    @TableField("COMPANYID")
+    private Long companyid;
+
+    @TableField("SUPSUBCOMID")
+    private Long supsubcomid;
+
+    @TableField("URL")
+    private String url;
+
+    @TableField("CANCELED")
+    private String canceled;
+
+    @TableField("SUBCOMPANYCODE")
+    private String subcompanycode;
+
+    @TableField("OUTKEY")
+    private String outkey;
+
+    @TableField("BUDGETATUOMOVEORDER")
+    private Integer budgetatuomoveorder;
+
+    @TableField("ECOLOGY_PINYIN_SEARCH")
+    private String ecologyPinyinSearch;
+
+    @TableField("LIMITUSERS")
+    private Integer limitusers;
+
+    @TableField("TLEVEL")
+    private Integer tlevel;
+
+    private LocalDateTime created;
+
+    private Integer creater;
+
+    private LocalDateTime modified;
+
+    private Integer modifier;
+
+    private String uuid;
+
+    private Double showorder;
+
+    @TableField("showOrderOfTree")
+    private Integer showorderoftree;
+
+
+}

+ 38 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/JobEntity.java

@@ -0,0 +1,38 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * <p>
+ * 部门表
+ * <p>
+ *
+ * @Author Steve
+ * @Since  2019-01-22
+ */
+@Data
+@TableName("job")
+public class JobEntity extends SysBaseField {
+    private static final long serialVersionUID = 1L;
+
+	@TableId(type = IdType.INPUT)
+	private Long id;
+
+	@ApiModelProperty(value = "岗位名称")
+	private String name;
+
+	@ApiModelProperty(value = "部门id")
+	private Long deptId;
+
+ 	@TableField("`desc`")
+	private String desc;
+
+	@ApiModelProperty(value = "数据来源")
+	private Integer dataSource;
+}

+ 47 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/SubCompanyEntity.java

@@ -0,0 +1,47 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="分公司对象", description="分公司对象详细信息")
+@TableName("sub_company")
+public class SubCompanyEntity extends SysBaseField {
+
+    @ApiModelProperty(value = "分公司ID")
+    @TableId(type = IdType.INPUT)
+    private Long id;
+
+    @ApiModelProperty(value = "公司ID")
+    private Long companyId;
+
+    @ApiModelProperty(value = "分公司名称")
+    private String name;
+
+    @ApiModelProperty(value = "描述")
+    @TableField("`desc`")
+    private String desc;
+
+    @ApiModelProperty(value = "公司负责人")
+    private Long leaderId;
+
+    @ApiModelProperty(value = "路由code")
+    private String routeCode;
+
+    @ApiModelProperty(value = "数据来源")
+    private Integer dataSource;
+
+    @ApiModelProperty(value = "部门负责人")
+    private String leaderName;
+
+}

+ 137 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/UserEntity.java

@@ -0,0 +1,137 @@
+package com.storlead.user.pojo.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.storlead.framework.mybatis.entity.SysBaseField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+import java.util.Date;
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("com/storlead/user")
+public class UserEntity extends SysBaseField {
+
+    @TableId(type = IdType.INPUT)
+    @ApiModelProperty(value = "用户ID")
+    private Long id;
+
+    @ApiModelProperty(value = "用户名")
+    private String userName;
+
+    private String password;
+
+    private String xworkUserId;
+
+    @ApiModelProperty(value = "头像")
+    private String avatar;
+
+    @ApiModelProperty(value = "性别")
+    private String sex;
+
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @ApiModelProperty(value = "姓名")
+    private String realName;
+
+    @ApiModelProperty(value = "手机号")
+    private String mobile;
+
+    @ApiModelProperty(value = "email")
+    private String email;
+
+    @ApiModelProperty(value = "岗位ID")
+    private Long jobId;
+
+    @ApiModelProperty(value = "部门ID")
+    private Long deptId;
+
+    @ApiModelProperty(value = "分公司ID")
+    private Long subCompanyId;
+
+    @ApiModelProperty(value = "公司ID")
+    private Long companyId;
+
+    @ApiModelProperty(value = "直接上级ID")
+    private Long managerId;
+
+    @ApiModelProperty(value = "领导路由")
+    private String managers;
+
+    private String idNum;
+    private String address;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern="yyyy-MM-dd")
+    private LocalDate birthday;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern="yyyy-MM-dd")
+    private LocalDate entryDate;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern="yyyy-MM-dd")
+    private LocalDate permanentDate;
+
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern="yyyy-MM-dd")
+    private LocalDate resignDate;
+    private String bankName;
+    private String bankCardNum;
+
+    @ApiModelProperty(value = "状态 0:试用期 1:正式期 2:临时 3:试用延期 5:离职流程")
+    private String status;
+    private Integer isShenzhenCensus;
+    private String census;
+    private String ethnic;
+    private String marriage;
+    private String education;
+    @ApiModelProperty(value = "是否负责人:0 否,1分公司负责人,2部门负责人")
+    private Integer isLeader;
+
+    @ApiModelProperty(value = "0:任何都不允许登录,1:允许登录销售管理系统,9::允许登录许昌监督项目")
+    private Integer externalUserType;
+
+    @ApiModelProperty(value = "数据权限")
+    @TableField(exist = false)
+    private String dataScope;
+
+    @ApiModelProperty(value = "测试")
+    @TableField(exist = false)
+    private Integer test;
+
+    @ApiModelProperty(value = "是否冻结: 1 冻结,0:未冻结")
+    private Integer isFreeze;
+
+
+    @ApiModelProperty(value = "组织路由")
+    private String orgRouteCode;
+
+    @ApiModelProperty(value = "数据来源")
+    private Integer dataSource;
+
+    @ApiModelProperty(value = "岗位职责")
+    private String jobDes;
+
+    @ApiModelProperty(value = "最近的活动时间")
+    private Date lastActivityTime;
+
+    public UserEntity(Long id, String userName, String password) {
+        this.id = id;
+        this.userName = userName;
+        this.password = password;
+    }
+}

+ 29 - 0
storlead-user/src/main/java/com/storlead/user/pojo/entity/UserForm.java

@@ -0,0 +1,29 @@
+package com.storlead.user.pojo.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @program: sp-sales
+ * @description: 修改用户密码form
+ * @author: xiaojiawei
+ * @create: 2022-03-08 17:53
+ **/
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "用户类", description = "用户请求参数对象")
+public class UserForm {
+    @ApiModelProperty(value = "原密码")
+    @NotBlank(message = "原密码不能为空")
+    private String password;
+
+    @ApiModelProperty(value = "新密码")
+    @NotBlank(message = "新密码不能为空")
+    private String newPass;
+}

+ 20 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/ApiDataQuery.java

@@ -0,0 +1,20 @@
+package com.storlead.user.pojo.vo;
+
+import com.storlead.common.object.Page;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class ApiDataQuery extends Page {
+
+//    @ApiModelProperty(value = "应用id")
+//    private Long appId;
+    @ApiModelProperty(value = "菜单code")
+    private Integer permissionType;
+    @ApiModelProperty(value = "组id")
+    private Long groupId;
+    @ApiModelProperty(value = "组code")
+    private String groupCode;
+    @ApiModelProperty(value = "菜单code")
+    private String menuCode;
+}

+ 35 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/AppServiceVO.java

@@ -0,0 +1,35 @@
+package com.storlead.user.pojo.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-07-13 14:27
+ */
+@Data
+public class AppServiceVO {
+
+    @ApiModelProperty(value = "主键id" )
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "应用名称" )
+    private String appName;
+
+    @ApiModelProperty(value = "应用Code" )
+    private String appCode;
+
+    @ApiModelProperty(value = "应用英文标识(机器识别)" )
+    private String appTag;
+
+    @ApiModelProperty(value = "前台展示名称" )
+    private String appTitle;
+
+    @ApiModelProperty(value = "应用名称" )
+    private String appDescribe;
+}

+ 22 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/DateInfoVO.java

@@ -0,0 +1,22 @@
+package com.storlead.user.pojo.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+/**
+ * DateInfoVO
+ *
+ * @author blank
+ * @date 2021-3-18 下午 3:03
+ */
+@Data
+public class DateInfoVO implements Serializable {
+    private static final long serialVersionUID = -8179374640095915823L;
+
+    private Long subCompanyId;
+    private String dateType;
+    private LocalDate date;
+    private String dateDesc;
+}

+ 141 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/DepartmentTree.java

@@ -0,0 +1,141 @@
+package com.storlead.user.pojo.vo;
+
+import com.storlead.user.pojo.entity.CompanyEntity;
+import com.storlead.user.pojo.entity.DeptEntity;
+import com.storlead.user.pojo.entity.SubCompanyEntity;
+import lombok.Data;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-05-13 15:55
+ */
+@Data
+public class DepartmentTree {
+
+    private Long id;
+    private String treeId;
+    private Long parentId;
+    private String title;
+    private String code;
+    private Object arg;
+    private String photo;
+    private String avatar;
+    private Long leaderId;
+    private String leaderName;
+    private Boolean checked = false;
+    private Boolean _showChildren = true;
+    private Boolean expand = false;
+    private Boolean disableCheckbox = false;
+    private Boolean disabled = true;
+    /**
+     * 类型:10: 集团,20:公司 30:部门 40:小组,99:人员
+     */
+    private Integer type;
+    private List<DepartmentTree> children;
+
+
+    /**
+     * 公司转换
+     * @param vals
+     * @return
+     */
+    public static List<DepartmentTree> companyListToDepartmentTreeVoList(List<CompanyEntity> vals) {
+        if (CollectionUtils.isEmpty(vals)) {
+            return null;
+        }
+        List<DepartmentTree> departmentTrees = vals.stream().map(DepartmentTree::companyToDepartmentTreeVo).filter(obj -> !Objects.isNull(obj)).collect(Collectors.toList());
+        return departmentTrees;
+    }
+
+    public static DepartmentTree  companyToDepartmentTreeVo(CompanyEntity val) {
+        if (null == val) {
+            return null;
+        }
+        DepartmentTree departmentTree = new DepartmentTree();
+
+        departmentTree.setId(val.getId());
+        departmentTree.setParentId(0L);
+        departmentTree.setTitle(val.getName());
+        departmentTree.set_showChildren(true);
+        // departmentTree.setCode(d.getOrgCode());
+        departmentTree.setArg(val);
+        departmentTree.setType(Integer.valueOf(10));
+        departmentTree.setTreeId(departmentTree.getType()+"-"+val.getId());
+        return departmentTree;
+    }
+
+    /**
+     * 子公司转换
+     * @param vals
+     * @return
+     */
+    public static List<DepartmentTree> subCompanyListToDepartmentTreeVoList(List<SubCompanyEntity> vals) {
+        if (CollectionUtils.isEmpty(vals)) {
+            return null;
+        }
+        List<DepartmentTree> departmentTrees = vals.stream().map(DepartmentTree::subCompanyToDepartmentTreeVo).filter(obj -> !Objects.isNull(obj)).collect(Collectors.toList());
+        return departmentTrees;
+    }
+
+    public static DepartmentTree  subCompanyToDepartmentTreeVo(SubCompanyEntity val) {
+        if (null == val) {
+            return null;
+        }
+        DepartmentTree departmentTree = new DepartmentTree();
+        departmentTree.setId(val.getId());
+        departmentTree.setParentId(val.getCompanyId());
+        departmentTree.setTitle(val.getName());
+        departmentTree.set_showChildren(false);
+        departmentTree.setLeaderName(val.getLeaderName());
+        departmentTree.setLeaderId(val.getLeaderId());
+        departmentTree.setArg(val);
+        departmentTree.setType(Integer.valueOf(20));
+        departmentTree.setTreeId(departmentTree.getType()+"-"+val.getId());
+
+        return departmentTree;
+    }
+
+
+    /**
+     * 部门转换
+     * @param vals
+     * @return
+     */
+    public static List<DepartmentTree> deptListToDepartmentTreeVoList(List<DeptEntity> vals) {
+        if (CollectionUtils.isEmpty(vals)) {
+            return null;
+        }
+        List<DepartmentTree> departmentTrees = vals.stream().map(DepartmentTree::deptToDepartmentTreeVo).filter(obj -> !Objects.isNull(obj)).collect(Collectors.toList());
+        return departmentTrees;
+    }
+
+    public static DepartmentTree  deptToDepartmentTreeVo(DeptEntity val) {
+        if (null == val) {
+            return null;
+        }
+        DepartmentTree departmentTree = new DepartmentTree();
+        departmentTree.setId(val.getId());
+        if(Long.valueOf(0).equals(val.getPid())) {
+            departmentTree.setParentId(val.getSubCompanyId());
+        } else {
+            departmentTree.setParentId(val.getPid());
+        }
+        departmentTree.set_showChildren(false);
+        departmentTree.setTitle(val.getName());
+        departmentTree.setLeaderName(val.getLeaderName());
+        departmentTree.setLeaderId(val.getManagerId());
+        departmentTree.setArg(val);
+        departmentTree.setType(Integer.valueOf(30));
+        departmentTree.setTreeId(departmentTree.getType()+"-"+val.getId());
+
+        return departmentTree;
+    }
+
+}

+ 26 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/DeptTreeVO.java

@@ -0,0 +1,26 @@
+package com.storlead.user.pojo.vo;
+
+import com.storlead.user.pojo.entity.UserEntity;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * hrm 部门树列表vo
+ * DeptTreeVO
+ *
+ * @author blank
+ * @date 2021-3-8 下午 3:46
+ */
+@Data
+public class DeptTreeVO implements Serializable {
+    private static final long serialVersionUID = -624966431749742391L;
+
+    private Long id;
+    private String name;
+
+    private List<DeptTreeVO> childList;
+    private List<UserEntity> userList;
+
+}

+ 35 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/DeptWxVo.java

@@ -0,0 +1,35 @@
+package com.storlead.user.pojo.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-09-01 15:52
+ */
+@Data
+public class DeptWxVo {
+
+    private List<DeptWxVo> childs;
+
+    private Long orgId;
+
+    private Long companyId;
+
+    private Long subCompanyId;
+
+    private Long parentId;
+
+    private String orgRoute;
+
+    private String orgName;
+
+    private String orgNameRoute;
+
+    private String pOrgNameRoute;
+
+    private Integer type = 0;
+}

+ 33 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/MenuResTreeVo.java

@@ -0,0 +1,33 @@
+package com.storlead.user.pojo.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @program: sp-cloud
+ * @description:
+ * @author: chenkq
+ * @create: 2022-05-26 09:42
+ */
+@Data
+public class MenuResTreeVo {
+    private Long id;
+    private String treeId;
+    private Long parentId;
+    private Long appId;
+    private String title;
+    private String code;
+    private Object arg;
+    private Boolean checked = false;
+    private Boolean _showChildren = true;
+    private Boolean expand = false;
+    private Boolean disableCheckbox = false;
+    private Boolean disabled = false;
+    /**
+     * 10:应用,20:菜单,30:权限资源
+     */
+    private Integer type;
+    private List<MenuResTreeVo> children;
+
+}

+ 52 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/SetUserDetailVo.java

@@ -0,0 +1,52 @@
+package com.storlead.user.pojo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-08-23 14:58
+ */
+@Data
+public class SetUserDetailVo implements Serializable  {
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "用户名")
+    private String userName;
+
+    @ApiModelProperty(value = "头像")
+    private String avatar;
+
+    @ApiModelProperty(value = "岗位ID")
+    private Long jobId;
+
+    @ApiModelProperty(value = "部门ID")
+    private Long deptId;
+
+    @ApiModelProperty(value = "岗位ID")
+    private String jobName;
+
+    @ApiModelProperty(value = "部门")
+    private String deptName;
+
+    @ApiModelProperty(value = "手机号")
+    private String mobile;
+
+    @ApiModelProperty(value = "邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "部门岗位职责")
+    private String deptJobDes;
+
+    @ApiModelProperty(value = "岗位职责")
+    private String jobDes;
+
+    @ApiModelProperty(value = "是否是领导")
+    private Integer isLeader;
+}

+ 42 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/UserVo.java

@@ -0,0 +1,42 @@
+package com.storlead.user.pojo.vo;
+
+import com.storlead.user.pojo.entity.UserEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+
+/**
+ * UserVO
+ *
+ * @author blank
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class UserVo extends UserEntity {
+
+    @ApiModelProperty(value = "岗位名称")
+    private String jobName;
+
+    @ApiModelProperty(value = "直接领导")
+    private String managerName;
+
+    @ApiModelProperty(value = "部门名称")
+    private String deptName;
+
+    @ApiModelProperty(value = "岗位职责")
+    private String deptJobDes;
+
+    @ApiModelProperty(value = "角色名称")
+    private List<String> roleNames;
+
+    @ApiModelProperty(value = "角色Id")
+    private List<Long> roleIds;
+
+}

+ 13 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/WeChatPhone.java

@@ -0,0 +1,13 @@
+package com.storlead.user.pojo.vo;
+
+import lombok.Data;
+
+@Data
+public class WeChatPhone{
+    // getPhoneNumber接口返回的code
+    private String code;
+    // 小程序的appid(一般是在程序中配置,不需要前端传参)
+    private String appid;
+    // 小程序的secretKey(一般是在程序中配置,不需要前端传参)
+    private String secretKey;
+}

+ 15 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/WeChatPhoneInfo.java

@@ -0,0 +1,15 @@
+package com.storlead.user.pojo.vo;
+
+import lombok.Data;
+
+@Data
+public class WeChatPhoneInfo {
+    // 用户绑定的手机号(国外手机号会有区号)
+    private String phoneNumber;
+    // 没有区号的手机号
+    private String purePhoneNumber;
+    // 区号
+    private String countryCode;
+    // 数据水印
+    private String watermark;
+}

+ 39 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/WxExcelOrgVo.java

@@ -0,0 +1,39 @@
+package com.storlead.user.pojo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-09-01 09:37
+ */
+@Data
+public class WxExcelOrgVo {
+
+    private String realName;
+
+    private String xworkUserId;
+
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @ApiModelProperty(value = "岗位")
+    private String jobName;
+
+    @ApiModelProperty(value = "部门")
+    private String deptName;
+
+    @ApiModelProperty(value = "性别")
+    private String sex;
+
+    @ApiModelProperty(value = "手机")
+    private String mobile;
+
+    @ApiModelProperty(value = "邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "是否启用(1:启用 0:禁用)")
+    private Boolean enabled;
+}

+ 21 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/WxUserInfo.java

@@ -0,0 +1,21 @@
+package com.storlead.user.pojo.vo;
+
+import lombok.Data;
+
+/**
+ * @program: sp-project-system
+ * @description:
+ * @author: chenkq
+ * @create: 2021-12-28 17:35
+ */
+@Data
+public class WxUserInfo {
+    private String userid;
+    private String position;
+    private String email;
+    private String alias;
+    private String address;
+    private Integer gender;
+    private Integer status;
+    private Integer qr_code;
+}

+ 22 - 0
storlead-user/src/main/java/com/storlead/user/pojo/vo/WxUserVO.java

@@ -0,0 +1,22 @@
+package com.storlead.user.pojo.vo;
+
+import com.storlead.user.model.UserInfo;
+import lombok.Data;
+
+import java.util.List;
+
+
+/**
+ * UserVO
+ *
+ * @author YPZ
+ */
+@Data
+public class WxUserVO  {
+
+    //拼音首字母
+    private String letter;
+    //用户列表
+    private List<UserInfo> data;
+
+}

+ 21 - 0
storlead-user/src/main/java/com/storlead/user/property/UserSystemConfigProperties.java

@@ -0,0 +1,21 @@
+package com.storlead.user.property;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @program: sp-sales
+ * @description:
+ * @author: chenkq
+ * @create: 2022-07-20 10:24
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "system.config")
+public class UserSystemConfigProperties {
+
+    @Value("")
+    private Integer orgSyncMode;
+}

+ 9 - 0
storlead-user/src/main/java/com/storlead/user/service/ICompanyService.java

@@ -0,0 +1,9 @@
+package com.storlead.user.service;
+
+import com.storlead.framework.mybatis.service.MyBaseService;
+import com.storlead.user.pojo.entity.CompanyEntity;
+
+public interface ICompanyService extends MyBaseService<CompanyEntity> {
+
+    void truncateTable();
+}

+ 79 - 0
storlead-user/src/main/java/com/storlead/user/service/IDepartService.java

@@ -0,0 +1,79 @@
+package com.storlead.user.service;
+
+import com.storlead.framework.mybatis.service.MyBaseService;
+import com.storlead.user.model.DepartIdModel;
+import com.storlead.user.model.DeptTreeModel;
+import com.storlead.user.pojo.entity.DeptEntity;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>
+ * 部门表 服务实现类
+ * <p>
+ *
+ * @Author:Steve
+ * @Since:   2019-01-22
+ */
+public interface IDepartService extends MyBaseService<DeptEntity> {
+
+    /**
+     * 查询所有部门信息,并分节点进行显示
+     * @return
+     */
+    void truncateDept();
+
+    /**
+     * 查询所有部门信息,并分节点进行显示
+     * @return
+     */
+    List<DeptTreeModel> queryTreeList();
+
+    List<DeptTreeModel> queryTreeListWithSubCompanyId(Integer subCompanyId);
+
+    /**
+     * 查询所有部门DepartId信息,并分节点进行显示
+     * @return
+     */
+    public List<DepartIdModel> queryDepartIdTreeList();
+
+    /**
+     * 根据关键字搜索相关的部门数据
+     * @param keyWord
+     * @return
+     */
+    List<DeptTreeModel> searhBy(String keyWord);
+
+
+    List<DeptTreeModel> queryDeptBySubList(Integer subCompanyId);
+
+
+    Set<Long> findDeptIdsBySubCompanyId(Long subCompanyId);
+
+    /**
+     * 根据角色ID查询部门列表
+     *
+     * @param id 角色ID
+     * @return java.util.Set<com.storlead.salary.entity.Dept>
+     * @author blank
+     * @date 2020-3-16 下午 3:34
+     */
+    Set<DeptEntity> findByRoleId(Long id);
+
+    /**
+     * 根据父ID查询部门列表
+     *
+     * @param id pid
+     * @return java.util.List<com.storlead.salary.entity.Dept>
+     * @author blank
+     * @date 2020-3-16 下午 3:38
+     */
+    List<DeptEntity> findByPid(Long id);
+
+
+    List<Long> getDeptChildren(List<DeptEntity> deptList);
+
+    Map<Long, DeptEntity> getDeptMap(List<Long> deptIdList);
+}

+ 8 - 0
storlead-user/src/main/java/com/storlead/user/service/IHrmcompanyService.java

@@ -0,0 +1,8 @@
+package com.storlead.user.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.storlead.user.pojo.entity.Hrmcompany;
+
+public interface IHrmcompanyService extends IService<Hrmcompany> {
+
+}

+ 8 - 0
storlead-user/src/main/java/com/storlead/user/service/IHrmdepartmentService.java

@@ -0,0 +1,8 @@
+package com.storlead.user.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.storlead.user.pojo.entity.Hrmdepartment;
+
+public interface IHrmdepartmentService extends IService<Hrmdepartment> {
+
+}

+ 8 - 0
storlead-user/src/main/java/com/storlead/user/service/IHrmdepartmentdefinedService.java

@@ -0,0 +1,8 @@
+package com.storlead.user.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.storlead.user.pojo.entity.Hrmdepartmentdefined;
+
+public interface IHrmdepartmentdefinedService extends IService<Hrmdepartmentdefined> {
+
+}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.