qzyReal 2 years ago
commit
0bf2cb0f48
100 changed files with 7726 additions and 0 deletions
  1. 16 0
      .gitignore
  2. 23 0
      business-system/alarm-system/pom.xml
  3. 15 0
      business-system/alarm-system/src/main/java/com/pj/KKController.java
  4. 16 0
      business-system/filing-system/pom.xml
  5. 100 0
      business-system/filing-system/src/main/java/com/pj/biz/TbCarBlackController.java
  6. 99 0
      business-system/filing-system/src/main/java/com/pj/biz/TbCarFilingController.java
  7. 100 0
      business-system/filing-system/src/main/java/com/pj/biz/TbPersonBlackController.java
  8. 100 0
      business-system/filing-system/src/main/java/com/pj/biz/TbPersonFilingController.java
  9. 27 0
      business-system/pom.xml
  10. 25 0
      business-system/venues-system/pom.xml
  11. 89 0
      business-system/venues-system/src/main/java/com/pj/biz/TbChannelController.java
  12. 89 0
      business-system/venues-system/src/main/java/com/pj/biz/TbTerminalController.java
  13. 89 0
      business-system/venues-system/src/main/java/com/pj/biz/TbVenuesController.java
  14. 16 0
      business-system/venues-system/src/main/java/com/pj/biz/UserController.java
  15. 92 0
      business-system/venues-system/src/main/java/com/pj/netty/HeartBeatHandler.java
  16. 49 0
      business-system/venues-system/src/main/java/com/pj/netty/NettyServer.java
  17. 18 0
      business-system/venues-system/src/main/java/com/pj/netty/NettyServerChannelInitializer.java
  18. 156 0
      business-system/venues-system/src/main/java/com/pj/netty/NettyServerHandler.java
  19. 22 0
      business-system/venues-system/src/main/java/com/pj/netty/StartNetty.java
  20. 174 0
      pom.xml
  21. 30 0
      sp-admin/pom.xml
  22. 80 0
      sp-admin/src/main/java/com/pj/project4sp/admin/SpAdmin.java
  23. 193 0
      sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminController.java
  24. 77 0
      sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminMapper.java
  25. 111 0
      sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminMapper.xml
  26. 68 0
      sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminService.java
  27. 94 0
      sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminUtil.java
  28. 73 0
      sp-admin/src/main/java/com/pj/project4sp/admin4acc/SpAccAdminController.java
  29. 138 0
      sp-admin/src/main/java/com/pj/project4sp/admin4acc/SpAccAdminService.java
  30. 89 0
      sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLogin.java
  31. 63 0
      sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLoginController.java
  32. 47 0
      sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLoginMapper.java
  33. 70 0
      sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLoginMapper.xml
  34. 46 0
      sp-admin/src/main/java/com/pj/project4sp/admin4password/SpAdminPasswordController.java
  35. 34 0
      sp-admin/src/main/java/com/pj/project4sp/admin4password/SpAdminPasswordService.java
  36. 6 0
      sp-admin/src/main/java/com/pj/project4sp/package-info.java
  37. 90 0
      sp-admin/src/main/java/com/pj/project4sp/redis4console/RedisConsoleController.java
  38. 190 0
      sp-admin/src/main/java/com/pj/project4sp/redis4console/RedisConsoleUtil.java
  39. 35 0
      sp-admin/src/main/java/com/pj/project4sp/role/SpRole.java
  40. 84 0
      sp-admin/src/main/java/com/pj/project4sp/role/SpRoleController.java
  41. 60 0
      sp-admin/src/main/java/com/pj/project4sp/role/SpRoleMapper.java
  42. 62 0
      sp-admin/src/main/java/com/pj/project4sp/role/SpRoleMapper.xml
  43. 104 0
      sp-admin/src/main/java/com/pj/project4sp/role/SpRoleUtil.java
  44. 70 0
      sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionController.java
  45. 42 0
      sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionMapper.java
  46. 26 0
      sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionMapper.xml
  47. 55 0
      sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionService.java
  48. 27 0
      sp-admin/src/main/java/com/pj/project4sp/test/TestController.java
  49. 48 0
      sp-admin/src/main/java/com/pj/satoken/StpInterfaceImpl.java
  50. 21 0
      sp-core/pom.xml
  51. 56 0
      sp-core/src/main/java/com/pj/current/SaPlusStartup.java
  52. 54 0
      sp-core/src/main/java/com/pj/current/config/MyConfig.java
  53. 72 0
      sp-core/src/main/java/com/pj/current/config/PerformConfigure.java
  54. 38 0
      sp-core/src/main/java/com/pj/current/config/ProjectConfigure.java
  55. 77 0
      sp-core/src/main/java/com/pj/current/config/RemoveDruidAdConfig.java
  56. 41 0
      sp-core/src/main/java/com/pj/current/config/SystemObject.java
  57. 57 0
      sp-core/src/main/java/com/pj/current/global/ApilogAspect.java
  58. 43 0
      sp-core/src/main/java/com/pj/current/global/ApilogStartInterceptor.java
  59. 46 0
      sp-core/src/main/java/com/pj/current/global/BusinessException.java
  60. 84 0
      sp-core/src/main/java/com/pj/current/global/GlobalExceptionHandler.java
  61. 40 0
      sp-core/src/main/java/com/pj/current/global/NotFoundHandle.java
  62. 150 0
      sp-core/src/main/java/com/pj/current/mybatis/MybatisMapperDynamicLoader.java
  63. 75 0
      sp-core/src/main/java/com/pj/current/mybatis/MybatisStdOutImpl.java
  64. 36 0
      sp-core/src/main/java/com/pj/current/mybatis/RefConfig.java
  65. 47 0
      sp-core/src/main/java/com/pj/current/satoken/AuthConst.java
  66. 71 0
      sp-core/src/main/java/com/pj/current/satoken/SaTokenConfigure.java
  67. 865 0
      sp-core/src/main/java/com/pj/current/satoken/StpUserUtil.java
  68. 54 0
      sp-core/src/main/java/com/pj/current/sentinel/SentinelConfigure.java
  69. 70 0
      sp-core/src/main/java/com/pj/project/sys_dict/SysDict.java
  70. 104 0
      sp-core/src/main/java/com/pj/project/sys_dict/SysDictController.java
  71. 28 0
      sp-core/src/main/java/com/pj/project/sys_dict/SysDictMapper.java
  72. 56 0
      sp-core/src/main/java/com/pj/project/sys_dict/SysDictMapper.xml
  73. 49 0
      sp-core/src/main/java/com/pj/project/sys_dict/SysDictService.java
  74. 102 0
      sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlack.java
  75. 30 0
      sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlackMapper.java
  76. 66 0
      sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlackMapper.xml
  77. 82 0
      sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlackService.java
  78. 132 0
      sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFiling.java
  79. 30 0
      sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFilingMapper.java
  80. 88 0
      sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFilingMapper.xml
  81. 96 0
      sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFilingService.java
  82. 100 0
      sp-core/src/main/java/com/pj/project/tb_channel/TbChannel.java
  83. 28 0
      sp-core/src/main/java/com/pj/project/tb_channel/TbChannelMapper.java
  84. 74 0
      sp-core/src/main/java/com/pj/project/tb_channel/TbChannelMapper.xml
  85. 49 0
      sp-core/src/main/java/com/pj/project/tb_channel/TbChannelService.java
  86. 65 0
      sp-core/src/main/java/com/pj/project/tb_channel/TbChannelUtil.java
  87. 105 0
      sp-core/src/main/java/com/pj/project/tb_dept/TbDept.java
  88. 98 0
      sp-core/src/main/java/com/pj/project/tb_dept/TbDeptController.java
  89. 28 0
      sp-core/src/main/java/com/pj/project/tb_dept/TbDeptMapper.java
  90. 73 0
      sp-core/src/main/java/com/pj/project/tb_dept/TbDeptMapper.xml
  91. 86 0
      sp-core/src/main/java/com/pj/project/tb_dept/TbDeptService.java
  92. 119 0
      sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlack.java
  93. 29 0
      sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlackMapper.java
  94. 69 0
      sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlackMapper.xml
  95. 79 0
      sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlackService.java
  96. 129 0
      sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFiling.java
  97. 31 0
      sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFilingMapper.java
  98. 78 0
      sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFilingMapper.xml
  99. 74 0
      sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFilingService.java
  100. 125 0
      sp-core/src/main/java/com/pj/project/tb_terminal/TbTerminal.java

+ 16 - 0
.gitignore

@@ -0,0 +1,16 @@
+target/
+.project
+.classpath
+.settings
+
+.factorypath
+
+/.idea/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+*.iml
+
+

+ 23 - 0
business-system/alarm-system/pom.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>business-system</artifactId>
+        <groupId>com.pj</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>alarm-system</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.pj</groupId>
+            <artifactId>sp-core</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 15 - 0
business-system/alarm-system/src/main/java/com/pj/KKController.java

@@ -0,0 +1,15 @@
+package com.pj;
+
+import com.pj.utils.sg.AjaxJson;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RequestMapping("kk")
+@RestController
+public class KKController {
+
+    @RequestMapping(value = "test")
+    public AjaxJson test(){
+        return AjaxJson.getSuccess();
+    }
+}

+ 16 - 0
business-system/filing-system/pom.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>business-system</artifactId>
+        <groupId>com.pj</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+
+    <artifactId>filing-system</artifactId>
+
+
+</project>

+ 100 - 0
business-system/filing-system/src/main/java/com/pj/biz/TbCarBlackController.java

@@ -0,0 +1,100 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import com.pj.project.tb_car_black.TbCarBlack;
+import com.pj.project.tb_car_black.TbCarBlackService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_car_black -- 车辆黑名单
+ *
+ * @author qzyReal
+ */
+@RestController
+@RequestMapping("/TbCarBlack/")
+public class TbCarBlackController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbCarBlackService tbCarBlackService;
+
+    /**
+     * 增
+     */
+    @RequestMapping("add")
+    @SaCheckPermission(TbCarBlack.PERMISSION_CODE_ADD)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson add(TbCarBlack t) {
+        tbCarBlackService.add(t);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 删
+     */
+    @RequestMapping("delete")
+    @SaCheckPermission(TbCarBlack.PERMISSION_CODE_DEL)
+    public AjaxJson delete(Long id) {
+        tbCarBlackService.delete(id);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 删 - 根据id列表
+     */
+    @RequestMapping("deleteByIds")
+    @SaCheckPermission(TbCarBlack.PERMISSION_CODE_DEL)
+    public AjaxJson deleteByIds() {
+        List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+        int line = SP.publicMapper.deleteByIds(TbCarBlack.TABLE_NAME, ids);
+        return AjaxJson.getByLine(line);
+    }
+
+    /**
+     * 改
+     */
+    @RequestMapping("update")
+    @SaCheckPermission(TbCarBlack.PERMISSION_CODE_EDIT)
+    public AjaxJson update(TbCarBlack t) {
+        tbCarBlackService.update(t);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    public AjaxJson getById(Long id) {
+        TbCarBlack t = tbCarBlackService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        long deptId = StpUserUtil.getDeptId();
+        if (deptId != StpUserUtil.ADMIN_DEPT_ID) {
+            so.put("deptId", deptId);
+        }
+        List<TbCarBlack> list = tbCarBlackService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+
+}

+ 99 - 0
business-system/filing-system/src/main/java/com/pj/biz/TbCarFilingController.java

@@ -0,0 +1,99 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import com.pj.current.satoken.StpUserUtil;
+import com.pj.project.tb_car_filing.TbCarFiling;
+import com.pj.project.tb_car_filing.TbCarFilingService;
+import com.pj.project4sp.SP;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_car_filing -- 车辆备案
+ *
+ * @author qzyReal
+ */
+@RestController
+@RequestMapping("/TbCarFiling/")
+public class TbCarFilingController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbCarFilingService tbCarFilingService;
+
+    /**
+     * 增
+     */
+    @RequestMapping("add")
+    @SaCheckPermission(TbCarFiling.PERMISSION_CODE_ADD)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson add(TbCarFiling t) {
+        tbCarFilingService.add(t);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 删
+     */
+    @RequestMapping("delete")
+    @SaCheckPermission(TbCarFiling.PERMISSION_CODE_DEL)
+    public AjaxJson delete(Long id) {
+        tbCarFilingService.delete(id);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 删 - 根据id列表
+     */
+    @RequestMapping("deleteByIds")
+    @SaCheckPermission(TbCarFiling.PERMISSION_CODE_DEL)
+    public AjaxJson deleteByIds() {
+        List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+        int line = SP.publicMapper.deleteByIds(TbCarFiling.TABLE_NAME, ids);
+        return AjaxJson.getByLine(line);
+    }
+
+    /**
+     * 改
+     */
+    @RequestMapping("update")
+    @SaCheckPermission(TbCarFiling.PERMISSION_CODE_DEL)
+    public AjaxJson update(TbCarFiling t) {
+        tbCarFilingService.update(t);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    public AjaxJson getById(Long id) {
+        TbCarFiling t = tbCarFilingService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        long deptId = StpUserUtil.getDeptId();
+        if (deptId != StpUserUtil.ADMIN_DEPT_ID) {
+            so.put("deptId", deptId);
+        }
+        List<TbCarFiling> list = tbCarFilingService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+
+}

+ 100 - 0
business-system/filing-system/src/main/java/com/pj/biz/TbPersonBlackController.java

@@ -0,0 +1,100 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import com.pj.project.tb_person_black.TbPersonBlack;
+import com.pj.project.tb_person_black.TbPersonBlackService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_person_black -- 人员黑名单
+ *
+ * @author qzyReal
+ */
+@RestController
+@RequestMapping("/TbPersonBlack/")
+public class TbPersonBlackController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbPersonBlackService tbPersonBlackService;
+
+    /**
+     * 增
+     */
+    @RequestMapping("add")
+    @SaCheckPermission(TbPersonBlack.PERMISSION_CODE_ADD)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson add(TbPersonBlack t) {
+        tbPersonBlackService.add(t);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 删
+     */
+    @RequestMapping("delete")
+    @SaCheckPermission(TbPersonBlack.PERMISSION_CODE_DEL)
+    public AjaxJson delete(Long id) {
+        tbPersonBlackService.delete(id);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 删 - 根据id列表
+     */
+    @RequestMapping("deleteByIds")
+    @SaCheckPermission(TbPersonBlack.PERMISSION_CODE_DEL)
+    public AjaxJson deleteByIds() {
+        List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+        int line = SP.publicMapper.deleteByIds(TbPersonBlack.TABLE_NAME, ids);
+        return AjaxJson.getByLine(line);
+    }
+
+    /**
+     * 改
+     */
+    @RequestMapping("update")
+    @SaCheckPermission(TbPersonBlack.PERMISSION_CODE_EDIT)
+    public AjaxJson update(TbPersonBlack t) {
+        tbPersonBlackService.update(t);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    public AjaxJson getById(Long id) {
+        TbPersonBlack t = tbPersonBlackService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        long deptId = StpUserUtil.getDeptId();
+        if (deptId != StpUserUtil.ADMIN_DEPT_ID) {
+            so.put("deptId", deptId);
+        }
+        List<TbPersonBlack> list = tbPersonBlackService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+
+}

+ 100 - 0
business-system/filing-system/src/main/java/com/pj/biz/TbPersonFilingController.java

@@ -0,0 +1,100 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.pj.project.tb_person_filing.TbPersonFiling;
+import com.pj.project.tb_person_filing.TbPersonFilingService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_person_filing -- 人员备案
+ *
+ * @author qzyReal
+ */
+@RestController
+@RequestMapping("/TbPersonFiling/")
+public class TbPersonFilingController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbPersonFilingService tbPersonFilingService;
+
+    /**
+     * 增
+     */
+    @RequestMapping("add")
+    @SaCheckPermission(TbPersonFiling.PERMISSION_CODE_ADD)
+    public AjaxJson add(TbPersonFiling t) {
+        tbPersonFilingService.add(t);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 删
+     */
+    @RequestMapping("delete")
+    @SaCheckPermission(TbPersonFiling.PERMISSION_CODE_DEL)
+    public AjaxJson delete(Integer id) {
+        tbPersonFilingService.delete(id);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 删 - 根据id列表
+     */
+    @RequestMapping("deleteByIds")
+    @SaCheckPermission(TbPersonFiling.PERMISSION_CODE_DEL)
+    public AjaxJson deleteByIds() {
+        List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+        int line = SP.publicMapper.deleteByIds(TbPersonFiling.TABLE_NAME, ids);
+        return AjaxJson.getByLine(line);
+    }
+
+    /**
+     * 改
+     */
+    @RequestMapping("update")
+    @SaCheckPermission(TbPersonFiling.PERMISSION_CODE_EDIT)
+    public AjaxJson update(TbPersonFiling t) {
+        tbPersonFilingService.update(t);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    public AjaxJson getById(Integer id) {
+        TbPersonFiling t = tbPersonFilingService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        long deptId = StpUserUtil.getDeptId();
+        if (deptId != StpUserUtil.ADMIN_DEPT_ID) {
+            so.put("deptId", deptId);
+        }
+        List<TbPersonFiling> list = tbPersonFilingService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+
+}

+ 27 - 0
business-system/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>face-admin</artifactId>
+        <groupId>com.pj</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>business-system</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>alarm-system</module>
+        <module>venues-system</module>
+        <module>filing-system</module>
+    </modules>
+    <dependencies>
+        <dependency>
+            <groupId>com.pj</groupId>
+            <artifactId>sp-core</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 25 - 0
business-system/venues-system/pom.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>business-system</artifactId>
+        <groupId>com.pj</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>venues-system</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>4.1.59.Final</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 89 - 0
business-system/venues-system/src/main/java/com/pj/biz/TbChannelController.java

@@ -0,0 +1,89 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import com.pj.project.tb_channel.TbChannel;
+import com.pj.project.tb_channel.TbChannelService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+* Controller: tb_channel -- 通道管理
+* @author qzyReal
+*/
+@RestController
+@RequestMapping("/TbChannel/")
+public class TbChannelController {
+
+/** 底层 Service 对象 */
+@Autowired
+TbChannelService tbChannelService;
+
+/** 增 */
+@RequestMapping("add")
+	@SaCheckPermission(TbChannel.PERMISSION_CODE)
+@Transactional(rollbackFor = Exception.class)
+public AjaxJson add(TbChannel t){
+tbChannelService.add(t);
+return AjaxJson.getSuccessData(t);
+}
+
+/** 删 */
+@RequestMapping("delete")
+	@SaCheckPermission(TbChannel.PERMISSION_CODE)
+public AjaxJson delete(Long id){
+tbChannelService.delete(id);
+return AjaxJson.getSuccess();
+}
+
+/** 删 - 根据id列表 */
+@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbChannel.PERMISSION_CODE)
+public AjaxJson deleteByIds(){
+List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+	int line = SP.publicMapper.deleteByIds(TbChannel.TABLE_NAME, ids);
+	return AjaxJson.getByLine(line);
+	}
+
+	/** 改 */
+	@RequestMapping("update")
+		@SaCheckPermission(TbChannel.PERMISSION_CODE)
+	public AjaxJson update(TbChannel t){
+		tbChannelService.update(t);
+	return AjaxJson.getSuccess();
+	}
+
+	/** 查 - 根据id */
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id){
+	TbChannel t = tbChannelService.getById(id);
+	return AjaxJson.getSuccessData(t);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
+	@RequestMapping("getList")
+	public AjaxJson getList() {
+	SoMap so = SoMap.getRequestSoMap();
+		List<TbChannel> list = tbChannelService.getList(so.startPage());
+	return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+
+
+
+
+
+
+
+
+
+
+			}

+ 89 - 0
business-system/venues-system/src/main/java/com/pj/biz/TbTerminalController.java

@@ -0,0 +1,89 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import com.pj.project.tb_terminal.TbTerminal;
+import com.pj.project.tb_terminal.TbTerminalService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+* Controller: tb_terminal -- 设备管理
+* @author qzyReal
+*/
+@RestController
+@RequestMapping("/TbTerminal/")
+public class TbTerminalController {
+
+/** 底层 Service 对象 */
+@Autowired
+TbTerminalService tbTerminalService;
+
+/** 增 */
+@RequestMapping("add")
+	@SaCheckPermission(TbTerminal.PERMISSION_CODE)
+@Transactional(rollbackFor = Exception.class)
+public AjaxJson add(TbTerminal t){
+tbTerminalService.add(t);
+return AjaxJson.getSuccessData(t);
+}
+
+/** 删 */
+@RequestMapping("delete")
+	@SaCheckPermission(TbTerminal.PERMISSION_CODE)
+public AjaxJson delete(Long id){
+tbTerminalService.delete(id);
+return AjaxJson.getSuccess();
+}
+
+/** 删 - 根据id列表 */
+@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbTerminal.PERMISSION_CODE)
+public AjaxJson deleteByIds(){
+List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+	int line = SP.publicMapper.deleteByIds(TbTerminal.TABLE_NAME, ids);
+	return AjaxJson.getByLine(line);
+	}
+
+	/** 改 */
+	@RequestMapping("update")
+		@SaCheckPermission(TbTerminal.PERMISSION_CODE)
+	public AjaxJson update(TbTerminal t){
+		tbTerminalService.update(t);
+	return AjaxJson.getSuccess();
+	}
+
+	/** 查 - 根据id */
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id){
+	TbTerminal t = tbTerminalService.getById(id);
+	return AjaxJson.getSuccessData(t);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
+	@RequestMapping("getList")
+	public AjaxJson getList() {
+	SoMap so = SoMap.getRequestSoMap();
+		List<TbTerminal> list = tbTerminalService.getList(so.startPage());
+	return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+
+
+
+
+
+
+
+
+
+
+			}

+ 89 - 0
business-system/venues-system/src/main/java/com/pj/biz/TbVenuesController.java

@@ -0,0 +1,89 @@
+package com.pj.biz;
+
+import java.util.List;
+
+import com.pj.project.tb_venues.TbVenues;
+import com.pj.project.tb_venues.TbVenuesService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+* Controller: tb_venues -- 场所管理
+* @author qzyReal
+*/
+@RestController
+@RequestMapping("/TbVenues/")
+public class TbVenuesController {
+
+/** 底层 Service 对象 */
+@Autowired
+TbVenuesService tbVenuesService;
+
+/** 增 */
+@RequestMapping("add")
+	@SaCheckPermission(TbVenues.PERMISSION_CODE)
+@Transactional(rollbackFor = Exception.class)
+public AjaxJson add(TbVenues t){
+tbVenuesService.add(t);
+return AjaxJson.getSuccessData(t);
+}
+
+/** 删 */
+@RequestMapping("delete")
+	@SaCheckPermission(TbVenues.PERMISSION_CODE)
+public AjaxJson delete(Long id){
+tbVenuesService.delete(id);
+return AjaxJson.getSuccess();
+}
+
+/** 删 - 根据id列表 */
+@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbVenues.PERMISSION_CODE)
+public AjaxJson deleteByIds(){
+List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+	int line = SP.publicMapper.deleteByIds(TbVenues.TABLE_NAME, ids);
+	return AjaxJson.getByLine(line);
+	}
+
+	/** 改 */
+	@RequestMapping("update")
+		@SaCheckPermission(TbVenues.PERMISSION_CODE)
+	public AjaxJson update(TbVenues t){
+		tbVenuesService.update(t);
+	return AjaxJson.getSuccess();
+	}
+
+	/** 查 - 根据id */
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id){
+	TbVenues t = tbVenuesService.getById(id);
+	return AjaxJson.getSuccessData(t);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
+	@RequestMapping("getList")
+	public AjaxJson getList() {
+	SoMap so = SoMap.getRequestSoMap();
+		List<TbVenues> list = tbVenuesService.getList(so.startPage());
+	return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+
+
+
+
+
+
+
+
+
+
+			}

+ 16 - 0
business-system/venues-system/src/main/java/com/pj/biz/UserController.java

@@ -0,0 +1,16 @@
+package com.pj.biz;
+
+import com.pj.utils.sg.AjaxJson;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RequestMapping("test")
+@RestController
+public class UserController {
+
+    @RequestMapping(value = "test")
+    public AjaxJson test(){
+
+        return AjaxJson.getSuccess();
+    }
+}

+ 92 - 0
business-system/venues-system/src/main/java/com/pj/netty/HeartBeatHandler.java

@@ -0,0 +1,92 @@
+package com.pj.netty;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.StandardCharsets;
+
+
+@ChannelHandler.Sharable
+@Slf4j
+@Component
+public class HeartBeatHandler extends ChannelInboundHandlerAdapter {
+
+    /**
+     * 接收报文
+     */
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) {
+        ByteBuf byteBuf = (ByteBuf) msg;
+        int len = byteBuf.readableBytes();
+        log.info("---------------start process msg--------------------");
+        log.info("readable bytes is:" + len);
+        byte[] old = new byte[len];
+        for (int i = 0; i < len; i++) {
+            old[i] = byteBuf.readByte();
+        }
+        log.info(String.format("message:%s", msg));
+        //相关处理
+    }
+    public static String toBinaryString(String str) {
+        if (str == null) {
+            return null;
+        }
+
+        StringBuffer sb = new StringBuffer();
+
+        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
+        System.out.println(bytes.length);
+        for (byte aByte : bytes) {
+            sb.append(Integer.toBinaryString(aByte));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 接收到客户端信息完成
+     */
+    @Override
+    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+        log.info("接收到客户端信息完成");
+        ctx.flush();
+    }
+
+    /**
+     * 异常信息
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        if (cause instanceof Exception) {
+            log.info("异常捕获");
+            cause.printStackTrace();
+        }
+    }
+    /**
+     * 接入连接
+     */
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        log.info("CLIENT" + getRemoteAddress(ctx) + " 接入连接");
+    }
+
+    /**
+     * 断开连接
+     */
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+        log.info("CLIENT" + getRemoteAddress(ctx) + " 断开连接");
+        ctx.close();
+    }
+
+    /**
+     * 获取设备IP地址
+     */
+    public static String getRemoteAddress(ChannelHandlerContext ctx) {
+        return ctx.channel().remoteAddress().toString();
+    }
+
+}

+ 49 - 0
business-system/venues-system/src/main/java/com/pj/netty/NettyServer.java

@@ -0,0 +1,49 @@
+package com.pj.netty;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.FixedLengthFrameDecoder;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpServerCodec;
+import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
+import io.netty.handler.stream.ChunkedWriteHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.net.InetSocketAddress;
+
+@Slf4j
+@Component
+public class NettyServer {
+
+    public void start(InetSocketAddress address) {
+        //配置服务端的NIO线程组
+        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
+        EventLoopGroup workerGroup = new NioEventLoopGroup();
+
+        try {
+            ServerBootstrap bootstrap = new ServerBootstrap()
+                    .group(bossGroup, workerGroup)  // 绑定线程池
+                    .channel(NioServerSocketChannel.class)
+                    .localAddress(address)
+                    .childHandler(new NettyServerChannelInitializer())//编码解码
+                    .option(ChannelOption.SO_BACKLOG, 128)  //服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝
+                    .childOption(ChannelOption.SO_KEEPALIVE, true);  //保持长连接,2小时无数据激活心跳机制
+
+            // 绑定端口,开始接收进来的连接
+            ChannelFuture future = bootstrap.bind(address).sync();
+            log.info("netty服务器开始监听端口:" + address.getPort());
+            //关闭channel和块,直到它被关闭
+            future.channel().closeFuture().sync();
+        } catch (Exception e) {
+            e.printStackTrace();
+            bossGroup.shutdownGracefully();
+            workerGroup.shutdownGracefully();
+        }
+    }
+
+
+}

+ 18 - 0
business-system/venues-system/src/main/java/com/pj/netty/NettyServerChannelInitializer.java

@@ -0,0 +1,18 @@
+package com.pj.netty;
+
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.util.CharsetUtil;
+
+public class NettyServerChannelInitializer extends ChannelInitializer<SocketChannel> {
+    @Override
+    protected void initChannel(SocketChannel channel) throws Exception {
+
+        channel.pipeline().addLast("decoder",new StringDecoder(CharsetUtil.UTF_8));
+        channel.pipeline().addLast("encoder",new StringEncoder(CharsetUtil.UTF_8));
+        channel.pipeline().addLast(new NettyServerHandler());
+    }
+
+}

+ 156 - 0
business-system/venues-system/src/main/java/com/pj/netty/NettyServerHandler.java

@@ -0,0 +1,156 @@
+package com.pj.netty;
+
+import io.netty.channel.*;
+import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@ChannelHandler.Sharable
+@Component
+public class NettyServerHandler extends ChannelInboundHandlerAdapter {
+    /**
+     * 管理一个全局map,保存连接进服务端的通道数量
+     */
+    private static final ConcurrentHashMap<ChannelId, ChannelHandlerContext> CHANNEL_MAP = new ConcurrentHashMap<>();
+
+
+
+    /**
+     * @param ctx
+     * @DESCRIPTION: 有客户端连接服务器会触发此函数
+     * @return: void
+     */
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) {
+
+        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
+
+        String clientIp = insocket.getAddress().getHostAddress();
+        int clientPort = insocket.getPort();
+
+        //获取连接通道唯一标识
+        ChannelId channelId = ctx.channel().id();
+
+        System.out.println();
+        //如果map中不包含此连接,就保存连接
+        if (CHANNEL_MAP.containsKey(channelId)) {
+            log.info("客户端【" + channelId + "】是连接状态,连接通道数量: " + CHANNEL_MAP.size());
+        } else {
+            //保存连接
+            CHANNEL_MAP.put(channelId, ctx);
+
+            log.info("客户端【" + channelId + "】连接netty服务器[IP:" + clientIp + "--->PORT:" + clientPort + "]");
+            log.info("连接通道数量: " + CHANNEL_MAP.size());
+        }
+    }
+
+    /**
+     * @param ctx
+     * @DESCRIPTION: 有客户端终止连接服务器会触发此函数
+     * @return: void
+     */
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) {
+
+        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
+
+        String clientIp = insocket.getAddress().getHostAddress();
+
+        ChannelId channelId = ctx.channel().id();
+
+        //包含此客户端才去删除
+        if (CHANNEL_MAP.containsKey(channelId)) {
+            //删除连接
+            CHANNEL_MAP.remove(channelId);
+            System.out.println();
+            log.info("客户端【" + channelId + "】退出netty服务器[IP:" + clientIp + "--->PORT:" + insocket.getPort() + "]");
+            log.info("连接通道数量: " + CHANNEL_MAP.size());
+        }
+    }
+
+    /**
+     * @param ctx
+     * @DESCRIPTION: 有客户端发消息会触发此函数
+     * @return: void
+     */
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+
+        String msgStr = String.valueOf(msg);
+        System.out.println();
+        log.info("加载客户端报文......");
+        log.info("【" + ctx.channel().id() + "】" + " :" + msg);
+
+        //响应客户端
+        log.info("服务端端返回报文......");
+        log.info("【" + ctx.channel().id() + "】" + " :" + msg);
+        this.channelWrite(ctx.channel().id(), msg);
+    }
+
+    /**
+     * @param msg        需要发送的消息内容
+     * @param channelId 连接通道唯一id
+     * @DESCRIPTION: 服务端给客户端发送消息
+     * @return: void
+     */
+    public void channelWrite(ChannelId channelId, Object msg) throws Exception {
+
+        ChannelHandlerContext ctx = CHANNEL_MAP.get(channelId);
+
+        if (ctx == null) {
+            log.info("通道【" + channelId + "】不存在");
+            return;
+        }
+
+        if (msg == null || msg == "") {
+            log.info("服务端响应空的消息");
+            return;
+        }
+
+        //将客户端的信息直接返回写入ctx
+        ctx.write(msg);
+        //刷新缓存区
+        ctx.flush();
+    }
+
+    @Override
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+
+        String socketString = ctx.channel().remoteAddress().toString();
+
+        if (evt instanceof IdleStateEvent) {
+            IdleStateEvent event = (IdleStateEvent) evt;
+            if (event.state() == IdleState.READER_IDLE) {
+                log.info("Client: " + socketString + " READER_IDLE 读超时");
+                ctx.disconnect();
+            } else if (event.state() == IdleState.WRITER_IDLE) {
+                log.info("Client: " + socketString + " WRITER_IDLE 写超时");
+                ctx.disconnect();
+            } else if (event.state() == IdleState.ALL_IDLE) {
+                log.info("Client: " + socketString + " ALL_IDLE 总超时");
+                ctx.disconnect();
+            }
+        }
+    }
+
+    /**
+     * @param ctx
+     * @DESCRIPTION: 发生异常会触发此函数
+     * @return: void
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+
+        System.out.println();
+        ctx.close();
+        log.info(ctx.channel().id() + " 发生了错误,此连接被关闭" + "此时连通数量: " + CHANNEL_MAP.size());
+        //cause.printStackTrace();
+    }
+
+}

+ 22 - 0
business-system/venues-system/src/main/java/com/pj/netty/StartNetty.java

@@ -0,0 +1,22 @@
+package com.pj.netty;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.net.InetSocketAddress;
+
+@Component
+@Slf4j
+public class StartNetty implements CommandLineRunner {
+    @Resource
+    private NettyServer nettyServer;
+    @Override
+    public void run(String... args) throws Exception {
+        InetSocketAddress address = new InetSocketAddress("192.168.3.27",9999);
+        log.info("neety服务器启动地址:192.168.3.27:9999 ");
+        nettyServer.start(address);
+
+    }
+}

+ 174 - 0
pom.xml

@@ -0,0 +1,174 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>com.pj</groupId>
+	<artifactId>face-admin</artifactId>
+    <packaging>pom</packaging>
+    <version>0.0.1-SNAPSHOT</version>
+    <modules>
+        <!-- 核心模块 -->
+        <module>sp-core</module>
+        <!-- Sa-plus内置的代码模块 -->
+        <module>sp-admin</module>
+        <!-- 启动类模块 -->
+        <module>sp-start</module>
+		<module>business-system</module>
+
+
+	</modules>
+
+	<!-- SpringBoot -->
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.3.3.RELEASE</version>
+	</parent>
+
+	<!-- 指定一些属性 -->
+	<properties> 
+		<java.version>1.8</java.version>
+		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+	</properties>
+	
+	
+	<dependencies>
+
+		<!-- SpringBoot 依赖 -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-aop</artifactId>
+		</dependency>
+
+       	<!-- SpringBoot 集成 mybatis-plus -->
+		<dependency>
+		    <groupId>com.baomidou</groupId>
+		    <artifactId>mybatis-plus-boot-starter</artifactId>
+		    <version>3.3.2</version>
+		</dependency>
+		
+        <!-- pagehelper分页插件 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.2.13</version>
+        </dependency>
+        
+		<!-- mysql -->
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+		</dependency>
+		
+		<!-- 阿里 druid 连接池  -->
+		<dependency>
+	        <groupId>com.alibaba</groupId>
+	        <artifactId>druid-spring-boot-starter</artifactId>
+	        <version>1.1.10</version>
+	    </dependency>
+
+		<!-- 神器lombok插件 -->
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<optional>true</optional>
+		</dependency>
+
+		<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
+		<dependency>
+		    <groupId>cn.dev33</groupId>
+		    <artifactId>sa-token-spring-boot-starter</artifactId>
+		    <version>1.29.0</version>
+		</dependency>
+		
+	    <!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
+	    <dependency>
+	        <groupId>cn.dev33</groupId>
+	        <artifactId>sa-token-dao-redis-jackson</artifactId>
+		    <version>1.29.0</version>
+	    </dependency>
+        
+        <!-- 工具类大全 - 在线文档:https://hutool.cn/docs/#/ -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.7.15</version>
+        </dependency>
+        
+        <!-- User-Agent 解析 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>1.21</version>
+        </dependency>
+                
+        <!-- OkHttps网络请求库: http://okhttps.ejlchina.com/ -->
+        <dependency>
+		     <groupId>com.ejlchina</groupId>
+		     <artifactId>okhttps</artifactId>
+		     <version>3.2.0</version>
+		</dependency>
+        
+        <!-- redis java客户端jar包 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+        
+        <!--Alijson插件-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.73</version>
+        </dependency>
+
+        <!-- Sentinel 限流 -->
+        <dependency>
+		    <groupId>com.alibaba.csp</groupId>
+		    <artifactId>sentinel-core</artifactId>
+		    <version>1.8.3</version>
+		</dependency>
+		<dependency>
+			<groupId>com.alibaba.csp</groupId>
+			<artifactId>sentinel-annotation-aspectj</artifactId>
+		    <version>1.8.3</version>
+		</dependency>
+
+		<!-- ConfigurationProperties -->
+        <dependency>
+        	<groupId>org.springframework.boot</groupId>
+        	<artifactId>spring-boot-configuration-processor</artifactId>
+        	<optional>true</optional>
+        </dependency>
+        
+    </dependencies>
+
+
+	<!-- 构建配置 -->
+    <build>
+        <!-- 配置资源目录  -->
+    	<resources>
+			<resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.xml</include>
+                </includes>
+			</resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>**/*.*</include>
+                </includes>
+            </resource>
+		</resources>
+    </build>
+
+
+</project>

+ 30 - 0
sp-admin/pom.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>face-admin</artifactId>
+        <groupId>com.pj</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>sp-admin</artifactId>
+    <packaging>jar</packaging>
+
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.pj</groupId>
+            <artifactId>sp-core</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+
+
+    </dependencies>
+
+
+
+</project>

+ 80 - 0
sp-admin/src/main/java/com/pj/project4sp/admin/SpAdmin.java

@@ -0,0 +1,80 @@
+package com.pj.project4sp.admin;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import lombok.Data;
+
+/**
+ * Model: 系统管理员表
+ * @author kong
+ */
+@Data
+public class SpAdmin implements Serializable  {
+
+	private static final long serialVersionUID = 1L;
+
+
+	/** id,--主键、自增 */
+	public Long id;	
+	
+	/** admin名称 */
+	public String name;	
+	public String nickname;
+	private Long deptId;
+
+	/** 头像地址 */
+	public String avatar;	
+	
+	/** 密码 */
+	public String password;	
+	
+	/** 明文密码 */
+	// public String pw;	
+	
+	/** 手机号 */
+	public String phone;	
+	
+	/** 所属角色id */
+	public Long roleId;	
+	
+	/** 账号状态(1=正常, 2=禁用) */
+	public Integer status;	
+	
+	/** 创建自哪个管理员 */
+	public Long createByAid;	
+	
+	/** 创建时间 */
+	public Date createTime;	
+	
+	/** 上次登陆时间 */
+	public Date loginTime;	
+	
+	/** 上次登陆IP */
+	public String loginIp;	
+	
+	/** 登陆次数 */
+	public Integer loginCount;	
+	
+	
+	// -------- 额外字段 
+	
+	/** 所属角色名称   */
+	private String roleName;
+
+	private String deptName;
+
+
+	/** 防止密码被传递到前台  */
+    public String getPassword(){
+    	return "********";
+    }
+    /** 获取真实密码   */
+    @JsonIgnore()
+    public String getPassword2(){
+    	return this.password;
+    }
+	
+}

+ 193 - 0
sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminController.java

@@ -0,0 +1,193 @@
+package com.pj.project4sp.admin;
+
+import java.util.List;
+
+import com.pj.current.satoken.StpUserUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.current.satoken.AuthConst;
+import com.pj.project4sp.SP;
+import com.pj.project4sp.admin4password.SpAdminPasswordService;
+import com.pj.project4sp.role.SpRoleUtil;
+import com.pj.utils.sg.AjaxError;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * Controller -- 系统管理员表
+ * @author kong
+ */
+@RestController
+@RequestMapping("/admin/")
+public class SpAdminController {
+
+	@Autowired
+	SpAdminMapper spAdminMapper;
+	
+	@Autowired
+	SpAdminService spAdminService;
+	
+	@Autowired
+	SpAdminPasswordService spAdminPasswordService;
+
+	/** 增  */
+	@RequestMapping("add")
+	@SaCheckPermission(AuthConst.ADMIN_ADD)
+	AjaxJson add(SpAdmin admin){
+		long id = spAdminService.add(admin);
+		return AjaxJson.getSuccessData(id);
+	}
+
+	/** 删 */
+	@RequestMapping("delete")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson delete(long id){
+		// 不能自己删除自己
+		if(StpUtil.getLoginIdAsLong() == id) {
+			return AjaxJson.getError("不能自己删除自己");
+		}
+		int line = spAdminMapper.delete(id);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 删 - 根据id列表 */
+	@RequestMapping("deleteByIds")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson deleteByIds(){
+		// 不能自己删除自己
+		List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class); 
+		if(ids.contains(StpUtil.getLoginIdAsLong())) {
+			return AjaxJson.getError("不能自己删除自己");
+		}
+		// 开始删除 
+		int line = SP.publicMapper.deleteByIds("sp_admin", ids);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改  -  name */
+	@RequestMapping("update")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson update(SpAdmin obj){
+		SpAdminUtil.checkName(obj.getId(), obj.getName());
+		int line = spAdminMapper.update(obj);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 改密码 */
+	@RequestMapping("updatePassword")
+	@SaCheckPermission({AuthConst.ADMIN_LIST, AuthConst.DEV})
+	AjaxJson updatePassword(long id, String password){
+		int line = spAdminPasswordService.updatePassword(id, password);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改头像  */
+	@RequestMapping("updateAvatar")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson updateAvatar(long id, String avatar){
+		int line = SP.publicMapper.updateColumnById("sp_admin", "avatar", avatar, id);
+		return AjaxJson.getByLine(line);
+	}
+	/** 改头像  */
+	@RequestMapping("updateNickName")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson updateNickName(long id, String nickname){
+		int line = SP.publicMapper.updateColumnById("sp_admin", "nickname", nickname, id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改状态  */
+	@RequestMapping("updateStatus")
+	@SaCheckPermission({AuthConst.ADMIN_LIST, AuthConst.DEV})
+	public AjaxJson updateStatus(long id, int status) {
+
+		// 验证对方是否为超管 
+		if(StpUtil.hasPermission(id, AuthConst.DEV)){
+			return AjaxJson.getError("抱歉,对方角色为最高权限,您暂时无法完成此操作");
+		}
+		
+		// 修改状态 
+		SP.publicMapper.updateColumnById("sp_admin", "status", status, id);
+		// 如果是禁用,就将其强制注销 
+		if(status == 2) {
+			StpUtil.logout(id);
+		}
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 改角色  */
+	@RequestMapping("updateRole")
+	@SaCheckPermission({AuthConst.ADMIN_LIST, AuthConst.DEV})
+	AjaxJson updateRole(long id, String roleId){
+		// 改角色 
+		int line = SP.publicMapper.updateColumnById("sp_admin", "role_id", roleId, id);
+		AjaxError.throwByLine(line);
+		
+		// 清缓存 
+		SpRoleUtil.clearRoleIdCache(id);
+		
+		// 返回 
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 查  */
+	@RequestMapping("getById")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson getById(long id){
+		Object data = spAdminMapper.getById(id);
+		return AjaxJson.getSuccessData(data);
+	}
+
+	/** 返回当前 Admin 信息  */
+	@RequestMapping("getByCurr")
+	AjaxJson getByCurr() {
+		SpAdmin admin = SpAdminUtil.getCurrAdmin();
+		return AjaxJson.getSuccessData(admin);
+	}
+	
+	/** 查 - 集合 */
+	@RequestMapping("getList")
+	@SaCheckPermission(AuthConst.ADMIN_LIST)
+	AjaxJson getList(){
+		SoMap so = SoMap.getRequestSoMap();
+		long deptId = StpUserUtil.getDeptId();
+		if (StpUserUtil.ADMIN_DEPT_ID != deptId) {
+			so.put("deptId", deptId);
+		}
+		List<SpAdmin> list = spAdminMapper.getList(so.startPage());
+		return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+
+	/** 当前 Admin 修改自己信息 */
+	@RequestMapping("updateInfo")
+	AjaxJson updateInfo(SpAdmin obj){
+		obj.setId(StpUtil.getLoginIdAsLong());
+		SpAdminUtil.checkName(obj.getId(), obj.getName());
+		int line = spAdminMapper.update(obj);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 模拟指定账号登录 */
+	@RequestMapping("runAs")
+	@SaCheckPermission({AuthConst.ADMIN_LIST, AuthConst.DEV})
+	AjaxJson runAs(long adminId) {
+		// 如果不存在这个账号 
+		if(SpAdminUtil.spAdminMapper.getById(adminId) == null) {
+			return AjaxJson.getError("未找到账号:" + adminId);
+		}
+		// 如果要模拟的账号就是当前账号 
+		if(StpUtil.getLoginIdAsLong() == adminId) {
+			return AjaxJson.getError("不能自己模拟自己");
+		}
+		
+		// 获取这个人的token 
+		String token = StpUtil.createLoginSession(adminId);
+		return AjaxJson.getSuccessData(token);
+	}
+	
+}

+ 77 - 0
sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminMapper.java

@@ -0,0 +1,77 @@
+package com.pj.project4sp.admin;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import com.pj.utils.so.SoMap;
+
+/**
+ * Mapper: 系统管理员表
+ * @author kong
+ */
+@Mapper
+public interface SpAdminMapper {
+
+
+	/**
+	 * 增 #{name}, #{password}, #{roleId} 
+	 * @param obj
+	 * @return
+	 */
+	int add(SpAdmin obj);
+
+	/**
+	 * 删 
+	 * @param id
+	 * @return
+	 */
+	int delete(long id);
+
+	/**
+	 * 改 
+	 * @param obj
+	 * @return
+	 */
+	int update(SpAdmin obj);
+
+	/**
+	 * 查 
+	 * @param id
+	 * @return
+	 */
+	SpAdmin getById(long id);
+
+	/**
+	 * 查  
+	 * @param so
+	 * @return
+	 */
+	List<SpAdmin> getList(SoMap so);
+
+	/**
+	 * 查询,根据name 
+	 * @param name
+	 * @return
+	 */
+	SpAdmin getByName(String name);
+	
+	/**
+	 * 查询,根据 phone  
+	 * @param phone
+	 * @return
+	 */
+	SpAdmin getByPhone(String phone);
+
+
+	/**
+	 * 修改指定账号的 最后登录记录  
+	 * @param id
+	 * @param loginIp
+	 * @return
+	 */
+	public int updateLoginLog(@Param("id")long id, @Param("loginIp")String loginIp);
+	
+
+}

+ 111 - 0
sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminMapper.xml

@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project4sp.admin.SpAdminMapper">
+
+
+	<!-- 增 -->
+	<insert id="add">
+		insert into
+		sp_admin(name, avatar,nickname,detp_id, phone, role_id, create_by_aid, create_time)
+		values (#{name}, #{avatar},#{nickname},#{deptId}, #{phone}, #{roleId}, #{createByAid}, now())
+	</insert>
+
+
+	<!-- 删 -->
+	<delete id="delete">
+		delete from sp_admin where id = #{id} 
+	</delete>
+
+
+	<!-- 改 -->
+	<delete id="update">
+		update sp_admin set 
+		name = #{name} 
+		where id = #{id} 
+	</delete>
+	
+	<!-- 自己改自己 -->
+	<!-- <delete id="updateBy">
+		update sp_admin set 
+		name = #{name} 
+		where id = #{id} 
+	</delete> -->
+
+	<!-- =================== 查询相关 =================== -->
+
+	<!-- 通用映射 -->
+	<resultMap id="model" type="com.pj.project4sp.admin.SpAdmin">
+		<result property="id" column="id" />
+		<result property="name" column="name" />
+		<result property="deptId" column="dept_id" />
+		<result property="avatar" column="avatar" />
+		<result property="password" column="password" />
+		<!-- <result property="pw" column="pw" /> -->
+		<result property="phone" column="phone" />
+		<result property="roleId" column="role_id" />
+		<result property="status" column="status" />
+		<result property="createByAid" column="create_by_aid" />
+		<result property="createTime" column="create_time" />
+		<result property="loginTime" column="login_time" />
+		<result property="loginIp" column="login_ip" />
+		<result property="loginCount" column="login_count" />
+		<result property="roleName" column="role_name" />
+	</resultMap>
+	
+	<!-- 查询sql -->
+	<sql id="select_sql">
+		select *,
+		(select name from sp_role where id = sp_admin.role_id) as role_name,(select name from tb_dept where id=sp_admin.dept_id) as deptName
+		from sp_admin 
+	</sql>
+
+
+	<!-- 查询,根据id -->
+	<select id="getById" resultMap="model">
+		<include refid="select_sql"></include>
+		where id = #{id}
+	</select>
+
+	<!-- 查询,根据名称 -->
+	<select id="getByName" resultMap="model">
+		<include refid="select_sql"></include>
+		where name = #{name}
+	</select>
+
+	<!-- 查询,根据名称 -->
+	<select id="getByPhone" resultMap="model">
+		<include refid="select_sql"></include>
+		where phone = #{phone}
+	</select>
+
+
+	<!-- 查询 -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		where 1=1
+		<if test=' this.has("id")  '>and id = #{id} </if>
+		<if test=' this.has("deptId")  '>and dept_id = #{deptId} </if>
+		<if test=' this.has("name")  '>and name like concat('%', #{name}, '%')  </if>
+		<if test=' this.has("roleId")  '>and role_id = #{roleId} </if>
+		order by 
+		<choose>
+			<when test=' sortType == "id" '> id desc </when> 
+			<when test=' sortType == "id__asc" '> id asc </when> 
+			<when test=' sortType == "loginTime" '> login_time desc </when> 
+			<when test=' sortType == "loginCount" ' > login_count desc </when> 
+		 	<otherwise>id desc</otherwise>
+		 </choose>
+	</select>
+	
+	<!-- 修改指定账号的 最后登录记录 -->
+	<update id="updateLoginLog">
+		update sp_admin set 
+		login_ip = #{loginIp},
+		login_time = NOW(),
+		login_count = login_count + 1
+		where id = #{id}
+	</update>
+	
+
+
+</mapper>

+ 68 - 0
sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminService.java

@@ -0,0 +1,68 @@
+package com.pj.project4sp.admin;
+
+import cn.hutool.core.util.PhoneUtil;
+import com.pj.current.global.BusinessException;
+import com.pj.project.tb_dept.TbDept;
+import com.pj.project.tb_dept.TbDeptService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.pj.project4sp.SP;
+import com.pj.project4sp.admin4password.SpAdminPasswordService;
+
+import cn.dev33.satoken.stp.StpUtil;
+
+import javax.annotation.Resource;
+
+/**
+ * Service: admin管理员
+ *
+ * @author kong
+ */
+@Service
+public class SpAdminService {
+
+
+    @Resource
+    SpAdminMapper spAdminMapper;
+
+    @Resource
+    SpAdminPasswordService spAdminPasswordService;
+    @Resource
+    private TbDeptService tbDeptService;
+
+    /**
+     * 管理员添加一个管理员
+     *
+     * @param admin
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
+    public long add(SpAdmin admin) {
+        String phone = admin.getPhone();
+        if (!PhoneUtil.isPhone(phone)) {
+            throw new BusinessException("请输入正确的手机号");
+        }
+        admin.setName(admin.getPhone());
+        // 检查姓名是否合法
+        SpAdminUtil.checkAdmin(admin);
+
+        // 创建人,为当前账号
+        admin.setCreateByAid(StpUtil.getLoginIdAsLong());
+        // 开始添加
+        spAdminMapper.add(admin);
+        TbDept tbDept = tbDeptService.getById(admin.getDeptId());
+        tbDept.setPeopleNum(tbDept.getPeopleNum() + 1);
+        tbDeptService.updateById(tbDept);
+        // 获取主键
+        long id = SP.publicMapper.getPrimarykey();
+        // 更改密码(md5与明文)
+        spAdminPasswordService.updatePassword(id, admin.getPassword2());
+
+        // 返回主键
+        return id;
+    }
+
+}

+ 94 - 0
sp-admin/src/main/java/com/pj/project4sp/admin/SpAdminUtil.java

@@ -0,0 +1,94 @@
+package com.pj.project4sp.admin;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.pj.utils.sg.AjaxError;
+import com.pj.utils.sg.NbUtil;
+
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * admin工具类 
+ * @author kong
+ *
+ */
+@Component
+public class SpAdminUtil {
+
+	
+	public static SpAdminMapper spAdminMapper;
+	@Autowired
+	public void setSpAdminMapper(SpAdminMapper spAdminMapper) {
+		SpAdminUtil.spAdminMapper = spAdminMapper;
+	}
+	
+	
+	/**
+	 * 当前admin
+	 * @return
+	 */
+	public static SpAdmin getCurrAdmin() {
+		long adminId = StpUtil.getLoginIdAsLong();
+		return spAdminMapper.getById(adminId);
+	}
+	
+	/**
+	 * 检查指定姓名是否合法 ,如果不合法,则抛出异常 
+	 * @param adminId
+	 * @param name
+	 * @return
+	 */
+	public static boolean checkName(long adminId, String name) {
+		if(NbUtil.isNull(name)) {
+			throw AjaxError.get("账号名称不能为空");
+		}
+
+		// 如果能查出来数据,而且不是本人,则代表与已有数据重复
+		SpAdmin a2 = spAdminMapper.getByName(name);
+		if(a2 != null && a2.getId() != adminId) {	
+			throw AjaxError.get("账号名称已有账号使用,请更换");
+		} 
+		return true;
+	}
+	
+	/**
+	 * 检查整个admin是否合格 
+	 * @param a
+	 * @return
+	 */
+	public static boolean checkAdmin(SpAdmin a) {
+		// 检查姓名 
+		checkName(a.getId(), a.getName());
+		// 检查密码 
+		if(a.getPassword2().length() < 4) {
+			throw new AjaxError("密码不得低于4位");
+		}
+		return true;
+	}
+	
+	
+	
+	/**
+	 * 指定的name是否可用 
+	 * @param name
+	 * @return
+	 */
+	public static boolean nameIsOk(String name) {
+		SpAdmin a2 = spAdminMapper.getByName(name);
+		if(a2 == null) {
+			return true;
+		}
+		return false;
+	}
+	
+	
+
+
+
+
+
+
+	
+	
+}

+ 73 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4acc/SpAccAdminController.java

@@ -0,0 +1,73 @@
+package com.pj.project4sp.admin4acc;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.alibaba.csp.sentinel.annotation.SentinelResource;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.pj.project4sp.admin.SpAdmin;
+import com.pj.project4sp.admin.SpAdminUtil;
+import com.pj.project4sp.role4permission.SpRolePermissionService;
+import com.pj.project4sp.spcfg.SpCfgUtil;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.sg.NbUtil;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * Admin账号相关的接口 
+ * 
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/AccAdmin/")
+public class SpAccAdminController {
+
+	@Autowired
+	SpAccAdminService spAccAdminService;
+	
+	@Autowired
+	SpRolePermissionService spRolePermissionService;
+	
+	/** 账号、密码登录  */
+	@RequestMapping("doLogin")
+	@SentinelResource(value = "qps-max-1", blockHandler = "doLoginBlock")
+	AjaxJson doLogin(String key, String password) {
+		// 1、验证参数 
+		if(NbUtil.hasNull(key, password)) {
+			return AjaxJson.getError("请提供key与password参数");
+		}
+		return spAccAdminService.doLogin(key, password);
+	}
+	// 限流之后触发的函数 
+	AjaxJson doLoginBlock(String key, String password, BlockException e) {
+		return AjaxJson.getError("访问过于频繁,请稍后再试");
+	}
+	
+	/** 退出登录  */
+	@RequestMapping("doExit")
+	AjaxJson doExit() {
+		StpUtil.logout();
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 获取会话信息 */
+	@RequestMapping("getLoginInfo")
+	AjaxJson getLoginInfo(HttpServletRequest request) {
+		// 当前admin
+		SpAdmin admin = SpAdminUtil.getCurrAdmin();
+		
+		// 组织参数 (admin信息,权限信息,配置信息)
+		SoMap map = new SoMap();
+		map.set("admin", admin);	
+		map.set("perList", spRolePermissionService.getPcodeByRid(admin.getRoleId()));				
+		map.set("appCfg", SpCfgUtil.getAppCfg());	
+		return AjaxJson.getSuccessData(map); 
+	}
+	
+}

+ 138 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4acc/SpAccAdminService.java

@@ -0,0 +1,138 @@
+package com.pj.project4sp.admin4acc;
+
+
+import java.util.Date;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+
+import com.pj.current.satoken.StpUserUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.pj.current.config.SystemObject;
+import com.pj.project4sp.admin.SpAdmin;
+import com.pj.project4sp.admin.SpAdminMapper;
+import com.pj.project4sp.admin4login.SpAdminLogin;
+import com.pj.project4sp.admin4login.SpAdminLoginMapper;
+import com.pj.project4sp.role4permission.SpRolePermissionService;
+import com.pj.project4sp.spcfg.SpCfgUtil;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.sg.IpUtil;
+import com.pj.utils.sg.NbUtil;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.spring.SpringMVCUtil;
+import cn.dev33.satoken.stp.StpUtil;
+import eu.bitwalker.useragentutils.UserAgent;
+
+/**
+ * service:admin账号相关
+ * @author kong
+ *
+ */
+@Service
+public class SpAccAdminService {
+
+	@Resource
+	SpAdminMapper spAdminMapper;
+	
+	@Autowired
+	SpRolePermissionService spRolePermissionService;
+
+	@Autowired
+	SpAdminLoginMapper sysLoginLogMapper;
+	
+	/**
+	  * 登录 
+	 * @param key 账号 (ID / 名称 / 手机号)
+	 * @param password 密码 
+	 * @return
+	 */
+	@Transactional(rollbackFor = Exception.class)
+	public AjaxJson doLogin(String key, String password) {
+		
+		// 0、判断 way (1=ID, 2=昵称,3=手机号  )
+    	int way = 2;	
+    	if(NbUtil.isNumber(key) == true){
+    		way = 1;
+    		if(key.length() == 11){
+    			way = 3;
+    		}
+    	}
+		
+		// 2、获取admin
+        SpAdmin admin = null;	
+        if(way == 1) {
+        	admin = spAdminMapper.getById(Long.parseLong(key)); 
+        }
+        if(way == 2) {
+        	admin = spAdminMapper.getByName(key); 
+        }
+        if(way == 3) {
+        	admin = spAdminMapper.getByPhone(key); 
+        }
+        
+
+        // 3、开始验证
+        if(admin == null){
+        	return AjaxJson.getError("无此账号");	
+        }
+        if(NbUtil.isNull(admin.getPassword2())) {
+        	return AjaxJson.getError("此账号尚未设置密码,无法登陆");
+        }
+        String md5Password = SystemObject.getPasswordMd5(admin.getId(), password);
+        if(admin.getPassword2().equals(md5Password) == false){
+        	return AjaxJson.getError("密码错误");	
+        }
+        
+        // 4、是否禁用
+        if(admin.getStatus() == 2) {
+        	return AjaxJson.getError("此账号已被禁用,如有疑问,请联系管理员");	
+        }
+
+        // =========== 至此, 已登录成功 ============ 
+        StpUtil.login(admin.getId()); 		
+        String tokenValue = StpUtil.getTokenValue();
+        successLogin(admin, tokenValue);
+		StpUserUtil.setDeptId(admin.getDeptId());
+        // 组织返回参数
+		SoMap map = new SoMap();
+		map.put("admin", admin);
+		map.put("appCfg", SpCfgUtil.getAppCfg());
+		map.put("perList", spRolePermissionService.getPcodeByRid(admin.getRoleId()));
+		map.put("tokenInfo", StpUtil.getTokenInfo());
+		return AjaxJson.getSuccessData(map);	
+	}
+	
+	/**
+	 * 指定id的账号成功登录一次 (修改最后登录时间等数据 )
+	 * @param s
+	 * @return
+	 */
+	void successLogin(SpAdmin s, String tokenValue){
+		HttpServletRequest request = SpringMVCUtil.getRequest();
+		UserAgent ua = UserAgent.parseUserAgentString(request.getHeader("user-agent"));
+		String loginIp = IpUtil.getIP(request);
+		
+		// 1、修改 admin表 最后登录日志 
+		int line = spAdminMapper.updateLoginLog(s.getId(), loginIp);
+		if(line > 0) {
+	        s.setLoginIp(loginIp);
+	        s.setLoginTime(new Date());
+	        s.setLoginCount(s.getLoginCount() + 1);
+		}
+		
+		// 2、在管理员登录日志表增加记录 
+		SpAdminLogin al = new SpAdminLogin();	// 声明对象 
+		al.setAccId(s.getId());		// 管理员id 
+		al.setAccToken(tokenValue);	// 本次登录Token 
+		al.setLoginIp(loginIp);		// 登陆IP 
+		al.setAddress(IpUtil.getAddres(loginIp));		// 客户端所在地址 
+		al.setDevice(ua.getBrowser().getName());	// 客户端标识 
+		al.setSystem(ua.getOperatingSystem().getName()); 	// 客户端系统 
+		sysLoginLogMapper.add(al);
+	}
+	
+}

+ 89 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLogin.java

@@ -0,0 +1,89 @@
+package com.pj.project4sp.admin4login;
+
+import java.io.Serializable;
+import java.util.*;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: sp_admin_login -- 管理员登录日志表 
+ * 
+ * @author shengzhang 
+ */
+@Data
+@Accessors(chain = true)
+public class SpAdminLogin implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "sp_admin_login";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "sp-admin-login";	
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * id号 
+	 */
+	private Long id;	
+
+	/**
+	 * 管理员账号id 
+	 */
+	private Long accId;	
+
+	/**
+	 * 本次登录Token 
+	 */
+	private String accToken;	
+
+	/**
+	 * 登陆IP 
+	 */
+	private String loginIp;	
+
+	/**
+	 * 登陆地点
+	 */
+	private String address;	
+
+	/**
+	 * 客户端设备标识
+	 */
+	private String device;	
+
+	/**
+	 * 客户端系统标识 
+	 */
+	private String system;	
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;	
+
+
+
+	// ---------- 额外字段 ----------
+	/**
+	 * 管理员名称 
+	 */
+	private String spAdminName;	
+
+	/**
+	 * 管理员头像 
+	 */
+	private String spAdminAvatar;	
+	
+
+
+}

+ 63 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLoginController.java

@@ -0,0 +1,63 @@
+package com.pj.project4sp.admin4login;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.project4sp.SP;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: sp_admin_login -- 管理员登录日志表 
+ * 
+ * @author shengzhang 
+ */
+@RestController
+@RequestMapping("/SpAdminLogin/")
+public class SpAdminLoginController {
+
+	/** 底层 Mapper 对象 */
+	@Autowired
+	SpAdminLoginMapper sysLoginLogMapper;
+
+	/** 删 */  
+	@RequestMapping("delete")
+	@SaCheckPermission(SpAdminLogin.PERMISSION_CODE)
+	public AjaxJson delete(Long id){
+		int line = sysLoginLogMapper.delete(id);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 删 - 根据id列表 */  
+	@RequestMapping("deleteByIds")
+	@SaCheckPermission(SpAdminLogin.PERMISSION_CODE)
+	public AjaxJson deleteByIds(){
+		List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class); 
+		int line = SP.publicMapper.deleteByIds(SpAdminLogin.TABLE_NAME, ids);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 查 - 根据id */  
+	@RequestMapping("getById")
+	@SaCheckPermission(SpAdminLogin.PERMISSION_CODE)
+	public AjaxJson getById(Long id){
+		SpAdminLogin s = sysLoginLogMapper.getById(id);
+		return AjaxJson.getSuccessData(s);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	@RequestMapping("getList")
+	@SaCheckPermission(SpAdminLogin.PERMISSION_CODE)
+	public AjaxJson getList() { 
+		SoMap so = SoMap.getRequestSoMap();
+		List<SpAdminLogin> list = sysLoginLogMapper.getList(so.startPage());
+		return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+	
+}

+ 47 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLoginMapper.java

@@ -0,0 +1,47 @@
+package com.pj.project4sp.admin4login;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: sp_admin_login -- 管理员登录日志表 
+ * 
+ * @author shengzhang 
+ */
+@Mapper
+@Repository
+public interface SpAdminLoginMapper {
+
+	/**
+	 * 增  
+	 * @param s 实体对象 
+	 * @return 受影响行数 
+	 */
+	int add(SpAdminLogin s);
+
+	/**
+	 * 删  
+	 * @param id 要删除的数据id  
+	 * @return 受影响行数 
+	 */
+	int delete(Long id);	 
+
+	/** 
+	 * 查 - 根据id  
+	 * @param id 要查询的数据id 
+	 * @return 实体对象 
+	 */
+	SpAdminLogin getById(Long id);	 
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合 
+	 * @return 数据列表 
+	 */
+	List<SpAdminLogin> getList(SoMap so);
+
+}

+ 70 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4login/SpAdminLoginMapper.xml

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project4sp.admin4login.SpAdminLoginMapper">
+
+	<!-- 增 -->
+	<insert id="add">
+		insert into 
+		sp_admin_login (id, acc_id, acc_token, login_ip, address, device, `system`, create_time)
+		values (0, #{accId}, #{accToken}, #{loginIp}, #{address}, #{device}, #{system}, now()) 
+	</insert>
+
+	<!-- 删 -->
+	<delete id="delete">
+		delete from sp_admin_login 
+		where id = #{id} 
+	</delete>
+
+	<!-- ================================== 查询相关 ================================== -->
+	
+	<!-- 通用映射:手动模式 -->
+	<resultMap id="model" type="com.pj.project4sp.admin4login.SpAdminLogin">
+		<result property="id" column="id" />
+		<result property="accId" column="acc_id" />
+		<result property="accToken" column="acc_token" />
+		<result property="loginIp" column="login_ip" />
+		<result property="address" column="address" />
+		<result property="device" column="device" />
+		<result property="system" column="system" />
+		<result property="createTime" column="create_time" />
+		<result property="spAdminName" column="sp_admin_name" />
+		<result property="spAdminAvatar" column="sp_admin_avatar" />
+	</resultMap>
+	
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select 
+			*, 
+			(select name from sp_admin where id = sp_admin_login.acc_id) as sp_admin_name, 
+			(select avatar from sp_admin where id = sp_admin_login.acc_id) as sp_admin_avatar
+		from sp_admin_login 
+	</sql>
+	
+	<!-- 查 - 根据id -->
+	<select id="getById" resultMap="model">
+		<include refid="select_sql"></include>
+		where id = #{id}
+	</select>
+	
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+			<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("accId") '> and acc_id = #{accId} </if>
+			<if test=' this.has("accToken") '> and acc_token = #{accToken} </if>
+			<if test=' this.has("loginIp") '> and login_ip = #{loginIp} </if>
+		</where>
+		order by id desc 
+	</select>
+	
+	
+	
+	
+	
+	
+	
+	
+	
+
+</mapper>

+ 46 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4password/SpAdminPasswordController.java

@@ -0,0 +1,46 @@
+package com.pj.project4sp.admin4password;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.current.config.SystemObject;
+import com.pj.project4sp.admin.SpAdmin;
+import com.pj.project4sp.admin.SpAdminUtil;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.sg.NbUtil;
+
+/**
+ * admin表 密码相关 
+ * 
+ * @author shengzhang
+ */
+@RestController
+@RequestMapping("/AdminPassword/")
+public class SpAdminPasswordController {
+
+	@Autowired
+	SpAdminPasswordService spAdminPasswordService;
+
+	/** 指定用户修改自己密码 */
+	@RequestMapping("update")
+	AjaxJson updatePassword(String oldPwd, String newPwd) {
+		// 1、转md5
+		SpAdmin a = SpAdminUtil.getCurrAdmin();
+		String oldPwdMd5 = SystemObject.getPasswordMd5(a.getId(), oldPwd);
+		
+		// 2、验证
+		if(NbUtil.isNull(a.getPassword2()) && NbUtil.isNull(oldPwd)) {
+			// 如果没有旧密码,则不用取验证 
+		} else {
+			if(oldPwdMd5.equals(a.getPassword2()) == false) {
+				return AjaxJson.getError("旧密码输入错误");
+			}
+		}
+		
+		// 3、开始改 
+		int line = spAdminPasswordService.updatePassword(a.getId(), newPwd);
+		return AjaxJson.getByLine(line);
+	}
+	
+}

+ 34 - 0
sp-admin/src/main/java/com/pj/project4sp/admin4password/SpAdminPasswordService.java

@@ -0,0 +1,34 @@
+package com.pj.project4sp.admin4password;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.pj.current.config.SystemObject;
+import com.pj.project4sp.SP;
+
+/**
+ * 用户表 密码相关 
+ * @author kong
+ *
+ */
+@Service
+public class SpAdminPasswordService {
+
+	
+	// REQUIRED=如果调用方有事务  就继续使用调用方的事务 
+	/** 修改一个admin的密码为  */
+	@Transactional(rollbackFor = Exception.class, propagation=Propagation.REQUIRED)	
+	public int updatePassword(long adminId, String password) {
+		// 更改密码 
+		SP.publicMapper.updateColumnById("sp_admin", "password", SystemObject.getPasswordMd5(adminId, password), adminId);
+		if(SystemObject.config.getIsPw()) {
+			// 明文密码 
+			SP.publicMapper.updateColumnById("sp_admin", "pw", password, adminId);		
+			return 2;
+		}
+		return 1;
+	}
+	
+	
+}

+ 6 - 0
sp-admin/src/main/java/com/pj/project4sp/package-info.java

@@ -0,0 +1,6 @@
+
+
+/**
+ * 此模块为sa-plus的代码
+ */
+package com.pj.project4sp;

+ 90 - 0
sp-admin/src/main/java/com/pj/project4sp/redis4console/RedisConsoleController.java

@@ -0,0 +1,90 @@
+package com.pj.project4sp.redis4console;
+
+import java.util.List;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.current.satoken.AuthConst;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+/**
+ * redis相关操作 
+ * @author kong 
+ *
+ */
+@RestController
+@RequestMapping("/RedisConsole/")
+public class RedisConsoleController {
+
+	/** 获取一些基本预览信息  */
+	@RequestMapping("getPreInfo")
+	@SaCheckPermission(AuthConst.REDIS_CONSOLE)
+	public AjaxJson getPreInfo() {
+		SoMap so = RedisConsoleUtil.getInfo();
+		return AjaxJson.getSuccessData(so);
+	}
+
+	/** 查询key集合   */
+	@RequestMapping("getKeys")
+	@SaCheckPermission(AuthConst.REDIS_CONSOLE)
+	public AjaxJson getKeys(String k) {
+		List<String> keys = RedisConsoleUtil.getKeys(k);
+		return AjaxJson.getSuccessData(keys);
+	}
+	
+	/** 查询某个值的详细信息  */
+	@RequestMapping("getByKey")
+	@SaCheckPermission(AuthConst.REDIS_CONSOLE)
+	public AjaxJson getByKey(String key) {
+		SoMap soMap = RedisConsoleUtil.getByKey(key);
+		return AjaxJson.getSuccessData(soMap);
+	}
+	
+	/** 添加一个键值  */
+	@RequestMapping("set")
+	@SaCheckPermission({AuthConst.REDIS_CONSOLE, AuthConst.DEV})
+	public AjaxJson set(String key, String value, long ttl) {
+		RedisConsoleUtil.setBySeconds(key, value, ttl);
+		return AjaxJson.getSuccess();
+	}
+
+	/** 删除一个键值  */
+	@RequestMapping("del")
+	@SaCheckPermission({AuthConst.REDIS_CONSOLE, AuthConst.DEV})
+	public AjaxJson del(String key) {
+		RedisConsoleUtil.del(key);
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 修改一个值的value  */
+	@RequestMapping("updateValue")
+	@SaCheckPermission({AuthConst.REDIS_CONSOLE, AuthConst.DEV})
+	public AjaxJson updateValue(String key, String value) {
+		RedisConsoleUtil.updateValue(key, value);
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 修改一个值的ttl  */
+	@RequestMapping("updateTtl")
+	@SaCheckPermission({AuthConst.REDIS_CONSOLE, AuthConst.DEV})
+	public AjaxJson updateTtl(String key, long ttl) {
+		RedisConsoleUtil.updateTtl(key, ttl);
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 删除多个键值  */
+	@RequestMapping("deleteByKeys")
+	@SaCheckPermission({AuthConst.REDIS_CONSOLE, AuthConst.DEV})
+	public AjaxJson deleteByKeys() {
+		List<String> keys = SoMap.getRequestSoMap().getListByComma("keys", String.class);
+		for (String k : keys) {
+			RedisConsoleUtil.del(k);
+		}
+		return AjaxJson.getSuccess();
+	}
+	
+}

+ 190 - 0
sp-admin/src/main/java/com/pj/project4sp/redis4console/RedisConsoleUtil.java

@@ -0,0 +1,190 @@
+package com.pj.project4sp.redis4console;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import com.pj.utils.sg.AjaxError;
+import com.pj.utils.so.SoMap;
+
+
+/**
+ * redis 控制台相关操作 util 
+ * @author kong
+ *
+ */
+@Component
+public class RedisConsoleUtil {
+
+	
+	static String dbN;
+
+	/** 默认超时时间,单位周,此为一周 */
+	public static long ttl = 24* 7;	
+
+	/** 最大加载数量 */
+	static long loadMax = 10000;
+
+	/** string专用 */
+	static StringRedisTemplate stringRedisTemplate;
+	@Autowired
+	public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplates, @Value("${spring.redis.database}") String dbN) {
+		RedisConsoleUtil.stringRedisTemplate = stringRedisTemplates;
+		RedisConsoleUtil.dbN = dbN;
+	}
+
+	
+	
+	/** 获取reids信息  */
+	public static SoMap getInfo() {
+		// 加载所有信息  
+		Properties info = stringRedisTemplate.getRequiredConnectionFactory().getConnection().info();
+//		System.out.println(info);
+		SoMap map = new SoMap();
+		for (String key : info.stringPropertyNames()) {
+			map.put(key, info.getProperty(key));
+		}
+		
+		// 加载所有信息 
+		SoMap so = new SoMap();
+		so.set("keys_count", getKeyCount(map));	// key 总数 
+		so.set("keyspace_hits", map.get("keyspace_hits"));	// 被命中个数 
+		so.set("used_memory_human", map.get("used_memory_human"));	// 已经占用内存数量 
+		so.set("used_memory_peak_human", map.get("used_memory_peak_human"));	// 内存消耗峰值 
+		so.set("uptime_in_seconds", map.get("uptime_in_seconds"));	// redis 已经启动的秒数 
+		so.set("isGtMax", so.getLong("keys_count") > loadMax);	// 是否已经超过了最大值 
+		
+		return so;
+	}
+	
+	
+
+	/** 获取keys列表   */
+	public static List<String> getKeys(String k) {
+
+		// 如果为空,则查询所有 
+		if(k == null || k.equals("")) {
+			k = "*";
+		}
+		
+		// 检查是否超过上限 
+		Set<String> keysSet = stringRedisTemplate.keys(k);
+		AjaxError.throwBy(keysSet.size() > loadMax, 501, "key值数量超" + loadMax + "<br/>为性能考虑无法返回数据,请更换筛选条件");
+		
+		// 排序
+		List<String> keys = new ArrayList<String>();
+		keys.addAll(keysSet);
+		
+		// 按照字典排序 
+		Collections.sort(keys, new Comparator<String>() {  
+            @Override  
+            public int compare(String o1, String o2) {  
+                Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);  
+                return com.compare(o1, o2);  
+  
+            }  
+        });
+
+		return keys;
+	}
+
+
+	/** 获取单个的详情 */
+	public static SoMap getByKey(String key) {
+		// 键值 
+		String value = null;
+		try {
+			value = stringRedisTemplate.opsForValue().get(key);
+		} catch (Exception e) {
+			value = "未能成功获取:" + e.getMessage();
+		}
+		
+		// 过期时间 
+		long expire = stringRedisTemplate.getExpire(key);	
+		
+		SoMap soMap = new SoMap()
+				.set("key", key)
+				.set("value", value)
+				.set("ttl", expire);
+		return soMap;
+	}
+	
+	/** 写入一个值  */
+	public static void setBySeconds(String key, String value, long timeout) {
+		stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
+	}
+	
+	/**  删除一个值  */
+	public static void del(String key) {
+		stringRedisTemplate.delete(key);
+	}
+
+	/** 修改一个值的value  */
+	public static void updateValue(String key, String value) {
+		long expire = stringRedisTemplate.getExpire(key);
+//		System.err.println(expire);
+		// 1 = 永久 
+		if(expire == -1) {
+			stringRedisTemplate.opsForValue().set(key, value);
+			return;
+		}
+		// -2 = 无此键 
+		if(expire == -2) {
+			return;
+		}
+		stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
+	}
+
+	/** 修改一个值的ttl  */
+	public static void updateTtl(String key, long ttl) {
+		if(ttl < 0) {
+			// 注意此处可能因为序列化格式的不同,导致数据修改为无效数据 
+			String value = stringRedisTemplate.opsForValue().get(key);
+			stringRedisTemplate.opsForValue().set(key, value);
+			return;
+			// 禁止修改
+//			throw AjaxError.get("ttl值需要>=0");
+		}
+		stringRedisTemplate.expire(key, ttl, TimeUnit.SECONDS);
+	}
+	
+	/** 根据info获取当前 key总数  */
+	private static long getKeyCount(SoMap map) {
+		long keysCount = 0;
+		try {
+			// 计算 key 总数
+			String dbName = dbN;
+			String dbInfo = map.getString("db" + dbName);
+			if(dbInfo != null) {
+				String[] arr = dbInfo.split(",");
+				for (String item : arr) {
+					String[] arr2 = item.split("=");
+					if("keys".equals(arr2[0])) {
+						keysCount = Long.valueOf(arr2[1]);
+					}
+				}
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return keysCount;
+	}
+	
+	
+	
+
+	
+	
+	
+	
+}

+ 35 - 0
sp-admin/src/main/java/com/pj/project4sp/role/SpRole.java

@@ -0,0 +1,35 @@
+package com.pj.project4sp.role;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+
+/**
+ * Model: 系统角色表
+ * @author kong
+ */
+@Data
+public class SpRole implements Serializable  {
+
+	private static final long serialVersionUID = 1L;
+
+	// ---------- 表中字段 ----------
+	/** 角色id,--主键、自增 */
+	public Long id;	
+	
+	/** 角色名称, 唯一约束 */
+	public String name;	
+	
+	/** 角色详细描述 */
+	public String info;	
+	
+	/** 是否锁定(1=是,2=否), 锁定之后不可随意删除, 防止用户误操作 */
+	public Integer isLock;	
+	
+	/** 创建时间 */
+	public Date createTime;	
+
+
+
+}

+ 84 - 0
sp-admin/src/main/java/com/pj/project4sp/role/SpRoleController.java

@@ -0,0 +1,84 @@
+package com.pj.project4sp.role;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.current.satoken.AuthConst;
+import com.pj.project4sp.SP;
+import com.pj.utils.sg.AjaxError;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+/**
+ * Controller: 系统角色表
+ * @author kong
+ */
+@RestController
+@RequestMapping("/role/")
+public class SpRoleController {
+
+	/** 底层Mapper依赖 */
+	@Autowired
+	SpRoleMapper spRoleMapper;
+
+	/** 增 */
+	@RequestMapping("add")
+	@SaCheckPermission(AuthConst.ROLE_LIST)
+	@Transactional(rollbackFor = Exception.class)
+	public AjaxJson add(SpRole s){
+		// 检验
+		if(spRoleMapper.getById(s.getId()) != null) {
+			return AjaxJson.getError("此id已存在,请更换");
+		}
+		SpRoleUtil.checkRoleThrow(s);
+		int line = spRoleMapper.add(s);
+		AjaxError.throwByLine(line, "添加失败");
+		// 返回这个对象 
+		long id = s.getId();
+		if(id == 0) {
+			id = SP.publicMapper.getPrimarykey();
+		}
+		return AjaxJson.getSuccessData(spRoleMapper.getById(id));
+	}
+
+	/** 删 */
+	@RequestMapping("delete")
+	@SaCheckPermission({AuthConst.ROLE_LIST, AuthConst.DEV})
+	AjaxJson delete(long id){
+		int line = spRoleMapper.delete(id);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 改 */ 
+	@RequestMapping("update")
+	@SaCheckPermission({AuthConst.ROLE_LIST, AuthConst.DEV})
+	AjaxJson update(SpRole s){
+		SpRoleUtil.checkRoleThrow(s);
+		int line = spRoleMapper.update(s);
+		return AjaxJson.getByLine(line);
+	}
+
+	/** 查 */ 
+	@RequestMapping("getById")
+	@SaCheckPermission(AuthConst.IN_SYSTEM)
+	AjaxJson getById(long id){
+		SpRole s = spRoleMapper.getById(id);
+		return AjaxJson.getSuccessData(s);
+	}
+
+	/** 查 - 集合  */
+	@RequestMapping("getList")
+	@SaCheckPermission(AuthConst.IN_SYSTEM)
+	AjaxJson getList(){
+		SoMap so = SoMap.getRequestSoMap();
+		List<SpRole> list = spRoleMapper.getList(so);
+		return AjaxJson.getSuccessData(list);
+	}
+
+}

+ 60 - 0
sp-admin/src/main/java/com/pj/project4sp/role/SpRoleMapper.java

@@ -0,0 +1,60 @@
+package com.pj.project4sp.role;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.SoMap;
+
+/**
+ * Mapper: 系统角色表
+ * @author kong
+ */
+@Mapper
+public interface SpRoleMapper {
+
+
+	/**
+	 * 增 
+	 * @param obj
+	 * @return
+	 */
+	int add(SpRole obj);
+
+	/**
+	 * 删
+	 * @param id
+	 * @return
+	 */
+	int delete(long id);
+
+	/**
+	 * 改 
+	 * @param obj
+	 * @return
+	 */
+	int update(SpRole obj);
+
+	/**
+	 *  查 
+	 * @param id
+	 * @return
+	 */
+	SpRole getById(long id);
+
+	/**
+	 * 查 
+	 * @param soMap
+	 * @return
+	 */
+	List<SpRole> getList(SoMap soMap);
+
+
+	/**
+	 * 查,根据角色名字
+	 * @param name
+	 * @return
+	 */
+	SpRole getByRoleName(String name);
+
+}

+ 62 - 0
sp-admin/src/main/java/com/pj/project4sp/role/SpRoleMapper.xml

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project4sp.role.SpRoleMapper">
+
+
+	<!-- 增 -->
+	<insert id="add" >
+		insert into 
+		sp_role(id, name, info, is_lock, create_time) 
+		values (#{id}, #{name}, #{info}, 2, now())
+	</insert>
+
+
+	<!-- 删 -->
+	<delete id="delete" >
+		delete from sp_role 
+		where id = #{id}
+	</delete>
+
+
+	<!-- 改 -->
+	<update id="update" >
+		update sp_role set 
+		name = #{name}, 
+		info = #{info}
+		where id=#{id}
+	</update>
+
+
+	<!-- 通用映射 -->
+	<resultMap id="model" type="com.pj.project4sp.role.SpRole">
+		<result property="id" column="id" />
+		<result property="name" column="name" />
+		<result property="info" column="info" />
+		<result property="isLock" column="is_lock" />
+		<result property="createTime" column="create_time" />
+	</resultMap>
+
+	<!-- 查 -->
+	<select id="getById" resultMap="model" >
+		select * from sp_role 
+		where id = #{id}
+	</select>
+
+
+	<!-- 查询 -->
+	<select id="getList" resultMap="model" >
+		select * from sp_role where 1=1 
+		<if test=' this.has("name")  '>
+			and name like concat('%', #{name}, '%')
+		</if>
+	</select>
+
+	<!-- 查 - 根据角色名字 -->
+	<select id="getByRoleName" resultMap="model">
+		select * from sp_role 
+		where name = #{name}
+	</select>
+
+
+	
+</mapper>

+ 104 - 0
sp-admin/src/main/java/com/pj/project4sp/role/SpRoleUtil.java

@@ -0,0 +1,104 @@
+package com.pj.project4sp.role;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.pj.current.satoken.AuthConst;
+import com.pj.project4sp.admin.SpAdminUtil;
+import com.pj.utils.sg.AjaxError;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.sg.NbUtil;
+
+import cn.dev33.satoken.session.SaSession;
+import cn.dev33.satoken.stp.StpUtil;
+
+/**
+ * 工具类:SysRole模块 
+ * @author kong
+ *
+ */
+@Component
+public class SpRoleUtil {
+	
+	/** 底层Mapper依赖 */
+	static SpRoleMapper spRoleMapper;
+	@Autowired
+	public void setspRoleMapper(SpRoleMapper spRoleMapper) {
+		SpRoleUtil.spRoleMapper = spRoleMapper;
+	}
+	
+	/**
+	 * 验证一个SysRole对象 是否符合标准 
+	 * @param s
+	 * @return
+	 */
+	static AjaxJson checkRole(SpRole s) {
+		
+		// 1、名称相关 
+		if(NbUtil.isNull(s.getName())) {
+			return AjaxJson.getError("昵称不能为空");
+		}
+		// 2、如果该名称已存在,并且不是当前角色 
+		SpRole s2 = spRoleMapper.getByRoleName(s.getName());
+		if(s2 != null && s2.getId() != s.getId()) {
+			return AjaxJson.getError("昵称与已有角色重复,请更换");
+		}
+		
+		// 重重检验,最终合格
+		return AjaxJson.getSuccess();
+	}
+	
+	/**
+	 * 验证一个Role是否符合标准, 不符合则抛出异常 
+	 * @param s
+	 */
+	static void checkRoleThrow(SpRole s) {
+		AjaxJson aj = checkRole(s);
+		if(aj.getCode() != AjaxJson.CODE_SUCCESS){
+			throw AjaxError.get(aj.getMsg());
+		}
+	}
+
+
+	/**
+	 * 获取当前会话的roleId 
+	 */
+	public static long getCurrRoleId() {
+		return getRoleIdByAdminId(StpUtil.getLoginIdAsLong());
+	}
+
+	/**
+	 * 获取指定 Admin 账号的 roleId 
+	 */
+	public static long getRoleIdByAdminId(long adminId) {
+		// 先获取其 User-Session 
+		SaSession session = StpUtil.getSessionByLoginId(adminId, false);
+		if(session == null) {
+			// 如果此账号的 User-Session 尚未创建,则直接查库,避免创建 Session 缓存 
+			return SpAdminUtil.spAdminMapper.getById(adminId).getRoleId();
+		}
+		
+		// 从 Session 中获取 
+		long roleId = session.get(AuthConst.ROLE_ID_KEY, () -> {
+			return SpAdminUtil.spAdminMapper.getById(adminId).getRoleId();
+		});
+		
+		return roleId;
+	}
+	
+	/**
+	 * 清空指定 Admin 账号的 roleId 值缓存 
+	 */
+	public static void clearRoleIdCache(long adminId) {
+		// 先获取其 User-Session 
+		SaSession session = StpUtil.getSessionByLoginId(adminId, false);
+		if(session == null) {
+			// 如果此账号的 User-Session 尚未创建,则不执行任何动作 
+			return;
+		}
+		// 清空值 
+		session.delete(AuthConst.ROLE_ID_KEY);
+	}
+	
+	
+}

+ 70 - 0
sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionController.java

@@ -0,0 +1,70 @@
+package com.pj.project4sp.role4permission;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.current.satoken.AuthConst;
+import com.pj.project4sp.role.SpRoleUtil;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+/**
+ * Controller: 角色与权限的中间表 
+ * @author kong
+ *
+ */
+@RestController
+@RequestMapping("/SpRolePermission/")
+public class SpRolePermissionController {
+
+	/** 底层Service */
+	@Autowired
+	SpRolePermissionService spRolePermissionService;
+	
+	/**
+	 * 拉取权限id列表  根据指定roleId 
+	 * @param roleId
+	 * @return
+	 */
+	@RequestMapping("getPcodeByRid")
+	@SaCheckPermission({AuthConst.ROLE_LIST, AuthConst.DEV})
+    public AjaxJson getPcodeByRid(@RequestParam(defaultValue="0") long roleId){
+		// 防止拉出全部 	
+		if(roleId == 0){
+			return AjaxJson.getError("roleId不能为null或0");		
+		}
+		return AjaxJson.getSuccessData(spRolePermissionService.getPcodeByRid(roleId));
+	}
+	
+	/** 拉取菜单id列表  根据当前用户roleId  */
+	@RequestMapping("getPcodeByCurrRid")
+	public AjaxJson getPcodeByCurrRid(){
+		long roleId = SpRoleUtil.getCurrRoleId();
+		List<String> list = spRolePermissionService.getPcodeByRid(roleId);
+		return AjaxJson.getSuccessData(list);
+	}
+	
+	/**
+	 * 修改指定角色的拥有的权限 
+	 * @param roleId 角色id
+	 * @param code 拥有的权限码集合 
+	 * @return
+	 */
+	@RequestMapping("updatePcodeByRid")
+	@SaCheckPermission({AuthConst.ROLE_LIST, AuthConst.DEV})
+	public AjaxJson updatePcodeByRid(long roleId){
+
+		// 获取前端传过来的权限码集合 
+    	List<String> list = SoMap.getRequestSoMap().getListByComma("codes", String.class); 
+    	
+		int line = spRolePermissionService.updateRoleMenu(roleId, list);
+		return AjaxJson.getSuccessData(line);
+	}
+	
+}

+ 42 - 0
sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionMapper.java

@@ -0,0 +1,42 @@
+package com.pj.project4sp.role4permission;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * Mapper: 角色权限中间表
+ * @author kong
+ */
+@Mapper
+public interface SpRolePermissionMapper {
+
+
+	/**
+	 * 增 
+	 * @param roleId
+	 * @param pcode
+	 * @return
+	 */
+	int add(@Param("roleId")long roleId, @Param("pcode")String pcode);
+
+	
+	/**
+	 * 删除指定角色的所有权限 
+	 * @param roleId
+	 * @return
+	 */
+	int deleteByRoleId(long roleId);
+	
+	
+	/**
+	 * 指定roleId的所有权限码 
+	 * @param roleId
+	 * @return
+	 */
+	List<String> getPcodeByRoleId(long roleId);
+	
+	
+
+}

+ 26 - 0
sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionMapper.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project4sp.role4permission.SpRolePermissionMapper">
+
+
+	<!-- 增 -->
+	<insert id="add" >
+		insert into 
+		sp_role_permission(role_id, permission_code, create_time) 
+		values (#{roleId}, #{pcode}, now())
+	</insert>
+	
+	<!-- 删除指定角色的所有权限 -->
+	<delete id="deleteByRoleId">
+		delete from sp_role_permission
+		where role_id = #{roleId} 
+	</delete>
+
+	<!-- 指定roleId的所有权限码   -->
+	<select id="getPcodeByRoleId" resultType="String">
+		select permission_code from sp_role_permission
+		where role_id = #{roleId}
+	</select>
+
+
+</mapper>

+ 55 - 0
sp-admin/src/main/java/com/pj/project4sp/role4permission/SpRolePermissionService.java

@@ -0,0 +1,55 @@
+package com.pj.project4sp.role4permission;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 角色权限中间表 
+ * @author kong
+ *
+ */
+@Service
+public class SpRolePermissionService {
+
+	@Autowired
+	SpRolePermissionMapper spRolePermissionMapper;
+	
+	/**
+	 * 获取指定角色的所有权限码 【增加缓存】
+	 */
+    @Cacheable(value="api_pcode_list", key="#roleId")	
+    public List<String> getPcodeByRid(long roleId){
+    	return spRolePermissionMapper.getPcodeByRoleId(roleId);
+    }
+
+    /**
+     * [T] 修改角色的一组权限关系 【清除缓存 】
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @CacheEvict(value= {"api_pcode_list"}, key="#roleId")	
+    public int updateRoleMenu(long roleId, List<String> pcodeArray){
+
+    	// 万一为空 
+    	if(pcodeArray == null){
+    		pcodeArray = new ArrayList<>();
+    	}
+    	
+    	// 先删
+    	spRolePermissionMapper.deleteByRoleId(roleId);
+    	
+    	// 再添加
+    	for(String pcode : pcodeArray){
+    		spRolePermissionMapper.add(roleId, pcode);
+        }
+    	
+    	// 返回
+        return pcodeArray.size();
+    }
+	
+}

+ 27 - 0
sp-admin/src/main/java/com/pj/project4sp/test/TestController.java

@@ -0,0 +1,27 @@
+package com.pj.project4sp.test;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.utils.sg.AjaxJson;
+
+/**
+ * 测试controller 
+ * @author kong 
+ */
+@RestController
+public class TestController {
+
+	
+	/**
+	 * 测试请求,如果能正常访问此路由,则证明项目已经部署成功 
+	 * @return
+	 */
+	@RequestMapping("/test")
+	public AjaxJson test() {
+		System.out.println("------------------ 成功进入请求 ------------------");
+		return AjaxJson.getSuccess("请求成功");
+	}
+
+	
+}

+ 48 - 0
sp-admin/src/main/java/com/pj/satoken/StpInterfaceImpl.java

@@ -0,0 +1,48 @@
+package com.pj.satoken;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.pj.project4sp.admin.SpAdminMapper;
+import com.pj.project4sp.role.SpRoleUtil;
+import com.pj.project4sp.role4permission.SpRolePermissionService;
+
+import cn.dev33.satoken.stp.StpInterface;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.util.SaFoxUtil;
+
+/**
+ * 自定义Sa-Token权限认证接口扩展 
+ * 
+ * @author kong
+ *
+ */
+@Component	
+public class StpInterfaceImpl implements StpInterface {
+
+	@Autowired
+	SpAdminMapper spAdminMapper;
+	
+	@Autowired
+	SpRolePermissionService spRolePermissionService;
+	
+	/** 返回一个账号所拥有的权限码集合  */
+	@Override
+	public List<String> getPermissionList(Object loginId, String loginType) {
+		if(loginType.equals(StpUtil.TYPE)) {
+			long adminId = SaFoxUtil.getValueByType(loginId, long.class);
+			long roleId = SpRoleUtil.getRoleIdByAdminId(adminId);
+			return spRolePermissionService.getPcodeByRid(roleId);								
+		}
+		return null;
+	}
+	
+	/** 返回一个账号所拥有的角色标识集合  */
+	@Override
+	public List<String> getRoleList(Object loginId, String loginType) {
+		return null;
+	}
+
+}

+ 21 - 0
sp-core/pom.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>face-admin</artifactId>
+        <groupId>com.pj</groupId>
+        <version>0.0.1-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>sp-core</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+
+
+    </dependencies>
+
+</project>

+ 56 - 0
sp-core/src/main/java/com/pj/current/SaPlusStartup.java

@@ -0,0 +1,56 @@
+package com.pj.current;
+
+import java.net.InetAddress;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+/**
+ * springboot启动之后 
+ * @author kong
+ *
+ */
+@Component
+public class SaPlusStartup implements CommandLineRunner {
+
+	@Value("${spring.application.name:sa-plus}")
+    private String applicationName;
+	
+	@Value("${server.port:8080}")
+    private String port;
+
+    @Value("${server.servlet.context-path:}")
+    private String path;
+
+    @Value("${spring.profiles.active:}")
+    private String active;
+   
+    @Override
+    public void run(String... args) throws Exception {
+    	 String ip = InetAddress.getLocalHost().getHostAddress();
+         String str = "\n------------- " + applicationName + " (" + active + ") 启动成功 --by " + getNow() + " -------------\n" + 
+                 "\t- Local:   http://localhost:" + port + path + "\n" +
+                 "\t- Local2:  http://127.0.0.1:" + port + path + ""
+                 ;
+         System.out.println(str);
+         // 
+         try {
+        	 System.out.println("\t- Network: http://" + ip + ":" + port + path + "\n");
+         } catch (Exception e) {
+        	 System.out.println("\t- Network: 未能成功获取\n");
+        	 System.err.println("异常:" + e.getMessage());
+         }
+    }
+
+	/**
+	 * 返回系统当前时间的YYYY-MM-dd hh:mm:ss 字符串格式
+	 */
+	private static String getNow(){
+		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+	}
+    
+}
+

+ 54 - 0
sp-core/src/main/java/com/pj/current/config/MyConfig.java

@@ -0,0 +1,54 @@
+package com.pj.current.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+
+import lombok.Data;
+
+/**
+ * 项目自定义配置 
+ * @author kong
+ *
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix="spring.myconfig")	
+public class MyConfig {
+
+	/**
+	 * md5的盐 
+	 */
+	private String md5Salt;		
+	
+	/** 
+	 * 是否明文存储密码 
+	 */
+	private Boolean isPw;		
+	
+	/** 
+	 * 本项目部署到的服务器域名(文件上传、微信支付等等模块  要用到) 
+	 */
+	private String domain;			
+	
+	/**
+	 * 是否彩色SQL日志 
+	 */
+	private Boolean colorSql = true;		
+
+	/**
+	 * 是否抛出SQL(将sql报错抛出到前端,方便调试,请只在开发环境打开,在生产模式请关闭)
+	 */
+	private Boolean throwSql = true;		
+	
+	/**
+	 * 是否把API请求日志输出在控制台 
+	 */
+	private Boolean logToFile = true;
+
+	/**
+	 * 是否把API请求日志记录在数据库 
+	 */
+	private Boolean logToDb = true;
+	
+}

+ 72 - 0
sp-core/src/main/java/com/pj/current/config/PerformConfigure.java

@@ -0,0 +1,72 @@
+package com.pj.current.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import com.pj.utils.sg.AjaxError;
+
+import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+import cn.dev33.satoken.router.SaRouter;
+
+/**
+ * 演示模式的拦截器(如果你不准备搭建演示程序,可以删除此配置类) 
+ * <p> 使用方法:
+ * 	配置文件里增加以下配置: 
+ * 		per=true 
+ *  即可打开
+ * @author kong 
+ */
+@Configuration
+@ConditionalOnProperty("per")
+public class PerformConfigure implements WebMvcConfigurer {
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+    	System.out.println("\n---------------------- 演示模式启动 \n");
+        registry.addInterceptor(new SaRouteInterceptor((req, res, handler)->{
+        	// 演示模式校验 
+			SaRouter.match(
+					// 管理员 
+					"/admin/add", "/admin/delete", "/admin/deleteByIds", "/admin/update", "/admin/updatePassword", 
+					"/admin/updateAvatar", "/admin/updateStatus", "/admin/updateRole", "/admin/updateInfo", 
+					
+					// 修改密码
+					"/AdminPassword/update", 
+					
+					// 全局日志
+					"/SgApilog/delete", "/SgApilog/deleteByIds", "/SgApilog/deleteByStartEnd", 
+					
+					// redis
+					"/RedisConsole/set", "/RedisConsole/del", "/RedisConsole/updateValue", "/RedisConsole/updateTTL", "/RedisConsole/deleteByKeys", 
+					
+					// 角色 
+					"/role/delete", "/role/update", 
+					
+					// 权限 
+					"/SpRolePermission/updatePcodeByRid", 
+					
+					// 全局配置 
+					"/SpCfg/updateCfg", 
+					
+					// sql控制台
+					"/druid/**", "/druid/sql.html",
+					
+					// 业务代码 
+					"/SerArticle/delete", "/SerArticle/deleteByIds",
+					"/SerGoods/delete", "/SerGoods/deleteByIds",
+					"/SysDept/delete", "/SysDept/deleteByIds",
+					"/SysNotice/delete", "/SysNotice/deleteByIds",
+					"/SysRedeem/delete", "/SysRedeem/deleteByIds",
+					"/SysType/delete", "/SysType/deleteByIds"
+					
+					)
+				.check(r -> {
+					throw new AjaxError("演示模式,不可操作,将项目部署到本地预览即可测试此功能");
+				})
+				;
+        })).addPathPatterns("/**").order(-1000); 
+    }
+    
+}

+ 38 - 0
sp-core/src/main/java/com/pj/current/config/ProjectConfigure.java

@@ -0,0 +1,38 @@
+package com.pj.current.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * 项目配置 
+ * 
+ * @author kong 
+ */
+@Configuration
+public class ProjectConfigure {
+
+	/** 设定项目的默认缓存策略  */
+    @Bean
+	@Primary
+    public RedisCacheManager myCacheManager(RedisConnectionFactory redisConnectionFactory){
+        // 配置序列化为 json序列化格式 
+        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
+                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
+                ;
+        // 初始化缓存管理器 
+        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
+                .cacheDefaults(config)
+                .build();
+        return cacheManager;
+    }
+
+
+}

+ 77 - 0
sp-core/src/main/java/com/pj/current/config/RemoveDruidAdConfig.java

@@ -0,0 +1,77 @@
+package com.pj.current.config;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+
+/**
+ * 类名称:RemoveDruidAdConfig 类描述: 去除druid底部的广告配置类 
+ */
+@Configuration
+@ConditionalOnWebApplication
+@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
+@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true", matchIfMissing = true)
+public class RemoveDruidAdConfig {
+
+	/**
+	 * 方法名: removeDruidAdFilterRegistrationBean 方法描述: 除去页面底部的广告 @param
+	 * properties @return
+	 * org.springframework.boot.web.servlet.FilterRegistrationBean @throws
+	 */
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	@Bean
+	public FilterRegistrationBean removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {
+		// 获取web监控页面的参数
+		DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+		// 提取common.js的配置路径
+		String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+		String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+
+		final String filePath = "support/http/resources/js/common.js";
+
+		// 创建filter进行过滤
+		Filter filter = new Filter() {
+			@Override
+			public void init(FilterConfig filterConfig) throws ServletException {
+			}
+
+			@Override
+			public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+					throws IOException, ServletException {
+				chain.doFilter(request, response);
+				// 重置缓冲区,响应头不会被重置
+				response.resetBuffer();
+				// 获取common.js
+				String text = Utils.readFromResource(filePath);
+				// 正则替换banner, 除去底部的广告信息
+				text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+				text = text.replaceAll("powered.*?shrek.wang</a>", "");
+				response.getWriter().write(text);
+			}
+
+			@Override
+			public void destroy() {
+			}
+		};
+		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+		registrationBean.setFilter(filter);
+		registrationBean.addUrlPatterns(commonJsPattern);
+		return registrationBean;
+	}
+}

+ 41 - 0
sp-core/src/main/java/com/pj/current/config/SystemObject.java

@@ -0,0 +1,41 @@
+package com.pj.current.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import cn.hutool.crypto.SecureUtil;
+
+/**
+ * 有关当前项目的一些全局工具方法封装 
+ * @author kong
+ *
+ */
+@Component
+public class SystemObject {
+
+	// ===================================== 一些二次封装的方法 ===================================================
+	
+	/** 返回md5加密后的密码,根据当前配置的salt
+	 *   格式为: md5(salt + userid + password) 
+	 */ 
+	public static String getPasswordMd5(long userId, String password) {
+		return SecureUtil.md5(config.getMd5Salt() + userId + password).toUpperCase();
+	}
+	
+	/** 返回md5加密后的密码,根据当前配置的salt
+	 *  格式为: md5(salt + 0 + password) 
+	 */ 
+	public static String getPasswordMd5(String password) {
+		return getPasswordMd5(0, password);
+	}
+	
+	
+	// ===================================== yml自定义配置信息 ===================================================
+	
+	public static MyConfig config;
+	@Autowired
+	void setMyConfig(MyConfig config) {
+		SystemObject.config = config;
+	}
+	
+}

+ 57 - 0
sp-core/src/main/java/com/pj/current/global/ApilogAspect.java

@@ -0,0 +1,57 @@
+package com.pj.current.global;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+import com.pj.project4sp.apilog.SpApilogUtil;
+import com.pj.utils.sg.AjaxJson;
+
+/**
+ * API全局日志, Controller 层切面 
+ *
+ * @author kong
+ */
+@Aspect
+@Component
+public class ApilogAspect {
+    
+	/**
+	 * 定义AOP签名 --> 项目代码(所有class名成带有Controller字符的)
+	 */
+	@Pointcut("execution(* com.pj..*Controller*.*(..))")
+    public void webLogProject(){}
+
+    /**
+     * 环绕日志 
+     * @param pjp
+     * @return 
+     * @throws Throwable
+     */
+    @Around("webLogProject()")
+    public Object surround(ProceedingJoinPoint pjp) throws Throwable {
+        try {
+        	// 1、执行 
+            Object obj =  pjp.proceed();
+            
+            // 2、解析返回结果 
+            // 如果是 AjaxJson 
+            if(obj instanceof AjaxJson){	
+            	SpApilogUtil.endRequest((AjaxJson)obj);
+            } 
+            // 如果是 String  
+            else if (obj instanceof String) {	
+            	SpApilogUtil.endRequest(AjaxJson.get(901, String.valueOf(obj)));
+            } 
+            // 如果都不是 
+            else {	 
+            	SpApilogUtil.endRequest(AjaxJson.get(902, String.valueOf(obj)));
+            }
+            return obj;
+        } catch (Throwable e) {
+        	throw e;
+        }
+    }
+    
+}

+ 43 - 0
sp-core/src/main/java/com/pj/current/global/ApilogStartInterceptor.java

@@ -0,0 +1,43 @@
+package com.pj.current.global;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import com.pj.project4sp.apilog.SpApilogUtil;
+
+import cn.dev33.satoken.interceptor.SaRouteInterceptor;
+
+/**
+ * API全局日志 初始化拦截器 - 注册 
+ * 
+ * @author kong
+ */
+@Configuration
+public class ApilogStartInterceptor implements WebMvcConfigurer {
+
+	/**
+	 * 注册API日志拦截器  
+	 */
+	@Override
+	public void addInterceptors(InterceptorRegistry registry) {
+		registry.addInterceptor(new SaRouteInterceptor((req, res, handler) -> {
+			/*
+			 * 这里是请求的入口 (除过滤器外代码最先开始执行的地方):
+			 * 		用来初始化本次请求的日志记录 
+			 * 请求出口有三个地方:
+			 * 		情况1:请求在 Controller 正常执行,会在 GlobalAspect 全局日志处走出 
+			 * 		情况2:请求在 Controller 发生异常,会在 GlobalException 全局异常处走出 
+			 * 		情况3:请求的 /path 404 了,会在 NotFoundHandle 处走出 
+			 */
+			SpApilogUtil.startRequest();
+		}))
+		
+		 // 排除掉 /SgApilog/** 相关接口,因为访问 [全局日志相关API] 本身时不应该产生API日志 
+		.addPathPatterns("/**").excludePathPatterns("/SgApilog/**", "/error")
+		 
+		// -10000 保证此拦截器总是最先执行,因为靠后了容易失掉记录日志的机会 
+		.order(-10000);
+	}
+
+}

+ 46 - 0
sp-core/src/main/java/com/pj/current/global/BusinessException.java

@@ -0,0 +1,46 @@
+package com.pj.current.global;
+
+import lombok.Data;
+
+/**
+
+ * @description 业务异常
+ * @date Create in 2018/2/27 14:36
+ */
+@Data
+public class BusinessException extends RuntimeException {
+
+    private static final long serialVersionUID = -8661950806210020649L;
+    private Integer code;
+
+    /**
+     * 验证的时候,手动抛该异常
+     *
+     * @param errMsg 定义的错误信息
+     */
+    public BusinessException(String errMsg) {
+        super(errMsg);
+        this.code=500;
+    }
+    /**
+     * 验证的时候,手动抛该异常
+     *
+     * @param errMsg 定义的错误信息
+     */
+    public BusinessException(String errMsg, Integer code) {
+        super(errMsg);
+        this.code=code;
+    }
+
+
+    /**
+     * catch中抛该异常
+     *
+     * @param errMsg 自定义的错误信息
+     * @param e      异常
+     */
+    public BusinessException(String errMsg, Throwable e) {
+        super(errMsg, e);
+    }
+
+}

+ 84 - 0
sp-core/src/main/java/com/pj/current/global/GlobalExceptionHandler.java

@@ -0,0 +1,84 @@
+package com.pj.current.global;
+
+import java.sql.SQLException;
+
+import org.springframework.data.redis.RedisConnectionFailureException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import com.pj.current.config.SystemObject;
+import com.pj.project4sp.apilog.SpApilogUtil;
+import com.pj.utils.sg.AjaxError;
+import com.pj.utils.sg.AjaxJson;
+
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.exception.NotPermissionException;
+
+/**
+ * 全局异常处理 
+ * 
+ * <p> @ControllerAdvice 可指定包前缀,例如:(basePackages = "com.pj.controller.admin")
+ * @author kong
+ *
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+	/** 全局异常拦截  */
+	@ExceptionHandler
+	public AjaxJson handlerException(Exception e) {
+
+		// 打印堆栈,以供调试
+		e.printStackTrace(); 
+
+    	// 记录日志信息
+    	AjaxJson aj = null;
+		Throwable e2 = e.getCause();
+		
+		// ------------- 判断异常类型,提供个性化提示信息 
+		
+    	// 如果是未登录异常 
+		if(e instanceof NotLoginException){	
+			aj = AjaxJson.getNotLogin();
+		} 
+		// 如果是权限异常
+		else if(e instanceof NotPermissionException) {	
+			NotPermissionException ee = (NotPermissionException) e;
+			aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
+		} 
+		// 如果是AjaxError,则获取其具体code码 
+		else if(e instanceof AjaxError) {		
+			AjaxError ee = (AjaxError) e;
+			aj = AjaxJson.get(ee.getCode(), ee.getMessage());
+		}  
+		// 如果是SQLException,并且指定了hideSql,则只返回sql error 
+		else if((e instanceof SQLException || e2 instanceof SQLException) && SystemObject.config.getThrowSql() == false) {	
+			// 无论是否打开隐藏sql,日志表记录的都是真实异常信息 
+			aj = AjaxJson.getError(e2.getMessage());
+			SpApilogUtil.endRequest(aj);	
+			return AjaxJson.getError("Sql Error").set("reqId", SpApilogUtil.getCurrReqId());
+		}
+		// 如果是redis连接异常 ( 由于redis连接异常,系统已经无法正常工作,所以此处需要立即返回 )
+		else if(e instanceof RedisConnectionFailureException) {	
+			aj = AjaxJson.getError("Redis异常,请检查连接信息");
+			aj.set("reqId", SpApilogUtil.getCurrReqId());
+			return aj;
+		}
+		else if (e instanceof BusinessException){
+			aj = AjaxJson.getError(e.getMessage());
+			SpApilogUtil.endRequest(aj);
+		}
+		// 普通异常输出:500 + 异常信息 
+		else {
+			aj = AjaxJson.getError(e.getMessage());
+		}
+		
+		// 插入到日志表 
+		SpApilogUtil.endRequest(aj);
+		
+		// 返回到前台 
+		aj.set("reqId", SpApilogUtil.getCurrReqId());
+		return aj;
+	}
+	
+}

+ 40 - 0
sp-core/src/main/java/com/pj/current/global/NotFoundHandle.java

@@ -0,0 +1,40 @@
+package com.pj.current.global;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.boot.web.servlet.error.ErrorController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.pj.project4sp.apilog.SpApilogUtil;
+import com.pj.utils.sg.AjaxJson;
+
+/**
+ * 404 处理 
+ * 
+ * @author kong 
+ */
+@RestController
+public class NotFoundHandle implements ErrorController {
+
+	@Override
+	public String getErrorPath() {
+		return "/error";
+	}
+
+	// 由于除404以外的异常都会被全局异常处理掉,所以走到这里的请求都是404了 
+	@RequestMapping("/error")
+    public Object error(HttpServletRequest request, HttpServletResponse response) throws IOException {
+		// 记录API访问日志 
+		AjaxJson aj = AjaxJson.get(404, "not found");
+		SpApilogUtil.endRequest(aj);
+		
+		// 返回json消息 
+		response.setStatus(200);
+		return aj;
+    }
+	
+}

+ 150 - 0
sp-core/src/main/java/com/pj/current/mybatis/MybatisMapperDynamicLoader.java

@@ -0,0 +1,150 @@
+package com.pj.current.mybatis;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.ibatis.builder.xml.XMLMapperBuilder;
+import org.apache.ibatis.executor.ErrorContext;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
+/**
+ * mapper.xml热刷新操作类
+ * @author kong 
+ */
+public class MybatisMapperDynamicLoader implements InitializingBean, ApplicationContextAware {
+
+	public boolean enabled = true;	
+	public MybatisMapperDynamicLoader(boolean enabled) {
+		this.enabled = enabled;
+	}
+	
+    private final HashMap<String, String> mappers = new HashMap<String, String>();
+    private volatile ConfigurableApplicationContext context = null;
+    private volatile Scanner scanner = null;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.context = (ConfigurableApplicationContext) applicationContext;
+    }
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+    	// 如果未开启 直接返回
+    	if(!enabled) {
+    		return;
+    	}
+        try {
+            scanner = new Scanner();
+            new Timer(true).schedule(new TimerTask() {
+            	@Override
+                public void run() {
+                    try {
+                        if (scanner.isChanged()) {
+                            // System.out.println("load mapper.xml");
+                        	String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+                        	System.out.println("mapper.xml热刷新成功,当前时间:" + now);
+                            scanner.reloadXml();
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }, 10 * 1000, 3 * 1000);
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+    }
+
+    class Scanner {
+        private static final String XML_RESOURCE_PATTERN = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "**/*Mapper.xml";
+        private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
+        public Scanner() throws IOException {
+            Resource[] resources = findResource();
+            if (resources != null) {
+                for (Resource resource : resources) {
+                    String key = resource.getURI().toString();
+                    String value = getMd(resource);
+                    mappers.put(key, value);
+                }
+            }
+        }
+        public void reloadXml() throws Exception {
+            SqlSessionFactory factory = context.getBean(SqlSessionFactory.class);
+            Configuration configuration = factory.getConfiguration();
+            
+//            org.apache.ibatis.session.Configuration
+//            com.baomidou.mybatisplus.core.MybatisConfiguration
+            
+            removeConfig(configuration);
+            for (Resource resource : findResource()) {
+                try {
+                    XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(), configuration, resource.toString(), configuration.getSqlFragments());
+                    xmlMapperBuilder.parse();
+                } finally {
+                    ErrorContext.instance().reset();
+                }
+            }
+        }
+        private void removeConfig(Configuration configuration) throws Exception {
+            Class<?> classConfig = configuration.getClass();
+            // 如果使用了mybatis-plus,可能会获取不到真正的 Configuration类,需要加上以下代码,才能正确运行   ====== start
+            if(classConfig.equals(org.apache.ibatis.session.Configuration.class) == false) {
+//            	System.err.println("开始 转化");
+            	classConfig = classConfig.getSuperclass();
+            }
+            //  ====== end 
+            clearMap(classConfig, configuration, "mappedStatements");
+            clearMap(classConfig, configuration, "caches");
+            clearMap(classConfig, configuration, "resultMaps");
+            clearMap(classConfig, configuration, "parameterMaps");
+            clearMap(classConfig, configuration, "keyGenerators");
+            clearMap(classConfig, configuration, "sqlFragments");
+            clearSet(classConfig, configuration, "loadedResources");
+        }
+        @SuppressWarnings("rawtypes")
+		private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
+            Field field = classConfig.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            ((Map) field.get(configuration)).clear();
+        }
+        @SuppressWarnings("rawtypes")
+		private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
+            Field field = classConfig.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            ((Set) field.get(configuration)).clear();
+        }
+        public boolean isChanged() throws IOException {
+            boolean isChanged = false;
+            for (Resource resource : findResource()) {
+                String key = resource.getURI().toString();
+                String value = getMd(resource);
+                if (!value.equals(mappers.get(key))) {
+                    isChanged = true;
+                    mappers.put(key, value);
+                }
+            }
+            return isChanged;
+        }
+        private Resource[] findResource() throws IOException {
+            return resourcePatternResolver.getResources(XML_RESOURCE_PATTERN);
+        }
+        private String getMd(Resource resource) throws IOException {
+            return new StringBuilder().append(resource.contentLength()).append("-").append(resource.lastModified()).toString();
+        }
+    }
+}

+ 75 - 0
sp-core/src/main/java/com/pj/current/mybatis/MybatisStdOutImpl.java

@@ -0,0 +1,75 @@
+package com.pj.current.mybatis;
+
+import org.apache.ibatis.logging.Log;
+
+import com.pj.current.config.SystemObject;
+
+/**
+ * 自定义mybatis日志层实现,优化mybatis日志输出,主要优化以下部分:
+ * <p> 1、删除无用日志信息
+ * <p> 2、SQL高亮显示
+ * @author kong
+ *
+ */
+public class MybatisStdOutImpl implements Log {
+	
+	public MybatisStdOutImpl(String clazz) {
+		// Do Nothing
+	}
+
+	@Override
+	public boolean isDebugEnabled() {
+		return true;
+	}
+
+	@Override
+	public boolean isTraceEnabled() {
+		return true;
+	}
+
+	@Override
+	public void error(String s, Throwable e) {
+		System.err.println(s);
+		e.printStackTrace(System.err);
+	}
+
+	@Override
+	public void error(String s) {
+		System.err.println(s);
+	}
+
+	/** 
+	 * MyBatis动作 打印 
+	 * 执行Sql与参数 打印
+	 */
+	@Override
+	public void debug(String s) {
+		// 以下日志,不再打印 
+		if(s.startsWith("Creating") || s.startsWith("SqlSession") || s.startsWith("Cache") || s.startsWith("JDBC") || s.startsWith("Closing")) {
+			return;
+		}
+		// 如果是sql语句,则: 蓝色、加粗、下划线 
+		// 参考:https://blog.csdn.net/soinice/article/details/97052030
+		if(SystemObject.config != null && SystemObject.config.getColorSql() && s.startsWith("==>  Preparing")) {
+			s = "\033[34;1;4m" + s + "\033[0m";
+//			s = s.replaceAll("==>  Preparing: ", "");
+//			s = "==>  Preparing: " + s;
+		}
+		System.out.println(s);
+	}
+
+	/** 
+	 * Sql执行结果,打印 
+	 */
+	@Override
+	public void trace(String s) {
+		System.out.println(s);
+	}
+
+	@Override
+	public void warn(String s) {
+		System.out.println(s);
+	}
+
+
+}

+ 36 - 0
sp-core/src/main/java/com/pj/current/mybatis/RefConfig.java

@@ -0,0 +1,36 @@
+package com.pj.current.mybatis;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * mapper.xml相关配置注入 
+ * @author kong
+ *
+ */
+@Configuration
+public class RefConfig {
+	
+	@Value("${autof5:true}")
+	boolean autof5;
+	
+	@Bean(name="MybatisMapperDynamicLoader")
+	public MybatisMapperDynamicLoader get() {
+		// System.out.println("是啥===:" + autof5);
+		return new MybatisMapperDynamicLoader(autof5);
+	}
+	
+
+	/**
+	 * 注入日志组件 (从yml文件中配置的方式,打包后有概率无法启动项目且无法解决,故用此方法注入自定义日志组件)
+	 * @param sqlSessionFactory
+	 */
+	@Autowired
+	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
+		sqlSessionFactory.getConfiguration().setLogImpl(MybatisStdOutImpl.class);
+	}
+	
+}

+ 47 - 0
sp-core/src/main/java/com/pj/current/satoken/AuthConst.java

@@ -0,0 +1,47 @@
+package com.pj.current.satoken;
+
+/**
+ * 权限码常量  
+ * @author kong
+ *
+ */
+public final class AuthConst {
+
+	/**
+	 *  私有构造方法 
+	 */
+	private AuthConst() {
+	}
+	
+	
+	// --------------- 代表身份的权限 --------------- 
+	
+	public static final String BAS = "bas"; 			 // 身份相关 
+	public static final String DEV = "dev"; 			 // 开发者权限 	--- 系统最高权限
+	public static final String IN_SYSTEM = "in-system";		  // 进入后台权限,没有此权限无法进入后台管理
+	
+	
+	// --------------- 所有权限码 --------------- 
+
+	public static final String AUTH = "auth";		   // 权限管理
+	public static final String ROLE_LIST = "role-list";		    // 权限管理 - 角色管理
+	public static final String MENU_LIST = "menu-list";		   // 权限管理 - 菜单列表
+	public static final String ADMIN_LIST = "admin-list";		   // 权限管理 - 管理员列表
+	public static final String ADMIN_ADD = "admin-add";		   // 权限管理 - 管理员添加
+
+	public static final String CONSOLE = "console";		   // 监控中心
+	public static final String SQL_CONSOLE = "sql-console";		      // 监控中心 - SQL监控
+	public static final String REDIS_CONSOLE = "redis-console";		   // 监控中心 - Redis 控制台
+	public static final String APILOG_LIST = "apilog-list";		   // 监控中心 - API 请求日志
+
+	public static final String SP_CFG = "sp-cfg";		  	 // 系统配置
+	public static final String SP_CFG_APP = "sp-cfg-app";		  	 // 系统配置 - 系统对公配置
+	public static final String SP_CFG_SERVER = "sp-cfg-server";		   // 系统配置 - 服务器私有配置
+
+	
+	// --------------- 其它常量 --------------- 
+	
+	/** 在 SaSession 上存储 角色id 使用的key */
+	public static final String ROLE_ID_KEY = "ROLE_ID";		   
+	
+}

+ 71 - 0
sp-core/src/main/java/com/pj/current/satoken/SaTokenConfigure.java

@@ -0,0 +1,71 @@
+package com.pj.current.satoken;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import com.pj.utils.sg.AjaxJson;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.filter.SaServletFilter;
+import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
+import cn.dev33.satoken.router.SaHttpMethod;
+import cn.dev33.satoken.router.SaRouter;
+
+/**
+ * Sa-Token 代码方式进行配置 
+ * @author kong 
+ */
+@Configuration
+public class SaTokenConfigure implements WebMvcConfigurer {
+
+	/**
+	 * 注册 Sa-Token 的拦截器,打开注解式鉴权功能 
+	 */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**"); 
+    }
+    
+    /**
+     * 注册 Sa-Token全局过滤器,解决跨域问题 
+     */
+    @Bean
+    public SaServletFilter getSaServletFilter() {
+        return new SaServletFilter()
+        		// 拦截与排除 path 
+        		.addInclude("/**").addExclude("/favicon.ico")
+        		
+        		// 全局认证函数 
+        		.setAuth(obj -> {
+        			// ... 
+        		})
+        		
+        		// 异常处理函数  
+        		.setError(e -> {
+        			return AjaxJson.getError(e.getMessage());
+        		})
+        		
+        		// 前置函数:在每次认证函数之前执行
+        		.setBeforeAuth(obj -> {
+        			// ---------- 设置跨域响应头 ----------
+        			SaHolder.getResponse()
+        			// 允许指定域访问跨域资源
+        			.setHeader("Access-Control-Allow-Origin", "*")
+        			// 允许所有请求方式
+        			.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
+        			// 有效时间
+        			.setHeader("Access-Control-Max-Age", "3600")
+        			// 允许的header参数
+        			.setHeader("Access-Control-Allow-Headers", "*");
+        			
+        			// 如果是预检请求,则立即返回到前端 
+        			SaRouter.match(SaHttpMethod.OPTIONS)
+        				.free(r -> System.out.println("--------OPTIONS预检请求,不做处理"))
+        				.back();
+        		})
+        		;
+    }
+	
+}

+ 865 - 0
sp-core/src/main/java/com/pj/current/satoken/StpUserUtil.java

@@ -0,0 +1,865 @@
+package com.pj.current.satoken;
+
+import java.util.List;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.fun.SaFunction;
+import cn.dev33.satoken.session.SaSession;
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpLogic;
+import cn.dev33.satoken.stp.StpUtil;
+import com.pj.utils.cache.RedisUtil;
+
+/**
+ * Sa-Token 权限认证工具类 (User版本)
+ * @author kong 
+ */
+public class StpUserUtil {
+	public static final long ADMIN_DEPT_ID=9999999L;
+
+	public static void setDeptId(Long deptId) {
+		String key = "dept:" + StpUtil.getLoginIdAsString();
+		RedisUtil.set(key, deptId.toString());
+	}
+
+	public static long getDeptId() {
+		String key = "dept:" + StpUtil.getLoginIdAsString();
+		String deptId = RedisUtil.get(key);
+		return Long.parseLong(deptId);
+	}
+	/**
+	 * 账号类型标识 
+	 */
+	public static final String TYPE = "login";
+	
+	/**
+	 * 底层的 StpLogic 对象  
+	 */
+	public static StpLogic stpLogic = new StpLogic(TYPE); 
+
+	/**
+	 * 获取当前 StpLogic 的账号类型
+	 * @return See Note 
+	 */
+	public static String getLoginType(){
+		return stpLogic.getLoginType();
+	}
+
+	/**
+	 * 重置 StpLogic 对象
+	 * @param stpLogic / 
+	 */
+	public static void setStpLogic(StpLogic stpLogic) {
+		StpUtil.stpLogic = stpLogic;
+		// 防止自定义 stpLogic 被覆盖 
+		SaManager.putStpLogic(stpLogic);
+	}
+	
+	
+	// =================== 获取token 相关 ===================
+
+	/**
+	 * 返回token名称 
+	 * @return 此StpLogic的token名称
+	 */
+	public static String getTokenName() {
+ 		return stpLogic.getTokenName();
+ 	}
+
+ 	/**
+ 	 * 在当前会话写入当前TokenValue 
+ 	 * @param tokenValue token值 
+ 	 * @param cookieTimeout Cookie存活时间(秒)
+ 	 */
+	public static void setTokenValue(String tokenValue, int cookieTimeout){
+		stpLogic.setTokenValue(tokenValue, cookieTimeout);
+	}
+ 	
+	/**
+	 * 获取当前TokenValue
+	 * @return 当前tokenValue
+	 */
+	public static String getTokenValue() {
+		return stpLogic.getTokenValue();
+	}
+
+	/**
+	 * 获取当前会话的Token信息 
+	 * @return token信息 
+	 */
+	public static SaTokenInfo getTokenInfo() {
+		return stpLogic.getTokenInfo();
+	}
+
+	
+	// =================== 登录相关操作 ===================
+
+	// --- 登录 
+	
+	/**
+	 * 会话登录 
+	 * @param id 账号id,建议的类型:(long | int | String)
+	 */
+	public static void login(Object id) {
+		stpLogic.login(id);
+	}
+
+	/**
+	 * 会话登录,并指定登录设备 
+	 * @param id 账号id,建议的类型:(long | int | String)
+	 * @param device 设备标识 
+	 */
+	public static void login(Object id, String device) {
+		stpLogic.login(id, device);
+	}
+
+	/**
+	 * 会话登录,并指定是否 [记住我] 
+	 * @param id 账号id,建议的类型:(long | int | String)
+	 * @param isLastingCookie 是否为持久Cookie 
+	 */
+	public static void login(Object id, boolean isLastingCookie) {
+		stpLogic.login(id, isLastingCookie);
+	}
+
+	/**
+	 * 会话登录,并指定所有登录参数Model 
+	 * @param id 登录id,建议的类型:(long | int | String)
+	 * @param loginModel 此次登录的参数Model 
+	 */
+	public static void login(Object id, SaLoginModel loginModel) {
+		stpLogic.login(id, loginModel);
+	}
+
+	// --- 注销 
+	
+	/** 
+	 * 会话注销 
+	 */
+	public static void logout() {
+		stpLogic.logout();
+	}
+
+	/**
+	 * 会话注销,根据账号id 
+	 * @param loginId 账号id 
+	 */
+	public static void logout(Object loginId) {
+		stpLogic.logout(loginId);
+	}
+
+	/**
+	 * 会话注销,根据账号id 和 设备标识 
+	 * 
+	 * @param loginId 账号id 
+	 * @param device 设备标识 (填null代表所有注销设备) 
+	 */
+	public static void logout(Object loginId, String device) {
+		stpLogic.logout(loginId, device);
+	}
+	
+	/**
+	 * 会话注销,根据指定 Token 
+	 * 
+	 * @param tokenValue 指定token
+	 */
+	public static void logoutByTokenValue(String tokenValue) {
+		stpLogic.logoutByTokenValue(tokenValue);
+	}
+	
+	/**
+	 * 踢人下线,根据账号id 
+	 * <p> 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-5 </p>
+	 * 
+	 * @param loginId 账号id 
+	 */
+	public static void kickout(Object loginId) {
+		stpLogic.kickout(loginId);
+	}
+	
+	/**
+	 * 踢人下线,根据账号id 和 设备标识 
+	 * <p> 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-5 </p>
+	 * 
+	 * @param loginId 账号id 
+	 * @param device 设备标识 (填null代表踢出所有设备) 
+	 */
+	public static void kickout(Object loginId, String device) {
+		stpLogic.kickout(loginId, device);
+	}
+
+	/**
+	 * 踢人下线,根据指定 Token 
+	 * <p> 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-5 </p>
+	 * 
+	 * @param tokenValue 指定token
+	 */
+	public static void kickoutByTokenValue(String tokenValue) {
+		stpLogic.kickoutByTokenValue(tokenValue);
+	}
+	
+	/**
+	 * 顶人下线,根据账号id 和 设备标识 
+	 * <p> 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-4 </p>
+	 * 
+	 * @param loginId 账号id 
+	 * @param device 设备标识 (填null代表顶替所有设备) 
+	 */
+	public static void replaced(Object loginId, String device) {
+		stpLogic.replaced(loginId, device);
+	}
+	
+	
+	// 查询相关
+
+	/** 
+ 	 * 当前会话是否已经登录 
+ 	 * @return 是否已登录 
+ 	 */
+	public static boolean isLogin() {
+		return stpLogic.isLogin();
+	}
+
+	/** 
+ 	 * 检验当前会话是否已经登录,如未登录,则抛出异常 
+ 	 */
+ 	public static void checkLogin() {
+ 		stpLogic.checkLogin();
+ 	}
+
+ 	/** 
+ 	 * 获取当前会话账号id, 如果未登录,则抛出异常 
+ 	 * @return 账号id
+ 	 */
+	public static Object getLoginId() {
+		return stpLogic.getLoginId();
+	}
+
+	/** 
+	 * 获取当前会话账号id, 如果未登录,则返回默认值 
+	 * @param <T> 返回类型 
+	 * @param defaultValue 默认值
+	 * @return 登录id 
+	 */
+	public static <T> T getLoginId(T defaultValue) {
+		return stpLogic.getLoginId(defaultValue);
+	}
+
+	/** 
+	 * 获取当前会话账号id, 如果未登录,则返回null 
+	 * @return 账号id 
+	 */
+	public static Object getLoginIdDefaultNull() {
+		return stpLogic.getLoginIdDefaultNull();
+ 	}
+
+	/** 
+	 * 获取当前会话账号id, 并转换为String类型
+	 * @return 账号id 
+	 */
+	public static String getLoginIdAsString() {
+		return stpLogic.getLoginIdAsString();
+	}
+
+	/** 
+	 * 获取当前会话账号id, 并转换为int类型
+	 * @return 账号id 
+	 */
+	public static int getLoginIdAsInt() {
+		return stpLogic.getLoginIdAsInt();
+	}
+
+	/**
+	 * 获取当前会话账号id, 并转换为long类型 
+	 * @return 账号id 
+	 */
+	public static long getLoginIdAsLong() {
+		return stpLogic.getLoginIdAsLong();
+	}
+
+	/** 
+ 	 * 获取指定Token对应的账号id,如果未登录,则返回 null 
+ 	 * @param tokenValue token
+ 	 * @return 账号id
+ 	 */
+ 	public static Object getLoginIdByToken(String tokenValue) {
+ 		return stpLogic.getLoginIdByToken(tokenValue);
+ 	}
+	
+ 	
+	// =================== User-Session 相关 ===================
+
+ 	/** 
+	 * 获取指定账号id的Session, 如果Session尚未创建,isCreate=是否新建并返回
+	 * @param loginId 账号id
+	 * @param isCreate 是否新建
+	 * @return Session对象
+	 */
+	public static SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
+		return stpLogic.getSessionByLoginId(loginId, isCreate);
+	}
+
+	/** 
+	 * 获取指定key的Session, 如果Session尚未创建,则返回null
+	 * @param sessionId SessionId
+	 * @return Session对象 
+	 */
+	public static SaSession getSessionBySessionId(String sessionId) {
+		return stpLogic.getSessionBySessionId(sessionId);
+	}
+
+	/** 
+	 * 获取指定账号id的Session,如果Session尚未创建,则新建并返回 
+	 * @param loginId 账号id 
+	 * @return Session对象 
+	 */
+	public static SaSession getSessionByLoginId(Object loginId) {
+		return stpLogic.getSessionByLoginId(loginId);
+	}
+
+	/** 
+	 * 获取当前会话的Session, 如果Session尚未创建,isCreate=是否新建并返回 
+	 * @param isCreate 是否新建 
+	 * @return Session对象 
+	 */
+	public static SaSession getSession(boolean isCreate) {
+		return stpLogic.getSession(isCreate);
+	}
+
+	/** 
+	 * 获取当前会话的Session,如果Session尚未创建,则新建并返回 
+	 * @return Session对象 
+	 */
+	public static SaSession getSession() {
+		return stpLogic.getSession();
+	}
+
+	
+	// =================== Token-Session 相关 ===================  
+	
+	/** 
+	 * 获取指定Token-Session,如果Session尚未创建,则新建并返回 
+	 * @param tokenValue Token值
+	 * @return Session对象  
+	 */
+	public static SaSession getTokenSessionByToken(String tokenValue) {
+		return stpLogic.getTokenSessionByToken(tokenValue);
+	}
+	
+	/** 
+	 * 获取当前Token-Session,如果Session尚未创建,则新建并返回
+	 * @return Session对象 
+	 */
+	public static SaSession getTokenSession() {
+		return stpLogic.getTokenSession();
+	}
+
+
+	// =================== [临时过期] 验证相关 ===================  
+
+	/**
+ 	 * 检查当前token 是否已经[临时过期],如果已经过期则抛出异常  
+ 	 */
+ 	public static void checkActivityTimeout() {
+ 		stpLogic.checkActivityTimeout();
+ 	}
+
+ 	/**
+ 	 * 续签当前token:(将 [最后操作时间] 更新为当前时间戳) 
+ 	 * <h1>请注意: 即时token已经 [临时过期] 也可续签成功,
+ 	 * 如果此场景下需要提示续签失败,可在此之前调用 checkActivityTimeout() 强制检查是否过期即可 </h1>
+ 	 */
+ 	public static void updateLastActivityToNow() {
+ 		stpLogic.updateLastActivityToNow();
+ 	}
+ 	
+
+	// =================== 过期时间相关 ===================  
+
+ 	/**
+ 	 * 获取当前登录者的 token 剩余有效时间 (单位: 秒)
+ 	 * @return token剩余有效时间
+ 	 */
+ 	public static long getTokenTimeout() {
+ 		return stpLogic.getTokenTimeout();
+ 	}
+ 	
+ 	/**
+ 	 * 获取当前登录者的 User-Session 剩余有效时间 (单位: 秒)
+ 	 * @return token剩余有效时间
+ 	 */
+ 	public static long getSessionTimeout() {
+ 		return stpLogic.getSessionTimeout();
+ 	}
+
+ 	/**
+ 	 * 获取当前 Token-Session 剩余有效时间 (单位: 秒) 
+ 	 * @return token剩余有效时间
+ 	 */
+ 	public static long getTokenSessionTimeout() {
+ 		return stpLogic.getTokenSessionTimeout();
+ 	}
+ 	
+ 	/**
+ 	 * 获取当前 token [临时过期] 剩余有效时间 (单位: 秒)
+ 	 * @return token [临时过期] 剩余有效时间
+ 	 */
+ 	public static long getTokenActivityTimeout() {
+ 		return stpLogic.getTokenActivityTimeout();
+ 	}
+ 	
+
+ 	
+	// =================== 角色验证操作 ===================  
+
+	/**
+	 * 获取:当前账号的角色集合 
+	 * @return /
+	 */
+	public static List<String> getRoleList() {
+		return stpLogic.getRoleList();
+	}
+
+	/**
+	 * 获取:指定账号的角色集合 
+	 * @param loginId 指定账号id 
+	 * @return /
+	 */
+	public static List<String> getRoleList(Object loginId) {
+		return stpLogic.getRoleList(loginId);
+	}
+
+ 	/** 
+ 	 * 判断:当前账号是否拥有指定角色, 返回true或false 
+ 	 * @param role 角色标识
+ 	 * @return 是否含有指定角色标识
+ 	 */
+ 	public static boolean hasRole(String role) {
+ 		return stpLogic.hasRole(role);
+ 	}
+
+ 	/** 
+ 	 * 判断:指定账号是否含有指定角色标识, 返回true或false 
+ 	 * @param loginId 账号id
+ 	 * @param role 角色标识
+ 	 * @return 是否含有指定角色标识
+ 	 */
+ 	public static boolean hasRole(Object loginId, String role) {
+ 		return stpLogic.hasRole(loginId, role);
+ 	}
+ 	
+ 	/** 
+ 	 * 判断:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过] 
+ 	 * @param roleArray 角色标识数组
+ 	 * @return true或false
+ 	 */
+ 	public static boolean hasRoleAnd(String... roleArray){
+ 		return stpLogic.hasRoleAnd(roleArray);
+ 	}
+
+ 	/** 
+ 	 * 判断:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] 
+ 	 * @param roleArray 角色标识数组
+ 	 * @return true或false
+ 	 */
+ 	public static boolean hasRoleOr(String... roleArray){
+ 		return stpLogic.hasRoleOr(roleArray);
+ 	}
+ 	
+ 	/** 
+ 	 * 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException 
+ 	 * @param role 角色标识
+ 	 */
+ 	public static void checkRole(String role) {
+ 		stpLogic.checkRole(role);
+ 	}
+
+ 	/** 
+ 	 * 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过] 
+ 	 * @param roleArray 角色标识数组
+ 	 */
+ 	public static void checkRoleAnd(String... roleArray){
+ 		stpLogic.checkRoleAnd(roleArray);
+ 	}
+
+ 	/** 
+ 	 * 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] 
+ 	 * @param roleArray 角色标识数组
+ 	 */
+ 	public static void checkRoleOr(String... roleArray){
+ 		stpLogic.checkRoleOr(roleArray);
+ 	}
+
+	
+	// =================== 权限验证操作 ===================
+
+	/**
+	 * 获取:当前账号的权限码集合 
+	 * @return / 
+	 */
+	public static List<String> getPermissionList() {
+		return stpLogic.getPermissionList();
+	}
+
+	/**
+	 * 获取:指定账号的权限码集合 
+	 * @param loginId 指定账号id
+	 * @return / 
+	 */
+	public static List<String> getPermissionList(Object loginId) {
+		return stpLogic.getPermissionList(loginId);
+	}
+
+ 	/** 
+ 	 * 判断:当前账号是否含有指定权限, 返回true或false 
+ 	 * @param permission 权限码
+ 	 * @return 是否含有指定权限
+ 	 */
+	public static boolean hasPermission(String permission) {
+		return stpLogic.hasPermission(permission);
+	}
+
+ 	/** 
+ 	 * 判断:指定账号id是否含有指定权限, 返回true或false 
+ 	 * @param loginId 账号id
+ 	 * @param permission 权限码
+ 	 * @return 是否含有指定权限
+ 	 */
+	public static boolean hasPermission(Object loginId, String permission) {
+		return stpLogic.hasPermission(loginId, permission);
+	}
+
+ 	/** 
+ 	 * 判断:当前账号是否含有指定权限, [指定多个,必须全部具有] 
+ 	 * @param permissionArray 权限码数组
+ 	 * @return true 或 false 
+ 	 */
+ 	public static boolean hasPermissionAnd(String... permissionArray){
+ 		return stpLogic.hasPermissionAnd(permissionArray);
+ 	}
+
+ 	/** 
+ 	 * 判断:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可] 
+ 	 * @param permissionArray 权限码数组
+ 	 * @return true 或 false 
+ 	 */
+ 	public static boolean hasPermissionOr(String... permissionArray){
+ 		return stpLogic.hasPermissionOr(permissionArray);
+ 	}
+ 	
+ 	/** 
+ 	 * 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException 
+ 	 * @param permission 权限码
+ 	 */
+	public static void checkPermission(String permission) {
+		stpLogic.checkPermission(permission);
+	}
+
+ 	/** 
+ 	 * 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过] 
+ 	 * @param permissionArray 权限码数组
+ 	 */
+	public static void checkPermissionAnd(String... permissionArray) {
+		stpLogic.checkPermissionAnd(permissionArray);
+	}
+
+ 	/** 
+ 	 * 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可] 
+ 	 * @param permissionArray 权限码数组
+ 	 */
+	public static void checkPermissionOr(String... permissionArray) {
+		stpLogic.checkPermissionOr(permissionArray);
+	}
+
+
+	// =================== id 反查token 相关操作 ===================  
+	
+	/** 
+	 * 获取指定账号id的tokenValue 
+	 * <p> 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
+	 * 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId 
+	 * @param loginId 账号id
+	 * @return token值 
+	 */
+	public static String getTokenValueByLoginId(Object loginId) {
+		return stpLogic.getTokenValueByLoginId(loginId);
+	}
+
+	/** 
+	 * 获取指定账号id指定设备端的tokenValue 
+	 * <p> 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
+	 * 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId 
+	 * @param loginId 账号id
+	 * @param device 设备标识 
+	 * @return token值 
+	 */
+	public static String getTokenValueByLoginId(Object loginId, String device) {
+		return stpLogic.getTokenValueByLoginId(loginId, device);
+	}
+	
+	/** 
+	 * 获取指定账号id的tokenValue集合 
+	 * @param loginId 账号id 
+	 * @return 此loginId的所有相关token 
+ 	 */
+	public static List<String> getTokenValueListByLoginId(Object loginId) {
+		return stpLogic.getTokenValueListByLoginId(loginId);
+	}
+
+	/** 
+	 * 获取指定账号id指定设备端的tokenValue 集合 
+	 * @param loginId 账号id 
+	 * @param device 设备标识 
+	 * @return 此loginId的所有相关token 
+ 	 */
+	public static List<String> getTokenValueListByLoginId(Object loginId, String device) {
+		return stpLogic.getTokenValueListByLoginId(loginId, device);
+	}
+	
+	/**
+	 * 返回当前会话的登录设备 
+	 * @return 当前令牌的登录设备 
+	 */
+	public static String getLoginDevice() {
+		return stpLogic.getLoginDevice(); 
+	}
+
+	
+	// =================== 会话管理 ===================  
+
+	/**
+	 * 根据条件查询Token 
+	 * @param keyword 关键字 
+	 * @param start 开始处索引 (-1代表查询所有) 
+	 * @param size 获取数量 
+	 * @return token集合 
+	 */
+	public static List<String> searchTokenValue(String keyword, int start, int size) {
+		return stpLogic.searchTokenValue(keyword, start, size);
+	}
+	
+	/**
+	 * 根据条件查询SessionId 
+	 * @param keyword 关键字 
+	 * @param start 开始处索引 (-1代表查询所有) 
+	 * @param size 获取数量 
+	 * @return sessionId集合 
+	 */
+	public static List<String> searchSessionId(String keyword, int start, int size) {
+		return stpLogic.searchSessionId(keyword, start, size);
+	}
+
+	/**
+	 * 根据条件查询Token专属Session的Id 
+	 * @param keyword 关键字 
+	 * @param start 开始处索引 (-1代表查询所有) 
+	 * @param size 获取数量 
+	 * @return sessionId集合 
+	 */
+	public static List<String> searchTokenSessionId(String keyword, int start, int size) {
+		return stpLogic.searchTokenSessionId(keyword, start, size);
+	}
+
+	
+	// ------------------- 账号封禁 -------------------  
+
+	/**
+	 * 封禁指定账号
+	 * <p> 此方法不会直接将此账号id踢下线,而是在对方再次登录时抛出`DisableLoginException`异常 
+	 * @param loginId 指定账号id 
+	 * @param disableTime 封禁时间, 单位: 秒 (-1=永久封禁)
+	 */
+	public static void disable(Object loginId, long disableTime) {
+		stpLogic.disable(loginId, disableTime);
+	}
+	
+	/**
+	 * 指定账号是否已被封禁 (true=已被封禁, false=未被封禁) 
+	 * @param loginId 账号id
+	 * @return see note
+	 */
+	public static boolean isDisable(Object loginId) {
+		return stpLogic.isDisable(loginId);
+	}
+	
+	/**
+	 * 获取指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
+	 * @param loginId 账号id
+	 * @return see note 
+	 */
+	public static long getDisableTime(Object loginId) {
+		return stpLogic.getDisableTime(loginId);
+	}
+
+	/**
+	 * 解封指定账号
+	 * @param loginId 账号id 
+	 */
+	public static void untieDisable(Object loginId) {
+		stpLogic.untieDisable(loginId);
+	}
+	
+	
+	// =================== 身份切换 ===================  
+
+	/**
+	 * 临时切换身份为指定账号id 
+	 * @param loginId 指定loginId 
+	 */
+	public static void switchTo(Object loginId) {
+		stpLogic.switchTo(loginId);
+	}
+	
+	/**
+	 * 结束临时切换身份
+	 */
+	public static void endSwitch() {
+		stpLogic.endSwitch();
+	}
+
+	/**
+	 * 当前是否正处于[身份临时切换]中 
+	 * @return 是否正处于[身份临时切换]中 
+	 */
+	public static boolean isSwitch() {
+		return stpLogic.isSwitch();
+	}
+
+	/**
+	 * 在一个代码段里方法内,临时切换身份为指定账号id
+	 * @param loginId 指定账号id 
+	 * @param function 要执行的方法 
+	 */
+	public static void switchTo(Object loginId, SaFunction function) {
+		stpLogic.switchTo(loginId, function);
+	}
+	
+
+	// ------------------- 二级认证 -------------------  
+	
+	/**
+	 * 在当前会话 开启二级认证 
+	 * @param safeTime 维持时间 (单位: 秒) 
+	 */
+	public static void openSafe(long safeTime) {
+		stpLogic.openSafe(safeTime);
+	}
+
+	/**
+	 * 当前会话 是否处于二级认证时间内 
+	 * @return true=二级认证已通过, false=尚未进行二级认证或认证已超时 
+	 */
+	public static boolean isSafe() {
+		return stpLogic.isSafe();
+	}
+
+	/**
+	 * 检查当前会话是否已通过二级认证,如未通过则抛出异常 
+	 */
+	public static void checkSafe() {
+		stpLogic.checkSafe();
+	}
+	
+	/**
+	 * 获取当前会话的二级认证剩余有效时间 (单位: 秒, 返回-2代表尚未通过二级认证)
+	 * @return 剩余有效时间
+	 */
+	public static long getSafeTime() {
+		return stpLogic.getSafeTime();
+	}
+
+	/**
+	 * 在当前会话 结束二级认证 
+	 */
+	public static void closeSafe() {
+		stpLogic.closeSafe();
+	}
+
+
+	// =================== 历史API,兼容旧版本 ===================  
+
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.getLoginType() ,使用方式保持不变 </h1>
+	 * 
+	 * 获取当前StpLogin的loginKey 
+	 * @return 当前StpLogin的loginKey
+	 */
+	@Deprecated
+	public static String getLoginKey(){
+		return stpLogic.getLoginType();
+	}
+
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变 </h1>
+	 * 
+	 * 在当前会话上登录id 
+	 * @param loginId 登录id,建议的类型:(long | int | String)
+	 */
+	@Deprecated
+	public static void setLoginId(Object loginId) {
+		stpLogic.login(loginId);
+	}
+
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变 </h1>
+	 * 
+	 * 在当前会话上登录id, 并指定登录设备 
+	 * @param loginId 登录id,建议的类型:(long | int | String)
+	 * @param device 设备标识 
+	 */
+	@Deprecated
+	public static void setLoginId(Object loginId, String device) {
+		stpLogic.login(loginId, device);
+	}
+
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变 </h1>
+	 * 
+	 * 在当前会话上登录id, 并指定登录设备 
+	 * @param loginId 登录id,建议的类型:(long | int | String)
+	 * @param isLastingCookie 是否为持久Cookie 
+	 */
+	@Deprecated
+	public static void setLoginId(Object loginId, boolean isLastingCookie) {
+		stpLogic.login(loginId, isLastingCookie);
+	}
+	
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.login() ,使用方式保持不变 </h1>
+	 * 
+	 * 在当前会话上登录id, 并指定所有登录参数Model 
+	 * @param loginId 登录id,建议的类型:(long | int | String)
+	 * @param loginModel 此次登录的参数Model 
+	 */
+	@Deprecated
+	public static void setLoginId(Object loginId, SaLoginModel loginModel) {
+		stpLogic.login(loginId, loginModel);
+	}
+	
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.kickout() ,使用方式保持不变 </h1>
+	 * 
+	 * 会话注销,根据账号id (踢人下线)
+	 * <p> 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
+	 * @param loginId 账号id 
+	 */
+	@Deprecated
+	public static void logoutByLoginId(Object loginId) {
+		stpLogic.kickout(loginId);
+	}
+	
+	/**
+	 * <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 StpUtil.kickout() ,使用方式保持不变 </h1>
+	 * 
+	 * 会话注销,根据账号id and 设备标识 (踢人下线)
+	 * <p> 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2 </p>
+	 * @param loginId 账号id 
+	 * @param device 设备标识 (填null代表所有注销设备) 
+	 */
+	@Deprecated
+	public static void logoutByLoginId(Object loginId, String device) {
+		stpLogic.kickout(loginId, device);
+	}
+	
+}

+ 54 - 0
sp-core/src/main/java/com/pj/current/sentinel/SentinelConfigure.java

@@ -0,0 +1,54 @@
+package com.pj.current.sentinel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
+
+/**
+ * Sentinel 限流配置 
+ * 
+ * @author kong
+ *
+ */
+@Configuration
+public class SentinelConfigure {
+	
+	/**
+	 * 注册Sentinel切面对象 
+	 * @return 
+	 */
+	@Bean
+    public SentinelResourceAspect sentinelResourceAspect() {
+		initFlowRules();
+        return new SentinelResourceAspect();
+    }
+	
+	/**
+	 * 初始化降级规则 
+	 */
+	private static void initFlowRules() {
+		System.out.println("----------------------- 初始化限流规则 !!!");
+		
+        List<FlowRule> rules = new ArrayList<>();
+
+        // 规则  qps > 1 时,触发降级 
+        FlowRule rule = new FlowRule();
+        rule.setResource("qps-max-1");
+        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
+        rule.setCount(1);
+        rules.add(rule);
+
+        // 可创建多个规则
+        // ...
+        
+        FlowRuleManager.loadRules(rules);
+    }
+
+}

+ 70 - 0
sp-core/src/main/java/com/pj/project/sys_dict/SysDict.java

@@ -0,0 +1,70 @@
+package com.pj.project.sys_dict;
+
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: sys_dict -- 字典管理
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(SysDict.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class SysDict extends Model<SysDict> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "sys_dict";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "sys-dict";	
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * id 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Integer id;	
+
+	/**
+	 *  父ID  
+	 */
+	private Integer pid;	
+
+	/**
+	 *  数据编码  
+	 */
+	private String dataCode;	
+
+	/**
+	 *  数据名称/值  
+	 */
+	private String dataValue;	
+
+	/**
+	 * 数据描述 
+	 */
+	private String dataDesc;	
+
+
+
+
+
+	
+
+
+}

+ 104 - 0
sp-core/src/main/java/com/pj/project/sys_dict/SysDictController.java

@@ -0,0 +1,104 @@
+package com.pj.project.sys_dict;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: sys_dict -- 字典管理
+ *
+ * @author qzyReal
+ */
+@RestController
+@RequestMapping("/SysDict/")
+public class SysDictController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    SysDictService sysDictService;
+
+    /**
+     * 增
+     */
+    @RequestMapping("add")
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson add(SysDict s) {
+        sysDictService.add(s);
+        return AjaxJson.getSuccessData(s);
+    }
+
+    /**
+     * 删
+     */
+    @RequestMapping("delete")
+    public AjaxJson delete(Integer id) {
+        sysDictService.delete(id);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 删 - 根据id列表
+     */
+    @RequestMapping("deleteByIds")
+    public AjaxJson deleteByIds() {
+        List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+        int line = SP.publicMapper.deleteByIds(SysDict.TABLE_NAME, ids);
+        return AjaxJson.getByLine(line);
+    }
+
+    /**
+     * 改
+     */
+    @RequestMapping("update")
+    public AjaxJson update(SysDict s) {
+        sysDictService.update(s);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    public AjaxJson getById(Integer id) {
+        SysDict s = sysDictService.getById(id);
+        return AjaxJson.getSuccessData(s);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        List<SysDict> list = sysDictService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+    /**
+     * 查集合 (整个表数据转化为tree结构返回)
+     */
+    @RequestMapping("getTree")
+    public AjaxJson getTree() {
+        // 获取记录
+        SoMap so = SoMap.getRequestSoMap();
+        List<SysDict> list = sysDictService.getList(so);
+        // 转为tree结构,并返回
+        List<SoMap> listMap = SoMap.getSoMapByList(list);
+        List<SoMap> listTree = SoMap.listToTree(listMap, "id", "pid", "children");
+        return AjaxJson.getPageData(Long.valueOf(listMap.size()), listTree);
+    }
+
+
+}

+ 28 - 0
sp-core/src/main/java/com/pj/project/sys_dict/SysDictMapper.java

@@ -0,0 +1,28 @@
+package com.pj.project.sys_dict;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+	import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+* Mapper: sys_dict -- 字典管理
+* @author qzyReal
+*/
+
+@Mapper
+@Repository
+public interface SysDictMapper extends BaseMapper <SysDict> {
+
+/**
+* 查集合 - 根据条件(参数为空时代表忽略指定条件)
+* @param so 参数集合
+* @return 数据列表
+*/
+List<SysDict> getList(SoMap so);
+
+
+}

+ 56 - 0
sp-core/src/main/java/com/pj/project/sys_dict/SysDictMapper.xml

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.sys_dict.SysDictMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, pid, data_code, data_value, data_desc from sys_dict  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.sys_dict.SysDict">
+				<result property="id" column="id" />
+				<result property="pid" column="pid" />
+				<result property="dataCode" column="data_code" />
+				<result property="dataValue" column="data_value" />
+				<result property="dataDesc" column="data_desc" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *
+		from sys_dict
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("pid") '> and pid = #{pid} </if>
+			<if test=' this.has("dataCode") '> and data_code = #{dataCode} </if>
+			<if test=' this.has("dataValue") '> and data_value = #{dataValue} </if>
+			<if test=' this.has("dataDesc") '> and data_desc = #{dataDesc} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> pid desc </when>
+			<when test='sortType == 3'> data_code desc </when>
+			<when test='sortType == 4'> data_value desc </when>
+			<when test='sortType == 5'> data_desc desc </when>
+			<otherwise> id asc </otherwise>
+		</choose>
+	</select>
+
+
+
+
+
+
+
+
+
+
+</mapper>

+ 49 - 0
sp-core/src/main/java/com/pj/project/sys_dict/SysDictService.java

@@ -0,0 +1,49 @@
+package com.pj.project.sys_dict;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+/**
+ * Service: sys_dict -- 字典管理
+ * @author qzyReal 
+ */
+@Service
+public class SysDictService extends ServiceImpl<SysDictMapper, SysDict> implements IService<SysDict>{
+
+	/** 底层 Mapper 对象 */
+	@Autowired
+	SysDictMapper sysDictMapper;
+
+
+	/** 增 */
+	void add(SysDict s){
+	this.save( s);
+	}
+
+	/** 删 */
+	void delete(Integer id){
+	this.removeById(id);
+	}
+
+	/** 改 */
+	void update(SysDict s){
+	this.updateById(s);
+	}
+
+	/** 查 */
+	SysDict getById(Integer id){
+	return super.getById(id);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	List<SysDict> getList(SoMap so) { 
+		return sysDictMapper.getList(so);	
+	}
+	
+
+}

+ 102 - 0
sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlack.java

@@ -0,0 +1,102 @@
+package com.pj.project.tb_car_black;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_car_black -- 车辆黑名单
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbCarBlack.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbCarBlack extends Model<TbCarBlack> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_car_black";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE_LIST = "tb-car-black-list";
+	public static final String PERMISSION_CODE_ADD = "tb-car-black-add";
+	public static final String PERMISSION_CODE_DEL = "tb-car-black-del";
+	public static final String PERMISSION_CODE_EDIT = "tb-car-black-edit";
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 部门ID 
+	 */
+	private Long deptId;	
+
+	/**
+	 * 车牌号 
+	 */
+	private String carNo;	
+
+	/**
+	 * 禁行原因 
+	 */
+	private String reason;	
+
+	/**
+	 * 禁行开始 
+	 */
+	private Date startTime;
+
+	/**
+	 * 禁行结束 
+	 */
+	private Date endTime;
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 创建人 
+	 */
+	private String createBy;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 更新人 
+	 */
+	private String updateBy;
+	@TableField(exist = false)
+	private String deptName;
+
+
+
+
+
+	
+
+
+}

+ 30 - 0
sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlackMapper.java

@@ -0,0 +1,30 @@
+package com.pj.project.tb_car_black;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_car_black -- 车辆黑名单
+ *
+ * @author qzyReal
+ */
+
+@Mapper
+@Repository
+public interface TbCarBlackMapper extends BaseMapper<TbCarBlack> {
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     *
+     * @param so 参数集合
+     * @return 数据列表
+     */
+    List<TbCarBlack> getList(SoMap so);
+
+    TbCarBlack getById(Long id);
+}

+ 66 - 0
sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlackMapper.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_car_black.TbCarBlackMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, dept_id, car_no, reason, start_time, end_time, create_time, create_by, update_time, update_by from tb_car_black  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.tb_car_black.TbCarBlack">
+				<result property="id" column="id" />
+				<result property="deptId" column="dept_id" />
+				<result property="carNo" column="car_no" />
+				<result property="reason" column="reason" />
+				<result property="startTime" column="start_time" />
+				<result property="endTime" column="end_time" />
+				<result property="createTime" column="create_time" />
+				<result property="createBy" column="create_by" />
+				<result property="updateTime" column="update_time" />
+				<result property="updateBy" column="update_by" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *,(select name from tb_dept where id=tb_car_black.dept_id) as deptName
+		from tb_car_black
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultType="com.pj.project.tb_car_black.TbCarBlack">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("deptId") '> and dept_id = #{deptId} </if>
+			<if test=' this.has("carNo") '> and car_no like concat('%', #{carNo}, '%') </if>
+			<if test=' this.has("reason") '> and reason = #{reason} </if>
+			<if test=' this.has("startTime") '> and start_time = #{startTime} </if>
+			<if test=' this.has("endTime") '> and end_time = #{endTime} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and create_by = #{createBy} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and update_by = #{updateBy} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> dept_id desc </when>
+			<when test='sortType == 3'> car_no desc </when>
+			<when test='sortType == 4'> reason desc </when>
+			<when test='sortType == 5'> start_time desc </when>
+			<when test='sortType == 6'> end_time desc </when>
+			<when test='sortType == 7'> create_time desc </when>
+			<when test='sortType == 8'> create_by desc </when>
+			<when test='sortType == 9'> update_time desc </when>
+			<when test='sortType == 10'> update_by desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+	<select id="getById" resultType="com.pj.project.tb_car_black.TbCarBlack">
+		<include refid="select_sql"/> where  id=#{id}
+	</select>
+
+
+</mapper>

+ 82 - 0
sp-core/src/main/java/com/pj/project/tb_car_black/TbCarBlackService.java

@@ -0,0 +1,82 @@
+package com.pj.project.tb_car_black;
+
+import java.util.Date;
+import java.util.List;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.IdcardUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.current.global.BusinessException;
+import com.pj.current.satoken.StpUserUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+/**
+ * Service: tb_car_black -- 车辆黑名单
+ *
+ * @author qzyReal
+ */
+@Service
+public class TbCarBlackService extends ServiceImpl<TbCarBlackMapper, TbCarBlack> implements IService<TbCarBlack> {
+
+    /**
+     * 底层 Mapper 对象
+     */
+    @Autowired
+    TbCarBlackMapper tbCarBlackMapper;
+
+
+    /**
+     * 增
+     */
+    public void add(TbCarBlack t) {
+        Date now = new Date();
+        String loginId = StpUtil.getLoginIdAsString();
+        t.setCreateTime(now).setCreateBy(loginId).setUpdateBy(loginId).setUpdateTime(now);
+        this.save(t);
+    }
+
+    /**
+     * 删
+     */
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+    /**
+     * 改
+     */
+    public void update(TbCarBlack t) {
+        Date now = new Date();
+        String loginId = StpUtil.getLoginIdAsString();
+        t.setUpdateBy(loginId).setUpdateTime(now);
+        this.updateById(t);
+    }
+
+    /**
+     * 查
+     */
+    public TbCarBlack getById(Long id) {
+        return tbCarBlackMapper.getById(id);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    public List<TbCarBlack> getList(SoMap so) {
+        return tbCarBlackMapper.getList(so);
+    }
+
+
+    public List<TbCarBlack> findByCarNo(String carNo) {
+        QueryWrapper<TbCarBlack> ew = new QueryWrapper<>();
+        ew.eq("car_no", carNo.toUpperCase());
+        return list(ew);
+    }
+
+
+}

+ 132 - 0
sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFiling.java

@@ -0,0 +1,132 @@
+package com.pj.project.tb_car_filing;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import cn.hutool.core.util.IdcardUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_car_filing -- 车辆备案
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbCarFiling.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbCarFiling extends Model<TbCarFiling> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_car_filing";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE_LIST = "tb-car-filing-list";
+	public static final String PERMISSION_CODE_ADD = "tb-car-filing-add";
+	public static final String PERMISSION_CODE_DEL = "tb-car-filing-del";
+	public static final String PERMISSION_CODE_EDIT = "tb-car-filing-edit";
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 *  
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 部门ID 
+	 */
+	private Long deptId;	
+	private String deptName;
+
+	/**
+	 * 车牌号 
+	 */
+	private String carNo;	
+
+	/**
+	 * 类型(1=临时,2=内部) 
+	 */
+	private int type=1;
+
+	/**
+	 * 联系人 
+	 */
+	private String driverName;	
+
+	/**
+	 * 联系电话 
+	 */
+	private String driverContact;	
+
+	/**
+	 * 联系人身份证 
+	 */
+	private String driverIdCard;	
+
+	/**
+	 * 预计来访时间 
+	 */
+	private Date preComeTime;
+
+	/**
+	 * 预计结束时间 
+	 */
+	private Date preLeaveTime;
+
+	/**
+	 * 状态 0未到访,1已来防
+	 */
+	private int visit;
+
+	/**
+	 * 备注 
+	 */
+	private String remark;	
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 创建人 
+	 */
+	private String createBy;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 更新人 
+	 */
+	private String updateBy;	
+
+
+	@TableField(exist = false)
+	private String driverIdCardStr;
+
+	public String getDriverIdCardStr() {
+		String str = IdcardUtil.getBirthByIdCard(driverIdCard);
+		if (StrUtil.isNotEmpty(str)) {
+			return driverIdCard.replace(str, "********");
+		}
+		return driverIdCard;
+	}
+}

+ 30 - 0
sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFilingMapper.java

@@ -0,0 +1,30 @@
+package com.pj.project.tb_car_filing;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_car_filing -- 车辆备案
+ *
+ * @author qzyReal
+ */
+
+@Mapper
+@Repository
+public interface TbCarFilingMapper extends BaseMapper<TbCarFiling> {
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     *
+     * @param so 参数集合
+     * @return 数据列表
+     */
+    List<TbCarFiling> getList(SoMap so);
+
+    TbCarFiling getById(Long id);
+}

+ 88 - 0
sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFilingMapper.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_car_filing.TbCarFilingMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, dept_id, car_no, type, driver_name, driver_contact, driver_id_card, pre_come_time, pre_leave_time, visit, remark, create_time, create_by, update_time, update_by from tb_car_filing  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.tb_car_filing.TbCarFiling">
+				<result property="id" column="id" />
+				<result property="deptId" column="dept_id" />
+				<result property="carNo" column="car_no" />
+				<result property="type" column="type" />
+				<result property="driverName" column="driver_name" />
+				<result property="driverContact" column="driver_contact" />
+				<result property="driverIdCard" column="driver_id_card" />
+				<result property="preComeTime" column="pre_come_time" />
+				<result property="preLeaveTime" column="pre_leave_time" />
+				<result property="visit" column="visit" />
+				<result property="remark" column="remark" />
+				<result property="createTime" column="create_time" />
+				<result property="createBy" column="create_by" />
+				<result property="updateTime" column="update_time" />
+				<result property="updateBy" column="update_by" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *
+		from tb_car_filing
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("deptId") '> and dept_id = #{deptId} </if>
+			<if test=' this.has("carNo") '> and car_no  like concat('%',#{carNo} ,'%')</if>
+			<if test=' this.has("type") '> and type = #{type} </if>
+			<if test=' this.has("driverName") '> and driver_name like concat('%', #{driverName} ,'%')</if>
+			<if test=' this.has("driverContact") '> and driver_contact  like concat('%', #{driverContact} ,'%')</if>
+			<if test=' this.has("driverIdCard") '> and driver_id_card = #{driverIdCard} </if>
+			<if test=' this.has("preComeTime") '> and pre_come_time = #{preComeTime} </if>
+			<if test=' this.has("preLeaveTime") '> and pre_leave_time = #{preLeaveTime} </if>
+			<if test=' this.has("visit") '> and visit = #{visit} </if>
+			<if test=' this.has("remark") '> and remark = #{remark} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and create_by = #{createBy} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and update_by = #{updateBy} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> dept_id desc </when>
+			<when test='sortType == 3'> car_no desc </when>
+			<when test='sortType == 4'> type desc </when>
+			<when test='sortType == 5'> driver_name desc </when>
+			<when test='sortType == 6'> driver_contact desc </when>
+			<when test='sortType == 7'> driver_id_card desc </when>
+			<when test='sortType == 8'> pre_come_time desc </when>
+			<when test='sortType == 9'> pre_leave_time desc </when>
+			<when test='sortType == 10'> visit desc </when>
+			<when test='sortType == 11'> remark desc </when>
+			<when test='sortType == 12'> create_time desc </when>
+			<when test='sortType == 13'> create_by desc </when>
+			<when test='sortType == 14'> update_time desc </when>
+			<when test='sortType == 15'> update_by desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+
+	<select id="getById" resultType="com.pj.project.tb_car_filing.TbCarFiling">
+		<include refid="select_sql"/> where  id=#{id}
+	</select>
+
+
+
+
+
+
+
+
+</mapper>

+ 96 - 0
sp-core/src/main/java/com/pj/project/tb_car_filing/TbCarFilingService.java

@@ -0,0 +1,96 @@
+package com.pj.project.tb_car_filing;
+
+import java.util.Date;
+import java.util.List;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.IdcardUtil;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.current.global.BusinessException;
+import com.pj.project.tb_car_black.TbCarBlack;
+import com.pj.project.tb_car_black.TbCarBlackService;
+import com.pj.project.tb_dept.TbDept;
+import com.pj.project.tb_dept.TbDeptService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+import javax.annotation.Resource;
+
+/**
+ * Service: tb_car_filing -- 车辆备案
+ *
+ * @author qzyReal
+ */
+@Service
+public class TbCarFilingService extends ServiceImpl<TbCarFilingMapper, TbCarFiling> implements IService<TbCarFiling> {
+
+    /**
+     * 底层 Mapper 对象
+     */
+    @Autowired
+    TbCarFilingMapper tbCarFilingMapper;
+
+    @Resource
+    private TbDeptService tbDeptService;
+
+
+
+
+    /**
+     * 增
+     */
+    public void add(TbCarFiling t) {
+        t.setCreateBy(StpUtil.getLoginIdAsString()).setCreateTime(new Date());
+        handler(t);
+        this.save(t);
+    }
+
+    private void handler(TbCarFiling t) {
+        if (!IdcardUtil.isValidCard(t.getDriverIdCard())) {
+            throw new BusinessException("身份证不正确");
+        }
+        TbDept tbDept = tbDeptService.getById(t.getDeptId());
+        if (tbDept == null) {
+            throw new BusinessException("请选择部门");
+        }
+        String carNo = t.getCarNo().toUpperCase();
+        Date now = new Date();
+        t.setDeptName(tbDept.getName()).setUpdateTime(now).setCarNo(carNo)
+                .setUpdateBy(StpUtil.getLoginIdAsString());
+        t.setCarNo(t.getCarNo().toUpperCase());
+    }
+
+    /**
+     * 删
+     */
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+    /**
+     * 改
+     */
+    public void update(TbCarFiling t) {
+        handler(t);
+        this.updateById(t);
+    }
+
+    /**
+     * 查
+     */
+    public TbCarFiling getById(Long id) {
+        return tbCarFilingMapper.getById(id);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    public List<TbCarFiling> getList(SoMap so) {
+        return tbCarFilingMapper.getList(so);
+    }
+
+
+}

+ 100 - 0
sp-core/src/main/java/com/pj/project/tb_channel/TbChannel.java

@@ -0,0 +1,100 @@
+package com.pj.project.tb_channel;
+
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_channel -- 通道管理
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbChannel.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbChannel extends Model<TbChannel> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_channel";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-channel";	
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 *  
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 部门ID 
+	 */
+	private Long deptId;	
+
+	/**
+	 * 名称 
+	 */
+	private String name;	
+
+	/**
+	 * 场所ID 
+	 */
+	private Long venuesId;	
+
+	/**
+	 * 场所名称 
+	 */
+	private String venuesName;	
+
+	/**
+	 * 设备数 
+	 */
+	private Integer terminalNum;	
+
+	/**
+	 * 备注 
+	 */
+	private String remark;	
+
+	/**
+	 * 创建时间 
+	 */
+	private String createTime;	
+
+	/**
+	 * 创建人 
+	 */
+	private String createBy;	
+
+	/**
+	 * 更新时间 
+	 */
+	private String updateTime;	
+
+	/**
+	 * 更新人 
+	 */
+	private String updateBy;	
+
+
+
+
+
+	
+
+
+}

+ 28 - 0
sp-core/src/main/java/com/pj/project/tb_channel/TbChannelMapper.java

@@ -0,0 +1,28 @@
+package com.pj.project.tb_channel;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+	import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+* Mapper: tb_channel -- 通道管理
+* @author qzyReal
+*/
+
+@Mapper
+@Repository
+public interface TbChannelMapper extends BaseMapper <TbChannel> {
+
+/**
+* 查集合 - 根据条件(参数为空时代表忽略指定条件)
+* @param so 参数集合
+* @return 数据列表
+*/
+List<TbChannel> getList(SoMap so);
+
+
+}

+ 74 - 0
sp-core/src/main/java/com/pj/project/tb_channel/TbChannelMapper.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_channel.TbChannelMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, dept_id, name, venues_id, venues_name, terminal_num, remark, create_time, create_by, update_time, update_by from tb_channel  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.tb_channel.TbChannel">
+				<result property="id" column="id" />
+				<result property="deptId" column="dept_id" />
+				<result property="name" column="name" />
+				<result property="venuesId" column="venues_id" />
+				<result property="venuesName" column="venues_name" />
+				<result property="terminalNum" column="terminal_num" />
+				<result property="remark" column="remark" />
+				<result property="createTime" column="create_time" />
+				<result property="createBy" column="create_by" />
+				<result property="updateTime" column="update_time" />
+				<result property="updateBy" column="update_by" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *
+		from tb_channel
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("deptId") '> and dept_id = #{deptId} </if>
+			<if test=' this.has("name") '> and name = #{name} </if>
+			<if test=' this.has("venuesId") '> and venues_id = #{venuesId} </if>
+			<if test=' this.has("venuesName") '> and venues_name = #{venuesName} </if>
+			<if test=' this.has("terminalNum") '> and terminal_num = #{terminalNum} </if>
+			<if test=' this.has("remark") '> and remark = #{remark} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and create_by = #{createBy} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and update_by = #{updateBy} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> dept_id desc </when>
+			<when test='sortType == 3'> name desc </when>
+			<when test='sortType == 4'> venues_id desc </when>
+			<when test='sortType == 5'> venues_name desc </when>
+			<when test='sortType == 6'> terminal_num desc </when>
+			<when test='sortType == 7'> remark desc </when>
+			<when test='sortType == 8'> create_time desc </when>
+			<when test='sortType == 9'> create_by desc </when>
+			<when test='sortType == 10'> update_time desc </when>
+			<when test='sortType == 11'> update_by desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+
+
+
+
+
+
+
+
+
+
+</mapper>

+ 49 - 0
sp-core/src/main/java/com/pj/project/tb_channel/TbChannelService.java

@@ -0,0 +1,49 @@
+package com.pj.project.tb_channel;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+/**
+ * Service: tb_channel -- 通道管理
+ * @author qzyReal 
+ */
+@Service
+public class TbChannelService extends ServiceImpl<TbChannelMapper, TbChannel> implements IService<TbChannel>{
+
+	/** 底层 Mapper 对象 */
+	@Autowired
+	TbChannelMapper tbChannelMapper;
+
+
+	/** 增 */
+    public void add(TbChannel t){
+	this.save( t);
+	}
+
+	/** 删 */
+	public void delete(Long id){
+	this.removeById(id);
+	}
+
+	/** 改 */
+	public void update(TbChannel t){
+	this.updateById(t);
+	}
+
+	/** 查 */
+	TbChannel getById(Long id){
+	return super.getById(id);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */
+	public List<TbChannel> getList(SoMap so) {
+		return tbChannelMapper.getList(so);	
+	}
+	
+
+}

+ 65 - 0
sp-core/src/main/java/com/pj/project/tb_channel/TbChannelUtil.java

@@ -0,0 +1,65 @@
+package com.pj.project.tb_channel;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.pj.utils.sg.*;
+
+/**
+ * 工具类:tb_channel -- 通道管理
+ * @author qzyReal 
+ *
+ */
+@Component
+public class TbChannelUtil {
+
+	
+	/** 底层 Mapper 对象 */
+	public static TbChannelMapper tbChannelMapper;
+	@Autowired
+	private void setTbChannelMapper(TbChannelMapper tbChannelMapper) {
+		TbChannelUtil.tbChannelMapper = tbChannelMapper;
+	}
+	
+	
+	/** 
+	 * 将一个 TbChannel 对象进行进行数据完整性校验 (方便add/update等接口数据校验) [G] 
+	 */
+	static void check(TbChannel t) {
+		AjaxError.throwByIsNull(t.getId(), "[] 不能为空");		// 验证:  
+		AjaxError.throwByIsNull(t.getDeptId(), "[部门ID] 不能为空");		// 验证: 部门ID 
+		AjaxError.throwByIsNull(t.getName(), "[名称] 不能为空");		// 验证: 名称 
+		AjaxError.throwByIsNull(t.getVenuesId(), "[场所ID] 不能为空");		// 验证: 场所ID 
+		AjaxError.throwByIsNull(t.getVenuesName(), "[场所名称] 不能为空");		// 验证: 场所名称 
+		AjaxError.throwByIsNull(t.getTerminalNum(), "[设备数] 不能为空");		// 验证: 设备数 
+		AjaxError.throwByIsNull(t.getRemark(), "[备注] 不能为空");		// 验证: 备注 
+		AjaxError.throwByIsNull(t.getCreateTime(), "[创建时间] 不能为空");		// 验证: 创建时间 
+		AjaxError.throwByIsNull(t.getCreateBy(), "[创建人] 不能为空");		// 验证: 创建人 
+		AjaxError.throwByIsNull(t.getUpdateTime(), "[更新时间] 不能为空");		// 验证: 更新时间 
+		AjaxError.throwByIsNull(t.getUpdateBy(), "[更新人] 不能为空");		// 验证: 更新人 
+	}
+
+	/** 
+	 * 获取一个TbChannel (方便复制代码用) [G] 
+	 */ 
+	static TbChannel getTbChannel() {
+		TbChannel t = new TbChannel();	// 声明对象 
+		t.setId(0L);		//  
+		t.setDeptId(0L);		// 部门ID 
+		t.setName("");		// 名称 
+		t.setVenuesId(0L);		// 场所ID 
+		t.setVenuesName("");		// 场所名称 
+		t.setTerminalNum(0);		// 设备数 
+		t.setRemark("");		// 备注 
+		t.setCreateTime("");		// 创建时间 
+		t.setCreateBy("");		// 创建人 
+		t.setUpdateTime("");		// 更新时间 
+		t.setUpdateBy("");		// 更新人 
+		return t;
+	}
+	
+	
+	
+	
+	
+}

+ 105 - 0
sp-core/src/main/java/com/pj/project/tb_dept/TbDept.java

@@ -0,0 +1,105 @@
+package com.pj.project.tb_dept;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_dept -- 组织管理
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbDept.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbDept extends Model<TbDept> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_dept";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-dept";	
+	public static final String PERMISSION_CODE_ADD = "tb-dept-add";
+	public static final String PERMISSION_CODE_DEL = "tb-dept-del";
+	public static final String PERMISSION_CODE_EDIT = "tb-dept-edit";
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 名称 
+	 */
+	private String name;	
+
+	/**
+	 * 人数 
+	 */
+	private int peopleNum;
+
+	/**
+	 * 描述 
+	 */
+	private String deptDesc;
+
+	/**
+	 * 负责人 
+	 */
+	private String chargePerson;	
+
+	/**
+	 * 联系号码 
+	 */
+	private String contact;	
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 创建人 
+	 */
+	private String createBy;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 更新人 
+	 */
+	private String updateBy;	
+
+	/**
+	 * 备注 
+	 */
+	private String remark;	
+
+
+
+
+
+	
+
+
+}

+ 98 - 0
sp-core/src/main/java/com/pj/project/tb_dept/TbDeptController.java

@@ -0,0 +1,98 @@
+package com.pj.project.tb_dept;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.utils.so.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_dept -- 组织管理
+ *
+ * @author qzyReal
+ */
+@RestController
+@RequestMapping("/TbDept/")
+public class TbDeptController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbDeptService tbDeptService;
+
+    /**
+     * 增
+     */
+    @RequestMapping("add")
+    @SaCheckPermission(TbDept.PERMISSION_CODE_ADD)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxJson add(TbDept t) {
+        tbDeptService.add(t);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 删
+     */
+    @RequestMapping("delete")
+    @SaCheckPermission(TbDept.PERMISSION_CODE_DEL)
+    public AjaxJson delete(Long id) {
+        tbDeptService.delete(id);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 删 - 根据id列表
+     */
+    @RequestMapping("deleteByIds")
+    @SaCheckPermission(TbDept.PERMISSION_CODE_DEL)
+    public AjaxJson deleteByIds() {
+        List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class);
+        int line = SP.publicMapper.deleteByIds(TbDept.TABLE_NAME, ids);
+        return AjaxJson.getByLine(line);
+    }
+
+    /**
+     * 改
+     */
+    @RequestMapping("update")
+    @SaCheckPermission(TbDept.PERMISSION_CODE_EDIT)
+    public AjaxJson update(TbDept t) {
+        tbDeptService.update(t);
+        return AjaxJson.getSuccess();
+    }
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    public AjaxJson getById(Long id) {
+        TbDept t = tbDeptService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        long deptId = StpUserUtil.getDeptId();
+        if (StpUserUtil.ADMIN_DEPT_ID != deptId) {
+            so.put("id", deptId);
+        }
+        List<TbDept> list = tbDeptService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+
+}

+ 28 - 0
sp-core/src/main/java/com/pj/project/tb_dept/TbDeptMapper.java

@@ -0,0 +1,28 @@
+package com.pj.project.tb_dept;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+	import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+* Mapper: tb_dept -- 组织管理
+* @author qzyReal
+*/
+
+@Mapper
+@Repository
+public interface TbDeptMapper extends BaseMapper <TbDept> {
+
+/**
+* 查集合 - 根据条件(参数为空时代表忽略指定条件)
+* @param so 参数集合
+* @return 数据列表
+*/
+List<TbDept> getList(SoMap so);
+
+
+}

+ 73 - 0
sp-core/src/main/java/com/pj/project/tb_dept/TbDeptMapper.xml

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_dept.TbDeptMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, name, people_num, desc, charge_person, contact, create_time, create_by, update_time, update_by, remark from tb_dept  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.tb_dept.TbDept">
+				<result property="id" column="id" />
+				<result property="name" column="name" />
+				<result property="peopleNum" column="people_num" />
+				<result property="desc" column="desc" />
+				<result property="chargePerson" column="charge_person" />
+				<result property="contact" column="contact" />
+				<result property="createTime" column="create_time" />
+				<result property="createBy" column="create_by" />
+				<result property="updateTime" column="update_time" />
+				<result property="updateBy" column="update_by" />
+				<result property="remark" column="remark" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *
+		from tb_dept
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("name") '> and name like concat('%', #{name}, '%') </if>
+			<if test=' this.has("peopleNum") '> and people_num = #{peopleNum} </if>
+			<if test=' this.has("desc") '> and desc = #{desc} </if>
+			<if test=' this.has("chargePerson") '> and charge_person = #{chargePerson} </if>
+			<if test=' this.has("contact") '> and contact like concat('%', #{contact}, '%') </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and create_by = #{createBy} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and update_by = #{updateBy} </if>
+			<if test=' this.has("remark") '> and remark = #{remark} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> name desc </when>
+			<when test='sortType == 3'> people_num desc </when>
+			<when test='sortType == 4'> desc desc </when>
+			<when test='sortType == 5'> charge_person desc </when>
+			<when test='sortType == 6'> contact desc </when>
+			<when test='sortType == 7'> create_time desc </when>
+			<when test='sortType == 8'> create_by desc </when>
+			<when test='sortType == 9'> update_time desc </when>
+			<when test='sortType == 10'> update_by desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+
+
+
+
+
+
+
+
+
+
+</mapper>

+ 86 - 0
sp-core/src/main/java/com/pj/project/tb_dept/TbDeptService.java

@@ -0,0 +1,86 @@
+package com.pj.project.tb_dept;
+
+import java.util.Date;
+import java.util.List;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.current.global.BusinessException;
+import com.pj.project.tb_terminal.TbTerminal;
+import com.pj.project.tb_terminal.TbTerminalService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+import javax.annotation.Resource;
+
+/**
+ * Service: tb_dept -- 组织管理
+ *
+ * @author qzyReal
+ */
+@Service
+public class TbDeptService extends ServiceImpl<TbDeptMapper, TbDept> implements IService<TbDept> {
+
+    /**
+     * 底层 Mapper 对象
+     */
+    @Autowired
+    TbDeptMapper tbDeptMapper;
+    @Resource
+    private TbTerminalService tbTerminalService;
+
+
+    /**
+     * 增
+     */
+    void add(TbDept t) {
+        Date now = new Date();
+        t.setCreateTime(now).setUpdateTime(now)
+                .setCreateBy(StpUtil.getLoginIdAsString())
+                .setUpdateBy(StpUtil.getLoginIdAsString());
+        this.save(t);
+    }
+
+    /**
+     * 删
+     */
+    void delete(Long id) {
+        TbDept db=super.getById(id);
+        if (db.getPeopleNum()>0){
+            throw new BusinessException("部门有用户数据,不能删除");
+        }
+        SoMap soMap = new SoMap();
+        soMap.put("deptId", id);
+        List<TbTerminal> tbTerminals = tbTerminalService.getList(soMap);
+        if (!tbTerminals.isEmpty()) {
+            throw new BusinessException("部门存在设备,不能删除");
+        }
+        this.removeById(id);
+    }
+
+    /**
+     * 改
+     */
+    void update(TbDept t) {
+        this.updateById(t);
+    }
+
+    /**
+     * 查
+     */
+    TbDept getById(Long id) {
+        return super.getById(id);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    List<TbDept> getList(SoMap so) {
+        return tbDeptMapper.getList(so);
+    }
+
+
+}

+ 119 - 0
sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlack.java

@@ -0,0 +1,119 @@
+package com.pj.project.tb_person_black;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import cn.hutool.core.util.IdcardUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_person_black -- 人员黑名单
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbPersonBlack.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbPersonBlack extends Model<TbPersonBlack> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_person_black";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE_LIST = "tb-person-black-list";
+	public static final String PERMISSION_CODE_ADD = "tb-person-black-add";
+	public static final String PERMISSION_CODE_DEL = "tb-person-black-del";
+	public static final String PERMISSION_CODE_EDIT = "tb-person-black-edit";
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 部门ID 
+	 */
+	private Long deptId;	
+
+	/**
+	 * 名字 
+	 */
+	private String name;	
+
+	/**
+	 * 身份证 
+	 */
+	private String idCard;	
+
+	/**
+	 * 禁行原因 
+	 */
+	private String reason;	
+
+	/**
+	 * 禁行开始 
+	 */
+	private Date startTime;
+
+	/**
+	 * 禁行结束 
+	 */
+	private Date endTime;
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 创建人 
+	 */
+	private String createBy;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 更新人 
+	 */
+	private String updateBy;
+	@TableField(exist = false)
+	private String deptName;
+
+	@TableField(exist = false)
+	private String idCadStr;
+
+	public String getIdCadStr() {
+		String str = IdcardUtil.getBirthByIdCard(idCard);
+		if (StrUtil.isNotEmpty(str)) {
+			return idCard.replace(str, "********");
+		}
+		return idCard;
+	}
+
+
+
+
+	
+
+
+}

+ 29 - 0
sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlackMapper.java

@@ -0,0 +1,29 @@
+package com.pj.project.tb_person_black;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+	import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+* Mapper: tb_person_black -- 人员黑名单
+* @author qzyReal
+*/
+
+@Mapper
+@Repository
+public interface TbPersonBlackMapper extends BaseMapper <TbPersonBlack> {
+
+/**
+* 查集合 - 根据条件(参数为空时代表忽略指定条件)
+* @param so 参数集合
+* @return 数据列表
+*/
+List<TbPersonBlack> getList(SoMap so);
+
+
+    TbPersonBlack getById(Long id);
+}

+ 69 - 0
sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlackMapper.xml

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_person_black.TbPersonBlackMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, dept_id, name, id_card, reason, start_time, end_time, create_time, create_by, update_time, update_by from tb_person_black  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.tb_person_black.TbPersonBlack">
+				<result property="id" column="id" />
+				<result property="deptId" column="dept_id" />
+				<result property="name" column="name" />
+				<result property="idCard" column="id_card" />
+				<result property="reason" column="reason" />
+				<result property="startTime" column="start_time" />
+				<result property="endTime" column="end_time" />
+				<result property="createTime" column="create_time" />
+				<result property="createBy" column="create_by" />
+				<result property="updateTime" column="update_time" />
+				<result property="updateBy" column="update_by" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *,(select name from tb_dept where id=tb_person_black.dept_id) as deptName
+		from tb_person_black
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultType="com.pj.project.tb_person_black.TbPersonBlack">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("deptId") '> and dept_id = #{deptId} </if>
+			<if test=' this.has("name") '> and name like concat('%', #{name}, '%') </if>
+			<if test=' this.has("idCard") '> and id_card = #{idCard} </if>
+			<if test=' this.has("reason") '> and reason = #{reason} </if>
+			<if test=' this.has("startTime") '> and start_time = #{startTime} </if>
+			<if test=' this.has("endTime") '> and end_time = #{endTime} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and create_by = #{createBy} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and update_by = #{updateBy} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> dept_id desc </when>
+			<when test='sortType == 3'> name desc </when>
+			<when test='sortType == 4'> id_card desc </when>
+			<when test='sortType == 5'> reason desc </when>
+			<when test='sortType == 6'> start_time desc </when>
+			<when test='sortType == 7'> end_time desc </when>
+			<when test='sortType == 8'> create_time desc </when>
+			<when test='sortType == 9'> create_by desc </when>
+			<when test='sortType == 10'> update_time desc </when>
+			<when test='sortType == 11'> update_by desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+	<select id="getById" resultType="com.pj.project.tb_person_black.TbPersonBlack">
+		<include refid="select_sql"/> where  id=#{id}
+	</select>
+
+
+</mapper>

+ 79 - 0
sp-core/src/main/java/com/pj/project/tb_person_black/TbPersonBlackService.java

@@ -0,0 +1,79 @@
+package com.pj.project.tb_person_black;
+
+import java.util.Date;
+import java.util.List;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.IdcardUtil;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.pj.current.global.BusinessException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+/**
+ * Service: tb_person_black -- 人员黑名单
+ *
+ * @author qzyReal
+ */
+@Service
+public class TbPersonBlackService extends ServiceImpl<TbPersonBlackMapper, TbPersonBlack> implements IService<TbPersonBlack> {
+
+    /**
+     * 底层 Mapper 对象
+     */
+    @Autowired
+    TbPersonBlackMapper tbPersonBlackMapper;
+
+
+    /**
+     * 增
+     */
+    public void add(TbPersonBlack t) {
+        if (!IdcardUtil.isValidCard(t.getIdCard())) {
+            throw new BusinessException("身份证不正确");
+        }
+        Date now = new Date();
+        String loginId = StpUtil.getLoginIdAsString();
+        t.setCreateTime(now).setCreateBy(loginId).setUpdateBy(loginId).setUpdateTime(now);
+        this.save(t);
+    }
+
+    /**
+     * 删
+     */
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+    /**
+     * 改
+     */
+    public void update(TbPersonBlack t) {
+        if (!IdcardUtil.isValidCard(t.getIdCard())) {
+            throw new BusinessException("身份证不正确");
+        }
+        Date now = new Date();
+        String loginId = StpUtil.getLoginIdAsString();
+        t.setUpdateBy(loginId).setUpdateTime(now);
+        this.updateById(t);
+    }
+
+    /**
+     * 查
+     */
+    public TbPersonBlack getById(Long id) {
+        return tbPersonBlackMapper.getById(id);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    public List<TbPersonBlack> getList(SoMap so) {
+        return tbPersonBlackMapper.getList(so);
+    }
+
+
+}

+ 129 - 0
sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFiling.java

@@ -0,0 +1,129 @@
+package com.pj.project.tb_person_filing;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import cn.hutool.core.util.IdcardUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_person_filing -- 人员备案
+ *
+ * @author qzyReal
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbPersonFiling.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbPersonFiling extends Model<TbPersonFiling> implements Serializable {
+
+    // ---------- 模块常量 ----------
+    /**
+     * 序列化版本id
+     */
+    private static final long serialVersionUID = 1L;
+    /**
+     * 此模块对应的表名
+     */
+    public static final String TABLE_NAME = "tb_person_filing";
+    /**
+     * 此模块对应的权限码
+     */
+    public static final String PERMISSION_CODE_LIST = "tb-person-filing-list";
+    public static final String PERMISSION_CODE_ADD = "tb-person-filing-add";
+    public static final String PERMISSION_CODE_EDIT = "tb-person-filing-edit";
+    public static final String PERMISSION_CODE_DEL = "tb-person-filing-del";
+
+
+    // ---------- 表中字段 ----------
+    /**
+     *
+     */
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 部门ID
+     */
+    private Long deptId;
+
+    /**
+     * 姓名
+     */
+    private String name;
+    private String phone;
+
+    /**
+     * 类型(1=临时,2=内部)
+     */
+    private Integer type = 1;
+
+    /**
+     * 身份证
+     */
+    private String idCard;
+
+    /**
+     * 来访事由
+     */
+    private String visitReason;
+
+    /**
+     * 预计来访时间
+     */
+    private Date preComeTime;
+
+    /**
+     * 预计结束时间
+     */
+    private Date preLeaveTime;
+
+    /**
+     * 状态
+     */
+    private String visit;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 创建人
+     */
+    private String createBy;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 更新人
+     */
+    private String updateBy;
+
+    @TableField(exist = false)
+    private String deptName;
+    @TableField(exist = false)
+    private String idCadStr;
+
+    public String getIdCadStr() {
+        String str = IdcardUtil.getBirthByIdCard(idCard);
+        if (StrUtil.isNotEmpty(str)) {
+            return idCard.replace(str, "********");
+        }
+        return idCard;
+    }
+}

+ 31 - 0
sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFilingMapper.java

@@ -0,0 +1,31 @@
+package com.pj.project.tb_person_filing;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_person_filing -- 人员备案
+ *
+ * @author qzyReal
+ */
+
+@Mapper
+@Repository
+public interface TbPersonFilingMapper extends BaseMapper<TbPersonFiling> {
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     *
+     * @param so 参数集合
+     * @return 数据列表
+     */
+    List<TbPersonFiling> getList(SoMap so);
+
+    TbPersonFiling getById(Integer id);
+
+}

+ 78 - 0
sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFilingMapper.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.project.tb_person_filing.TbPersonFilingMapper">
+
+
+	<!-- ================================== 查询相关 ================================== -->
+			<!-- select id, dept_id, name, type, id_card, visit_reason, pre_come_time, pre_leave_time, visit, remark, create_time, create_by, update_time, update_by from tb_person_filing  -->
+
+		<!-- 通用映射:手动模式 -->
+		<resultMap id="model" type="com.pj.project.tb_person_filing.TbPersonFiling">
+				<result property="id" column="id" />
+				<result property="deptId" column="dept_id" />
+				<result property="name" column="name" />
+				<result property="type" column="type" />
+				<result property="idCard" column="id_card" />
+				<result property="visitReason" column="visit_reason" />
+				<result property="preComeTime" column="pre_come_time" />
+				<result property="preLeaveTime" column="pre_leave_time" />
+				<result property="visit" column="visit" />
+				<result property="remark" column="remark" />
+				<result property="createTime" column="create_time" />
+				<result property="createBy" column="create_by" />
+				<result property="updateTime" column="update_time" />
+				<result property="updateBy" column="update_by" />
+		</resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select *,(select name  from tb_dept where tb_person_filing.dept_id=id) as deptName
+		from tb_person_filing
+	</sql>
+
+
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultType="com.pj.project.tb_person_filing.TbPersonFiling">
+		<include refid="select_sql"></include>
+		<where>
+						<if test=' this.has("id") '> and id = #{id} </if>
+			<if test=' this.has("deptId") '> and dept_id = #{deptId} </if>
+			<if test=' this.has("name") '> and name = #{name} </if>
+			<if test=' this.has("type") '> and type = #{type} </if>
+			<if test=' this.has("idCard") '> and id_card = #{idCard} </if>
+			<if test=' this.has("visitReason") '> and visit_reason = #{visitReason} </if>
+			<if test=' this.has("preComeTime") '> and pre_come_time = #{preComeTime} </if>
+			<if test=' this.has("preLeaveTime") '> and pre_leave_time = #{preLeaveTime} </if>
+			<if test=' this.has("visit") '> and visit = #{visit} </if>
+			<if test=' this.has("remark") '> and remark = #{remark} </if>
+			<if test=' this.has("createTime") '> and create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and create_by = #{createBy} </if>
+			<if test=' this.has("updateTime") '> and update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and update_by = #{updateBy} </if>
+		</where>
+		order by
+		<choose>
+						<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> dept_id desc </when>
+			<when test='sortType == 3'> name desc </when>
+			<when test='sortType == 4'> type desc </when>
+			<when test='sortType == 5'> id_card desc </when>
+			<when test='sortType == 6'> visit_reason desc </when>
+			<when test='sortType == 7'> pre_come_time desc </when>
+			<when test='sortType == 8'> pre_leave_time desc </when>
+			<when test='sortType == 9'> visit desc </when>
+			<when test='sortType == 10'> remark desc </when>
+			<when test='sortType == 11'> create_time desc </when>
+			<when test='sortType == 12'> create_by desc </when>
+			<when test='sortType == 13'> update_time desc </when>
+			<when test='sortType == 14'> update_by desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+	<select id="getById" resultType="com.pj.project.tb_person_filing.TbPersonFiling">
+		<include refid="select_sql"></include> where  id=#{id}
+	</select>
+
+
+</mapper>

+ 74 - 0
sp-core/src/main/java/com/pj/project/tb_person_filing/TbPersonFilingService.java

@@ -0,0 +1,74 @@
+package com.pj.project.tb_person_filing;
+
+import java.util.Date;
+import java.util.List;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.utils.so.*;
+
+/**
+ * Service: tb_person_filing -- 人员备案
+ *
+ * @author qzyReal
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class TbPersonFilingService extends ServiceImpl<TbPersonFilingMapper, TbPersonFiling> implements IService<TbPersonFiling> {
+
+    /**
+     * 底层 Mapper 对象
+     */
+    @Autowired
+    TbPersonFilingMapper tbPersonFilingMapper;
+
+
+    /**
+     * 增
+     */
+    public void add(TbPersonFiling t) {
+        this.handlerTime(t);
+        t.setCreateBy(StpUtil.getLoginIdAsString()).setCreateTime(new Date());
+        this.save(t);
+    }
+
+    private void handlerTime(TbPersonFiling t) {
+        t.setUpdateTime(new Date()).setUpdateBy(StpUtil.getLoginIdAsString());
+
+    }
+
+    /**
+     * 删
+     */
+    public void delete(Integer id) {
+        this.removeById(id);
+    }
+
+    /**
+     * 改
+     */
+    public void update(TbPersonFiling t) {
+        handlerTime(t);
+        this.updateById(t);
+    }
+
+    /**
+     * 查
+     */
+    public TbPersonFiling getById(Integer id) {
+        return tbPersonFilingMapper.getById(id);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    public List<TbPersonFiling> getList(SoMap so) {
+        return tbPersonFilingMapper.getList(so);
+    }
+
+
+}

+ 125 - 0
sp-core/src/main/java/com/pj/project/tb_terminal/TbTerminal.java

@@ -0,0 +1,125 @@
+package com.pj.project.tb_terminal;
+
+import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_terminal -- 设备管理
+ * @author qzyReal 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbTerminal.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbTerminal extends Model<TbTerminal> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_terminal";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-terminal";	
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 *  
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 部门ID 
+	 */
+	private Long deptId;	
+
+	/**
+	 * 名称 
+	 */
+	private String name;	
+
+	/**
+	 * IP地址 
+	 */
+	private String ipAddress;	
+
+	/**
+	 * 状态(0=离线,1=正常 no-add no-s) 
+	 */
+	private String state;	
+
+	/**
+	 * 序列号 
+	 */
+	private String sn;	
+
+	/**
+	 * 场所ID 
+	 */
+	private Long venuesId;	
+
+	/**
+	 * 场所名称 
+	 */
+	private String venuesName;	
+
+	/**
+	 * 通道ID 
+	 */
+	private Long channelId;	
+
+	/**
+	 * 通道名称 
+	 */
+	private String channelName;	
+
+	/**
+	 * 最近一次上线 
+	 */
+	private String lastOnLine;	
+
+	/**
+	 * 备注 
+	 */
+	private String remark;	
+
+	/**
+	 * 创建时间 
+	 */
+	private String createTime;	
+
+	/**
+	 * 创建人 
+	 */
+	private String createBy;	
+
+	/**
+	 * 更新时间 
+	 */
+	private String updateTime;	
+
+	/**
+	 * 更新人 
+	 */
+	private String updateBy;	
+
+
+
+
+
+	
+
+
+}

Some files were not shown because too many files changed in this diff