wuweihao 3 tahun lalu
induk
melakukan
902a60f4e2
100 mengubah file dengan 7018 tambahan dan 0 penghapusan
  1. 32 0
      gis_admin/pom.xml
  2. 26 0
      gis_admin/src/main/java/com/gis/admin/controller/ApiController.java
  3. 129 0
      gis_admin/src/main/java/com/gis/admin/controller/ExceptionController.java
  4. 42 0
      gis_admin/src/main/java/com/gis/admin/controller/LogController.java
  5. 299 0
      gis_admin/src/main/java/com/gis/admin/controller/LoginController.java
  6. 59 0
      gis_admin/src/main/java/com/gis/admin/controller/SysResourceController.java
  7. 88 0
      gis_admin/src/main/java/com/gis/admin/controller/SysRoleController.java
  8. 105 0
      gis_admin/src/main/java/com/gis/admin/controller/SysUserController.java
  9. 28 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/LoginDto.java
  10. 28 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/PasswordDto.java
  11. 56 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/RegisterDto.java
  12. 21 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/ResetPasswordDto.java
  13. 31 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/RoleDto.java
  14. 78 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/UserDto.java
  15. 65 0
      gis_admin/src/main/java/com/gis/admin/entity/dto/UserWebDto.java
  16. 63 0
      gis_admin/src/main/java/com/gis/admin/entity/po/SysResourceEntity.java
  17. 50 0
      gis_admin/src/main/java/com/gis/admin/entity/po/SysRoleEntity.java
  18. 74 0
      gis_admin/src/main/java/com/gis/admin/entity/po/SysUserEntity.java
  19. 12 0
      gis_admin/src/main/java/com/gis/admin/entity/vo/RoleVo.java
  20. 52 0
      gis_admin/src/main/java/com/gis/admin/mapper/SysResourceMapper.java
  21. 59 0
      gis_admin/src/main/java/com/gis/admin/mapper/SysRoleMapper.java
  22. 36 0
      gis_admin/src/main/java/com/gis/admin/mapper/SysUserMapper.java
  23. 40 0
      gis_admin/src/main/java/com/gis/admin/mapper/provider/SysRoleProvider.java
  24. 58 0
      gis_admin/src/main/java/com/gis/admin/mapper/provider/SysUserProvider.java
  25. 32 0
      gis_admin/src/main/java/com/gis/admin/service/SysResourceService.java
  26. 40 0
      gis_admin/src/main/java/com/gis/admin/service/SysRoleService.java
  27. 44 0
      gis_admin/src/main/java/com/gis/admin/service/SysUserService.java
  28. 201 0
      gis_admin/src/main/java/com/gis/admin/service/impl/SysResourceServiceImpl.java
  29. 270 0
      gis_admin/src/main/java/com/gis/admin/service/impl/SysRoleServiceImpl.java
  30. 340 0
      gis_admin/src/main/java/com/gis/admin/service/impl/SysUserServiceImpl.java
  31. 34 0
      gis_admin/src/main/java/com/gis/admin/shiro/JwtAuthenticationException.java
  32. 28 0
      gis_admin/src/main/java/com/gis/admin/shiro/JwtToken.java
  33. 270 0
      gis_admin/src/main/java/com/gis/admin/shiro/ShiroConfig.java
  34. 210 0
      gis_admin/src/main/java/com/gis/admin/shiro/ShiroRealm.java
  35. 76 0
      gis_admin/src/main/java/com/gis/admin/shiro/filters/CustomShiroFilterFactoryBean.java
  36. 149 0
      gis_admin/src/main/java/com/gis/admin/shiro/filters/JwtFilter.java
  37. 68 0
      gis_admin/src/main/java/com/gis/admin/shiro/filters/ResourceCheckFilter.java
  38. 107 0
      gis_admin/src/main/java/com/gis/admin/tree/SysResourceTreeUtil.java
  39. 51 0
      gis_admin/src/main/java/com/gis/admin/tree/vo/SysResourceTree.java
  40. 191 0
      gis_admin/src/main/resources/db/sys_admin.sql
  41. 27 0
      gis_admin/src/main/resources/db/资源表.csv
  42. 41 0
      gis_application/pom.xml
  43. 14 0
      gis_application/src/main/java/com/gis/GisApplication.java
  44. 73 0
      gis_application/src/main/resources/application-dev.properties
  45. 77 0
      gis_application/src/main/resources/application-pro.properties
  46. 76 0
      gis_application/src/main/resources/application-sit.properties
  47. 46 0
      gis_application/src/main/resources/application.properties
  48. 102 0
      gis_application/src/main/resources/db/sys_resource.sql
  49. 156 0
      gis_application/src/main/resources/logback-spring.xml
  50. 11 0
      gis_application/src/main/resources/sh/shutdown.sh
  51. 11 0
      gis_application/src/main/resources/sh/startup.sh
  52. 26 0
      gis_cms/pom.xml
  53. 81 0
      gis_cms/src/main/java/com/gis/cms/controller/BarrageController.java
  54. 90 0
      gis_cms/src/main/java/com/gis/cms/controller/CommentController.java
  55. 91 0
      gis_cms/src/main/java/com/gis/cms/controller/GoodsController.java
  56. 69 0
      gis_cms/src/main/java/com/gis/cms/controller/SensitiveController.java
  57. 134 0
      gis_cms/src/main/java/com/gis/cms/controller/WebController.java
  58. 17 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/BarrageDto.java
  59. 22 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/CommentDto.java
  60. 25 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/ContentDto.java
  61. 35 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/CountAnswerDto.java
  62. 61 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/GoodsDto.java
  63. 23 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/GoodsPageDateDto.java
  64. 20 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/SensitiveDto.java
  65. 16 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/StatusPageDataDto.java
  66. 23 0
      gis_cms/src/main/java/com/gis/cms/entity/dto/TypePageDateDto.java
  67. 28 0
      gis_cms/src/main/java/com/gis/cms/entity/po/BarrageEntity.java
  68. 55 0
      gis_cms/src/main/java/com/gis/cms/entity/po/CommentEntity.java
  69. 45 0
      gis_cms/src/main/java/com/gis/cms/entity/po/FileEntity.java
  70. 52 0
      gis_cms/src/main/java/com/gis/cms/entity/po/GoodsEntity.java
  71. 26 0
      gis_cms/src/main/java/com/gis/cms/entity/po/SensitiveEntity.java
  72. 22 0
      gis_cms/src/main/java/com/gis/cms/entity/vo/BarrageVoExcel.java
  73. 52 0
      gis_cms/src/main/java/com/gis/cms/entity/vo/CommentVo.java
  74. 28 0
      gis_cms/src/main/java/com/gis/cms/entity/vo/CommentVoExcel.java
  75. 41 0
      gis_cms/src/main/java/com/gis/cms/entity/vo/MournVo.java
  76. 32 0
      gis_cms/src/main/java/com/gis/cms/entity/vo/SearchVo.java
  77. 25 0
      gis_cms/src/main/java/com/gis/cms/mapper/BarrageMapper.java
  78. 38 0
      gis_cms/src/main/java/com/gis/cms/mapper/CommentMapper.java
  79. 32 0
      gis_cms/src/main/java/com/gis/cms/mapper/FileMapper.java
  80. 33 0
      gis_cms/src/main/java/com/gis/cms/mapper/GoodsMapper.java
  81. 29 0
      gis_cms/src/main/java/com/gis/cms/mapper/MyBaseMapper.java
  82. 18 0
      gis_cms/src/main/java/com/gis/cms/mapper/SensitiveMapper.java
  83. 46 0
      gis_cms/src/main/java/com/gis/cms/mapper/provider/BarrageProvider.java
  84. 17 0
      gis_cms/src/main/java/com/gis/cms/mapper/provider/BaseProvider.java
  85. 52 0
      gis_cms/src/main/java/com/gis/cms/mapper/provider/CommentProvider.java
  86. 100 0
      gis_cms/src/main/java/com/gis/cms/mapper/provider/GoodsProvider.java
  87. 28 0
      gis_cms/src/main/java/com/gis/cms/service/BarrageService.java
  88. 35 0
      gis_cms/src/main/java/com/gis/cms/service/CommentService.java
  89. 30 0
      gis_cms/src/main/java/com/gis/cms/service/FileService.java
  90. 44 0
      gis_cms/src/main/java/com/gis/cms/service/GoodsService.java
  91. 32 0
      gis_cms/src/main/java/com/gis/cms/service/SensitiveService.java
  92. 135 0
      gis_cms/src/main/java/com/gis/cms/service/impl/BarrageServiceImpl.java
  93. 155 0
      gis_cms/src/main/java/com/gis/cms/service/impl/CommentServiceImpl.java
  94. 114 0
      gis_cms/src/main/java/com/gis/cms/service/impl/FileServiceImpl.java
  95. 328 0
      gis_cms/src/main/java/com/gis/cms/service/impl/GoodsServiceImpl.java
  96. 148 0
      gis_cms/src/main/java/com/gis/cms/service/impl/SensitiveServiceImpl.java
  97. 139 0
      gis_cms/src/main/java/com/gis/cms/tree/CommentTreeUtil.java
  98. 44 0
      gis_cms/src/main/java/com/gis/cms/tree/vo/CommentTree.java
  99. 6 0
      gis_cms/src/main/resources/db/resource.sql
  100. 0 0
      gis_cms/src/main/resources/db/sys_admin.sql

+ 32 - 0
gis_admin/pom.xml

@@ -0,0 +1,32 @@
+<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/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>army_beijing_fourteen</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>gis_admin</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_common</artifactId>
+        </dependency>
+
+        <!-- shiro -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring-boot-starter</artifactId>
+        </dependency>
+
+    </dependencies>
+
+
+
+
+
+</project>

+ 26 - 0
gis_admin/src/main/java/com/gis/admin/controller/ApiController.java

@@ -0,0 +1,26 @@
+package com.gis.admin.controller;
+
+import com.gis.common.util.Result;
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import java.time.LocalDateTime;
+
+/**
+ * Created by owen on 2021/7/7 0007 8:27
+ */
+@ApiIgnore
+@Api(tags = "api-demo")
+@RestController
+@RequestMapping("api")
+public class ApiController {
+
+
+    @GetMapping("test")
+    public Result test(){
+        return Result.success("我是api: " +  LocalDateTime.now());
+    }
+}

+ 129 - 0
gis_admin/src/main/java/com/gis/admin/controller/ExceptionController.java

@@ -0,0 +1,129 @@
+package com.gis.admin.controller;
+
+import com.gis.common.base.exception.BaseRuntimeException;
+import com.gis.common.util.Result;
+import lombok.extern.log4j.Log4j2;
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.NoHandlerFoundException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+
+/**
+ * 统一捕捉异常,自定义返回参数
+ * 这里只可以捕获controller层的异常。
+ */
+@Log4j2
+@RestControllerAdvice
+public class ExceptionController {
+
+    // 捕捉shiro的异常
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ExceptionHandler(ShiroException.class)
+    public Result handle401(ShiroException e) {
+//        return Result.failure(5001, e.getMessage());
+        log.error("没有授权1");
+        return Result.failure(5001, "没有授权");
+    }
+
+
+
+    /**
+     * 捕捉UnauthorizedException
+     *
+     * 权限不够,会抛这个异常
+     */
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ExceptionHandler(UnauthorizedException.class)
+    public Result handle401() {
+        log.error("没有权限");
+        return Result.failure(5003, "没有权限");
+    }
+
+    // 捕捉其他所有异常
+    @ExceptionHandler(Exception.class)
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public Result globalException(HttpServletRequest request, Throwable ex) {
+        log.error(ex);
+        return Result.failure(getStatus(request).value(), ex.getMessage());
+    }
+
+
+    private HttpStatus getStatus(HttpServletRequest request) {
+        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
+        if (statusCode == null) {
+            return HttpStatus.INTERNAL_SERVER_ERROR;
+        }
+        return HttpStatus.valueOf(statusCode);
+    }
+
+    @ResponseBody
+    @ExceptionHandler(BaseRuntimeException.class)
+    @ResponseStatus(HttpStatus.OK)
+    public Result runtimeExceptionHandler(HttpServletRequest request, BaseRuntimeException e) {
+        log.error(request.getRequestURI() + ":" + e.getMsg());
+//        return Result.failure(e.getCode() == null ? Result.CODE_FAILURE : e.getCode(), e.getMsg());
+        return Result.failure(e.getCode(), e.getMsg());
+    }
+
+    /**
+     * 方法参数校验
+     *
+     * 注解验证异常
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+        return Result.failure(60001, e.getBindingResult().getFieldError().getDefaultMessage());
+    }
+
+    /**
+     * ValidationException
+     */
+    @ExceptionHandler(ValidationException.class)
+    public Result handleValidationException(ValidationException e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60002, e.getCause().getMessage());
+    }
+
+    /**
+     * ConstraintViolationException
+     */
+    @ExceptionHandler(ConstraintViolationException.class)
+    public Result handleConstraintViolationException(ConstraintViolationException e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60003, e.getMessage());
+    }
+
+    @ExceptionHandler(NoHandlerFoundException.class)
+    public Result handlerNoFoundException(Exception e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60004, "路径不存在,请检查路径是否正确");
+    }
+
+    /**
+     * 防止表单重复提交
+     * 需要结合数据库某个字段设置唯一字段使用
+     *
+     * 例如userName
+     *
+     * 也可以结合redis使用
+     */
+    @ExceptionHandler(DuplicateKeyException.class)
+    public Result handleDuplicateKeyException(DuplicateKeyException e) {
+        log.error(e.getMessage(), e);
+        return Result.failure(60005, "数据重复,请检查后提交: " + e.getMessage());
+    }
+
+
+
+}
+

+ 42 - 0
gis_admin/src/main/java/com/gis/admin/controller/LogController.java

@@ -0,0 +1,42 @@
+package com.gis.admin.controller;
+
+
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.entity.vo.LogVo;
+import com.gis.common.base.service.LogService;
+import com.gis.common.util.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * Created by owen on 2020/5/12 0018 12:17
+ * 日志管理,只有admin权限访问
+ */
+@Log4j2
+@Api(tags = "sys-日志管理")
+@RestController
+@RequestMapping("sys/log")
+//@RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+public class LogController  {
+
+    @Autowired
+    public LogService logService;
+
+
+    @ApiOperation("列表")
+    @PostMapping("list")
+    public Result<LogVo> list(@RequestBody PageDateDto param) {
+
+        return logService.search(param);
+    }
+
+}

+ 299 - 0
gis_admin/src/main/java/com/gis/admin/controller/LoginController.java

@@ -0,0 +1,299 @@
+package com.gis.admin.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.gis.admin.entity.po.SysResourceEntity;
+import com.gis.admin.entity.po.SysRoleEntity;
+import com.gis.common.base.entity.po.LogEntity;
+import com.gis.common.base.service.LogService;
+import com.gis.common.constant.ConfigConstant;
+import com.gis.common.util.*;
+import com.gis.admin.entity.po.SysUserEntity;
+import com.gis.admin.service.SysResourceService;
+import com.gis.admin.service.SysRoleService;
+import com.gis.admin.service.SysUserService;
+import com.gis.admin.entity.dto.LoginDto;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by owen on 2020/2/19 0019 15:53
+ */
+@Api(tags = "sys-登录")
+@RestController
+@Log4j2
+public class LoginController {
+
+    @Autowired
+    private LogService logService;
+
+    @Autowired
+    private SysUserService userService;
+
+    @Autowired
+    SysRoleService sysRoleService;
+
+    @Autowired
+    SysResourceService sysResourceService;
+
+//    @Autowired
+//    private RedisTemplate<String, String> redisTemplate;
+
+    @Autowired
+    ConfigConstant configConstant;
+
+    @Resource
+    protected HttpServletRequest request;
+
+    @Autowired
+    RedisUtil redisUtil;
+
+
+
+    // 目前是24h
+    private static Integer TOKEN_EXPIRE = 1000 * 60 * 60 * 24;
+
+    @ApiOperation("登录")
+    @PostMapping(value = "admin/login")
+    public Result login(@Valid @RequestBody LoginDto param)  {
+
+        String from = param.getFrom();
+        String[] checkFrom = {"cms","web"};
+        List<String> fromList = Arrays.asList(checkFrom);
+        if (!fromList.contains(from)) {
+            log.error("from: {}", from);
+            return Result.failure("非法用户");
+        }
+
+        // 1.获取用户
+        SysUserEntity entity = userService.findByUserName(param.getUserName());
+        if (entity == null){
+            log.error("用户不存在");
+            return Result.failure("用户不存在");
+        }
+
+        Long userId = entity.getId();
+        Object role = getRoleKey(userId);
+        log.info("role: {}", role);
+
+        if ("cms".equals(from)) {
+            if (((Set)role).contains("sys_visitor") || CollectionUtil.isEmpty((Set)role)){
+                log.error("游客不能登录管理后台");
+                return Result.failure("非法用户");
+            }
+
+        }
+
+        // 检查菜单权限
+        List<SysResourceEntity> menu = sysResourceService.getPermissionByUserIdAndType(userId, "menu");
+        if (CollectionUtil.isEmpty(menu)){
+            String errorMsg = "菜单权限为空,不允许登录";
+            log.error(errorMsg);
+            return Result.failure(errorMsg);
+        }
+
+        // 解密密码
+        String password = Base64Converter.decodePassword(param.getPassword());
+
+        // 验证密码,解密出来是明文密码,在跟输入密码比较
+        boolean decryptName = PasswordUtils.decrypt(entity.getPassword(), password, PasswordUtils.getStaticSalt());
+//        boolean decryptName = PasswordUtils.decrypt(entity.getPassword(), param.getPassword(), PasswordUtils.getStaticSalt());
+        if (!decryptName) {
+            log.error("密码错误");
+            return Result.failure("密码错误");
+        }
+
+        // 检查账号是否启用
+        if (entity.getIsEnabled() != 1) {
+            log.error("此账号已停用: {}", entity.getUserName());
+            return Result.failure("此账号已停用");
+        }
+
+        // 创建新token
+        HashMap<String, Object> tokenMap = new HashMap<>();
+        tokenMap.put("userName", entity.getUserName());
+        tokenMap.put("id", userId);
+        tokenMap.put("role", role);
+
+        String token = JwtUtil.createJWT(TOKEN_EXPIRE, tokenMap);
+
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("user", entity);
+        result.put("token", token);
+        // 角色控制系统管理(sys_admin)、内容管理
+        result.put("role", role);
+//        result.put("roleName", role.getRoleName());
+
+
+        // 保存操作日志
+        saveLog(userId);
+
+
+        // 更新到 redis, 有效期24h, 旧token无效, 做单用户登录 86400s-> 24H
+//        redisTemplate.opsForValue().set(configConstant.redisPrefix + token, token, Long.parseLong("23"), TimeUnit.HOURS);
+
+        redisUtil.set(configConstant.redisPrefix + token, token, 86400);
+
+
+        return Result.success(result);
+
+    }
+
+    @ApiOperation("退出")
+    @GetMapping("admin/logout")
+    public Result logout() {
+        String token = request.getHeader("token");
+        if (StringUtils.isBlank(token)) {
+            log.info("token is null");
+        }
+        redisUtil.del(configConstant.redisPrefix + token);
+        return Result.success();
+    }
+
+    @ApiOperation(value = "检查登录状态", notes = "true:已登录, false:已退出")
+    @GetMapping("admin/checkLogin")
+    public Result checkLogin() {
+        String token = request.getHeader("token");
+        if (StringUtils.isBlank(token)) {
+            log.info("token is null");
+        }
+        String o = (String) redisUtil.get(configConstant.redisPrefix + token);
+        return Result.success(o != null);
+    }
+
+    @ApiOperation("test-登录")
+    @PostMapping(value = "test/admin/login")
+    public Result testLogin(@Valid @RequestBody LoginDto param)  {
+
+        String from = param.getFrom();
+        String[] checkFrom = {"cms","web"};
+        List<String> fromList = Arrays.asList(checkFrom);
+        if (!fromList.contains(from)) {
+            log.error("from: {}", from);
+            return Result.failure("非法用户");
+        }
+
+        // 1.获取用户
+        SysUserEntity entity = userService.findByUserName(param.getUserName());
+        if (entity == null){
+            log.error("用户不存在");
+            return Result.failure("用户不存在");
+        }
+
+        Long userId = entity.getId();
+        Object role = getRoleKey(userId);
+        log.info("role: {}", role);
+
+        if ("cms".equals(from)) {
+            if (((Set)role).contains("sys_visitor") || CollectionUtil.isEmpty((Set)role)){
+                log.error("游客不能登录管理后台");
+                return Result.failure("非法用户");
+            }
+
+        }
+
+        // 检查菜单权限
+        List<SysResourceEntity> menu = sysResourceService.getPermissionByUserIdAndType(userId, "menu");
+        if (CollectionUtil.isEmpty(menu)){
+            String errorMsg = "菜单权限为空,不允许登录";
+            log.error(errorMsg);
+            return Result.failure(errorMsg);
+        }
+
+        // 验证密码,解密出来是明文密码,在跟输入密码比较
+        boolean decryptName = PasswordUtils.decrypt(entity.getPassword(), param.getPassword(), PasswordUtils.getStaticSalt());
+        if (!decryptName) {
+            log.error("密码错误");
+            return Result.failure("密码错误");
+        }
+
+        // 检查账号是否启用
+        if (entity.getIsEnabled() != 1) {
+            log.error("此账号已停用: {}", entity.getUserName());
+            return Result.failure("此账号已停用");
+        }
+
+        // 创建新token
+        HashMap<String, Object> tokenMap = new HashMap<>();
+        tokenMap.put("userName", entity.getUserName());
+        tokenMap.put("id", userId);
+        tokenMap.put("role", role);
+
+        String token = JwtUtil.createJWT(TOKEN_EXPIRE, tokenMap);
+
+
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("user", entity);
+        result.put("token", token);
+        // 角色控制系统管理(sys_admin)、内容管理
+        result.put("role", role);
+//        result.put("roleName", role.getRoleName());
+
+
+        // 保存操作日志
+        saveLog(userId);
+
+
+        // 更新到 redis, 有效期24h, 旧token无效, 做单用户登录 86400s-> 24H
+//        redisTemplate.opsForValue().set(configConstant.redisPrefix + token, token, Long.parseLong("23"), TimeUnit.HOURS);
+
+        redisUtil.set(configConstant.redisPrefix + token, token, 86400);
+
+
+        return Result.success(result);
+
+    }
+
+
+
+
+
+    @ApiIgnore
+    @GetMapping("admin/test")
+    public String test(){
+        return LocalDateTime.now().toString();
+    }
+
+
+    /**
+     * 保存日志
+     * @param userId
+     */
+    private void saveLog(Long userId){
+        LogEntity entity = new LogEntity(userId, "登录管理", "用户登录", request.getRemoteAddr());
+        logService.save(entity);
+    }
+
+
+    /**
+     * 获取角色key
+     * @param userId
+     * @return
+     */
+    private Set<String> getRoleKey(Long userId){
+        Set<String> roleKeys = sysRoleService.findRoleKeyByUserId(userId);
+        return roleKeys;
+    }
+
+    private SysRoleEntity getRole(Long userId){
+        return sysRoleService.findByUserId(userId);
+    }
+
+
+}

+ 59 - 0
gis_admin/src/main/java/com/gis/admin/controller/SysResourceController.java

@@ -0,0 +1,59 @@
+package com.gis.admin.controller;
+
+
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.util.Result;
+import com.gis.admin.service.SysResourceService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * Created by owen on 2021/7/6 0018 12:17common
+ * 日志管理,只有admin权限访问
+ */
+
+@Api(tags = "sys-资源管理")
+@RestController
+@RequestMapping("sys/resource")
+public class SysResourceController  {
+
+
+    @Autowired
+    SysResourceService entityService;
+
+//    @RequiresRoles("sys_admin")
+    @ApiOperation("获取树资源")
+    @GetMapping("getTreeResource")
+    public Result getTreeResource() {
+        return entityService.getTreeResource();
+    }
+
+    @ApiOperation("获取用户权限资源树")
+    @GetMapping("getTreePermissions")
+    public Result getTreePermissions() {
+        return entityService.getTreeAllPermissionsByUserId();
+    }
+
+    @RequiresRoles("sys_admin")
+    @WebControllerLog(description = "资源管理-删除缓存", addDb = true)
+    @ApiOperation(value = "删除缓存", notes = "更新资源表,需要刷新缓存")
+    @GetMapping("refresh")
+    public Result refreshRedisResource() {
+        return entityService.refreshRedisResource();
+    }
+
+
+    @WebControllerLog(description = "资源管理-测试缓存", addDb = true)
+    @ApiOperation(value = "测试缓存", notes = "更新资源表,需要刷新缓存")
+    @GetMapping("testCatch")
+    public Result testCatch() {
+        return entityService.testCatch();
+    }
+
+}

+ 88 - 0
gis_admin/src/main/java/com/gis/admin/controller/SysRoleController.java

@@ -0,0 +1,88 @@
+package com.gis.admin.controller;
+
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.dto.RoleDto;
+import com.gis.admin.service.SysRoleService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+
+/**
+ * Created by owen on 2021/6/29 0018 12:17
+ * 需要admin权限
+ */
+@Slf4j
+@Api(tags = "sys-角色管理")
+@RestController
+@RequestMapping("sys/role")
+//@RequiresRoles("sys_admin") //需要admin角色才可以访问此controller
+public class SysRoleController  {
+
+    @Autowired
+    private SysRoleService roleService;
+
+
+    /**
+     * 超级管理员角色只有一个
+     * @RequiresPermissions("admin:role:list")
+     */
+    @WebControllerLog(description = "角色权限-查询列表")
+    @ApiOperation("列表/搜索")
+    @PostMapping("list")
+    public Result list(@RequestBody PageDto param){
+        return roleService.listCount(param);
+    }
+
+//    @WebControllerLog(description = "角色权限-查询列表")
+//    @ApiOperation("列表/搜索(统计人数)")
+//    @PostMapping("listCount")
+//    public Result listCount(@RequestBody PageDto param){
+//        return roleService.listCount(param);
+//    }
+
+
+    @ApiOperation("查询角色对应的权限")
+    @GetMapping("detail/{id}")
+    public Result detail(@PathVariable Long id) {
+        return roleService.detail(id);
+    }
+
+    @RequiresPermissions("sys:role:edit")
+    @WebControllerLog(description = "角色权限-新增/修改", addDb = true)
+    @ApiOperation("新增或修改")
+    @PostMapping("save")
+    public Result save(@Valid @RequestBody RoleDto param){
+        return roleService.saveEntity(param);
+    }
+
+    @RequiresPermissions("sys:role:edit")
+    @WebControllerLog(description = "角色管理-角色启用/停用", addDb = true)
+    @ApiOperation(value = "角色启用/停用", notes = "isDisable-> 0:可用, 1:禁用")
+    @GetMapping("editStatus/{id}/{isDisable}")
+    public Result editStatus(@PathVariable Long id, @PathVariable Integer isDisable){
+        return roleService.editStatus(id, isDisable);
+    }
+
+    @RequiresPermissions("sys:role:remove")
+    @WebControllerLog(description = "角色权限-角色删除", addDb = true)
+    @ApiOperation("删除角色")
+    @GetMapping("remove/{id}")
+    public Result remove(@PathVariable Long id){
+        return roleService.remove(id);
+
+    }
+
+
+
+
+
+}

+ 105 - 0
gis_admin/src/main/java/com/gis/admin/controller/SysUserController.java

@@ -0,0 +1,105 @@
+package com.gis.admin.controller;
+
+
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.entity.dto.UserPageDateDto;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.dto.PasswordDto;
+import com.gis.admin.entity.dto.UserDto;
+import com.gis.admin.entity.po.SysUserEntity;
+import com.gis.admin.service.SysUserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.log4j.Log4j2;
+import org.apache.shiro.authz.annotation.Logical;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.transaction.Transactional;
+import javax.validation.Valid;
+
+/**
+ * Created by owen on 2020/2/18 0018 12:17
+ */
+@Log4j2
+@Api(tags = "sys-用户管理")
+@RestController
+@RequestMapping("sys/user")
+public class SysUserController {
+
+    @Autowired
+    private SysUserService userService;
+
+//    @RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+    @ApiOperation("用户列表")
+    @PostMapping("list")
+    public Result<SysUserEntity> list(@RequestBody UserPageDateDto param) {
+        return userService.search(param);
+    }
+
+//    @RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+//    @RequiresPermissions("sys:user:edit")
+    @WebControllerLog(description = "用户管理-修改用户", addDb = true)
+    @ApiOperation("新增/修改用户信息")
+    @PostMapping("save")
+    public Result save(@Valid @RequestBody UserDto param) {
+        return userService.saveEntity(param);
+    }
+
+
+    @ApiOperation("详情")
+    @GetMapping("detail/{id}")
+    public Result<SysUserEntity> detail(@PathVariable Long id) {
+        return userService.detail(id);
+    }
+
+    @WebControllerLog(description = "用户管理-修改密码", addDb = true)
+    @ApiOperation("修改密码")
+    @PostMapping("updatePwd")
+    public Result updatePwd(@Valid @RequestBody PasswordDto param)  {
+        return userService.updatePwd(param);
+
+    }
+
+
+    @RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+    @WebControllerLog(description = "用户管理-重置密码", addDb = true)
+    @ApiOperation("重置密码")
+    @GetMapping("resetPass/{id}")
+    public Result resetPass(@PathVariable Long id) {
+        return userService.resetPass(id);
+
+    }
+
+
+//    @RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+    @WebControllerLog(description = "用户管理-用户启用/停用", addDb = true)
+    @ApiOperation(value = "启用、停用账户", notes = "isEnabled-> 1:可用, 0:禁用")
+    @GetMapping("editStatus/{id}/{isEnabled}")
+    public Result editStatus(@PathVariable Long id, @PathVariable Integer isEnabled) {
+        return userService.editStatus(id, isEnabled);
+
+    }
+
+
+//    @RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+    @RequiresPermissions("sys:user:remove")
+    @WebControllerLog(description = "用户管理-删除",addDb = true)
+    @ApiOperation("删除")
+    @GetMapping("removes/{ids}")
+    public Result removes(@PathVariable String ids) {
+        return userService.removes(ids);
+    }
+
+//    @RequiresRoles(value = {"sys_admin"}, logical = Logical.OR)
+    @WebControllerLog(description = "用户管理-获取角色")
+    @ApiOperation("获取角色")
+    @GetMapping("getRole")
+    public Result getRole() {
+        return userService.getRole();
+    }
+}
+

+ 28 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/LoginDto.java

@@ -0,0 +1,28 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class LoginDto {
+
+    @NotBlank(message = "用户名不能为空")
+    @ApiModelProperty(value = "用户名", name = "userName", required = true)
+    private String userName;
+
+
+    @NotBlank(message = "密码不能为空")
+    @ApiModelProperty(value = "密码", name = "password", required = true)
+    private String password;
+
+    @NotBlank(message = "from不能为空")
+    @ApiModelProperty(value = "区分用户去向,cms:管理后台,web:展示页")
+    private String from;
+
+
+}

+ 28 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/PasswordDto.java

@@ -0,0 +1,28 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class PasswordDto {
+
+    @ApiModelProperty(value = "旧密码", name = "oldPassword")
+    private String oldPassword;
+
+    @NotBlank(message = "新密码不能为空")
+    @ApiModelProperty(value = "新密码", name = "newPassword", required = true)
+    private String newPassword;
+
+    /**门户网站使用*/
+    @ApiModelProperty(value = "身份码")
+    private String userName;
+
+    /**门户网站使用*/
+    @ApiModelProperty(value = "验证码")
+    private String code;
+}

+ 56 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/RegisterDto.java

@@ -0,0 +1,56 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2020/5/28 0028 16:36
+ * 游客注册
+ */
+@Data
+public class RegisterDto {
+
+    @NotBlank(message = "真实姓名不能为空")
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+
+    @NotBlank(message = "身份证号(军号)不能为空")
+    @ApiModelProperty(value = "身份证号(军号)", required = true)
+    private String userName;
+
+    @NotBlank(message = "昵称不能为空")
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @NotNull(message = "性别不能为空")
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+//    @NotBlank(message = "单位不能为空")
+    @ApiModelProperty(value = "单位")
+    private String unit;
+
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+    @Length(min = 6,message = "长度不能小于6位")
+//    @Length(max = 12, message = "长度不能大于12位")
+    @ApiModelProperty(value = "登录密码")
+    private String password;
+
+    @Length(min = 6,message = "长度不能小于6位")
+//    @Length(max = 12, message = "长度不能大于12位")
+    @ApiModelProperty(value = "确认密码")
+    private String verifyPassword;
+
+
+
+}

+ 21 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/ResetPasswordDto.java

@@ -0,0 +1,21 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class ResetPasswordDto {
+
+    @NotBlank(message = "注册姓名不能为空")
+    @ApiModelProperty(value = "姓名",  required = true)
+    private String realName;
+
+    @NotBlank(message = "身份码不能为空")
+    @ApiModelProperty(value = "身份码",  required = true)
+    private String userName;
+}

+ 31 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/RoleDto.java

@@ -0,0 +1,31 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.Set;
+
+/**
+ * Created by owen on 2020/2/18 0018 17:09
+ */
+@Data
+public class RoleDto {
+
+    private Long id;
+
+    @NotBlank(message = "角色名称不能为空")
+    @ApiModelProperty(value = "资源id", required = true)
+    private String roleName;
+
+    // 描述
+    private String roleDesc;
+
+    private String roleKey;
+
+    // 资源id
+    @NotNull(message = "权限不能为空")
+    @ApiModelProperty(value = "资源id", required = true)
+    private Set<Long> resources;
+}

+ 78 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/UserDto.java

@@ -0,0 +1,78 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2020/5/28 0028 16:36
+ */
+@Data
+public class UserDto {
+
+    @ApiModelProperty(value = "id, 修改时必须传,新增忽略", name = "id")
+    private Long id;
+
+
+//    @NotBlank(message = "真实姓名不能为空")
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+
+    @NotBlank(message = "管理员账号不能为空")
+    @ApiModelProperty(value = "管理员账号", required = true)
+    private String userName;
+
+//    @NotBlank(message = "昵称不能为空")
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+//    @NotNull(message = "性别不能为空")
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+//    @NotBlank(message = "单位不能为空")
+    @ApiModelProperty(value = "单位")
+    private String unit;
+
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+//    @NotNull(message = "启用状态不能为空")
+    @ApiModelProperty(value = "状态 1:启用  0:停用 ")
+    private Integer status;
+
+    @ApiModelProperty(value = "高清图url")
+    private String img;
+
+    @ApiModelProperty(value = "缩略图url")
+    private String thumb;
+
+//    @ApiModelProperty(value = "状态 0:启用(默认值)  1:禁用")
+//    private Integer isDisable;
+
+    @ApiModelProperty(value = "是否启动 0: 禁用  1:启用(默认值)")
+    private Integer isEnabled;
+
+
+//    @NotNull(message = "角色不能为空")
+//    @ApiModelProperty(value = "角色,sys_admin:系统管理员,sys_high:高级管理员, sys_normal:普通管理员, sys_visitor:游客" ,required = true)
+//    private String role;
+    @NotNull(message = "角色不能为空")
+    @ApiModelProperty(value = "角色id",notes = "目前一个用户只有一个角色", required = true)
+    private Long roleId;
+
+//    @NotBlank(message = "旧密码不能为空")
+//    @ApiModelProperty(value = "旧密码", name = "oldPassword")
+//    private String oldPassword;
+
+//    @NotBlank(message = "新密码不能为空")
+//    @ApiModelProperty(value = "新密码", name = "newPassword")
+//    private String newPassword;
+
+}

+ 65 - 0
gis_admin/src/main/java/com/gis/admin/entity/dto/UserWebDto.java

@@ -0,0 +1,65 @@
+package com.gis.admin.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2020/5/28 0028 16:36
+ */
+@Data
+public class UserWebDto {
+
+    @ApiModelProperty(value = "id, 修改时必须传,新增忽略", name = "id")
+    private Long id;
+
+
+//    @NotBlank(message = "真实姓名不能为空")
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+
+    @NotBlank(message = "管理员账号不能为空")
+    @ApiModelProperty(value = "管理员账号", required = true)
+    private String userName;
+
+//    @NotBlank(message = "昵称不能为空")
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+//    @NotNull(message = "性别不能为空")
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+//    @NotBlank(message = "单位不能为空")
+    @ApiModelProperty(value = "单位")
+    private String unit;
+
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+//    @NotNull(message = "启用状态不能为空")
+//    @ApiModelProperty(value = "状态 1:启用  0:停用 ")
+//    private Integer status;
+
+    @ApiModelProperty(value = "高清图url")
+    private String img;
+
+    @ApiModelProperty(value = "缩略图url")
+    private String thumb;
+
+//    @ApiModelProperty(value = "状态 0:启用(默认值)  1:禁用")
+//    private Integer isDisable;
+
+    @ApiModelProperty(value = "是否启动 0: 禁用  1:启用(默认值)")
+    private Integer isEnabled;
+
+
+
+
+}

+ 63 - 0
gis_admin/src/main/java/com/gis/admin/entity/po/SysResourceEntity.java

@@ -0,0 +1,63 @@
+package com.gis.admin.entity.po;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.gis.common.base.entity.po.BaseEntity;
+import lombok.Data;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.Serializable;
+
+/**
+ * Created by owen on 2021/6/28 0010 17:39
+ * 资源表
+ */
+
+@Data
+@Entity
+@Table(name = "sys_resource")
+public class SysResourceEntity extends BaseEntity implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = -293343757324080501L;
+
+    @Column(length = 50)
+    private String name;
+
+    // 描述
+    @JSONField(serialize = false)
+    @Column(name = "description")
+    private String description;
+
+    @JSONField(serialize = false)
+    @Column(name = "url")
+    private String url;
+
+//    @Column(length = 10)
+//    private String icon;
+
+//    @JSONField(serialize = false)
+    @Column(name = "resource_key")
+    private String resourceKey;
+
+    // 前端需要传menu、button
+    @Column(columnDefinition = "enum('menu','button')")
+    private String resourceType;
+
+    @Column(length = 2)
+    private Integer sort;
+
+    @Column(name = "parent_id")
+    private Long parentId;
+
+    /** 封装权限字段,不需要映射到数据库, 默认有全部权限*/
+    @Transient
+//    private Boolean authority ;
+    private Boolean authority = true;
+
+
+}

+ 50 - 0
gis_admin/src/main/java/com/gis/admin/entity/po/SysRoleEntity.java

@@ -0,0 +1,50 @@
+package com.gis.admin.entity.po;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.Serializable;
+
+/**
+ * Created by owen on 2021/6/28 0010 17:39
+ * 角色表
+ */
+
+@Data
+@Entity
+@Table(name = "sys_role")
+public class SysRoleEntity extends BaseEntity implements Serializable {
+
+
+    private static final long serialVersionUID = -8093446477843493946L;
+
+    @ApiModelProperty(value = "角色名称")
+    private String roleName;
+
+    @ApiModelProperty(value = "角色描述")
+    private String roleDesc;
+
+    /**
+     * roleKey,前缀sys_开头的数据不能删除
+     * 以下角色,在数据库定义好
+     */
+    @ApiModelProperty(value = "角色key", notes = "角色,sys_admin:系统管理员,sys_high:高级管理员, sys_normal:普通管理员, sys_visitor:游客,内部指定的角色,才用的上key")
+    private String roleKey;
+
+    @ApiModelProperty(value = "排序")
+    private String sort;
+
+//    @ApiModelProperty(value = "状态 0:启用(默认值)  1:禁用")
+//    private Integer isDisable;
+
+    @ApiModelProperty(value = "是否启动 0: 禁用  1:启用(默认值)")
+    private Integer isEnabled;
+
+    @Transient
+    @ApiModelProperty(value = "该角色的用户数")
+    private Integer count;
+}

+ 74 - 0
gis_admin/src/main/java/com/gis/admin/entity/po/SysUserEntity.java

@@ -0,0 +1,74 @@
+package com.gis.admin.entity.po;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.Serializable;
+
+/**
+ * 用户表
+ */
+@Data
+@Entity
+@Table(name = "sys_user")
+public class SysUserEntity extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = -853504493430501564L;
+
+    @ApiModelProperty(value = "身份证号(军号)")
+    private String userName;
+
+    @JSONField(serialize = false)
+    private String password;
+
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
+    @ApiModelProperty(value = "昵称")
+    private String nickName;
+
+    @ApiModelProperty(value = "性别 0:男  1:女")
+    private Integer sex;
+
+    @ApiModelProperty(value = "电话")
+    private String phone;
+
+    @ApiModelProperty(value = "单位")
+    private String unit;
+
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+//    @ApiModelProperty(value = "超级管理员,1:是, 0:否")
+//    private Integer sysManager;
+
+    @ApiModelProperty(value = "是否启动 0: 禁用  1:启用(默认值)")
+    private Integer isEnabled;
+
+//    @ApiModelProperty(value = "高清图url")
+//    private String img;
+
+    @ApiModelProperty(value = "缩略图url")
+    private String thumb;
+
+//    @JSONField(serialize = false)
+    @Transient
+    @ApiModelProperty(value = "角色,sys_admin:系统管理员,sys_high:高级管理员, sys_normal:普通管理员, sys_visitor:游客")
+    private String roleKey;
+
+    @Transient
+    @ApiModelProperty(value = "角色id")
+    private Integer roleId;
+
+    @Transient
+    @ApiModelProperty(value = "角色名称")
+    private String roleName;
+
+
+
+}

+ 12 - 0
gis_admin/src/main/java/com/gis/admin/entity/vo/RoleVo.java

@@ -0,0 +1,12 @@
+package com.gis.admin.entity.vo;
+
+import lombok.Data;
+
+/**
+ * Created by owen on 2021/7/8 0008 17:20
+ */
+@Data
+public class RoleVo {
+
+
+}

+ 52 - 0
gis_admin/src/main/java/com/gis/admin/mapper/SysResourceMapper.java

@@ -0,0 +1,52 @@
+package com.gis.admin.mapper;
+
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.admin.entity.po.SysResourceEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+
+/**
+ * Created by owen on 2020/2/18 0018 11:13
+ */
+@Mapper
+@Component
+public interface SysResourceMapper extends IBaseMapper<SysResourceEntity, Long> {
+
+//    @Select(value = "select * from sys_role_resource z left join sys_resource r ON z.resource_id = r.id where z.role_id= #{roleId}")
+//    List<SysResourceEntity> findRoleResourceByRoleId(Long roleId);
+
+
+    /**
+     * 根据用户id查询权限
+     * 没有left ,直接用join,就不会前后表关联了
+     */
+    @Select(value = "select b.id, b.name, b.parent_id, b.resource_type, b.resource_key from " +
+            "((sys_user u left join sys_user_role ur on u.id = ur.user_id) " +
+            " join sys_role r on r.id = ur.role_id) " +
+            " join sys_role_resource a on r.id = a.role_id " +
+            " join sys_resource b on b.id = a.resource_id WHERE u.id = #{userId}")
+    List<SysResourceEntity> findResourceByUserId(Long userId);
+
+    /** 根据角色id查询权限 */
+    @Select(value = "select b.id, b.name, b.parent_id, b.resource_type, b.resource_key from " +
+            " sys_role r join sys_role_resource a on r.id = a.role_id " +
+            " join sys_resource b on b.id = a.resource_id WHERE r.is_delete=0 and r.id = #{roleId}")
+    List<SysResourceEntity> findResourceByRoleId(Long roleId);
+
+    @Select(value = "select b.id from " +
+            "((sys_user u left join sys_user_role ur on u.id = ur.user_id) " +
+            " join sys_role r on r.id = ur.role_id) " +
+            " join sys_role_resource a on r.id = a.role_id " +
+            " join sys_resource b on b.id = a.resource_id WHERE u.id = #{userId}")
+    List<String> getAllIdByUserId(Long userId);
+
+    /** 根据角色id查询权限 */
+    @Select(value = "select b.id from " +
+            " sys_role r join sys_role_resource a on r.id = a.role_id " +
+            " join sys_resource b on b.id = a.resource_id WHERE r.is_delete=0 and r.id = #{roleId}")
+    List<String> getAllIdByRoleId(Long roleId);
+}

+ 59 - 0
gis_admin/src/main/java/com/gis/admin/mapper/SysRoleMapper.java

@@ -0,0 +1,59 @@
+package com.gis.admin.mapper;
+
+import com.gis.admin.mapper.provider.SysRoleProvider;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.admin.entity.po.SysRoleEntity;
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Created by owen on 2020/2/18 0018 11:13
+ */
+@Component
+@Mapper
+public interface SysRoleMapper extends IBaseMapper<SysRoleEntity, Long> {
+
+
+    @Select(value = "insert into sys_role_resource (role_id, resource_id) values (#{roleId}, #{resourceId});")
+    void saveRoleResource(Long roleId, Long resourceId);
+
+    @Select(value = "delete from sys_role_resource where role_id=#{roleId}")
+    void deleteRoleResource(Long roleId);
+
+
+    @Select(value = "select z.role_key from sys_user_role ur left join sys_role z on z.id = ur.role_id where z.is_delete=0 and ur.user_id = #{userId}")
+    Set<String> findRoleKeyByUserId(Long userId);
+
+    @Delete(value = "delete from sys_user_role where user_id=#{userId}")
+    void deleteUserRoleByUserId(Long userId);
+
+    @Insert(value = "insert into sys_user_role (user_id, role_id) values (#{userId}, #{roleId})")
+    void saveUserRole(Long userId, Long roleId);
+
+    @Update("update sys_role set is_enabled = #{isDisable} , update_time = NOW() where is_delete=0 and id = #{id} ")
+    void setIsEnabled(Long id, Integer isDisable);
+
+//    @Select("SELECT a.*, count(*) as count " +
+//            "FROM sys_role a left JOIN sys_user_role b on b.role_id=a.id WHERE a.is_delete=0  GROUP BY a.id ")
+//    List<SysRoleEntity> listCount();
+
+    @SelectProvider(type = SysRoleProvider.class, method = "search")
+    List<SysRoleEntity> listCount(PageDto param);
+
+    @Select(value = "select a.* from sys_role a left join sys_user_role b on a.id = b.role_id where a.is_delete=0 and b.user_id = #{userId}")
+    SysRoleEntity findByUserId(Long userId);
+
+    /** 该角色是否有用户在使用*/
+    @Select("select b.user_id from sys_role a left join sys_user_role b on a.id=b.role_id left join sys_user c on c.id=b.user_id where a.is_delete=0 and c.is_delete=0 and a.id=#{roleId}")
+    List<Long> checkUseByRoleId(Long roleId);
+
+    @Update("update sys_user_role set role_id = #{roleId} , create_time = NOW() where user_id = #{userId} ")
+    void setUserIdByRoleId(Long userId, Long roleId);
+
+    @Select("select id from sys_role where is_delete=0 and role_name=#{roleName}")
+    List<Long> existByRoleName(String roleName);
+}

+ 36 - 0
gis_admin/src/main/java/com/gis/admin/mapper/SysUserMapper.java

@@ -0,0 +1,36 @@
+package com.gis.admin.mapper;
+
+
+import com.gis.admin.mapper.provider.SysUserProvider;
+import com.gis.common.base.entity.dto.UserPageDateDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.admin.entity.po.SysUserEntity;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+
+@Component
+@Mapper
+public interface SysUserMapper extends IBaseMapper<SysUserEntity, Long> {
+
+
+    @Select(value = "select * from sys_user where is_delete = '0' AND user_name= #{userName}")
+    SysUserEntity findByUserName(String userName);
+
+    @Select(value = "select a.*, b.role_id as roleId, c.role_name as roleName, c.role_key as roleKey from sys_user a " +
+            "left join sys_user_role b on b.user_id = a.id " +
+            "left join sys_role c on c.id=b.role_id where a.is_delete = 0 AND a.id= #{id}")
+    SysUserEntity detailMapper(Long id);
+
+    @SelectProvider(type = SysUserProvider.class, method = "search")
+    List<SysUserEntity> search(UserPageDateDto param);
+
+    @Delete(value = "delete from sys_user_role where user_id=#{userId}")
+    void deleteUserRoleByUserId(Long userId);
+
+}

+ 40 - 0
gis_admin/src/main/java/com/gis/admin/mapper/provider/SysRoleProvider.java

@@ -0,0 +1,40 @@
+package com.gis.admin.mapper.provider;
+
+import com.gis.common.base.entity.dto.PageDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class SysRoleProvider {
+
+    public String search(PageDto param) {
+
+
+        StringBuffer sql = new StringBuffer(
+                "select a.*, count(b.user_id) as count from sys_role a " +
+                        "left JOIN sys_user_role b on b.role_id=a.id WHERE a.is_delete=0 ");
+
+
+
+        String searchKey = param.getSearchKey();
+        if (!StringUtils.isAllBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            sql.append(" and ( a.role_name like '%").append(searchKey).append("%' )");
+        }
+
+
+        sql.append(" GROUP BY a.id");
+        sql.append(" order by a.sort, a.create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+
+}
+
+
+

+ 58 - 0
gis_admin/src/main/java/com/gis/admin/mapper/provider/SysUserProvider.java

@@ -0,0 +1,58 @@
+package com.gis.admin.mapper.provider;
+
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.entity.dto.UserPageDateDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ibatis.annotations.Select;
+
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class SysUserProvider {
+
+
+    @Select(value = "select a.*, b.role_id as roleId, c.role_name as roleName, c.role_key as roleKey from sys_user a " +
+            "left join sys_user_role b on b.user_id = a.id " +
+            "left join sys_role c on c.id=b.role_id where a.is_delete = 0 ")
+
+    public String search(UserPageDateDto param) {
+        StringBuffer sql = new StringBuffer(
+                "select a.*, b.role_id as roleId, c.role_name as roleName, c.role_key as roleKey from sys_user a " +
+                        "left join sys_user_role b on b.user_id = a.id " +
+                        "left join sys_role c on c.id=b.role_id where a.is_delete = 0 ");
+
+
+        if (StringUtils.isNotBlank(param.getStartTime()) && StringUtils.isNotBlank(param.getEndTime())) {
+
+            sql.append(" and a.create_time >= ").append("'").append(param.getStartTime()).append("'");
+            sql.append(" and a.create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+        String searchKey = param.getSearchKey();
+        if (!StringUtils.isAllBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            sql.append(" and (");
+            sql.append( "a.real_name like '%").append(searchKey).append("%'");
+//            sql.append( " or a.unit like '%").append(searchKey).append("%'");
+            sql.append(")");
+        }
+
+        Long roleId = param.getRoleId();
+        if (roleId != null) {
+            sql.append(" and c.id=").append(roleId);
+        }
+
+
+        sql.append(" order by a.create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+
+}
+
+
+

+ 32 - 0
gis_admin/src/main/java/com/gis/admin/service/SysResourceService.java

@@ -0,0 +1,32 @@
+package com.gis.admin.service;
+
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.po.SysResourceEntity;
+import com.gis.admin.tree.vo.SysResourceTree;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Created by owen on 2020/2/19 0019 10:22
+ */
+public interface SysResourceService extends IBaseService<SysResourceEntity, Long> {
+
+
+    Set<String> getPermissionByUserId(Long userId);
+
+    Result getTreeResource();
+
+    Result getTreeAllPermissionsByUserId();
+
+    Result refreshRedisResource();
+
+    List<SysResourceTree> getTreeAllPermissionsByRoleId(Long roleId);
+
+    Result testCatch();
+
+    List<SysResourceEntity> getPermissionByUserIdAndType(Long userId, String type);
+
+     List<SysResourceEntity> findCacheAll();
+}

+ 40 - 0
gis_admin/src/main/java/com/gis/admin/service/SysRoleService.java

@@ -0,0 +1,40 @@
+package com.gis.admin.service;
+
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.dto.RoleDto;
+import com.gis.admin.entity.po.SysRoleEntity;
+
+import java.util.Set;
+
+/**
+ * Created by owen on 2020/2/18 0018 11:36
+ */
+public interface SysRoleService extends IBaseService<SysRoleEntity, Long> {
+
+    void saveRoleResource(Long roleId, Long resourceId);
+
+    void deleteRoleResource(Long roleId);
+
+    Set<String> findRoleKeyByUserId(Long userId);
+
+    Result saveEntity(RoleDto param);
+
+    Result search(PageDto param);
+
+    void deleteUserRoleByUserId(Long userId);
+
+    void saveUserRole(Long userId, Long roleId);
+
+    Result remove(Long id);
+
+    Result detail(Long id);
+
+
+    Result editStatus(Long id, Integer isDisable);
+
+    Result listCount(PageDto param);
+
+    SysRoleEntity findByUserId(Long userId);
+}

+ 44 - 0
gis_admin/src/main/java/com/gis/admin/service/SysUserService.java

@@ -0,0 +1,44 @@
+package com.gis.admin.service;
+
+
+import com.gis.admin.entity.dto.ResetPasswordDto;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.entity.dto.UserPageDateDto;
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.dto.PasswordDto;
+import com.gis.admin.entity.dto.UserDto;
+import com.gis.admin.entity.dto.RegisterDto;
+import com.gis.admin.entity.po.SysUserEntity;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface SysUserService extends IBaseService<SysUserEntity, Long> {
+
+
+    SysUserEntity findByUserName(String userName);
+
+    Result saveEntity(UserDto param);
+
+    Result removes(String ids);
+
+    Result<SysUserEntity> search(UserPageDateDto param);
+
+    Result updatePwd(PasswordDto param);
+
+    Result resetPass(Long id);
+
+    Result editStatus(Long id, Integer isEnabled);
+
+    Result register(RegisterDto param);
+
+    Result getRole();
+
+    Result<SysUserEntity> detail(Long id);
+
+    Result retrievePassword(ResetPasswordDto param);
+
+    Result updatePwdByWeb(PasswordDto param);
+}

+ 201 - 0
gis_admin/src/main/java/com/gis/admin/service/impl/SysResourceServiceImpl.java

@@ -0,0 +1,201 @@
+package com.gis.admin.service.impl;
+
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.po.SysResourceEntity;
+import com.gis.admin.mapper.SysResourceMapper;
+import com.gis.admin.service.SysResourceService;
+import com.gis.admin.service.SysRoleService;
+import com.gis.admin.tree.SysResourceTreeUtil;
+import com.gis.admin.tree.vo.SysResourceTree;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+
+/**
+ * Created by owen on 2020/2/18 0018 11:37
+ */
+@Slf4j
+@Service
+@Transactional
+public class SysResourceServiceImpl extends IBaseServiceImpl<SysResourceEntity, Long> implements SysResourceService {
+
+    @Autowired
+    private SysResourceMapper resourceMapper;
+
+    @Autowired
+    SysRoleService sysRoleService;
+
+    static String REDIS_RESOURCE_KEY = "army:hospital:resource";
+
+
+    @Override
+    public IBaseMapper<SysResourceEntity, Long> getBaseMapper() {
+        return this.resourceMapper;
+    }
+
+
+    private List<String> getAllIdByUserId(Long userId) {
+        return resourceMapper.getAllIdByUserId(userId);
+    }
+
+
+
+    @Override
+    public Set<String> getPermissionByUserId(Long userId) {
+        List<SysResourceEntity> list = resourceMapper.findResourceByUserId(userId);
+        Set<String> permissions = new HashSet<>();
+        for (SysResourceEntity i : list) {
+            permissions.add(i.getResourceKey());
+        }
+        return permissions;
+    }
+
+    @Override
+    public Result getTreeResource() {
+        List<SysResourceEntity> all = findCacheAll();
+        SysResourceTreeUtil tree = new SysResourceTreeUtil(all);
+        return Result.success(tree.buildTree());
+    }
+
+    /**
+     * 获取资源
+     * @param userId 用户id
+     * @param type 资源类型,菜单、按钮, 不传:返回全部
+     * @return
+     */
+    @Override
+    public List<SysResourceEntity> getPermissionByUserIdAndType(Long userId, String type) {
+
+        List<SysResourceEntity> list = resourceMapper.findResourceByUserId(userId);
+        List<SysResourceEntity> results =  new ArrayList<>();
+        for (SysResourceEntity i : list) {
+            if (StringUtils.isBlank(type)){
+                results.add(i);
+            } else if (type.equals(i.getResourceType())){
+                results.add(i);
+            }
+        }
+
+        return results;
+    }
+
+
+
+
+    /**
+     * 获取所有权限列表
+     * 会把所有权限都会列出来的,通过Authority判断是否有权限
+     *
+     * 只控制button
+     * @return
+     */
+    @Override
+    public Result getTreeAllPermissionsByUserId() {
+        Long userId = getTokenUserId();
+        SysResourceTreeUtil tree ;
+        List<SysResourceEntity> cacheAll = findCacheAll();
+
+        // 设置用户权限
+        List roles = getTokenRole();
+        // 系统管理员, 拥有所有权限
+        if (roles.contains("sys_admin")) {
+            tree = new SysResourceTreeUtil(cacheAll);
+        } else {
+            List<String> ids = getAllIdByUserId(userId);
+            tree = new SysResourceTreeUtil(getAllPer(ids));
+        }
+        return Result.success(tree.buildTree());
+    }
+
+
+    @Override
+    public List<SysResourceTree> getTreeAllPermissionsByRoleId(Long roleId) {
+        List<String> ids = getAllIdByRoleId(roleId);
+        List<SysResourceEntity> allPer = getAllPer(ids);
+        return new SysResourceTreeUtil(allPer).buildTree();
+    }
+
+    @Override
+    public Result testCatch() {
+//        List<SysResourceEntity> cacheAll2 = findCacheAll2();
+        List<SysResourceEntity> cacheAll2 = findCacheAll2();
+
+        SysResourceTreeUtil tree = new SysResourceTreeUtil(cacheAll2);
+        return Result.success(tree.buildTree());
+    }
+
+    /**
+     * 处理authority 是否有权限
+     * @param perIds 有权限的id集合
+     * @return
+     */
+    private List<SysResourceEntity> getAllPer(List<String> perIds) {
+        List<SysResourceEntity> cacheAll = findCacheAll();
+        List<SysResourceEntity> results =  new ArrayList<>();
+        for (SysResourceEntity entity : cacheAll) {
+            // 默认是true, 把没有权限的对象设置false, 只对按钮设置
+//            if (!perIds.contains(entity.getId().toString()) && entity.getResourceType().equals("button")) {
+            if (!perIds.contains(entity.getId().toString()) ) {
+                entity.setAuthority(false);
+            }
+            results.add(entity);
+        }
+        return results;
+    }
+
+
+    private List<String> getAllIdByRoleId(Long roleId) {
+        return resourceMapper.getAllIdByRoleId(roleId);
+    }
+
+    @Override
+    public Result refreshRedisResource() {
+        redisUtil.del(REDIS_RESOURCE_KEY);
+        return Result.success();
+    }
+
+
+
+    /**
+     * 获取db所有资源, authority默认true
+     * @return
+     *
+     * 2021-07-16 list放到redis后, id会为null
+     */
+
+    @Override
+    public List<SysResourceEntity> findCacheAll(){
+        List all = redisUtil.getJsonList(REDIS_RESOURCE_KEY, SysResourceEntity.class);
+        if (all == null) {
+            log.info("从数据库获取");
+            all = this.findAll();
+            // 21600-> 6h
+            redisUtil.setObjectToJson(REDIS_RESOURCE_KEY, all, 21600);
+        }
+        log.info("走缓存");
+        return all;
+
+    }
+
+
+    private List<SysResourceEntity> findCacheAll2(){
+        List all = redisUtil.getJsonList(REDIS_RESOURCE_KEY, SysResourceEntity.class);
+        if (all == null) {
+            log.info("从数据库获取");
+            all = this.findAll();
+            // 21600-> 6h
+            redisUtil.setObjectToJson(REDIS_RESOURCE_KEY, all, 21600);
+        }
+        log.info("走缓存");
+        return all;
+
+    }
+
+}

+ 270 - 0
gis_admin/src/main/java/com/gis/admin/service/impl/SysRoleServiceImpl.java

@@ -0,0 +1,270 @@
+package com.gis.admin.service.impl;
+
+import com.gis.admin.entity.po.SysResourceEntity;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.dto.RoleDto;
+import com.gis.admin.entity.po.SysRoleEntity;
+import com.gis.admin.mapper.SysRoleMapper;
+import com.gis.admin.service.SysResourceService;
+import com.gis.admin.service.SysRoleService;
+import com.gis.admin.tree.vo.SysResourceTree;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.entity.Condition;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.*;
+
+
+/**
+ * Created by owen on 2020/2/18 0018 11:37
+ */
+@Slf4j
+@Service
+@Transactional(rollbackFor=Exception.class)
+public class SysRoleServiceImpl extends IBaseServiceImpl<SysRoleEntity, Long> implements SysRoleService {
+
+    @Autowired
+    private SysRoleMapper entityMapper;
+
+    @Override
+    public IBaseMapper<SysRoleEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+    @Autowired
+    SysResourceService sysResourceService;
+
+
+    @Override
+    public void saveRoleResource(Long roleId, Long resourceId) {
+        entityMapper.saveRoleResource(roleId, resourceId);
+    }
+
+    @Override
+    public void deleteRoleResource(Long roleId) {
+        entityMapper.deleteRoleResource(roleId);
+    }
+
+
+    @Override
+    public Set<String> findRoleKeyByUserId(Long userId) {
+        return entityMapper.findRoleKeyByUserId(userId);
+    }
+
+    @Override
+    public Result saveEntity(RoleDto param) {
+        if (StringUtils.isBlank(param.getRoleName())){
+            log.error("角色名称不能为空");
+            return Result.failure("角色名称不能为空");
+        }
+
+        if (param.getResources() == null){
+            log.error("权限不能为空");
+            return Result.failure("权限不能为空");
+        }
+
+
+        SysRoleEntity roleEntity = null;
+        boolean flag = false;
+
+        if (param.getId() == null) {
+            roleEntity = new SysRoleEntity();
+            BeanUtils.copyProperties(param, roleEntity);
+
+            if (existByRoleName(param.getRoleName())){
+                return Result.failure("角色名称已存在,请重新输入");
+            }
+
+            this.save(roleEntity);
+            flag = true;
+        } else {
+            roleEntity = this.findById(param.getId());
+            if (roleEntity == null) {
+                log.error("此角色不存在");
+                return Result.failure("此角色不存在");
+
+            }
+
+            String roleKey = roleEntity.getRoleKey();
+            if (StringUtils.equals(roleKey, "sys_admin")){
+                return Result.failure("超级管理员为预设角色, 不能修改");
+            }
+
+            BeanUtils.copyProperties(param, roleEntity);
+            roleEntity.setUpdateTime(LocalDateTime.now());
+
+            if (!StringUtils.equals(param.getRoleName(), roleEntity.getRoleName())){
+                if (existByRoleName(param.getRoleName())){
+                    return Result.failure("角色名称已存在,请重新输入");
+                }
+            }
+
+            this.update(roleEntity);
+
+            // 每次修改,删除角色资源表信息,重新添加
+            this.deleteRoleResource(param.getId());
+            flag = true;
+        }
+
+        // 添加权限
+        if (flag){
+            if (param.getResources() != null){
+                Set<Long> menuAndSonId = getMenuAndSonId(param.getResources());
+                log.info("更新的权限id: {}", menuAndSonId);
+                for (long i : menuAndSonId) {
+                    this.saveRoleResource(roleEntity.getId(), i);
+                }
+                return Result.success();
+            }
+        }
+
+        return Result.failure("保存失败");
+    }
+
+    /**
+     * 合并父子id
+     * @param resources 子id
+     * @return
+     */
+    public Set<Long> getMenuAndSonId(Set<Long> resources){
+        // 查询所有资源
+        List<SysResourceEntity> all = sysResourceService.findCacheAll();
+        Set<Long> menuIds = new HashSet<>();
+        for (SysResourceEntity entity : all) {
+            if ("button".equals(entity.getResourceType())){
+                if (resources.contains(entity.getId())){
+                    menuIds.add(entity.getParentId());
+                }
+            }
+        }
+
+        // 处理二级菜单
+        for (SysResourceEntity entity : all) {
+            if (menuIds.contains(entity.getId()) && "menu".equals(entity.getResourceType())){
+                if (entity.getParentId()!=null){
+                    menuIds.add(entity.getParentId());
+                }
+            }
+        }
+
+        resources.addAll(menuIds);
+        return resources;
+    }
+
+    /**
+     * 判断用户名是否重复
+     * @param roleName
+     * @return
+     */
+    public boolean existByRoleName(String roleName){
+        List<Long> n = entityMapper.existByRoleName(roleName);
+        return n.size() > 0;
+    }
+
+    @Override
+    public Result search(PageDto param) {
+        startPage(param);
+        Condition condition = new Condition(SysRoleEntity.class);
+        // 参数名是属性
+        String searchKey = param.getSearchKey();
+        if (StringUtils.isNotBlank(searchKey)) {
+            condition.and().andLike("roleName", "%" + param.getSearchKey()+ "%");
+        }
+        // 排除系统管理员
+        condition.and().andNotEqualTo("roleKey", "sys_admin");
+        PageInfo<SysRoleEntity> pageInfo = this.findAll(condition, param.getPageNum(), param.getPageSize());
+        return Result.success(pageInfo);
+    }
+
+    @Override
+    public void deleteUserRoleByUserId(Long userId) {
+        entityMapper.deleteUserRoleByUserId(userId);
+    }
+
+    @Override
+    public void saveUserRole(Long userId, Long roleId) {
+        entityMapper.saveUserRole(userId, roleId);
+    }
+
+    @Override
+    public Result remove(Long id) {
+        SysRoleEntity roleEntity = this.findById(id);
+        if (roleEntity.getRoleKey().startsWith("sys_")) {
+            return Result.failure("系统预设角色不能删除");
+        }
+
+        // 检测是否有用户在使用该角色, 如果使用,将该角色设置为游客角色
+        checkUserRole(id);
+
+        // db数据真删除, 会把中间表数据也删除
+        this.deleteById(id);
+        return Result.success();
+    }
+
+    /**
+     * 重置角色为默认角色(游客)
+     * @param roleId 角色id
+     */
+    private void checkUserRole(Long roleId){
+        List<Long> userIds = entityMapper.checkUseByRoleId(roleId);
+        if (userIds.size() > 0) {
+            // 需要确认数据库sys_role.role_key:2=sys_visitor
+            for (Long userId : userIds) {
+                entityMapper.setUserIdByRoleId(userId, 2L);
+            }
+        }
+    }
+
+
+
+
+    @Override
+    public Result detail(Long id) {
+        SysRoleEntity roleEntity = this.findById(id);
+        List<SysResourceTree> permission = new ArrayList<>();
+        if (roleEntity != null) {
+             permission = sysResourceService.getTreeAllPermissionsByRoleId(id);
+        }
+
+        HashMap<Object, Object> resultMap = new HashMap<>();
+        resultMap.put("role", roleEntity);
+        resultMap.put("permission", permission);
+
+        return Result.success(resultMap);
+    }
+
+    @Override
+    public Result editStatus(Long id, Integer isDisable) {
+        // 禁用时,将关联用户的角色设置为默认角色(游客)
+
+        entityMapper.setIsEnabled(id, isDisable);
+        if (isDisable == 0) {
+            checkUserRole(id);
+        }
+        return Result.success();
+    }
+
+    @Override
+    public Result listCount(PageDto param) {
+        startPage(param);
+        List<SysRoleEntity> lists = entityMapper.listCount(param);
+        return Result.success(new PageInfo<>(lists));
+    }
+
+    @Override
+    public SysRoleEntity findByUserId(Long userId) {
+        return entityMapper.findByUserId(userId);
+    }
+
+
+}

+ 340 - 0
gis_admin/src/main/java/com/gis/admin/service/impl/SysUserServiceImpl.java

@@ -0,0 +1,340 @@
+package com.gis.admin.service.impl;
+
+import cn.hutool.core.util.RandomUtil;
+import com.gis.admin.entity.dto.ResetPasswordDto;
+import com.gis.admin.entity.po.SysRoleEntity;
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.entity.dto.UserPageDateDto;
+import com.gis.common.base.entity.po.LogEntity;
+import com.gis.common.base.exception.BaseRuntimeException;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.LogService;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.constant.MsgCode;
+import com.gis.common.util.Base64Converter;
+import com.gis.common.util.JwtUtil;
+import com.gis.common.util.PasswordUtils;
+import com.gis.common.util.Result;
+import com.gis.admin.entity.dto.PasswordDto;
+import com.gis.admin.entity.dto.UserDto;
+import com.gis.admin.entity.dto.RegisterDto;
+import com.gis.admin.entity.po.SysUserEntity;
+import com.gis.admin.mapper.SysUserMapper;
+import com.gis.admin.service.SysRoleService;
+import com.gis.admin.service.SysUserService;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.RandomUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Condition;
+
+import javax.validation.constraints.NotBlank;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Created by owen on 2021/6/29 0011 16:16
+ */
+@Slf4j
+@Service
+public class SysUserServiceImpl extends IBaseServiceImpl<SysUserEntity, Long> implements SysUserService {
+
+    @Autowired
+    private SysUserMapper entityMapper;
+
+    @Autowired
+    SysRoleService sysRoleService;
+
+    @Autowired
+    LogService logService;
+
+    /**重置密码redis key*/
+    final static String RESET_PASSWORD_KEY = "reset:password:";
+
+    @Override
+    public IBaseMapper<SysUserEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+    @Override
+    public SysUserEntity findByUserName(String userName) {
+        return entityMapper.findByUserName(userName);
+    }
+
+    @Override
+    public Result saveEntity(UserDto param) {
+        SysUserEntity entity = null;
+        Long id = param.getId();
+        if (id == null) {
+            entity = this.findByUserName(param.getUserName());
+            if (entity != null) {
+                return Result.failure("身份码已存在");
+            }
+            entity = new SysUserEntity();
+            BeanUtils.copyProperties(param, entity);
+            entity.setPassword(PasswordUtils.encrypt(param.getUserName(), "123456", PasswordUtils.getStaticSalt()));
+            this.save(entity);
+            id = entity.getId();
+        } else {
+            entity = this.findById(id);
+            if (entity == null) {
+                log.error("用户不存在: {}", id);
+                return Result.failure("用户不存在");
+            }
+
+            Long userId = entity.getId();
+
+            BeanUtils.copyProperties(param, entity);
+            entity.setUpdateTime(LocalDateTime.now());
+            this.update(entity);
+
+            // 更新密码
+//            String oldPassword = param.getOldPassword();
+//            String newPassword = param.getNewPassword();
+//            if (oldPassword !=null && newPassword != null) {
+//                PasswordDto dto = new PasswordDto();
+//                dto.setOldPassword(oldPassword);
+//                dto.setNewPassword(newPassword);
+//                updatePassword(dto);
+//            }
+
+            // 每次修改,删除用户角色表信息,重新添加, 系统管理员不能修改
+            if (userId!=1){
+                sysRoleService.deleteUserRoleByUserId(id);
+            }
+        }
+
+
+        // 更新用户角色表
+        Long roleId = param.getRoleId();
+        if (roleId != null && entity.getId() != 1) {
+            sysRoleService.saveUserRole(id, roleId);
+        }
+
+        return Result.success();
+    }
+
+    @Override
+    public Result removes(String ids) {
+
+        List<SysUserEntity> entityList = this.findByIds(ids);
+        for (SysUserEntity entity: entityList) {
+            Long id = entity.getId();
+
+            if (id==1){
+                return Result.failure("系统预设账号不能删除");
+            }
+
+            Set<String> roleKeys = sysRoleService.findRoleKeyByUserId(id);
+            if (roleKeys.contains("sys_admin")) {
+                log.error("管理员账户不能删除 {}", id);
+                return Result.failure("管理员账户不能删除");
+            }
+            entity.setIsDelete(1);
+            entity.setUpdateTime(LocalDateTime.now());
+            this.update(entity);
+
+            // 删除用户角色表的用户id, 不删除角色统计人数会有误
+            entityMapper.deleteUserRoleByUserId(id);
+        }
+
+        return Result.success();
+    }
+
+    @Override
+    public Result<SysUserEntity> search(UserPageDateDto param) {
+        startPage(param);
+        PageInfo<SysUserEntity> page = new PageInfo<>(entityMapper.search(param));
+        return Result.success(page);
+    }
+
+
+    private void updatePassword(PasswordDto param) {
+        SysUserEntity user = this.findByUserName(JwtUtil.getUsername(getToken()));
+
+        // 验证原密码
+        Boolean isBoolean = PasswordUtils.decrypt(user.getPassword(), param.getOldPassword(), PasswordUtils.getStaticSalt());
+        if (!isBoolean) {
+            log.error("原始密码错误");
+            throw new BaseRuntimeException("原始密码错误");
+        }
+
+        user.setPassword(PasswordUtils.encrypt(user.getUserName(), param.getNewPassword(), PasswordUtils.getStaticSalt()));
+        user.setUpdateTime(LocalDateTime.now());
+        this.update(user);
+    }
+
+    @Override
+    public Result updatePwd(PasswordDto param){
+
+        // 密码加密了,需要解密
+        String newPassword = Base64Converter.decodePassword(param.getNewPassword());
+        String oldPassword = Base64Converter.decodePassword(param.getOldPassword());
+        param.setNewPassword(newPassword);
+        param.setOldPassword(oldPassword);
+        SysUserEntity user = this.findByUserName(JwtUtil.getUsername(getToken()));
+
+            updatePwd(param, user, true);
+            return Result.success();
+
+    }
+
+    private void updatePwd(PasswordDto param, SysUserEntity user, boolean flag) {
+
+        if (flag){
+            // 验证原密码
+            Boolean isBoolean = PasswordUtils.decrypt(user.getPassword(), param.getOldPassword(), PasswordUtils.getStaticSalt());
+            if (!isBoolean) {
+                log.error("原始密码错误");
+                throw new BaseRuntimeException(3008,"原始密码错误");
+            }
+
+        }
+
+        user.setPassword(PasswordUtils.encrypt(user.getUserName(), param.getNewPassword(), PasswordUtils.getStaticSalt()));
+        user.setUpdateTime(LocalDateTime.now());
+        this.update(user);
+    }
+
+    @Override
+    public Result resetPass(Long id) {
+        SysUserEntity user = this.findById(id);
+
+        if (user == null) {
+            log.error("用户不存在: {}", id);
+            return Result.failure("用户不存在");
+        }
+
+        user.setPassword(PasswordUtils.encrypt(user.getUserName(), "123456", PasswordUtils.getStaticSalt()));
+        user.setUpdateTime(LocalDateTime.now());
+        this.update(user);
+        return Result.success();
+    }
+
+    @Override
+    public Result editStatus(Long id, Integer isEnabled) {
+
+        SysUserEntity user = this.findById(id);
+        if (user == null) {
+            log.error("用户不存在: {}", id);
+            return Result.failure("用户不存在");
+        }
+
+//        List tokenRole = getTokenRole();
+        Set<String> roleKey = sysRoleService.findRoleKeyByUserId(user.getId());
+        if (roleKey.contains("sys_admin")) {
+            log.error("管理员账户不能停用/注销: {}", id);
+            return Result.failure("管理员账户不能停用/注销");
+        }
+
+        user.setIsEnabled(isEnabled);
+        user.setUpdateTime(LocalDateTime.now());
+        this.update(user);
+        return Result.success();
+    }
+
+    @Override
+    public Result register(RegisterDto param) {
+        if (!param.getPassword().equals(param.getVerifyPassword())) {
+            log.error("确认密码不一致");
+            return Result.failure("确认密码不一致");
+        }
+
+        SysUserEntity entity = this.findByUserName(param.getUserName());
+        if (entity != null) {
+            log.error("该身份码已注册: {}", param.getUserName());
+            return Result.failure("该身份码已注册");
+        }
+
+        entity = new SysUserEntity();
+        BeanUtils.copyProperties(param, entity);
+
+        entity.setPassword(PasswordUtils.encrypt(param.getUserName(), param.getPassword(), PasswordUtils.getStaticSalt()));
+        // 默认启用
+        entity.setIsEnabled(1);
+        this.save(entity);
+
+        // 设置默认角色, 2:sys_visitor游客角色
+        Long userId = entity.getId();
+        sysRoleService.saveUserRole(userId, Long.valueOf("2"));
+
+        // 保存操作日志
+        logService.save(new LogEntity(userId,"用户注册","新增用户", request.getRemoteAddr()));
+        return Result.success();
+    }
+
+    @Override
+    public Result getRole() {
+        Condition condition = new Condition(SysRoleEntity.class);
+        condition.and().andEqualTo("isEnabled", 1);
+        return Result.success(sysRoleService.findAll(condition));
+    }
+
+    @Override
+    public Result<SysUserEntity> detail(Long id) {
+
+        SysUserEntity user = entityMapper.detailMapper(id);
+
+
+        return Result.success(user);
+    }
+
+    /**
+     * 不正确返回空
+     * 正确返回 code
+     * @param param
+     * @return
+     */
+    @Override
+    public Result retrievePassword(ResetPasswordDto param) {
+        String userName = param.getUserName();
+        SysUserEntity entity = entityMapper.findByUserName(param.getUserName());
+        if (entity == null) {
+            return Result.success(false);
+        }
+
+        if (!param.getRealName().equals(entity.getRealName())) {
+            return Result.success(false);
+        }
+
+        String redisKey = RESET_PASSWORD_KEY + userName;
+        String code = RandomUtil.randomString(9);
+
+        // code 有效期5分钟
+        redisUtil.set(redisKey, code , 300);
+        return Result.success((Object) code);
+    }
+
+    @Override
+    public Result updatePwdByWeb(PasswordDto param) {
+        String userName = param.getUserName();
+        SysUserEntity entity = entityMapper.findByUserName(userName);
+        if (entity == null) {
+            return Result.failure(MsgCode.e3001, "对象不存在");
+        }
+
+        String redisKey = RESET_PASSWORD_KEY + userName;
+        String redisCode = (String)redisUtil.get(redisKey);
+        if (!redisCode.equals(param.getCode())) {
+            return Result.failure(MsgCode.e3005, "验证码失效");
+        }
+
+//        updatePwd(param, entity, false);
+
+        return Result.success();
+    }
+
+    public static void main(String[] args) {
+       String oldPassword="6iaBtlEIIxMTE=31knu3HyMTUx79pGbV";
+        String  newPassword="O8rFRVDwExMTExMTtIZcNbMTfBi8C4VN";
+        System.out.println(Base64Converter.decodePassword(oldPassword));
+        System.out.println(Base64Converter.decodePassword(newPassword));
+    }
+
+
+}

+ 34 - 0
gis_admin/src/main/java/com/gis/admin/shiro/JwtAuthenticationException.java

@@ -0,0 +1,34 @@
+package com.gis.admin.shiro;
+
+import org.apache.shiro.ShiroException;
+
+public class JwtAuthenticationException extends ShiroException {
+
+    private static final long serialVersionUID = 2899335020273674736L;
+
+    private int code;
+
+    private String msg;
+
+    public JwtAuthenticationException(int code, String msg){
+        super(msg);
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

+ 28 - 0
gis_admin/src/main/java/com/gis/admin/shiro/JwtToken.java

@@ -0,0 +1,28 @@
+package com.gis.admin.shiro;
+ 
+import org.apache.shiro.authc.AuthenticationToken;
+
+/**
+ * @Author Scott
+ * @create 2018-07-12 15:19
+ * @desc
+ **/
+public class JwtToken implements AuthenticationToken {
+	
+	private static final long serialVersionUID = 1L;
+	private String token;
+ 
+    public JwtToken(String token) {
+        this.token = token;
+    }
+ 
+    @Override
+    public Object getPrincipal() {
+        return token;
+    }
+ 
+    @Override
+    public Object getCredentials() {
+        return token;
+    }
+}

+ 270 - 0
gis_admin/src/main/java/com/gis/admin/shiro/ShiroConfig.java

@@ -0,0 +1,270 @@
+package com.gis.admin.shiro;
+
+import com.gis.admin.shiro.filters.CustomShiroFilterFactoryBean;
+import com.gis.admin.shiro.filters.JwtFilter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
+import org.apache.shiro.mgt.DefaultSubjectDAO;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.core.env.Environment;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+
+import javax.annotation.Resource;
+import javax.servlet.Filter;
+import java.util.*;
+
+/**
+ * @author: Scott
+ * @date: 2018/2/7
+ * @description: shiro 配置类
+ */
+
+@Slf4j
+@Configuration
+public class ShiroConfig {
+
+//    @Value("${jeecg.shiro.excludeUrls}")
+//    private String excludeUrls;
+    @Resource
+    LettuceConnectionFactory lettuceConnectionFactory;
+    @Autowired
+    private Environment env;
+
+
+    /**
+     * Filter Chain定义说明
+     *
+     * 1、一个URL可以配置多个Filter,使用逗号分隔
+     * 2、当设置多个过滤器时,全部验证通过,才视为通过
+     * 3、部分过滤器可指定参数,如perms,roles
+     */
+    @Bean("shiroFilter")
+    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
+        CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();
+        shiroFilterFactoryBean.setSecurityManager(securityManager);
+        // 拦截器
+        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
+//        if(oConvertUtils.isNotEmpty(excludeUrls)){
+//            String[] permissionUrl = excludeUrls.split(",");
+//            for(String url : permissionUrl){
+//                filterChainDefinitionMap.put(url,"anon");
+//            }
+//        }
+        // 配置不会被拦截的链接 顺序判断
+//        filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
+////        filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
+////        filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
+////        filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
+////        filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
+////        filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
+////        filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
+////        filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
+////        filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
+////        filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
+////        filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
+////        filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
+////        filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息
+////        filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
+////        filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
+////        filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
+////        filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
+////        filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
+////        filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
+
+        // 不拦截
+        filterChainDefinitionMap.put("/login", "anon");
+        filterChainDefinitionMap.put("/logout", "anon");
+        filterChainDefinitionMap.put("/admin", "anon");
+        filterChainDefinitionMap.put("/admin/login", "anon");
+        filterChainDefinitionMap.put("/test/**", "anon");
+        filterChainDefinitionMap.put("/api/**", "anon");
+
+        filterChainDefinitionMap.put("/", "anon");
+        filterChainDefinitionMap.put("/doc.html", "anon");
+        filterChainDefinitionMap.put("/doc.html#/**", "anon");
+        filterChainDefinitionMap.put("/**/*.js", "anon");
+        filterChainDefinitionMap.put("/**/*.css", "anon");
+        filterChainDefinitionMap.put("/**/*.html", "anon");
+        filterChainDefinitionMap.put("/**/*.svg", "anon");
+        filterChainDefinitionMap.put("/**/*.pdf", "anon");
+        filterChainDefinitionMap.put("/**/*.jpg", "anon");
+        filterChainDefinitionMap.put("/**/*.png", "anon");
+        filterChainDefinitionMap.put("/**/*.ico", "anon");
+//        filterChainDefinitionMap.put("/**/*.mp4", "anon");
+
+        filterChainDefinitionMap.put("/**/*.ttf", "anon");
+        filterChainDefinitionMap.put("/**/*.woff", "anon");
+        filterChainDefinitionMap.put("/**/*.woff2", "anon");
+
+        // swagger 不拦截
+        filterChainDefinitionMap.put("/druid/**", "anon");
+        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
+        filterChainDefinitionMap.put("/swagger**/**", "anon");
+        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
+        filterChainDefinitionMap.put("/webjars/**", "anon");
+        filterChainDefinitionMap.put("/v2/**", "anon");
+
+
+        // update-begin--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
+        filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
+        // update-end--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
+
+        //积木报表排除
+        filterChainDefinitionMap.put("/jmreport/**", "anon");
+        filterChainDefinitionMap.put("/**/*.js.map", "anon");
+        filterChainDefinitionMap.put("/**/*.css.map", "anon");
+        //大屏设计器排除
+        filterChainDefinitionMap.put("/bigscreen/**", "anon");
+
+        //测试示例
+        filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子
+        //filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
+        //filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
+        //filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
+
+        //websocket排除
+        filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
+        filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
+        filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
+
+
+        //性能监控  TODO 存在安全漏洞泄露TOEKN(durid连接池也有)
+        filterChainDefinitionMap.put("/actuator/**", "anon");
+
+        // 添加自己的过滤器并且取名为jwt
+        Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
+        //如果cloudServer为空 则说明是单体 需要加载跨域配置
+        Object cloudServer = env.getProperty("");
+        filterMap.put("jwt", new JwtFilter(cloudServer==null));
+        shiroFilterFactoryBean.setFilters(filterMap);
+        // <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边
+//        filterChainDefinitionMap.put("/**", "jwt");
+        filterChainDefinitionMap.put("/sys/**", "jwt");
+        filterChainDefinitionMap.put("/cms/**", "jwt");
+
+        // 未授权界面返回JSON
+        shiroFilterFactoryBean.setUnauthorizedUrl("/sys/common/403");
+        shiroFilterFactoryBean.setLoginUrl("/sys/common/403");
+        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+        return shiroFilterFactoryBean;
+    }
+
+    @Bean("securityManager")
+    public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
+        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+        securityManager.setRealm(myRealm);
+
+        /*
+         * 关闭shiro自带的session,详情见文档
+         * http://shiro.apache.org/session-management.html#SessionManagement-
+         * StatelessApplications%28Sessionless%29
+         */
+        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
+        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
+        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
+        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
+        securityManager.setSubjectDAO(subjectDAO);
+        //自定义缓存实现,使用redis
+//        securityManager.setCacheManager(redisCacheManager());
+        return securityManager;
+    }
+
+    /**
+     * 下面的代码是添加注解支持
+     * @return
+     */
+    @Bean
+    @DependsOn("lifecycleBeanPostProcessor")
+    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
+        /**
+         * 解决重复代理问题 github#994
+         * 添加前缀判断 不匹配 任何Advisor
+         */
+        defaultAdvisorAutoProxyCreator.setUsePrefix(true);
+        defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
+        return defaultAdvisorAutoProxyCreator;
+    }
+
+    @Bean
+    public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+        return new LifecycleBeanPostProcessor();
+    }
+
+    @Bean
+    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
+        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+        advisor.setSecurityManager(securityManager);
+        return advisor;
+    }
+
+    /**
+     * cacheManager 缓存 redis实现
+     * 使用的是shiro-redis开源插件
+     *
+     * @return
+     */
+//    public RedisCacheManager redisCacheManager() {
+//        log.info("===============(1)创建缓存管理器RedisCacheManager");
+//        RedisCacheManager redisCacheManager = new RedisCacheManager();
+//        redisCacheManager.setRedisManager(redisManager());
+//        //redis中针对不同用户缓存(此处的id需要对应user实体中的id字段,用于唯一标识)
+//        redisCacheManager.setPrincipalIdFieldName("id");
+//        //用户权限信息缓存时间
+//        redisCacheManager.setExpire(200000);
+//        return redisCacheManager;
+//    }
+
+    /**
+     * 配置shiro redisManager
+     * 使用的是shiro-redis开源插件
+     *
+     * @return
+     */
+//    @Bean
+//    public IRedisManager redisManager() {
+//        log.info("===============(2)创建RedisManager,连接Redis..");
+//        IRedisManager manager;
+//        // redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
+//        if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
+//            RedisManager redisManager = new RedisManager();
+//            redisManager.setHost(lettuceConnectionFactory.getHostName());
+//            redisManager.setPort(lettuceConnectionFactory.getPort());
+//            redisManager.setDatabase(lettuceConnectionFactory.getDatabase());
+//            redisManager.setTimeout(0);
+//            if (!StringUtils.isEmpty(lettuceConnectionFactory.getPassword())) {
+//                redisManager.setPassword(lettuceConnectionFactory.getPassword());
+//            }
+//            manager = redisManager;
+//        }else{
+//            // redis集群支持,优先使用集群配置
+//            RedisClusterManager redisManager = new RedisClusterManager();
+//            Set<HostAndPort> portSet = new HashSet<>();
+//            lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));
+//            //update-begin--Author:scott Date:20210531 for:修改集群模式下未设置redis密码的bug issues/I3QNIC
+//            if (oConvertUtils.isNotEmpty(lettuceConnectionFactory.getPassword())) {
+//                JedisCluster jedisCluster = new JedisCluster(portSet, 2000, 2000, 5,
+//                    lettuceConnectionFactory.getPassword(), new GenericObjectPoolConfig());
+//                redisManager.setPassword(lettuceConnectionFactory.getPassword());
+//                redisManager.setJedisCluster(jedisCluster);
+//            } else {
+//                JedisCluster jedisCluster = new JedisCluster(portSet);
+//                redisManager.setJedisCluster(jedisCluster);
+//            }
+//            //update-end--Author:scott Date:20210531 for:修改集群模式下未设置redis密码的bug issues/I3QNIC
+//            manager = redisManager;
+//        }
+//        return manager;
+//    }
+
+}

+ 210 - 0
gis_admin/src/main/java/com/gis/admin/shiro/ShiroRealm.java

@@ -0,0 +1,210 @@
+package com.gis.admin.shiro;
+
+import com.gis.common.constant.ConfigConstant;
+import com.gis.common.util.JwtUtil;
+import com.gis.admin.entity.po.SysUserEntity;
+import com.gis.admin.service.SysResourceService;
+import com.gis.admin.service.SysUserService;
+import com.gis.common.util.RedisUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @Description: 用户登录鉴权和获取用户授权
+ * @Author: owen
+ * @Date: 2021-07-07
+ * @Version: 1.1
+ */
+@Component
+@Slf4j
+public class ShiroRealm extends AuthorizingRealm {
+//	@Lazy
+//    @Resource
+//    private CommonAPI commonAPI;
+
+//    @Lazy
+//    @Resource
+//    private RedisUtil redisUtil;
+
+    @Resource
+    HttpServletRequest request;
+
+    @Autowired
+    SysResourceService sysResourceService;
+
+    @Autowired
+    SysUserService sysUserService;
+
+//    @Autowired
+//    RedisTemplate<String, String> redisTemplate;
+
+    @Autowired
+    ConfigConstant configConstant;
+
+    @Autowired
+    RedisUtil redisUtil;
+
+
+    /**
+     * 必须重写此方法,不然Shiro会报错
+     */
+    @Override
+    public boolean supports(AuthenticationToken token) {
+        return token instanceof JwtToken;
+    }
+
+    /**
+     * 权限信息认证(包括角色以及权限)是用户访问controller的时候才进行验证(redis存储的此处权限信息)
+     * 触发检测用户权限时才会调用此方法,例如checkRole,checkPermission
+     *
+     * 只有当需要检测用户权限的时候才会调用此方法,例如checkRole,checkPermission之类的
+     *
+     * @param principals 身份信息
+     * @return AuthorizationInfo 权限信息
+     */
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+        log.info("===============Shiro权限认证开始============ [ roles、permissions]==========");
+        Long userId = null;
+
+        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+
+        String token = request.getHeader("token");
+        log.info("token: {}", token);
+        if (StringUtils.isNotBlank(token)){
+            List userRole = JwtUtil.getUserRole(token);
+            userId = JwtUtil.getUserId(token);
+            // list to set 添加角色sys_admin,sys
+            info.setRoles(new HashSet<>(userRole));
+        }
+
+
+        // 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add”
+        Set<String> permissions = sysResourceService.getPermissionByUserId(userId);
+        info.addStringPermissions(permissions);
+        log.info("===============Shiro权限认证成功==============");
+        return info;
+    }
+
+    /**
+     * 默认使用此方法进行用户名正确与否验证,错误抛出异常即可。
+     *
+     * 用户信息认证是在用户进行登录的时候进行验证(不存redis)
+     * 也就是说验证用户输入的账号和密码是否正确,错误抛出异常
+     *
+     * @param auth 用户登录的账号密码信息
+     * @return 返回封装了用户信息的 AuthenticationInfo 实例
+     * @throws AuthenticationException
+     */
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
+        log.debug("===============Shiro身份认证开始============doGetAuthenticationInfo==========");
+        String token = (String) auth.getCredentials();
+        log.info("token: {}", token);
+        if (token == null) {
+            throw new JwtAuthenticationException(5001, "header token is null");
+        }
+        // 校验token有效性
+        SysUserEntity sysUserEntity = this.checkUserTokenIsEffect(token);
+        return new SimpleAuthenticationInfo(sysUserEntity, token, getName());
+    }
+
+    /**
+     * 校验token的有效性
+     *
+     * @param token
+     */
+    private SysUserEntity checkUserTokenIsEffect(String token) throws AuthenticationException {
+        // 解密获得username,用于和数据库进行对比
+        String username = JwtUtil.getUsername(token);
+        if (username == null) {
+            throw new JwtAuthenticationException(5001, "token invalid");
+        }
+
+//        String redisToken = redisTemplate.opsForValue().get(configConstant.redisPrefix + token);
+        String redisToken = (String)redisUtil.get(configConstant.redisPrefix + token);
+
+        if (!token.equals(redisToken)) {
+            log.error("redis token is null");
+            throw new JwtAuthenticationException(5001, "redis token is null");
+
+        }
+        // 查询用户信息
+        if (! JwtUtil.isVerify(token, username)) {
+            log.error("error token username or password");
+            throw new JwtAuthenticationException(5001, "token invalid");
+        }
+
+        SysUserEntity userEntity = sysUserService.findByUserName(username);
+        if (userEntity == null) {
+            log.error("error token userEntity");
+            throw new JwtAuthenticationException(5001, "User didn't existed!");
+        }
+
+        return userEntity;
+    }
+
+    /**
+     * JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能)
+     * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍
+     * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
+     * 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
+     * 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
+     * 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。
+     *       用户过期时间 = Jwt有效时间 * 2。
+     *
+     * @param userName
+     * @param passWord
+     * @return
+     */
+//    public boolean jwtTokenRefresh(String token, String userName, String passWord) {
+//        String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
+//        if (oConvertUtils.isNotEmpty(cacheToken)) {
+//            // 校验token有效性
+//            if (!JwtUtil.verify(cacheToken, userName, passWord)) {
+//                String newAuthorization = JwtUtil.sign(userName, passWord);
+//                // 设置超时时间
+//                redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
+//                redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME *2 / 1000);
+//                log.debug("——————————用户在线操作,更新token保证不掉线—————————jwtTokenRefresh——————— "+ token);
+//            }
+//            //update-begin--Author:scott  Date:20191005  for:解决每次请求,都重写redis中 token缓存问题
+////			else {
+////				// 设置超时时间
+////				redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
+////				redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
+////			}
+//            //update-end--Author:scott  Date:20191005   for:解决每次请求,都重写redis中 token缓存问题
+//            return true;
+//        }
+//        return false;
+//    }
+
+    /**
+     * 清除当前用户的权限认证缓存
+     *
+     * @param principals 权限信息
+     */
+    @Override
+    public void clearCache(PrincipalCollection principals) {
+        super.clearCache(principals);
+    }
+
+}

+ 76 - 0
gis_admin/src/main/java/com/gis/admin/shiro/filters/CustomShiroFilterFactoryBean.java

@@ -0,0 +1,76 @@
+package com.gis.admin.shiro.filters;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.filter.InvalidRequestFilter;
+import org.apache.shiro.web.filter.mgt.DefaultFilter;
+import org.apache.shiro.web.filter.mgt.FilterChainManager;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+import org.springframework.beans.factory.BeanInitializationException;
+
+import javax.servlet.Filter;
+import java.util.Map;
+
+/**
+ * 自定义ShiroFilterFactoryBean解决资源中文路径问题
+ */
+@Slf4j
+public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean {
+    @Override
+    public Class getObjectType() {
+        return MySpringShiroFilter.class;
+    }
+
+    @Override
+    protected AbstractShiroFilter createInstance() throws Exception {
+
+        SecurityManager securityManager = getSecurityManager();
+        if (securityManager == null) {
+            String msg = "SecurityManager property must be set.";
+            throw new BeanInitializationException(msg);
+        }
+
+        if (!(securityManager instanceof WebSecurityManager)) {
+            String msg = "The security manager does not implement the WebSecurityManager interface.";
+            throw new BeanInitializationException(msg);
+        }
+
+        FilterChainManager manager = createFilterChainManager();
+        //Expose the constructed FilterChainManager by first wrapping it in a
+        // FilterChainResolver implementation. The AbstractShiroFilter implementations
+        // do not know about FilterChainManagers - only resolvers:
+        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
+        chainResolver.setFilterChainManager(manager);
+
+        Map<String, Filter> filterMap = manager.getFilters();
+        Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
+        if (invalidRequestFilter instanceof InvalidRequestFilter) {
+            //此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug
+            ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
+        }
+        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
+        //FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class
+        //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
+        //injection of the SecurityManager and FilterChainResolver:
+        return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
+    }
+
+    private static final class MySpringShiroFilter extends AbstractShiroFilter {
+        protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
+            if (webSecurityManager == null) {
+                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
+            } else {
+                this.setSecurityManager(webSecurityManager);
+                if (resolver != null) {
+                    this.setFilterChainResolver(resolver);
+                }
+
+            }
+        }
+    }
+
+}

+ 149 - 0
gis_admin/src/main/java/com/gis/admin/shiro/filters/JwtFilter.java

@@ -0,0 +1,149 @@
+package com.gis.admin.shiro.filters;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gis.admin.shiro.JwtAuthenticationException;
+import com.gis.admin.shiro.JwtToken;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.time.LocalDateTime;
+
+/**
+ * @Description: 鉴权登录拦截器
+ * @Author: Scott
+ * @Date: 2018/10/7
+ **/
+@Slf4j
+public class JwtFilter extends BasicHttpAuthenticationFilter {
+
+    private boolean allowOrigin = true;
+
+    public JwtFilter(){}
+    public JwtFilter(boolean allowOrigin){
+        this.allowOrigin = allowOrigin;
+    }
+
+    /**
+     * 执行登录认证
+     *
+     * @param request
+     * @param response
+     * @param mappedValue
+     * @return
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+        try {
+            executeLogin(request, response);
+            return true;
+        } catch (Exception e) {
+//            throw new AuthenticationException("Token失效,请重新登录", e);
+            exceptionMsg(e, response);
+
+        }
+        // 前端没有响应,接收不到异常
+        return false;
+    }
+
+    /**
+     *
+     */
+    @Override
+    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        String token = httpServletRequest.getHeader("token");
+        // update-begin--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
+        if(token == null){
+            token = httpServletRequest.getParameter("token");
+        }
+        // update-end--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
+
+        JwtToken jwtToken = new JwtToken(token);
+        // 提交给realm进行登入,如果错误他会抛出异常并被捕获
+        getSubject(request, response).login(jwtToken);
+        // 如果没有抛出异常则代表登入成功,返回true
+        return true;
+    }
+
+    /**
+     * 对跨域提供支持
+     */
+    @Override
+    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+        if(allowOrigin){
+            httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
+            httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
+            httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
+            //update-begin-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题
+            // 是否允许发送Cookie,默认Cookie不包括在CORS请求之中。设为true时,表示服务器允许Cookie包含在请求中。
+            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
+            //update-end-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题
+        }
+        // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态
+        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
+            httpServletResponse.setStatus(HttpStatus.OK.value());
+            return false;
+        }
+        //update-begin-author:taoyan date:20200708 for:多租户用到
+//        String tenant_id = httpServletRequest.getHeader(CommonConstant.TENANT_ID);
+//        TenantContext.setTenant(tenant_id);
+        //update-end-author:taoyan date:20200708 for:多租户用到
+        return super.preHandle(request, response);
+    }
+
+    /**
+     * 封装异常信息
+     */
+    private void exceptionMsg(Exception e, ServletResponse response) {
+        // 认证出现异常,传递错误信息msg
+        String msg = e.getMessage();
+        // 获取应用异常(该Cause是导致抛出此throwable(异常)的throwable(异常))
+        Throwable throwable = e.getCause();
+        JSONObject jsonObject = new JSONObject();
+        if (throwable instanceof JwtAuthenticationException) {
+            jsonObject.put("code", ((JwtAuthenticationException) throwable).getCode());
+            jsonObject.put("msg", ((JwtAuthenticationException) throwable).getMsg());
+        } else {
+            log.error(msg);
+            jsonObject.put("code", 5002);
+            jsonObject.put("msg", "token invalid");
+
+        }
+        jsonObject.put("timestamp", LocalDateTime.now());
+        // 直接返回Response信息
+        this.writeResponse(response, jsonObject);
+
+    }
+
+    /**
+     * 无需转发,直接返回Response信息
+     *
+     */
+    private void writeResponse(ServletResponse response, JSONObject msg) {
+        response.setCharacterEncoding("UTF-8");
+        response.setContentType("application/json; charset=utf-8");
+        ServletOutputStream outputStream = null;
+        try {
+            outputStream = response.getOutputStream();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        assert outputStream != null;
+        PrintWriter printWriter = new PrintWriter(outputStream, true);
+        printWriter.write(msg.toString());//直接将json输出到页面
+        printWriter.flush();
+        printWriter.close();
+
+    }
+}

+ 68 - 0
gis_admin/src/main/java/com/gis/admin/shiro/filters/ResourceCheckFilter.java

@@ -0,0 +1,68 @@
+package com.gis.admin.shiro.filters;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.AccessControlFilter;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @Author Scott
+ * @create 2019-02-01 15:56
+ * @desc 鉴权请求URL访问权限拦截器
+ */
+@Slf4j
+public class ResourceCheckFilter extends AccessControlFilter {
+
+    private String errorUrl;
+
+    public String getErrorUrl() {
+        return errorUrl;
+    }
+
+    public void setErrorUrl(String errorUrl) {
+        this.errorUrl = errorUrl;
+    }
+
+    /**
+     * 表示是否允许访问 ,如果允许访问返回true,否则false;
+     *
+     * @param servletRequest
+     * @param servletResponse
+     * @param o               表示写在拦截器中括号里面的字符串 mappedValue 就是 [urls] 配置中拦截器参数部分
+     * @return
+     * @throws Exception
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
+        Subject subject = getSubject(servletRequest, servletResponse);
+        String url = getPathWithinApplication(servletRequest);
+        log.info("当前用户正在访问的 url => " + url);
+        return subject.isPermitted(url);
+    }
+
+    /**
+     * onAccessDenied:表示当访问拒绝时是否已经处理了; 如果返回 true 表示需要继续处理; 如果返回 false
+     * 表示该拦截器实例已经处理了,将直接返回即可。
+     *
+     * @param servletRequest
+     * @param servletResponse
+     * @return
+     * @throws Exception
+     */
+    @Override
+    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
+        log.info("当 isAccessAllowed 返回 false 的时候,才会执行 method onAccessDenied ");
+
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        response.sendRedirect(request.getContextPath() + this.errorUrl);
+
+        // 返回 false 表示已经处理,例如页面跳转啥的,表示不在走以下的拦截器了(如果还有配置的话)
+        return false;
+    }
+
+}

+ 107 - 0
gis_admin/src/main/java/com/gis/admin/tree/SysResourceTreeUtil.java

@@ -0,0 +1,107 @@
+package com.gis.admin.tree;
+
+import com.gis.admin.entity.po.SysResourceEntity;
+import com.gis.admin.tree.vo.SysResourceTree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SysResourceTreeUtil {
+
+    private List<SysResourceTree> resultNodes = new ArrayList<SysResourceTree>();//树形结构排序之后list内容
+
+    private List<SysResourceTree> nodes = new ArrayList<SysResourceTree>();
+    //传入list参数
+
+    public SysResourceTreeUtil(List<SysResourceEntity> nodesList) {//通过构造函数初始化
+        for (SysResourceEntity n : nodesList) {
+            SysResourceTree treeGrid = new SysResourceTree();
+            treeGrid.setId(n.getId());
+            treeGrid.setName(n.getName());
+//            treeGrid.setIcon(n.getIcon());
+            treeGrid.setUrl(n.getUrl());
+            treeGrid.setResourceKey(n.getResourceKey());
+            treeGrid.setResourceType(n.getResourceType());
+
+            if (n.getAuthority() != null){
+                treeGrid.setAuthority(n.getAuthority());
+            }
+
+            if (n.getParentId() != null) {
+                treeGrid.setParentId(n.getParentId());
+            }
+            nodes.add(treeGrid);
+        }
+    }
+
+    public SysResourceTreeUtil() {
+    }
+
+    /**
+     * 构建树形结构list
+     *
+     * @return 返回树形结构List列表
+     */
+    public List<SysResourceTree> buildTree() {
+        for (SysResourceTree node : nodes) {
+            Long id = node.getParentId();
+            if (id == null) {//通过循环一级节点 就可以通过递归获取二级以下节点
+                resultNodes.add(node);//添加一级节点
+                node.setLevel(1);
+                build(node, node.getLevel());//递归获取二级、三级、。。。节点
+            }
+        }
+        return resultNodes;
+    }
+
+    /**
+     * 递归循环子节点
+     *
+     * @param node 当前节点
+     */
+    private void build(SysResourceTree node, int level) {
+        List<SysResourceTree> children = getChildren(node);
+        if (!children.isEmpty()) {//如果存在子节点
+            node.setChildren(children);
+//        	level++;
+            for (SysResourceTree child : children) {//将子节点遍历加入返回值中
+        		child.setLevel(level);
+                build(child, child.getLevel());
+            }
+        }
+    }
+
+    /**
+     * @param node
+     * @return 返回
+     */
+    private List<SysResourceTree> getChildren(SysResourceTree node) {
+        List<SysResourceTree> children = new ArrayList<SysResourceTree>();
+        Long id = node.getId();
+        for (SysResourceTree child : nodes) {
+            if (id.equals(child.getParentId())) {//如果id等于父id
+                children.add(child);//将该节点加入循环列表中
+            }
+        }
+        return children;
+    }
+
+    public List<SysResourceTree> buildTree(List<SysResourceEntity> all, List<SysResourceEntity> in) {
+        for (SysResourceEntity n : all) {
+            SysResourceTree treeGrid = new SysResourceTree();
+            treeGrid.setId(n.getId());
+            treeGrid.setName(n.getName());
+            for (SysResourceEntity nin : in) {
+                if (nin.getId().equals(n.getId())) {
+                    treeGrid.setChecked(true);
+                }
+            }
+            if (n.getParentId() != null) {
+                treeGrid.setParentId(n.getParentId());
+            }
+            nodes.add(treeGrid);
+        }
+        return buildTree();
+    }
+
+}

+ 51 - 0
gis_admin/src/main/java/com/gis/admin/tree/vo/SysResourceTree.java

@@ -0,0 +1,51 @@
+package com.gis.admin.tree.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SysResourceTree {
+
+    private Long id;
+
+    private String name;
+
+    private Long parentId;
+
+    @JSONField(serialize = false)
+    private boolean checked = false;
+
+    @JSONField(serialize = false)
+    private boolean spread = false;
+
+    @JSONField(serialize = false)
+    private String isHeader = "0";
+
+    @JSONField(serialize = false)
+    private String url;
+
+    @JSONField(serialize = false)
+    private String icon;
+
+    @JSONField(serialize = false)
+    private String resourceKey;
+
+//    @JSONField(serialize = false)
+    private String resourceType;
+
+    @JSONField(serialize = false)
+    private String order = "1";
+
+    // 子菜单/或按钮
+    private List<SysResourceTree> children;
+
+    @JSONField(serialize = false)
+    private int level;
+
+    // 默认都没有权限
+    private boolean authority ;
+
+
+}

+ 191 - 0
gis_admin/src/main/resources/db/sys_admin.sql

@@ -0,0 +1,191 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : 8.135.106.227_项目_sit
+ Source Server Type    : MySQL
+ Source Server Version : 50733
+ Source Host           : 8.135.106.227:3306
+ Source Schema         : sys_admin
+
+ Target Server Type    : MySQL
+ Target Server Version : 50733
+ File Encoding         : 65001
+
+ Date: 07/07/2021 18:19:00
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for sys_resource
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_resource`;
+CREATE TABLE `sys_resource`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
+  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源名称',
+  `resource_type` enum('menu','button') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源类型',
+  `resource_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源key',
+  `sort` int(6) NULL DEFAULT NULL COMMENT '排序',
+  `parent_id` bigint(20) NULL DEFAULT NULL COMMENT '父资源id',
+  `is_delete` int(1) NULL DEFAULT 0 COMMENT '是否删除,0:可用, 1:删除',
+  `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源地址',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源描述',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `FKf5ra2gn0xedeida2op8097sr5`(`parent_id`) USING BTREE,
+  CONSTRAINT `FKf5ra2gn0xedeida2op8097sr5` FOREIGN KEY (`parent_id`) REFERENCES `sys_resource` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB AUTO_INCREMENT = 237 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '资源表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_resource
+-- ----------------------------
+INSERT INTO `sys_resource` VALUES (100, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '史馆场景管理', 'menu', 'scene', 100, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (101, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '查看', 'button', 'scene:detail', 101, 100, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (102, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '编辑', 'button', 'scene:edit', 102, 100, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (103, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '删除', 'button', 'scene:remove', 103, 100, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (200, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '精品典藏管理', 'menu', 'goods', 200, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (210, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '模型管理', 'menu', 'goods:model', 210, 200, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (211, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '提交', 'button', 'goods:model:edit', 211, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (212, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '编辑', 'button', 'goods:model:edit', 212, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (213, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '删除', 'button', 'goods:model:remove', 213, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (214, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '审核', 'button', 'goods:model:audit', 214, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (215, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '查看', 'button', 'goods:model:detail', 215, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (216, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '是否显示', 'button', 'goods:model:display', 216, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (220, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '视频管理', 'menu', 'goods:video', 220, 200, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (221, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '提交', 'button', 'goods:video:edit', 221, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (222, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '编辑', 'button', 'goods:video:edit', 222, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (223, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '删除', 'button', 'goods:video:remove', 223, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (224, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '审核', 'button', 'goods:video:audit', 224, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (225, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '查看', 'button', 'goods:video:detail', 225, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (226, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '是否显示', 'button', 'goods:video:display', 226, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (230, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '图片管理', 'menu', 'goods:img', 230, 200, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (231, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '提交', 'button', 'goods:img:edit', 231, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (232, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '编辑', 'button', 'goods:img:edit', 232, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (233, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '删除', 'button', 'goods:img:remove', 233, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (234, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '审核', 'button', 'goods:img:audit', 234, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (235, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '查看', 'button', 'goods:img:detail', 235, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (236, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '是否显示', 'button', 'goods:img:display', 236, 230, 0, NULL, NULL);
+
+-- ----------------------------
+-- Table structure for sys_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role`;
+CREATE TABLE `sys_role`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
+  `role_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色描述',
+  `role_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色名',
+  `role_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '角色key,0:未定义角色(默认值)',
+  `sort` int(3) NULL DEFAULT NULL COMMENT '排序',
+  `is_delete` int(1) NULL DEFAULT 0 COMMENT '是否删除,0:可用, 1:删除',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_role
+-- ----------------------------
+INSERT INTO `sys_role` VALUES (1, '2021-06-28 17:31:38', '2021-06-28 17:31:38', '拥有所有权限', '超级管理员', 'sys_admin', 1, 0);
+INSERT INTO `sys_role` VALUES (20, '2021-06-29 10:52:00', '2021-06-29 10:52:00', '测试权限', '测试角色1-admin', '0', NULL, 0);
+
+-- ----------------------------
+-- Table structure for sys_role_resource
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role_resource`;
+CREATE TABLE `sys_role_resource`  (
+  `role_id` bigint(20) NOT NULL COMMENT '角色表id',
+  `resource_id` bigint(20) NOT NULL COMMENT '资源表id',
+  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`role_id`, `resource_id`) USING BTREE,
+  INDEX `FK868kc8iic48ilv5npa80ut6qo`(`resource_id`) USING BTREE,
+  CONSTRAINT `sys_role_resource_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `sys_role_resource_ibfk_2` FOREIGN KEY (`resource_id`) REFERENCES `sys_resource` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色资源关系表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_role_resource
+-- ----------------------------
+INSERT INTO `sys_role_resource` VALUES (20, 101, '2021-07-06 16:07:08');
+INSERT INTO `sys_role_resource` VALUES (20, 102, '2021-07-06 16:07:15');
+INSERT INTO `sys_role_resource` VALUES (20, 103, '2021-07-06 16:07:22');
+
+-- ----------------------------
+-- Table structure for sys_user
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user`;
+CREATE TABLE `sys_user`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `is_delete` int(1) NULL DEFAULT 0 COMMENT '状态,0:激活,1:禁用',
+  `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
+  `real_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
+  `user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号,用户号',
+  `nick_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',
+  `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱',
+  `sex` tinyint(4) NULL DEFAULT NULL COMMENT '性别, 0:男, 1:女',
+  `status` int(11) NULL DEFAULT NULL COMMENT '状态 0:启用  1:停用',
+  `view_count` int(11) NULL DEFAULT 0 COMMENT '登录次数',
+  `phone` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',
+  `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录密码',
+  `role` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色,sys_admin:系统管理员,sys_high:高级管理员, sys_normal, sys_visitor:游客',
+  `thumb` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '缩略图url',
+  `unit` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '单位',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_user
+-- ----------------------------
+INSERT INTO `sys_user` VALUES (1, '2020-04-13 08:57:41', 0, '2021-06-04 14:44:50', '超级管理员', 'admin', '系统管理员', '38@qq.com', 0, 1, 0, '15012345678', 'c44b01947c9e6e3f', 'sys_admin', '/data/media/thumb_20210416_083830938.jpg', '洪兴');
+INSERT INTO `sys_user` VALUES (2, '2021-05-19 10:44:59', 0, '2021-05-19 10:44:59', '', 'admin2', '', NULL, 0, 1, 0, '', '9ad4418857d43064', 'sys_admin', '', NULL);
+INSERT INTO `sys_user` VALUES (3, '2021-05-20 10:03:01', 0, '2021-06-11 12:00:43', '', 'owen', 'owen', NULL, 0, 1, 0, '', '57eaf7d9dde69c9b', 'sys_admin', '', NULL);
+INSERT INTO `sys_user` VALUES (4, '2021-06-11 11:48:14', 1, '2021-06-11 12:05:40', NULL, '测试普通用户账号001', '测试普通用户账号001', NULL, NULL, 0, 0, '13800138000', '13f0d6d25a83f9ad0063eed5567ff6faf1dd46cdcb61666a54ade1af4f3254bb', 'sys_normal', '', NULL);
+INSERT INTO `sys_user` VALUES (5, '2021-06-11 11:56:11', 0, '2021-06-11 12:00:20', NULL, 'testAdmin', 'testAdmin', NULL, NULL, 1, 0, '13800138000', '4a9776bceff9c1bb82c584e3a825c2ca', 'sys_admin', '', NULL);
+INSERT INTO `sys_user` VALUES (6, '2021-06-11 12:06:20', 0, '2021-06-11 12:06:20', NULL, 'user', 'user', NULL, NULL, 1, 0, '13800138000', '4a4858a9a6266662', 'sys_normal', '', NULL);
+
+-- ----------------------------
+-- Table structure for sys_user_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user_role`;
+CREATE TABLE `sys_user_role`  (
+  `user_id` bigint(20) NOT NULL COMMENT '用户表id',
+  `role_id` bigint(20) NOT NULL COMMENT '角色表id',
+  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  PRIMARY KEY (`user_id`, `role_id`) USING BTREE,
+  INDEX `role_id`(`role_id`) USING BTREE,
+  CONSTRAINT `sys_user_role_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `sys_user_role_ibfk_3` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户角色关系表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of sys_user_role
+-- ----------------------------
+INSERT INTO `sys_user_role` VALUES (1, 1, '2021-06-29 11:32:05');
+INSERT INTO `sys_user_role` VALUES (3, 20, '2021-07-06 16:06:40');
+
+-- ----------------------------
+-- Table structure for tb_log
+-- ----------------------------
+DROP TABLE IF EXISTS `tb_log`;
+CREATE TABLE `tb_log`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
+  `user_id` bigint(50) NULL DEFAULT NULL COMMENT '用户id',
+  `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作类型',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作详情',
+  `is_delete` int(1) NULL DEFAULT 0,
+  `ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ip地址',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 502 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of tb_log
+-- ----------------------------
+INSERT INTO `tb_log` VALUES (462, '2021-06-23 16:49:50', '2021-06-23 16:49:50', 1, '精品典藏', '新增/修改', 0, '127.0.0.1');
+INSERT INTO `tb_log` VALUES (463, '2021-06-23 16:50:43', '2021-06-23 16:50:43', 1, '精品典藏', '新增/修改', 0, '127.0.0.1');
+INSERT INTO `tb_log` VALUES (464, '2021-06-23 16:52:48', '2021-06-23 16:52:48', 1, '精品典藏', '新增/修改', 0, '127.0.0.1');
+INSERT INTO `tb_log` VALUES (465, '2021-06-23 16:58:20', '2021-06-23 16:58:20', 1, '精品典藏', '图片置顶', 0, '127.0.0.1');
+INSERT INTO `tb_log` VALUES (466, '2021-06-24 09:55:59', '2021-06-24 09:55:59', 1, '烈士管理', '新增/修改', 0, '127.0.0.1');

+ 27 - 0
gis_admin/src/main/resources/db/资源表.csv

@@ -0,0 +1,27 @@
+id,name,resource_type,resource_key,sort,parent_id
+100,史馆场景管理,menu,scene,100,
+101,查看,button,scene:detail,101,100
+102,编辑,button,scene:edit,102,100
+103,删除,button,scene:remove,103,100
+200,精品典藏管理,menu,goods,200,
+210,模型管理,menu,goods:model,210,200
+211,提交,button,goods:model:edit,211,210
+212,编辑,button,goods:model:edit,212,210
+213,删除,button,goods:model:remove,213,210
+214,审核,button,goods:model:audit,214,210
+215,查看,button,goods:model:detail,215,210
+216,是否显示,button,goods:model:display,216,210
+220,视频管理,menu,goods:video,220,200
+221,提交,button,goods:video:edit,221,220
+222,编辑,button,goods:video:edit,222,220
+223,删除,button,goods:video:remove,223,220
+224,审核,button,goods:video:audit,224,220
+225,查看,button,goods:video:detail,225,220
+226,是否显示,button,goods:video:display,226,220
+230,图片管理,menu,goods:img,230,200
+231,提交,button,goods:img:edit,231,230
+232,编辑,button,goods:img:edit,232,230
+233,删除,button,goods:img:remove,233,230
+234,审核,button,goods:img:audit,234,230
+235,查看,button,goods:img:detail,235,230
+236,是否显示,button,goods:img:display,236,230

+ 41 - 0
gis_application/pom.xml

@@ -0,0 +1,41 @@
+<?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>army_beijing_fourteen</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gis_application</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_admin</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_scene</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_cms</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+        <finalName>${parent.artifactId}</finalName>
+    </build>
+</project>

+ 14 - 0
gis_application/src/main/java/com/gis/GisApplication.java

@@ -0,0 +1,14 @@
+package com.gis;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+
+@SpringBootApplication
+public class GisApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(GisApplication.class, args);
+    }
+
+}

+ 73 - 0
gis_application/src/main/resources/application-dev.properties

@@ -0,0 +1,73 @@
+
+#DB
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.druid.username=root
+spring.datasource.druid.url=jdbc:mysql://8.135.106.227:3306/${project.en}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.druid.password=4dkk2021testproject%
+
+
+# \u521D\u59CB\u8FDE\u63A5\u6570
+spring.datasource.druid.initial-size=5
+# \u6700\u5C0F\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.min-idle=10
+# \u6700\u5927\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.max-active=20
+# \u914D\u7F6E\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u7684\u65F6\u95F4
+spring.datasource.druid.max-wait=60000
+# \u914D\u7F6E\u95F4\u9694\u591A\u4E45\u624D\u8FDB\u884C\u4E00\u6B21\u68C0\u6D4B\uFF0C\u68C0\u6D4B\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.time-between-eviction-runs-millis=60000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5C0F\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.min-evictable-idle-time-millis=30000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5927\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.max-evictable-idle-time-millis=90000
+# \u914D\u7F6E\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548
+spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
+spring.datasource.druid.test-while-idle=true
+spring.datasource.druid.test-on-borrow=false
+spring.datasource.druid.test-on-return=false
+spring.datasource.druid.web-stat-filter.enabled=true
+spring.datasource.druid.stat-view-servlet.enabled=true
+
+
+# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=0
+spring.redis.host=127.0.0.1
+spring.redis.port=6379
+spring.redis.password=
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D ms\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=3000ms
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F8\u3002
+spring.redis.jedis.pool.max-idle=8
+#\u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F0\u3002
+spring.redis.jedis.pool.min-idle=0
+# \u5982\u679C\u8D4B\u503C\u4E3A-1\uFF0C\u5219\u8868\u793A\u4E0D\u9650\u5236\uFF1B\u5982\u679Cpool\u5DF2\u7ECF\u5206\u914D\u4E86maxActive\u4E2Ajedis\u5B9E\u4F8B\uFF0C\u5219\u6B64\u65F6pool\u7684\u72B6\u6001\u4E3Aexhausted(\u8017\u5C3D)\u3002
+spring.redis.jedis.pool.max-active=8
+# \u7B49\u5F85\u53EF\u7528\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u95F4\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF0C\u9ED8\u8BA4\u503C\u4E3A-1\uFF0C\u8868\u793A\u6C38\u4E0D\u8D85\u65F6\u3002\u5982\u679C\u8D85\u8FC7\u7B49\u5F85\u65F6\u95F4\uFF0C\u5219\u76F4\u63A5\u629B\u51FAJedisConnectionException
+spring.redis.jedis.pool.max-wait=-1ms
+
+
+#log
+logging.file.path=E:/log/${project.en}_log
+logging.config=classpath:logback-spring.xml
+logging.level.com.gis=debug
+
+# file info
+server.file.path=E:\\data\\${project.en}_data
+
+#
+spring.mvc.static-path-pattern=/**
+### \u5339\u914D\u8DEF\u5F84\uFF0C \u6CE8\u610Ffile\u540E\u9762\u7684/ \uFF0Cwindows:\\  , linxu:\u5168\u8DEF\u5F84, \u4E0D\u9700\u8981\u7279\u522B\u52A0\u659C\u6760
+spring.resources.static-locations=file:\\${server.file.path}
+
+# swagger2 \u8BBE\u7F6E\u5168\u5C40\u5B57\u4F53\u683C\u5F0F\u4E3Autf-8
+swagger.package=com.gis
+swagger.title=${project.sc}-dev
+swagger.description=${swagger.title}
+swagger.version=1.0
+
+
+
+
+
+

+ 77 - 0
gis_application/src/main/resources/application-pro.properties

@@ -0,0 +1,77 @@
+
+#DB
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.druid.username=root
+spring.datasource.druid.url=jdbc:mysql://localhost:3306/${project.en}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
+spring.datasource.druid.password=4dkk2021testproject%
+
+
+# \u521D\u59CB\u8FDE\u63A5\u6570
+spring.datasource.druid.initial-size=5
+# \u6700\u5C0F\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.min-idle=10
+# \u6700\u5927\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.max-active=20
+# \u914D\u7F6E\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u7684\u65F6\u95F4
+spring.datasource.druid.max-wait=60000
+# \u914D\u7F6E\u95F4\u9694\u591A\u4E45\u624D\u8FDB\u884C\u4E00\u6B21\u68C0\u6D4B\uFF0C\u68C0\u6D4B\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.time-between-eviction-runs-millis=60000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5C0F\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.min-evictable-idle-time-millis=30000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5927\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.max-evictable-idle-time-millis=90000
+# \u914D\u7F6E\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548
+spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
+spring.datasource.druid.test-while-idle=true
+spring.datasource.druid.test-on-borrow=false
+spring.datasource.druid.test-on-return=false
+spring.datasource.druid.web-stat-filter.enabled=true
+spring.datasource.druid.stat-view-servlet.enabled=true
+
+
+# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=0
+spring.redis.host=127.0.0.1
+spring.redis.port=6379
+spring.redis.password=4dkk2021testproject%
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D ms\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=3000ms
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F8\u3002
+spring.redis.jedis.pool.max-idle=8
+#\u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F0\u3002
+spring.redis.jedis.pool.min-idle=0
+# \u5982\u679C\u8D4B\u503C\u4E3A-1\uFF0C\u5219\u8868\u793A\u4E0D\u9650\u5236\uFF1B\u5982\u679Cpool\u5DF2\u7ECF\u5206\u914D\u4E86maxActive\u4E2Ajedis\u5B9E\u4F8B\uFF0C\u5219\u6B64\u65F6pool\u7684\u72B6\u6001\u4E3Aexhausted(\u8017\u5C3D)\u3002
+spring.redis.jedis.pool.max-active=8
+# \u7B49\u5F85\u53EF\u7528\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u95F4\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF0C\u9ED8\u8BA4\u503C\u4E3A-1\uFF0C\u8868\u793A\u6C38\u4E0D\u8D85\u65F6\u3002\u5982\u679C\u8D85\u8FC7\u7B49\u5F85\u65F6\u95F4\uFF0C\u5219\u76F4\u63A5\u629B\u51FAJedisConnectionException
+spring.redis.jedis.pool.max-wait=-1ms
+
+
+#log
+logging.file.path=/home/dell/user/log/${project.en}_log
+logging.config=classpath:logback-spring.xml
+logging.level.com.gis=debug
+
+# file info
+server.file.path=/home/dell/user/data/${project.en}_data
+#server.file.path=/home/wyu/user/data/army_beijing_hospital_data
+
+#
+spring.mvc.static-path-pattern=/**
+### \u5339\u914D\u8DEF\u5F84\uFF0C \u6CE8\u610Ffile\u540E\u9762\u7684/ \uFF0Cwindows:\\  , linxu:\u5168\u8DEF\u5F84, \u4E0D\u9700\u8981\u7279\u522B\u52A0\u659C\u6760
+spring.resources.static-locations=file:${server.file.path}
+
+# swagger2 \u8BBE\u7F6E\u5168\u5C40\u5B57\u4F53\u683C\u5F0F\u4E3Autf-8
+swagger.package=com.gis
+swagger.title=${project.sc}-pro
+swagger.description=${swagger.title}
+swagger.version=1.0
+
+#swagger login
+knife4j.basic.enable=true
+knife4j.basic.username=owen
+knife4j.basic.password=owen
+
+
+
+

+ 76 - 0
gis_application/src/main/resources/application-sit.properties

@@ -0,0 +1,76 @@
+
+#DB
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.druid.username=root
+spring.datasource.druid.url=jdbc:mysql://8.135.106.227:3306/${project.en}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
+spring.datasource.druid.password=4dkk2021testproject%
+
+
+# \u521D\u59CB\u8FDE\u63A5\u6570
+spring.datasource.druid.initial-size=5
+# \u6700\u5C0F\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.min-idle=10
+# \u6700\u5927\u8FDE\u63A5\u6C60\u6570\u91CF
+spring.datasource.druid.max-active=20
+# \u914D\u7F6E\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u7684\u65F6\u95F4
+spring.datasource.druid.max-wait=60000
+# \u914D\u7F6E\u95F4\u9694\u591A\u4E45\u624D\u8FDB\u884C\u4E00\u6B21\u68C0\u6D4B\uFF0C\u68C0\u6D4B\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.time-between-eviction-runs-millis=60000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5C0F\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.min-evictable-idle-time-millis=30000
+# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5927\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2
+spring.datasource.druid.max-evictable-idle-time-millis=90000
+# \u914D\u7F6E\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548
+spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
+spring.datasource.druid.test-while-idle=true
+spring.datasource.druid.test-on-borrow=false
+spring.datasource.druid.test-on-return=false
+spring.datasource.druid.web-stat-filter.enabled=true
+spring.datasource.druid.stat-view-servlet.enabled=true
+
+
+# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
+spring.redis.database=0
+spring.redis.host=127.0.0.1
+spring.redis.port=6379
+spring.redis.password=
+# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D ms\uFF08\u6BEB\u79D2\uFF09
+spring.redis.timeout=3000ms
+# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F8\u3002
+spring.redis.jedis.pool.max-idle=8
+#\u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u9ED8\u8BA4\u503C\u4E5F\u662F0\u3002
+spring.redis.jedis.pool.min-idle=0
+# \u5982\u679C\u8D4B\u503C\u4E3A-1\uFF0C\u5219\u8868\u793A\u4E0D\u9650\u5236\uFF1B\u5982\u679Cpool\u5DF2\u7ECF\u5206\u914D\u4E86maxActive\u4E2Ajedis\u5B9E\u4F8B\uFF0C\u5219\u6B64\u65F6pool\u7684\u72B6\u6001\u4E3Aexhausted(\u8017\u5C3D)\u3002
+spring.redis.jedis.pool.max-active=8
+# \u7B49\u5F85\u53EF\u7528\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u95F4\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF0C\u9ED8\u8BA4\u503C\u4E3A-1\uFF0C\u8868\u793A\u6C38\u4E0D\u8D85\u65F6\u3002\u5982\u679C\u8D85\u8FC7\u7B49\u5F85\u65F6\u95F4\uFF0C\u5219\u76F4\u63A5\u629B\u51FAJedisConnectionException
+spring.redis.jedis.pool.max-wait=-1ms
+
+
+#log
+logging.file.path=D:/log/${project.en}_log
+logging.config=classpath:logback-spring.xml
+logging.level.com.gis=debug
+
+# file info
+server.file.path=D:\\data\\${project.en}_data
+
+# url info
+#server.url.prefix=/data/
+#spring.mvc.static-path-pattern=/${server.url.prefix}/**
+#
+spring.mvc.static-path-pattern=/**
+### \u5339\u914D\u8DEF\u5F84\uFF0C \u6CE8\u610Ffile\u540E\u9762\u7684/ \uFF0Cwindows:\\  , linxu:\u5168\u8DEF\u5F84, \u4E0D\u9700\u8981\u7279\u522B\u52A0\u659C\u6760
+spring.resources.static-locations=file:\\${server.file.path}
+
+# swagger2 \u8BBE\u7F6E\u5168\u5C40\u5B57\u4F53\u683C\u5F0F\u4E3Autf-8
+swagger.package=com.gis
+swagger.title=${project.sc}-sit
+swagger.description=${swagger.title}
+swagger.version=1.0
+
+
+
+
+
+

+ 46 - 0
gis_application/src/main/resources/application.properties

@@ -0,0 +1,46 @@
+server.port=8007
+
+spring.profiles.active=dev
+
+# \u9879\u76EE\u540D\u79F0
+project.en=army_beijing_fourteen
+project.sc=\u5317\u4EAC\u6B66\u8B66\u7B2C\u5341\u56DB\u652F\u961F-\u519B\u53F2\u9986
+# redis token \u524D\u7F00
+redis.prefix=${project.en}_token_
+
+# \u5141\u8BB8\u4E0A\u4F20\u6587\u4EF6\u540E\u7F00
+server.file.allow=.jpg,.gif,.png,.ico,.bmp,.jpeg,.zip,.zp,.rar,.mp3,.mp4,.avi,.mov,.flv,.3gp,.rmvb,.4dage,.wav,.wma,.m4a,.obj,.pdf,.audio,.ppt,.pptx,.xls,.doc,.docx,.txt
+
+
+
+# \u8BBF\u95EE\u9759\u6001\u8D44\u6E90\u8BBE\u7F6E
+spring.resources.static-locations=classpath:templates/,classpath:static/,classpath:web/
+
+#\u4E0A\u4F20\u6587\u4EF6\u5927\u5C0F
+spring.servlet.multipart.enabled=true
+spring.servlet.multipart.max-file-size=2048MB
+spring.servlet.multipart.max-request-size=2048MB
+
+
+
+#\u914D\u7F6E\u81EA\u52A8\u8BC6\u522B\u5B57\u6BB5\u8F6C\u6362
+mybatis.configuration.mapUnderscoreToCamelCase=true
+mapper.identity=MYSQL
+mapper.mappers=tk.mybatis.mapper.common.Mapper
+#pager
+pagehelper.helper-dialect=mysql
+pagehelper.params=count=countSql
+pagehelper.reasonable=false
+pagehelper.support-methods-arguments=true
+
+
+
+
+
+
+
+
+
+
+
+

+ 102 - 0
gis_application/src/main/resources/db/sys_resource.sql

@@ -0,0 +1,102 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : 8.135.106.227_项目_sit
+ Source Server Type    : MySQL
+ Source Server Version : 50733
+ Source Host           : 8.135.106.227:3306
+ Source Schema         : army_beijing_hospital
+
+ Target Server Type    : MySQL
+ Target Server Version : 50733
+ File Encoding         : 65001
+
+ Date: 22/02/2022 17:49:03
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for sys_resource
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_resource`;
+CREATE TABLE `sys_resource`  (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
+  `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '更新时间',
+  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源名称',
+  `resource_type` enum('menu','button') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源类型',
+  `resource_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源key',
+  `sort` int(6) NULL DEFAULT NULL COMMENT '排序',
+  `parent_id` bigint(20) NULL DEFAULT NULL COMMENT '父资源id',
+  `is_delete` int(1) NULL DEFAULT 0 COMMENT '是否删除,0:可用, 1:删除',
+  `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源地址',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '资源描述',
+  PRIMARY KEY (`id`) USING BTREE,
+  INDEX `FKf5ra2gn0xedeida2op8097sr5`(`parent_id`) USING BTREE,
+  CONSTRAINT `FKf5ra2gn0xedeida2op8097sr5` FOREIGN KEY (`parent_id`) REFERENCES `sys_resource` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB AUTO_INCREMENT = 812 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '资源表' ROW_FORMAT = DYNAMIC;
+
+-- ----------------------------
+-- Records of sys_resource
+-- ----------------------------
+INSERT INTO `sys_resource` VALUES (100, '2021-07-21 10:05:26', '2021-07-21 10:05:26', '史馆场景管理', 'menu', 'scene', 100, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (101, '2021-07-21 10:05:26', '2021-07-21 10:05:26', '查看', 'button', 'scene:detail', 101, 100, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (102, '2021-07-21 10:05:26', '2021-07-21 10:05:26', '编辑', 'button', 'scene:edit', 102, 100, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (103, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '删除', 'button', 'scene:remove', 103, 100, 1, NULL, NULL);
+
+INSERT INTO `sys_resource` VALUES (200, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '精品典藏管理', 'menu', 'goods', 200, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (210, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '模型管理', 'menu', 'goods:model', 210, 200, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (212, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '编辑', 'button', 'goods:edit', 212, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (213, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '删除', 'button', 'good:remove', 213, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (215, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '查看', 'button', 'goods:detail', 215, 210, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (216, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '是否显示', 'button', 'goods:display', 216, 210, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (217, '2021-08-19 21:48:01', '2021-08-19 21:48:01', '新增', 'button', 'goods:edit', 217, 210, 0, NULL, NULL);
+
+INSERT INTO `sys_resource` VALUES (220, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '视频管理', 'menu', 'goods:video', 220, 200, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (222, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '编辑', 'button', 'goods:edit', 222, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (223, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '删除', 'button', 'goods:remove', 223, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (225, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '查看', 'button', 'goods:detail', 225, 220, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (226, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '是否显示', 'button', 'goods:display', 226, 220, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (227, '2021-08-19 21:50:48', '2021-08-19 21:50:48', '新增', 'button', 'goods:edit', 227, 220, 0, NULL, NULL);
+
+INSERT INTO `sys_resource` VALUES (230, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '图片管理', 'menu', 'goods:img', 230, 200, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (231, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '提交', 'button', 'goods:edit', 231, 230, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (232, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '编辑', 'button', 'goods:edit', 232, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (233, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '删除', 'button', 'goods:remove', 233, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (235, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '查看', 'button', 'goods:detail', 235, 230, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (236, '2021-07-21 10:05:27', '2021-07-21 10:05:27', '是否显示', 'button', 'goods:display', 236, 230, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (237, '2021-08-19 21:51:17', '2021-08-19 21:51:17', '新增', 'button', 'goods:edit', 237, 230, 0, NULL, NULL);
+
+
+
+INSERT INTO `sys_resource` VALUES (500, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '互动模块管理', 'menu', 'comment&barrage', 500, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (510, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '留言管理', 'menu', 'comment', 510, 500, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (511, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '删除', 'button', 'comment:remove', 511, 510, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (512, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '查看', 'button', 'comment:detail', 512, 510, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (513, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '是否显示', 'button', 'comment:display', 513, 510, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (518, '2022-02-22 17:46:41', '2022-02-22 17:46:41', '导出', 'button', 'comment:export', NULL, 510, 1, NULL, NULL);
+
+INSERT INTO `sys_resource` VALUES (520, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '弹幕管理', 'menu', 'barrage', 520, 500, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (521, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '删除', 'button', 'barrage:remove', 521, 520, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (522, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '查看', 'button', 'barrage:detail', 522, 520, 1, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (523, '2021-07-21 10:05:28', '2021-07-21 10:05:28', '是否显示', 'button', 'barrage:display', 523, 520, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (528, '2022-02-22 17:47:07', '2022-02-22 17:47:07', '导出', 'button', 'barrage:export', NULL, 528, 1, NULL, NULL);
+
+
+INSERT INTO `sys_resource` VALUES (600, '2021-08-26 19:29:41', '2021-08-26 19:29:41', '用户管理', 'menu', 'sys:user', 600, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (610, '2021-08-26 19:30:48', '2021-08-26 19:30:48', '新增', 'button', 'sys:user:edit', 610, 600, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (611, '2021-08-26 19:31:28', '2021-08-26 19:31:28', '编辑', 'button', 'sys:user:edit', 611, 600, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (612, '2021-08-26 19:32:51', '2021-08-26 19:32:51', '是否启用', 'button', 'sys:user:display', 612, 600, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (613, '2021-08-26 19:33:32', '2021-08-26 19:33:32', '删除', 'button', 'sys:user:remove', 613, 600, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (700, '2021-08-26 19:34:24', '2021-08-26 19:34:24', '角色权限管理', 'menu', 'sys:role', 700, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (710, '2021-08-26 19:35:00', '2021-08-26 19:35:00', '新增', 'button', 'sys:role:edit', 710, 700, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (711, '2021-08-26 19:35:29', '2021-08-26 19:35:29', '编辑', 'button', 'sys:role:edit', 711, 700, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (712, '2021-08-26 19:36:07', '2021-08-26 19:36:07', '是否启用', 'button', 'sys:role:display', 712, 700, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (713, '2021-08-26 19:36:36', '2021-08-26 19:36:36', '删除', 'button', 'sys:role:remove', 713, 700, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (714, '2021-08-26 19:38:03', '2021-08-26 19:38:03', '权限设置', 'button', 'sys:role:auth', 714, 700, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (800, '2021-08-26 19:38:40', '2021-08-26 19:38:40', '操作日志', 'menu', 'sys:log', 800, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (811, '2022-01-18 09:46:29', '2022-01-18 09:46:29', '查看', 'button', 'sys:log:view', NULL, 800, 0, NULL, NULL);
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 156 - 0
gis_application/src/main/resources/logback-spring.xml

@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <property name="LOG_MAX_HISTORY" value="180"/>
+    <springProperty scope="context" name="LOG_PATH" source="logging.path"/>
+
+    <!-- 控制台输出 -->
+    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
+            <pattern>${LOG_PATH}/%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} %-5level %logger{50} - %msg%n</pattern>
+            <!--<charset>utf-8</charset>-->
+        </encoder>
+    </appender>
+    <!-- 按照每天生成日志文件:主项目日志 -->
+    <appender name="file.all" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 追加日志到原文件结尾 -->
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 -->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} %-5level %logger{500} - %msg%n</pattern>
+            <!--<charset>utf-8</charset>-->
+        </encoder>
+    </appender>
+
+    <!--info日志统一输出到这里-->
+    <appender name="file.info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 每小时生成日志文件 -->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/info/console-info.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <!--<charset>utf-8</charset>-->
+        </encoder>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!--错误日志统一输出到这里-->
+    <appender name="file.error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/error/console-error.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <!--<charset>utf-8</charset>-->
+        </encoder>
+        <!-- 此日志文件只记录error级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!--warn日志统一输出到这里-->
+    <appender name="file.warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 按小时生成日志-->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/warn/console-warn.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, -->
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <!--<charset>utf-8</charset>-->
+        </encoder>
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>WARN</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!--debug级别日志统一输出到这里-->
+    <appender name="file.debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <Prudent>true</Prudent>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--日志文件输出的文件名 按小时生成日志-->
+            <FileNamePattern>${LOG_PATH}/%d{yyyy-MM-dd}/debug/console-debug.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
+            <!-- 除按日志记录之外,还配置了日志文件不能超过5M,若超过5M,日志文件会以索引0开始,命名日志文件,例如console-debug.2018-08-24-09.1.log -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>10MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %method 方法名  %L 行数 %msg:日志消息,%n是换行符-->
+            <pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %X{TRACE_ID} %-5level %logger{56}.%method:%L - %msg%n</pattern>
+            <!--<charset>utf-8</charset>-->
+        </encoder>
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>DEBUG</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY </onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
+    <appender name="file.async" class="ch.qos.logback.classic.AsyncAppender">
+        <discardingThreshold>0</discardingThreshold>
+        <queueSize>256</queueSize>
+        <includeCallerData>true</includeCallerData>
+        <appender-ref ref="file.all" />
+    </appender>
+
+    <!--  日志输出级别 -->
+    <!-- TRACE\DEBUG\INFO\WARN\ERROR\FATAL\OFF -->
+    <root level="INFO">
+        <appender-ref ref="console" />
+        <appender-ref ref="file.async"/>
+        <appender-ref ref="file.error" />
+        <appender-ref ref="file.info" />
+        <appender-ref ref="file.debug" />
+        <appender-ref ref="file.warn" />
+    </root>
+
+</configuration>

+ 11 - 0
gis_application/src/main/resources/sh/shutdown.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+RESOURCE_NAME=army_beijing_hospital.jar
+   Pid=`awk '{print $1}' tpid`
+
+if [ ${Pid} ]; then
+kill -9 $Pid
+echo 'Kill Process!'
+else
+echo 'Stop failed!'
+fi
+

+ 11 - 0
gis_application/src/main/resources/sh/startup.sh

@@ -0,0 +1,11 @@
+#!/bin/sh
+RESOURCE_NAME=army_beijing_hospital.jar
+APP_DEBUG=5005
+rm -f tpid
+nohup java -jar -Xmx3072M -Xms512M ./$RESOURCE_NAME --spring.profiles.active=sit --server.port=8014 & echo $! > tpid
+echo Start Success!
+
+
+
+
+

+ 26 - 0
gis_cms/pom.xml

@@ -0,0 +1,26 @@
+<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/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>army_beijing_fourteen</artifactId>
+        <groupId>com.gis</groupId>
+        <version>1.0.0</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>gis_cms</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.gis</groupId>
+            <artifactId>gis_admin</artifactId>
+        </dependency>
+
+    </dependencies>
+
+
+
+
+
+</project>

+ 81 - 0
gis_cms/src/main/java/com/gis/cms/controller/BarrageController.java

@@ -0,0 +1,81 @@
+package com.gis.cms.controller;
+
+import com.gis.cms.entity.dto.BarrageDto;
+import com.gis.cms.entity.po.BarrageEntity;
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.DateDto;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.util.Result;
+import com.gis.cms.service.BarrageService;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * Created by owen on 2020/5/8 0008 9:54
+ */
+@Slf4j
+@Api(tags = "v0.1-弹幕管理")
+@RestController
+@RequestMapping("cms/barrage")
+public class BarrageController  {
+
+    @Autowired
+    private BarrageService entityService;
+
+    @WebControllerLog(description = "弹幕管理-导出Excel", addDb = true)
+    @ApiOperation("v0.1-导出Excel")
+    @PostMapping("exportExcel")
+    public Result exportExcel(@RequestBody DateDto param) {
+        return entityService.exportExcel(param);
+    }
+
+
+    @ApiOperation("列表")
+    @PostMapping("list")
+    public Result<PageInfo<BarrageEntity>> list(@RequestBody PageDateDto param) {
+        return entityService.search(param, null);
+    }
+
+    @WebControllerLog(description = "弹幕管理-新增留言", addDb = true)
+    @ApiOperation("新增留言")
+    @PostMapping("save")
+    public Result save(@Valid @RequestBody BarrageDto param) {
+        return entityService.saveEntity(param);
+    }
+
+
+    @WebControllerLog(description = "弹幕管理-删除", addDb = true)
+    @ApiOperation("删除")
+    @GetMapping("remove/{id}")
+    public Result remove(@PathVariable Long id) {
+        return entityService.remove(id);
+    }
+
+    @WebControllerLog(description = "弹幕管理-是否显示", addDb = true)
+    @ApiOperation("是否显示")
+    @GetMapping("display/{id}/{display}")
+    public Result display(@PathVariable Long id, @PathVariable Integer display) {
+        BarrageEntity entity = entityService.findById(id);
+        if (entity == null) {
+            log.error("对象id不存在 : {}", id);
+            return Result.failure("对象id不存在");
+        }
+        entity.setDisplay(display);
+        entityService.update(entity);
+        return Result.success();
+    }
+
+
+    @ApiOperation("详情")
+    @GetMapping("detail/{id}")
+    public Result<BarrageEntity> detail(@PathVariable Long id) {
+        return entityService.detail(id);
+    }
+
+}

+ 90 - 0
gis_cms/src/main/java/com/gis/cms/controller/CommentController.java

@@ -0,0 +1,90 @@
+package com.gis.cms.controller;
+
+import com.gis.cms.entity.po.CommentEntity;
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.DateDto;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.util.Result;
+import com.gis.cms.entity.dto.CommentDto;
+import com.gis.cms.entity.vo.CommentVo;
+import com.gis.cms.service.CommentService;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * Created by owen on 2020/5/8 0008 9:54
+ */
+@Slf4j
+@Api(tags = "v0.1-留言管理")
+@RestController
+@RequestMapping("cms/comment")
+public class CommentController  {
+
+    @Autowired
+    private CommentService entityService;
+
+
+//    @RequiresRoles(value = {"sys_admin", "sys_high"}, logical = Logical.OR)
+    @ApiOperation("列表")
+    @PostMapping("list")
+    public Result<PageInfo<CommentVo>> list(@RequestBody PageDateDto param) {
+        return entityService.search(param, null);
+    }
+
+
+    @WebControllerLog(description = "留言管理-导出Excel", addDb = true)
+    @ApiOperation("v0.1-导出Excel")
+    @PostMapping("exportExcel")
+    public Result exportExcel(@RequestBody DateDto param) {
+        return entityService.exportExcel(param);
+    }
+
+
+
+
+
+    @WebControllerLog(description = "留言管理-新增留言", addDb = true)
+    @ApiOperation("新增留言")
+    @PostMapping("save")
+    public Result save(@Valid @RequestBody CommentDto param) {
+        return entityService.saveEntity(param);
+    }
+
+
+    @WebControllerLog(description = "留言管理-删除留言", addDb = true)
+    @ApiOperation("删除")
+    @GetMapping("remove/{id}")
+    public Result remove(@PathVariable Long id) {
+        return entityService.remove(id);
+    }
+
+    @WebControllerLog(description = "留言管理-是否显示", addDb = true)
+    @ApiOperation("是否显示")
+    @GetMapping("display/{id}/{display}")
+    public Result display(@PathVariable Long id, @PathVariable Integer display) {
+        CommentEntity entity = entityService.findById(id);
+        if (entity == null) {
+            log.error("对象id不存在 : {}", id);
+            return Result.failure("对象id不存在");
+        }
+
+        entity.setDisplay(display);
+        entityService.update(entity);
+        return Result.success();
+    }
+
+
+    @ApiOperation("详情")
+    @GetMapping("detail/{id}")
+    public Result<CommentEntity> detail(@PathVariable Long id) {
+        return entityService.detail(id);
+    }
+
+
+}

+ 91 - 0
gis_cms/src/main/java/com/gis/cms/controller/GoodsController.java

@@ -0,0 +1,91 @@
+package com.gis.cms.controller;
+
+import com.gis.cms.entity.dto.GoodsPageDateDto;
+import com.gis.cms.entity.dto.TypePageDateDto;
+import com.gis.cms.entity.po.GoodsEntity;
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.util.Result;
+import com.gis.cms.entity.dto.GoodsDto;
+import com.gis.cms.service.GoodsService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.Valid;
+
+/**
+ * Created by owen on 2022/1/10 0008 9:54
+ */
+@Api(tags = "精品典藏管理")
+@RestController
+@RequestMapping("cms/goods")
+public class GoodsController  {
+
+    @Autowired
+    private GoodsService entityService;
+
+
+
+    @ApiOperation("列表")
+    @PostMapping("list")
+    public Result<GoodsEntity> list(@RequestBody GoodsPageDateDto param) {
+        return entityService.search(param, null);
+    }
+
+    @WebControllerLog(description = "精品典藏-新增/修改", addDb = true)
+    @ApiOperation(value = "新增/修改", notes = "type=img, 才使用fileIds")
+    @PostMapping("save")
+    public Result save(@Valid @RequestBody GoodsDto param) {
+        return entityService.saveEntity(param);
+    }
+
+    @WebControllerLog(description = "精品典藏-删除", addDb = true)
+    @ApiOperation("删除")
+    @GetMapping("remove/{id}")
+    public Result remove(@PathVariable Long id) {
+        return entityService.remove(id);
+    }
+
+    @ApiOperation("场景详情")
+    @GetMapping("detail/{id}")
+    public Result<GoodsEntity> detail(@PathVariable Long id) {
+        return entityService.detail(id);
+    }
+
+    @WebControllerLog(description = "精品典藏-上传")
+    @ApiOperation(value = "上传", notes = "类型, model:模型, video:视频, thumb:缩略图; 视频、模型使用原名存储(中文转拼音),相同名称会覆盖")
+    @PostMapping("upload/{type}")
+    public Result upload(MultipartFile file, @PathVariable String type) {
+        return entityService.upload(file, type);
+    }
+
+    @WebControllerLog(description = "精品典藏-上传图片")
+    @ApiOperation(value = "上传图片", notes = "图片类型使用,重命名文件")
+    @PostMapping("uploadImg")
+    public Result uploadImg(MultipartFile file, String code) {
+        return entityService.uploadImg(file, code);
+    }
+
+    @WebControllerLog(description = "精品典藏-删除图片", addDb = true)
+    @ApiOperation(value = "删除图片")
+    @GetMapping("remove/file/{fileId}")
+    public Result removeFile(@PathVariable Long fileId) {
+        return entityService.removeFile(fileId);
+    }
+
+    @WebControllerLog(description = "精品典藏-是否显示", addDb = true)
+    @ApiOperation(value = "是否显示", notes = "display, 0:不显示, 1:显示")
+    @GetMapping("display/{id}/{display}")
+    public Result updateDisplay(@PathVariable Long id, @PathVariable Integer display) {
+        return entityService.display(id, display);
+    }
+
+    @WebControllerLog(description = "精品典藏-重新上传图片", addDb = true)
+    @ApiOperation(value = "重新上传图片", notes = "fileId:图片id, code:目录码")
+    @PostMapping("afresh/uploadImg/{fileId}/{code}")
+    public Result afreshUploadImg(MultipartFile file, @PathVariable String code, @PathVariable Long fileId) {
+        return entityService.afreshUploadImg(file, code, fileId);
+    }
+}

+ 69 - 0
gis_cms/src/main/java/com/gis/cms/controller/SensitiveController.java

@@ -0,0 +1,69 @@
+package com.gis.cms.controller;
+
+import com.gis.cms.entity.dto.ContentDto;
+import com.gis.cms.entity.dto.SensitiveDto;
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.util.Result;
+import com.gis.cms.entity.po.SensitiveEntity;
+import com.gis.cms.service.SensitiveService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.validation.Valid;
+
+/**
+ * Created by owen on 2021/6/25 0008 9:54
+ */
+@ApiIgnore
+@Slf4j
+@Api(tags = "敏感词管理")
+@RestController
+@RequestMapping("cms/sensitive")
+public class SensitiveController  {
+
+    @Autowired
+    private SensitiveService entityService;
+
+    @ApiOperation("列表")
+    @PostMapping("list")
+    public Result<SensitiveEntity> search(@Valid @RequestBody PageDto param) {
+        return entityService.search(param);
+    }
+
+    @WebControllerLog(description = "知识管理-新增/修改", addDb = true)
+    @ApiOperation("新增/修改")
+    @PostMapping("save")
+    public Result save(@Valid @RequestBody SensitiveDto param) {
+        return entityService.saveEntity(param);
+    }
+
+
+    @WebControllerLog(description = "知识管理-删除", addDb = true)
+    @ApiOperation("删除")
+    @GetMapping("remove/{id}")
+    public Result remove(@PathVariable Long id) {
+        return entityService.remove(id);
+    }
+
+    @ApiOperation("场景详情")
+    @GetMapping("detail/{id}")
+    public Result<SensitiveEntity> detail(@PathVariable Long id) {
+        return entityService.detail(id);
+    }
+
+    @WebControllerLog(description = "敏感词管理-删除缓存", addDb = true)
+    @ApiOperation(value = "删除缓存", notes = "更新敏感词表,需要刷新缓存")
+    @GetMapping("refresh")
+    public Result refreshRedis() {
+        return entityService.refreshRedis();
+    }
+
+
+
+}

+ 134 - 0
gis_cms/src/main/java/com/gis/cms/controller/WebController.java

@@ -0,0 +1,134 @@
+package com.gis.cms.controller;
+
+import com.gis.cms.entity.dto.*;
+import com.gis.cms.entity.po.*;
+import com.gis.cms.entity.vo.CommentVo;
+import com.gis.cms.entity.vo.SearchVo;
+import com.gis.cms.mapper.MyBaseMapper;
+import com.gis.cms.service.*;
+import com.gis.common.base.aop.WebControllerLog;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.service.LogService;
+import com.gis.common.util.Result;
+import com.gis.admin.service.*;
+import com.github.pagehelper.PageInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+
+/**
+ * Created by owen on 2021/6/25 0025 17:17
+ */
+@Slf4j
+@Api(tags = "门户网站")
+@RestController
+@RequestMapping("api/web")
+public class WebController {
+
+    @Autowired
+    BarrageService barrageService;
+
+
+    @Autowired
+    GoodsService goodsService;
+
+    @Autowired
+    SysUserService sysUserService;
+
+    @Autowired
+    LogService logService;
+
+    @Autowired
+    MyBaseMapper myBaseMapper;
+
+    @Autowired
+    CommentService commentService;
+
+    
+
+    @WebControllerLog(description = "门户网站-弹幕列表")
+    @ApiOperation("弹幕-列表")
+    @PostMapping("barrage/list")
+    public Result barrageList(@RequestBody PageDateDto param){
+        return barrageService.search(param, 1);
+    }
+
+    @WebControllerLog(description = "门户网站-保存并获取访问量")
+    @ApiOperation("保存并获取访问量")
+    @GetMapping("webVisit")
+    public Result webVisit(){
+        myBaseMapper.addVisit("web");
+        return Result.success(myBaseMapper.getVisit("web"));
+    }
+
+
+    @WebControllerLog(description = "门户网站-场景点赞")
+    @ApiOperation("场景-点赞")
+    @GetMapping("scene/star/{num}")
+    public Result sceneStar(@PathVariable Integer num){
+        myBaseMapper.addVisitAndNum("star", num);
+
+        return Result.success(myBaseMapper.getVisit("star"));
+    }
+
+    @WebControllerLog(description = "门户网站-获取点赞")
+    @ApiOperation("场景-获取点赞")
+    @GetMapping("scene/getStar")
+    public Result getStar(){
+        return Result.success(myBaseMapper.getVisit("star"));
+    }
+
+
+    @WebControllerLog(description = "门户网站-精品典藏列表(详情)")
+    @ApiOperation("精品典藏-列表")
+    @PostMapping("goods/list")
+    public Result<GoodsEntity> goodsList(@RequestBody GoodsPageDateDto param){
+        return goodsService.search(param, 1);
+    }
+
+
+    @WebControllerLog(description = "门户网站-精品典藏详情")
+    @ApiOperation("精品典藏-详情")
+    @GetMapping("goods/detail/{id}")
+    public Result<GoodsEntity> goodsDetail(@PathVariable Long id){
+        goodsService.addVisit(id);
+        return goodsService.detail(id);
+    }
+
+    @ApiOperation(value = "搜索", notes = "典藏、专家搜索")
+    @PostMapping("search")
+    public Result<SearchVo> search(@RequestBody PageDto param){
+        return goodsService.searchGlobal(param);
+    }
+
+    @WebControllerLog(description = "门户网站-新增弹幕", addDb = true)
+    @ApiOperation("新增弹幕")
+    @PostMapping("barrageSave")
+    public Result barrageSave(@Valid @RequestBody BarrageDto param) {
+        return barrageService.saveEntity(param);
+    }
+
+
+
+    @WebControllerLog(description = "门户网站-留言", addDb = true)
+    @ApiOperation(value = "门户网站-留言")
+    @PostMapping("comment/save")
+    public Result commentSave(@Valid @RequestBody CommentDto param) {
+        return commentService.saveEntity(param);
+    }
+
+    @ApiOperation("门户网站-留言列表")
+    @PostMapping("commentList")
+    public Result<PageInfo<CommentVo>> commentList(@RequestBody PageDateDto param) {
+        return commentService.search(param, 1);
+    }
+
+
+
+}

+ 17 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/BarrageDto.java

@@ -0,0 +1,17 @@
+package com.gis.cms.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2022/1/10 0010 11:15
+ */
+@Data
+public class BarrageDto {
+
+    @NotBlank(message = "弹幕不能为空")
+    @ApiModelProperty(value = "弹幕", required = true)
+    private String content;
+}

+ 22 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/CommentDto.java

@@ -0,0 +1,22 @@
+package com.gis.cms.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class CommentDto {
+
+
+    @NotBlank(message = "留言不能为空")
+    @ApiModelProperty(value = "留言", required = true)
+    private String content;
+
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+}

+ 25 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/ContentDto.java

@@ -0,0 +1,25 @@
+package com.gis.cms.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2021/6/24 0009 12:20
+ * 公共dto
+ */
+@Data
+public class ContentDto {
+
+    @ApiModelProperty(value = "id")
+    private Long Id;
+
+    @NotBlank(message = "内容不能为空")
+    @ApiModelProperty(value = "内容", required = true)
+    private String content;
+
+
+
+
+}

+ 35 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/CountAnswerDto.java

@@ -0,0 +1,35 @@
+package com.gis.cms.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2021/8/23 0023 18:14
+ */
+@Data
+public class CountAnswerDto {
+
+    @NotNull(message = "题组id不能为空")
+    @ApiModelProperty(value = "题组id", required = true)
+    private Long questionGroupId;
+
+    @NotNull(message = "正确数量不能为空")
+    @ApiModelProperty(value = "正确数量", required = true)
+    private Integer score;
+
+    @NotNull(message = "百分比不能为空")
+    @ApiModelProperty(value = "百分比", required = true)
+    private Double  percent;
+
+    @NotNull(message = "用户id不能为空")
+    @ApiModelProperty(value = "用户id", required = true)
+    private Long  userId;
+
+//    @NotNull(message = "耗时不能为空")
+//    @ApiModelProperty(value = "耗时(单位:秒)", required = true)
+//    private Long  time;
+
+
+}

+ 61 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/GoodsDto.java

@@ -0,0 +1,61 @@
+package com.gis.cms.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * Created by owen on 2020/5/28 0028 16:36
+ */
+@Data
+public class GoodsDto {
+
+    @ApiModelProperty(value = "id, 修改时必须传,新增忽略", name = "id")
+    private Long id;
+
+
+    @NotBlank(message = "标题不能为空")
+    @ApiModelProperty(value = "标题", required = true)
+    private String name;
+
+    @NotBlank(message = "类型不能为空")
+    @ApiModelProperty(value = "类型, model:模型, img:图片, video:视频", required = true)
+    private String type;
+
+    @ApiModelProperty(value = "缩略图url", notes = "修改前端控制")
+    private String thumb;
+
+    @ApiModelProperty(value = "文件地址")
+    private String filePath;
+
+    @ApiModelProperty(value = "文件名称")
+    private String fileName;
+
+
+    @ApiModelProperty(value = "简介")
+    private String description;
+
+    @ApiModelProperty(value = "图片类型使用,文件id, 多个以逗号分隔, 修改时:把新增加的fileId传给后端; 默认拿序号最前面的作为首页")
+    private String fileIds;
+
+    @ApiModelProperty(value = "图片类型使用,目录, img类型才会有值")
+    private String code;
+
+    @NotNull(message = "是否展示不能为空")
+    @ApiModelProperty(value = "是否展示,0:不展示,1:展示, 默认展示", required = true)
+    private Integer display;
+
+    @ApiModelProperty(value = "封面图id")
+    private Long indexId;
+
+    @NotNull(message = "单元不能为空")
+    @ApiModelProperty(value = "单元,1:第一单元, 2:第二单元", required = true)
+    private Integer zone;
+
+
+
+
+
+}

+ 23 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/GoodsPageDateDto.java

@@ -0,0 +1,23 @@
+package com.gis.cms.entity.dto;
+
+import com.gis.common.base.entity.dto.PageDateDto;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class GoodsPageDateDto extends PageDateDto {
+
+    @ApiModelProperty(value = "类型")
+    private String type;
+
+    @ApiModelProperty(value = "单元")
+    private Integer zone;
+
+
+
+
+
+}

+ 20 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/SensitiveDto.java

@@ -0,0 +1,20 @@
+package com.gis.cms.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * Created by owen on 2021/8/10 0010 10:17
+ */
+@Data
+public class SensitiveDto {
+
+    @ApiModelProperty(value = "id")
+    private Long Id;
+
+    @NotBlank(message = "内容不能为空")
+    @ApiModelProperty(value = "内容", required = true)
+    private String name;
+}

+ 16 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/StatusPageDataDto.java

@@ -0,0 +1,16 @@
+package com.gis.cms.entity.dto;
+
+import com.gis.common.base.entity.dto.PageDateDto;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * Created by owen on 2021/6/23 0023 17:53
+ */
+@Data
+public class StatusPageDataDto extends PageDateDto {
+
+    @ApiModelProperty(value = "状态")
+    private Integer status;
+}

+ 23 - 0
gis_cms/src/main/java/com/gis/cms/entity/dto/TypePageDateDto.java

@@ -0,0 +1,23 @@
+package com.gis.cms.entity.dto;
+
+import com.gis.common.base.entity.dto.PageDateDto;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Created by owen on 2020/5/9 0009 12:20
+ */
+@Data
+public class TypePageDateDto extends PageDateDto {
+
+    @ApiModelProperty(value = "类型")
+    private String type;
+
+//    @ApiModelProperty(value = "状态")
+//    private Integer status;
+
+
+
+
+
+}

+ 28 - 0
gis_cms/src/main/java/com/gis/cms/entity/po/BarrageEntity.java

@@ -0,0 +1,28 @@
+package com.gis.cms.entity.po;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.Serializable;
+
+/**
+ * 弹幕表
+ */
+@Data
+@Table(name = "tb_barrage")
+public class BarrageEntity extends BaseEntity implements Serializable {
+
+
+    private static final long serialVersionUID = 9089790237975141585L;
+
+    @ApiModelProperty(value = "留言")
+    private String content;
+
+    @ApiModelProperty(value = "是否显示,1:是, 0:否")
+    private Integer display;
+
+
+}

+ 55 - 0
gis_cms/src/main/java/com/gis/cms/entity/po/CommentEntity.java

@@ -0,0 +1,55 @@
+package com.gis.cms.entity.po;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.Serializable;
+
+/**
+ * 留言评论
+ */
+@Data
+@Table(name = "tb_comment")
+public class CommentEntity extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = -8093446477843493946L;
+
+//    @ApiModelProperty(value = "用户id")
+//    private Long userId;
+
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+    @ApiModelProperty(value = "留言")
+    private String content;
+
+//    @ApiModelProperty(value = "父级id")
+//    private Long parentId;
+
+    @ApiModelProperty(value = "是否显示,1:是, 0:否")
+    private Integer display;
+
+//    @ApiModelProperty(value = "是否显示真实姓名: 1:是, 0:否")
+//    private Integer isRealName;
+
+//    @Transient
+//    @ApiModelProperty(value = "真实姓名")
+//    private String realName;
+//
+//    @Transient
+//    @ApiModelProperty(value = "单位")
+//    private String unit;
+//
+//    @Transient
+//    @ApiModelProperty(value = "昵称")
+//    private String nickName;
+
+
+
+
+
+
+}

+ 45 - 0
gis_cms/src/main/java/com/gis/cms/entity/po/FileEntity.java

@@ -0,0 +1,45 @@
+package com.gis.cms.entity.po;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Table;
+
+/**
+ * Created by owen on 2021/4/20 0010 17:39
+ * 文件表
+ */
+@Data
+@Table(name = "tb_file")
+public class FileEntity extends BaseEntity {
+
+    @ApiModelProperty(value = "名称" )
+    private String name;
+
+    @ApiModelProperty(value = "模块:exhibition:展览")
+    private String module;
+
+
+    @ApiModelProperty(value = "文件地址")
+    private String filePath;
+//
+//    @ApiModelProperty(value = "文件名")
+//    private String fileName;
+
+
+//    @ApiModelProperty(value = "ossURL")
+//    private String ossUrl;
+
+    @ApiModelProperty(value = "封面, 1:是, 0:否")
+    private Integer isIndex;
+
+    @ApiModelProperty(value = "模块id")
+    private Long moduleId;
+
+
+
+
+
+
+}

+ 52 - 0
gis_cms/src/main/java/com/gis/cms/entity/po/GoodsEntity.java

@@ -0,0 +1,52 @@
+package com.gis.cms.entity.po;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Table;
+
+/**
+ * Created by owen on 2021/4/20 0010 17:39
+ * 文物表
+ */
+@Data
+@Table(name = "tb_goods")
+public class GoodsEntity extends BaseEntity {
+
+    @ApiModelProperty(value = "名称" )
+    private String name;
+
+    @ApiModelProperty(value = "类型, model:模型, img:图片, video:视频")
+    private String type;
+
+    @ApiModelProperty(value = "缩略图url")
+    private String thumb;
+
+    @ApiModelProperty(value = "文件地址")
+    private String filePath;
+
+    @ApiModelProperty(value = "文件名称")
+    private String fileName;
+
+    @ApiModelProperty(value = "简介")
+    private String description;
+
+    @ApiModelProperty(value = "是否显示,1:显示, 0:不显示, 默认显示")
+    private Integer display;
+
+    @ApiModelProperty(value = "单元,1:第一单元, 2:第二单元")
+    private Integer zone;
+
+
+
+    @ApiModelProperty(value = "目录, img类型才会有值, 1对多图片放到目录里")
+    private String code;
+
+    @ApiModelProperty(value = "浏览量")
+    private Integer visit;
+
+    @ApiModelProperty(value = "封面图id")
+    private Long indexId;
+
+}

+ 26 - 0
gis_cms/src/main/java/com/gis/cms/entity/po/SensitiveEntity.java

@@ -0,0 +1,26 @@
+package com.gis.cms.entity.po;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * Created by owen on 2021/6/25 0025 10:53
+ * 敏感词表
+ */
+@Data
+@Table(name = "tb_sensitive")
+public class SensitiveEntity extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID = 5929496864816525045L;
+
+    @ApiModelProperty(value = "名称" )
+    private String name;
+
+    @ApiModelProperty(value = "用户名")
+    private String userName;
+
+}

+ 22 - 0
gis_cms/src/main/java/com/gis/cms/entity/vo/BarrageVoExcel.java

@@ -0,0 +1,22 @@
+package com.gis.cms.entity.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * Created by owen on 2022/2/17.
+ * 留言用
+ */
+@Data
+public class BarrageVoExcel {
+
+
+    @ApiModelProperty(value = "内容")
+    private String content;
+
+    @ApiModelProperty(value = "提交时间")
+    private String createTime;
+
+
+}

+ 52 - 0
gis_cms/src/main/java/com/gis/cms/entity/vo/CommentVo.java

@@ -0,0 +1,52 @@
+package com.gis.cms.entity.vo;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import com.gis.common.util.RedisUtil;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Set;
+
+/**
+ * Created by owen on 202/6/24.
+ * 留言用
+ */
+@Data
+public class CommentVo extends BaseEntity {
+
+
+
+//    @ApiModelProperty(value = "真实姓名")
+//    private String realName;
+//
+//    @ApiModelProperty(value = "单位")
+//    private String unit;
+//
+//    @ApiModelProperty(value = "昵称")
+//    private String nickName;
+
+        @ApiModelProperty(value = "姓名")
+    private String name;
+
+    @ApiModelProperty(value = "内容")
+    private String content;
+
+    @ApiModelProperty(value = "是否显示,1:是, 0:否")
+    private Integer display;
+
+    @ApiModelProperty(value = "父级id")
+    private Long parentId;
+
+//    @ApiModelProperty(value = "是否显示真实姓名: 1:是, 0:否")
+//    private Integer isRealName;
+
+
+//    public void setContent(String content) {
+//        Set<String> filterKey = (Set)redisUtil.get("army_xinjiang_token_filter");
+//        for (String s : filterKey) {
+//            content =  content.replaceAll(s, "**");
+//        }
+//        this.content = content;
+//    }
+}

+ 28 - 0
gis_cms/src/main/java/com/gis/cms/entity/vo/CommentVoExcel.java

@@ -0,0 +1,28 @@
+package com.gis.cms.entity.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * Created by owen on 2022/2/17.
+ * 留言用
+ */
+@Data
+public class CommentVoExcel  {
+
+
+
+
+
+    @ApiModelProperty(value = "昵称")
+    private String name;
+
+    @ApiModelProperty(value = "内容")
+    private String content;
+
+    @ApiModelProperty(value = "提交时间")
+    private String createTime;
+
+
+}

+ 41 - 0
gis_cms/src/main/java/com/gis/cms/entity/vo/MournVo.java

@@ -0,0 +1,41 @@
+package com.gis.cms.entity.vo;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * Created by owen on 2021/6/24 0024 12:22
+ * 专家表
+ */
+@Data
+public class MournVo extends BaseEntity implements Serializable {
+    private static final long serialVersionUID = 7167520531265687441L;
+
+
+
+    @ApiModelProperty(value = "姓名")
+    private String name;
+
+    @ApiModelProperty(value = "照片")
+    private String thumb;
+
+    @ApiModelProperty(value = "是否显示,0:不显示, 1:显示")
+    private Integer display;
+
+    @ApiModelProperty(value = "浏览量")
+    private Integer visit;
+
+//    @ApiModelProperty(value = "用户id")
+//    private Long userId;
+
+    @ApiModelProperty(value = "描述(介绍)")
+    private String description;
+
+
+
+
+}

+ 32 - 0
gis_cms/src/main/java/com/gis/cms/entity/vo/SearchVo.java

@@ -0,0 +1,32 @@
+package com.gis.cms.entity.vo;
+
+import com.gis.common.base.entity.po.BaseEntity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Created by owen on 202/6/24.
+ * 全局搜索用
+ */
+@Data
+public class SearchVo extends BaseEntity {
+
+
+    @ApiModelProperty(value = "对象id")
+    private Long id;
+
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+    @ApiModelProperty(value = "描述")
+    private String description;
+
+    @ApiModelProperty(value = "类型:goods:典藏, expert:专家")
+    private String type;
+
+
+
+
+
+
+}

+ 25 - 0
gis_cms/src/main/java/com/gis/cms/mapper/BarrageMapper.java

@@ -0,0 +1,25 @@
+package com.gis.cms.mapper;
+
+
+import com.gis.cms.entity.po.BarrageEntity;
+import com.gis.cms.entity.vo.BarrageVoExcel;
+import com.gis.cms.mapper.provider.BarrageProvider;
+import com.gis.cms.mapper.provider.BaseProvider;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@Mapper
+public interface BarrageMapper extends IBaseMapper<BarrageEntity, Long> {
+
+    @SelectProvider(type = BarrageProvider.class, method = "search")
+    List<BarrageEntity> search(PageDateDto param, Integer display);
+
+    @SelectProvider(type = BaseProvider.class, method = "selectSql")
+    List<BarrageVoExcel> expertSql(String sqlStr);
+}

+ 38 - 0
gis_cms/src/main/java/com/gis/cms/mapper/CommentMapper.java

@@ -0,0 +1,38 @@
+package com.gis.cms.mapper;
+
+
+import com.gis.cms.entity.vo.CommentVoExcel;
+import com.gis.cms.mapper.provider.BaseProvider;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.cms.entity.po.CommentEntity;
+import com.gis.cms.entity.vo.CommentVo;
+import com.gis.cms.mapper.provider.CommentProvider;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.apache.poi.ss.formula.functions.T;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Component
+@Mapper
+public interface CommentMapper extends IBaseMapper<CommentEntity, Long> {
+
+
+    @SelectProvider(type = CommentProvider.class, method = "search")
+    List<CommentVo> search(PageDateDto param, Integer display);
+
+
+    @Select("select COUNT(id) from tb_comment where is_delete = 0 AND  DATE_FORMAT( create_time, '%Y%m%d' ) = DATE_FORMAT(#{date} , '%Y%m%d' ) ")
+    Integer countFindByDate(LocalDate now);
+
+    @Select("select a.id, a.create_time, a.content, a.display, a.parent_id, b.unit, b.real_name, b.nick_name from tb_comment a left join sys_user b on b.id=a.user_id " +
+            "where a.is_delete = '0' and a.id=#{id}")
+    CommentEntity detailMapper(Long id);
+
+    @SelectProvider(type = BaseProvider.class, method = "selectSql")
+    List<CommentVoExcel> expertSql(String sql);
+}

+ 32 - 0
gis_cms/src/main/java/com/gis/cms/mapper/FileMapper.java

@@ -0,0 +1,32 @@
+package com.gis.cms.mapper;
+
+
+import com.gis.cms.entity.po.FileEntity;
+import com.gis.common.base.mapper.IBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+
+@Component
+@Mapper
+public interface FileMapper extends IBaseMapper<FileEntity, Long> {
+
+    @Update("update tb_file set is_index = 1 , update_time = NOW() where is_delete = 0 and id = #{fileId} ")
+    void indexEnabled(Long fileId);
+
+    @Update("update tb_file set is_index = 0 , update_time = NOW() where is_delete = 0 and is_index = 1 and module = #{module} and module_id = #{moduleId}")
+    void indexDisable(Long moduleId, String module);
+
+    @Update("update tb_file set module_id = #{moduleId} , update_time = NOW() where is_delete = 0 and module = #{module} and id in ( ${fileIds} )")
+    void addModuleIdToFile(String fileIds, Long moduleId, String module);
+
+    @Select("select * from tb_file where is_delete = 0 and is_index = 1 and module = #{module} and module_id = #{moduleId} limit 1")
+    List<FileEntity> findIndexByModule(Long moduleId, String module);
+
+    @Select("select * from tb_file where is_delete = 0 and module = #{module} and module_id = #{moduleId} ")
+    List<FileEntity> findByModuleId(Long moduleId, String module);
+}

+ 33 - 0
gis_cms/src/main/java/com/gis/cms/mapper/GoodsMapper.java

@@ -0,0 +1,33 @@
+package com.gis.cms.mapper;
+
+
+import com.gis.cms.entity.dto.GoodsPageDateDto;
+import com.gis.cms.entity.po.GoodsEntity;
+import com.gis.cms.entity.vo.SearchVo;
+import com.gis.cms.mapper.provider.GoodsProvider;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.cms.entity.dto.TypePageDateDto;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectProvider;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@Mapper
+public interface GoodsMapper extends IBaseMapper<GoodsEntity, Long> {
+
+
+
+    @SelectProvider(type = GoodsProvider.class, method = "search")
+    List<GoodsEntity> search(GoodsPageDateDto param, Integer display);
+
+    @Update("update tb_goods set visit = visit + 1 , update_time = NOW() where is_delete = 0  and id = #{id}")
+    void addVisit(Long id);
+
+    @SelectProvider(type = GoodsProvider.class, method = "searchGlobal")
+    List<SearchVo> searchGlobal(PageDto param);
+}

+ 29 - 0
gis_cms/src/main/java/com/gis/cms/mapper/MyBaseMapper.java

@@ -0,0 +1,29 @@
+package com.gis.cms.mapper;
+
+
+import com.gis.cms.entity.po.FileEntity;
+import com.gis.common.base.mapper.IBaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springframework.stereotype.Component;
+
+
+
+@Component
+@Mapper
+public interface MyBaseMapper extends IBaseMapper<FileEntity, Long> {
+
+
+
+    @Update("update tb_visit set visit = visit + 1 , update_time = NOW() where is_delete = 0  and module = #{module}")
+    void addVisit(String module);
+
+    @Update("update tb_visit set visit = visit + #{num} , update_time = NOW() where is_delete = 0  and module = #{module}")
+    void addVisitAndNum(String module, Integer num);
+
+    @Select("select visit from tb_visit where is_delete = 0  and module = #{module}")
+    Integer getVisit(String module);
+
+
+}

+ 18 - 0
gis_cms/src/main/java/com/gis/cms/mapper/SensitiveMapper.java

@@ -0,0 +1,18 @@
+package com.gis.cms.mapper;
+
+
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.cms.entity.po.SensitiveEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+@Component
+@Mapper
+public interface SensitiveMapper extends IBaseMapper<SensitiveEntity, Long> {
+
+    @Select("SELECT DISTINCT name FROM tb_sensitive WHERE is_delete=0")
+    Set<Object> getName();
+}

+ 46 - 0
gis_cms/src/main/java/com/gis/cms/mapper/provider/BarrageProvider.java

@@ -0,0 +1,46 @@
+package com.gis.cms.mapper.provider;
+
+import com.gis.common.base.entity.dto.PageDateDto;
+import lombok.extern.log4j.Log4j2;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+
+/**
+ * Created by owen on 2020/5/13.
+ */
+@Slf4j
+public class BarrageProvider {
+
+    public String search(PageDateDto param, Integer display){
+        StringBuffer sql = new StringBuffer(
+                "select a. * from tb_barrage a where a.is_delete = '0' ");
+
+
+        if(StringUtils.isNotBlank(param.getStartTime()) && StringUtils.isNotBlank(param.getEndTime())){
+
+            sql.append(" and a.create_time >= ").append("'").append(param.getStartTime()).append("'");
+            sql.append(" and a.create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+        String searchKey = param.getSearchKey();
+        if(!StringUtils.isAllBlank(searchKey)){
+            searchKey = StringUtils.trim(searchKey);
+            sql.append(" and (");
+            sql.append("  a.content like '%").append(searchKey).append("%'");
+            sql.append(" )");
+        }
+
+
+        if (display != null) {
+            sql.append(" and a.display = ").append(display);
+        }
+
+        sql.append(" order by a.create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+
+
+}

+ 17 - 0
gis_cms/src/main/java/com/gis/cms/mapper/provider/BaseProvider.java

@@ -0,0 +1,17 @@
+package com.gis.cms.mapper.provider;
+
+
+
+/**
+ * Created by owen on 2020/5/13.
+ */
+public class BaseProvider {
+
+    public String selectSql(String sql){
+
+        return sql;
+    }
+
+
+
+}

+ 52 - 0
gis_cms/src/main/java/com/gis/cms/mapper/provider/CommentProvider.java

@@ -0,0 +1,52 @@
+package com.gis.cms.mapper.provider;
+
+import com.gis.common.base.entity.dto.PageDateDto;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+
+/**
+ * Created by owen on 2020/5/13.
+ */
+@Log4j2
+public class CommentProvider {
+
+    public String search(PageDateDto param, Integer display){
+//        StringBuffer sql = new StringBuffer(
+//                "select a.id, a.create_time, a.content, a.display, a.parent_id, a.is_real_name, b.unit, b.real_name, b.nick_name " +
+//                        "from tb_comment a left join sys_user b on b.id=a.user_id  " +
+//                        "where a.is_delete = '0' ");
+
+        StringBuffer sql = new StringBuffer(
+                "select a.* from tb_comment a where a.is_delete = '0' ");
+
+
+        if(StringUtils.isNotBlank(param.getStartTime()) && StringUtils.isNotBlank(param.getEndTime())){
+
+            sql.append(" and a.create_time >= ").append("'").append(param.getStartTime()).append("'");
+            sql.append(" and a.create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+        String searchKey = param.getSearchKey();
+        if(!StringUtils.isAllBlank(searchKey)){
+            searchKey = StringUtils.trim(searchKey);
+            sql.append(" and (");
+            sql.append("  a.content like '%").append(searchKey).append("%'");
+//            sql.append(" or ( b.real_name like '%").append(searchKey).append("%' )");
+            sql.append(" )");
+        }
+
+
+        if (display != null) {
+            sql.append(" and a.display = ").append(display);
+        }
+
+        sql.append(" order by a.create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+
+
+
+}

+ 100 - 0
gis_cms/src/main/java/com/gis/cms/mapper/provider/GoodsProvider.java

@@ -0,0 +1,100 @@
+package com.gis.cms.mapper.provider;
+
+import com.gis.cms.entity.dto.GoodsPageDateDto;
+import com.gis.cms.entity.dto.TypePageDateDto;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.util.RegexUtil;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+
+/**
+ * Created by owen on 2020/6/13 0013 10:56
+ */
+@Log4j2
+public class GoodsProvider {
+
+
+    public String search(GoodsPageDateDto param, Integer display) {
+        StringBuffer sql = new StringBuffer(
+                "select * from tb_goods where is_delete = '0' ");
+
+
+        if (display != null) {
+            sql.append(" and  display = ").append(display);
+        }
+
+        String type = param.getType();
+        if (StringUtils.isNotBlank(type)) {
+            sql.append(" and  type = '").append(type).append("'");
+        }
+
+        Integer zone = param.getZone();
+        if (zone != null){
+            sql.append(" and  zone = ").append(zone);
+        }
+
+        if (StringUtils.isNotBlank(param.getStartTime()) && StringUtils.isNotBlank(param.getEndTime())) {
+
+            sql.append(" and create_time >= ").append("'").append(param.getStartTime()).append("'");
+            sql.append(" and create_time <= ").append("'").append(param.getEndTime()).append("'");
+        }
+
+
+
+        String searchKey = param.getSearchKey();
+        if (!StringUtils.isAllBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            sql.append(" and ( name like '%").append(searchKey).append("%' )");
+        }
+
+
+
+
+        sql.append(" order by create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+    /**
+     * 'goods' as type 区分表类型
+     * @param param
+     * @return
+     */
+    public String searchGlobal(PageDto param) {
+        StringBuffer sql = new StringBuffer(
+                "(select a.id,a.name, a.description ,a.create_time,a.update_time,'goods' as type  from tb_goods a where (a.is_delete=0 and a.display=1)");
+
+
+        String searchKey = param.getSearchKey();
+        if (!StringUtils.isAllBlank(searchKey)) {
+
+            searchKey = RegexUtil.sqlReplaceSpecialStr(searchKey);
+            sql.append(" and (");
+            sql.append(" a.name like '%").append(searchKey).append("%'");
+            sql.append(" or a.description like '%").append(searchKey).append("%'");
+            sql.append("))");
+        }
+
+        sql.append(" UNION ALL");
+
+        sql.append(" (select b.id,b.name, b.description,b.create_time,b.update_time, 'expert' as type from tb_expert b where (b.is_delete=0 and b.display=1)");
+
+        if (!StringUtils.isAllBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            sql.append(" and (");
+            sql.append(" b.name like '%").append(searchKey).append("%'");
+            sql.append(" or b.description like '%").append(searchKey).append("%'");
+            sql.append("))");
+        }
+//        sql.append(" order by a.create_time desc, b.create_time desc");
+        log.info("sql: {}", sql.toString());
+        return sql.toString();
+    }
+
+
+
+}
+
+
+

+ 28 - 0
gis_cms/src/main/java/com/gis/cms/service/BarrageService.java

@@ -0,0 +1,28 @@
+package com.gis.cms.service;
+
+
+import com.gis.cms.entity.dto.BarrageDto;
+import com.gis.cms.entity.po.BarrageEntity;
+import com.gis.common.base.entity.dto.DateDto;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.util.Result;
+import com.github.pagehelper.PageInfo;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface BarrageService extends IBaseService<BarrageEntity, Long> {
+
+
+    Result<PageInfo<BarrageEntity>> search(PageDateDto param, Integer display);
+
+    Result remove(Long id);
+
+    Result saveEntity(BarrageDto param);
+
+    Result<BarrageEntity> detail(Long id);
+
+    Result exportExcel(DateDto param);
+}

+ 35 - 0
gis_cms/src/main/java/com/gis/cms/service/CommentService.java

@@ -0,0 +1,35 @@
+package com.gis.cms.service;
+
+
+import com.gis.cms.entity.dto.CommentDto;
+import com.gis.cms.entity.po.CommentEntity;
+import com.gis.cms.entity.vo.CommentVo;
+import com.gis.common.base.entity.dto.DateDto;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.util.Result;
+import com.github.pagehelper.PageInfo;
+
+import java.time.LocalDate;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface CommentService extends IBaseService<CommentEntity, Long> {
+
+
+    Result<PageInfo<CommentVo>> search(PageDateDto param, Integer display);
+
+    Integer countFindByDate(LocalDate now);
+
+    Result remove(Long id);
+
+    Result saveEntity(CommentDto param);
+
+    Result<CommentVo> voListTree(PageDateDto param, Integer display);
+
+    Result<CommentEntity> detail(Long id);
+
+    Result exportExcel(DateDto param);
+}

+ 30 - 0
gis_cms/src/main/java/com/gis/cms/service/FileService.java

@@ -0,0 +1,30 @@
+package com.gis.cms.service;
+
+
+import com.gis.cms.entity.po.FileEntity;
+import com.gis.common.base.service.IBaseService;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface FileService extends IBaseService<FileEntity, Long> {
+
+
+    void indexDisable(Long moduleId, String module);
+
+    void indexEnabled(Long fileId);
+
+    void addModuleIdToFile(String fileIds, Long moduleId, String module);
+
+    List<FileEntity> findIndexByModule(Long moduleId, String module);
+
+
+    List<FileEntity> findByModuleId(Long moduleId, String module);
+
+    Map<String, Object> upload(MultipartFile file, String dir);
+}

+ 44 - 0
gis_cms/src/main/java/com/gis/cms/service/GoodsService.java

@@ -0,0 +1,44 @@
+package com.gis.cms.service;
+
+
+import com.gis.cms.entity.dto.GoodsDto;
+import com.gis.cms.entity.dto.GoodsPageDateDto;
+import com.gis.cms.entity.dto.TypePageDateDto;
+import com.gis.cms.entity.po.GoodsEntity;
+import com.gis.cms.entity.vo.SearchVo;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.util.Result;
+import org.springframework.web.multipart.MultipartFile;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface GoodsService extends IBaseService<GoodsEntity, Long> {
+
+
+    Result<GoodsEntity> search(GoodsPageDateDto param, Integer display);
+
+    Result saveEntity(GoodsDto param);
+
+    Result upload(MultipartFile file, String type);
+
+    Result removeFile(Long fileId);
+
+    Result detail(Long id);
+
+    Result remove(Long id);
+
+    Result setIndex(Long fileId);
+
+    Result uploadImg(MultipartFile file, String code);
+
+    Result display(Long id, Integer display);
+
+    void addVisit(Long id);
+
+    Result<SearchVo> searchGlobal(PageDto param);
+
+    Result afreshUploadImg(MultipartFile file, String code, Long fileId);
+}

+ 32 - 0
gis_cms/src/main/java/com/gis/cms/service/SensitiveService.java

@@ -0,0 +1,32 @@
+package com.gis.cms.service;
+
+
+import com.gis.cms.entity.dto.ContentDto;
+import com.gis.cms.entity.dto.SensitiveDto;
+import com.gis.cms.entity.po.SensitiveEntity;
+import com.gis.common.base.service.IBaseService;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.util.Result;
+
+import java.util.Set;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:14
+ */
+public interface SensitiveService extends IBaseService<SensitiveEntity, Long> {
+
+
+    Result saveEntity(SensitiveDto param);
+
+    Result remove(Long id);
+
+    Result<SensitiveEntity> detail(Long id);
+
+    Result<SensitiveEntity> search(PageDto param);
+
+    Set<Object> getFilterKey();
+
+
+    Result refreshRedis();
+}

+ 135 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/BarrageServiceImpl.java

@@ -0,0 +1,135 @@
+package com.gis.cms.service.impl;
+
+import com.gis.cms.entity.dto.BarrageDto;
+import com.gis.cms.entity.po.BarrageEntity;
+import com.gis.cms.entity.vo.BarrageVoExcel;
+import com.gis.cms.entity.vo.CommentVoExcel;
+import com.gis.cms.mapper.BarrageMapper;
+import com.gis.cms.service.SensitiveService;
+import com.gis.common.base.entity.dto.DateDto;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.exception.BaseRuntimeException;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.ExcelUtils;
+import com.gis.common.util.MyStrUtil;
+import com.gis.common.util.Result;
+import com.gis.cms.service.BarrageService;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:16
+ */
+@Slf4j
+@Service
+public class BarrageServiceImpl extends IBaseServiceImpl<BarrageEntity, Long> implements BarrageService {
+
+    @Autowired
+    private BarrageMapper entityMapper;
+
+    @Autowired
+    SensitiveService sensitiveService;
+
+    @Override
+    public IBaseMapper<BarrageEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+
+    @Override
+    public Result<PageInfo<BarrageEntity>> search(PageDateDto param, Integer display) {
+        startPage(param);
+        PageInfo<BarrageEntity> page = new PageInfo<>(entityMapper.search(param, display));
+
+        return Result.success(page);
+    }
+
+    @Override
+    public Result remove(Long id) {
+        BarrageEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.success();
+        }
+        // db数据软删除, 物理数据真删除
+        entity.setIsDelete(1);
+        entity.setUpdateTime(LocalDateTime.now());
+        this.update(entity);
+        return Result.success();
+    }
+
+    @Override
+    public Result saveEntity(BarrageDto param) {
+        BarrageEntity entity = new BarrageEntity();
+        BeanUtils.copyProperties(param, entity);
+        this.save(entity);
+        return Result.success();
+    }
+
+    @Override
+    public Result<BarrageEntity> detail(Long id) {
+        BarrageEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.failure("对象不存在");
+        }
+        return Result.success(entity);
+    }
+
+    @Override
+    public Result exportExcel(DateDto param) {
+        List<BarrageVoExcel> rows = findByDate(param);
+
+        // 保存地址
+        String filePath = "/excel/" + MyStrUtil.getTimeStr() + ".xlsx";
+        String savePath = configConstant.serverBasePath + filePath;
+
+
+        HashMap<String, String> rowTitle = new HashMap<>();
+        rowTitle.put("createTime", "提交时间");
+        rowTitle.put("content", "内容");
+
+        ExcelUtils.createExcel(rows, savePath, rowTitle);
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("size", rows.size());
+        result.put("path", filePath);
+
+
+        return Result.success(result);
+    }
+
+    private List<BarrageVoExcel> findByDate(DateDto param){
+
+        String startTime = param.getStartTime();
+        String endTime = param.getEndTime();
+        if (StringUtils.isBlank(startTime) || StringUtils.isBlank(endTime)){
+            throw new BaseRuntimeException("日期不能为空");
+        }
+
+        StringBuffer sql = new StringBuffer();
+        sql.append("select * from tb_barrage where is_delete=0 ");
+        sql.append(" and create_time >= ").append("'").append(startTime).append("'");
+        sql.append(" and create_time <= ").append("'").append(endTime).append("'");
+
+        String searchKey = param.getSearchKey();
+        if (StringUtils.isNotBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            sql.append("  and content like '%").append(searchKey).append("%'");
+        }
+
+        sql.append(" order by create_time desc");
+        String sqlStr = sql.toString();
+        log.info("sql: {}", sqlStr);
+        return entityMapper.expertSql(sqlStr);
+
+    }
+
+}

+ 155 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/CommentServiceImpl.java

@@ -0,0 +1,155 @@
+package com.gis.cms.service.impl;
+
+import com.gis.cms.entity.dto.CommentDto;
+import com.gis.cms.entity.po.CommentEntity;
+import com.gis.cms.entity.vo.CommentVo;
+import com.gis.cms.entity.vo.CommentVoExcel;
+import com.gis.cms.mapper.CommentMapper;
+import com.gis.cms.service.CommentService;
+import com.gis.cms.service.SensitiveService;
+import com.gis.cms.tree.CommentTreeUtil;
+import com.gis.cms.tree.vo.CommentTree;
+import com.gis.common.base.entity.dto.DateDto;
+import com.gis.common.base.entity.dto.PageDateDto;
+import com.gis.common.base.exception.BaseRuntimeException;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.ExcelUtils;
+import com.gis.common.util.MyStrUtil;
+import com.gis.common.util.Result;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:16
+ */
+@Slf4j
+@Service
+public class CommentServiceImpl extends IBaseServiceImpl<CommentEntity, Long> implements CommentService {
+
+    @Autowired
+    private CommentMapper entityMapper;
+
+    @Autowired
+    private SensitiveService sensitiveService;
+
+    @Override
+    public IBaseMapper<CommentEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+
+    @Override
+    public Result<PageInfo<CommentVo>> search(PageDateDto param, Integer display) {
+        startPage(param);
+        PageInfo<CommentVo> page = new PageInfo<>(entityMapper.search(param, display));
+        return Result.success(page);
+    }
+
+    @Override
+    public Integer countFindByDate(LocalDate now) {
+        return entityMapper.countFindByDate(now);
+    }
+
+    @Override
+    public Result remove(Long id) {
+        CommentEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.success();
+        }
+        // db数据软删除, 物理数据真删除
+        entity.setIsDelete(1);
+        entity.setUpdateTime(LocalDateTime.now());
+        this.update(entity);
+        return Result.success();
+    }
+
+    @Override
+    public Result saveEntity(CommentDto param) {
+        CommentEntity entity = new CommentEntity();
+        BeanUtils.copyProperties(param, entity);
+//        entity.setUserId(getTokenUserId());
+        this.save(entity);
+        return Result.success();
+    }
+
+    @Override
+    public Result<CommentVo> voListTree(PageDateDto param, Integer display) {
+        startPage(param);
+
+        List<CommentVo> search = entityMapper.search(param, display);
+
+        Set<Object> filterKey = sensitiveService.getFilterKey();
+        CommentTreeUtil commentTreeUtil = new CommentTreeUtil(search, filterKey);
+        List<CommentTree> commentTrees = commentTreeUtil.buildTree();
+
+        PageInfo<CommentTree> page = new PageInfo<>(commentTrees);
+        return Result.success(page);
+    }
+
+    @Override
+    public Result<CommentEntity> detail(Long id) {
+        CommentEntity entity = entityMapper.detailMapper(id);
+        return Result.success(entity);
+    }
+
+    @Override
+    public Result exportExcel(DateDto param) {
+        List<CommentVoExcel> rows = findByDate(param);
+
+        // 保存地址
+        String filePath = "/excel/" + MyStrUtil.getTimeStr() + ".xlsx";
+        String savePath = configConstant.serverBasePath + filePath;
+
+
+        HashMap<String, String> rowTitle = new HashMap<>();
+        rowTitle.put("name", "昵称");
+        rowTitle.put("createTime", "提交时间");
+        rowTitle.put("content", "内容");
+
+        ExcelUtils.createExcel(rows, savePath, rowTitle);
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("size", rows.size());
+        result.put("path", filePath);
+
+
+        return Result.success(result);
+    }
+
+    private List<CommentVoExcel> findByDate(DateDto param){
+
+        String startTime = param.getStartTime();
+        String endTime = param.getEndTime();
+        if (StringUtils.isBlank(startTime) || StringUtils.isBlank(endTime)){
+            throw new BaseRuntimeException("日期不能为空");
+        }
+
+        StringBuffer sql = new StringBuffer();
+        sql.append("select * from tb_comment where is_delete=0 ");
+        sql.append(" and create_time >= ").append("'").append(startTime).append("'");
+        sql.append(" and create_time <= ").append("'").append(endTime).append("'");
+
+        String searchKey = param.getSearchKey();
+        if (StringUtils.isNotBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            sql.append("  and content like '%").append(searchKey).append("%'");
+        }
+
+        sql.append(" order by create_time desc");
+        String sqlStr = sql.toString();
+        log.info("sql: {}", sqlStr);
+        return entityMapper.expertSql(sqlStr);
+
+    }
+}

+ 114 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/FileServiceImpl.java

@@ -0,0 +1,114 @@
+package com.gis.cms.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.FileUtil;
+import com.gis.cms.entity.po.FileEntity;
+import com.gis.cms.mapper.FileMapper;
+import com.gis.common.base.exception.BaseRuntimeException;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.RegexUtil;
+import com.gis.cms.service.FileService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Created by owen on 2021/6/21 0011 16:16
+ */
+@Slf4j
+@Service
+public class FileServiceImpl extends IBaseServiceImpl<FileEntity, Long> implements FileService {
+
+    @Autowired
+    private FileMapper entityMapper;
+
+    @Override
+    public IBaseMapper<FileEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+
+
+
+    @Override
+    public void indexDisable(Long moduleId, String module) {
+        entityMapper.indexDisable(moduleId, module);
+
+    }
+
+    @Override
+    public void indexEnabled(Long fileId) {
+        entityMapper.indexEnabled(fileId);
+    }
+
+    @Override
+    public void addModuleIdToFile(String fileIds, Long moduleId, String module) {
+        if (StringUtils.isBlank(fileIds)) {
+            return;
+        }
+        // 去除特殊符号,防止sql注入
+        fileIds = RegexUtil.specificSymbol(fileIds);
+        entityMapper.addModuleIdToFile(fileIds, moduleId, module);
+    }
+
+    @Override
+    public List<FileEntity> findIndexByModule(Long moduleId, String module) {
+        return entityMapper.findIndexByModule(moduleId, module);
+    }
+
+    @Override
+    public List<FileEntity> findByModuleId(Long moduleId, String module) {
+        return entityMapper.findByModuleId(moduleId, module);
+    }
+
+    /**
+     *
+     * @param file
+     * @param dir 中间拼接目录
+     * @return
+     */
+    @Override
+    public Map<String, Object> upload(MultipartFile file, String dir) {
+
+        // 检查非法文件上传
+        if (!fileUtils.checkFile(file)) {
+            throw new BaseRuntimeException("非法文件, 请重新上传");
+        }
+        String CommentVoName = getTimeName(file);
+        dir = dir + "/" + CommentVoName;
+        String savePath = configConstant.serverBasePath + dir ;
+        try {
+            FileUtil.writeFromStream(file.getInputStream(), savePath);
+            HashMap<String, Object> result = new HashMap<>();
+            result.put("fileName", file.getOriginalFilename());
+            result.put("filePath", dir);
+            log.info("文件写入完成: {}", savePath);
+            return result;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /** 返回时间戳名字*/
+    private static String getTimeName(MultipartFile file){
+        String time = DateUtil.format(LocalDateTime.now(), "yyyyMMdd_HHmmssSSS");
+        String originalFilename = file.getOriginalFilename();
+        String suffix = StringUtils.substringAfterLast(originalFilename, ".");
+        return time+ "." + suffix;
+
+    }
+
+
+}

+ 328 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/GoodsServiceImpl.java

@@ -0,0 +1,328 @@
+package com.gis.cms.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.FileUtil;
+import com.gis.cms.entity.dto.GoodsDto;
+import com.gis.cms.entity.dto.GoodsPageDateDto;
+import com.gis.cms.entity.dto.TypePageDateDto;
+import com.gis.cms.entity.po.FileEntity;
+import com.gis.cms.entity.po.GoodsEntity;
+import com.gis.cms.entity.vo.SearchVo;
+import com.gis.cms.mapper.GoodsMapper;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.exception.BaseRuntimeException;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.constant.MsgCode;
+import com.gis.common.constant.TypeCode;
+import com.gis.common.util.RegexUtil;
+import com.gis.common.util.Result;
+import com.gis.cms.service.FileService;
+import com.gis.cms.service.GoodsService;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Created by owen on 2020/3/11 0011 16:16
+ */
+@Slf4j
+@Service
+public class GoodsServiceImpl extends IBaseServiceImpl<GoodsEntity, Long> implements GoodsService {
+
+    @Autowired
+    private GoodsMapper entityMapper;
+
+    @Autowired
+    FileService fileService;
+
+
+
+
+    @Override
+    public IBaseMapper<GoodsEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+
+    @Override
+    public Result<GoodsEntity> search(GoodsPageDateDto param, Integer display) {
+        startPage(param);
+        return Result.success(new PageInfo<>(entityMapper.search(param, display)));
+    }
+
+    @Override
+    public Result saveEntity(GoodsDto param) {
+        Long id = param.getId();
+        GoodsEntity entity = null;
+        if (id == null) {
+            entity = new GoodsEntity();
+            BeanUtils.copyProperties(param, entity);
+//            entity.setUserName(getTokenUserName());
+            this.save(entity);
+        } else {
+            entity = this.findById(id);
+            if (entity == null) {
+                return Result.failure("对象不存在: " + id);
+            }
+
+            // 物理删除旧图片
+            String thumb = entity.getThumb();
+            if (!StringUtils.equals(thumb, param.getThumb())){
+                fileUtils.del(thumb);
+            }
+
+            BeanUtils.copyProperties(param, entity);
+
+
+
+            entity.setUpdateTime(LocalDateTime.now());
+            this.update(entity);
+        }
+
+        // 图片类型img,  将模块id绑定到文件表
+        String fileIds = param.getFileIds();
+        if (StringUtils.isNotBlank(fileIds)) {
+            Long moduleId = entity.getId();
+            fileService.addModuleIdToFile(fileIds, moduleId, TypeCode.MODULE_GOODS);
+        }
+
+
+        // 设置初始封面
+        Long indexId = param.getIndexId();
+        if (indexId != null){
+            setIndex(indexId, TypeCode.MODULE_GOODS, entity);
+        }
+        return Result.success(entity);
+    }
+
+
+
+    @Override
+    public Result remove(Long id) {
+        GoodsEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.success();
+        }
+        entity.setIsDelete(1);
+        entity.setUpdateTime(LocalDateTime.now());
+        this.update(entity);
+
+        return Result.success();
+    }
+
+    @Override
+    public Result removeFile(Long fileId) {
+        FileEntity entity = fileService.findById(fileId);
+        if (entity == null){
+            return Result.success();
+        }
+
+        entity.setIsDelete(1);
+        entity.setIsIndex(0);
+        entity.setUpdateTime(LocalDateTime.now());
+        fileService.update(entity);
+        return Result.success();
+    }
+
+    @Override
+    public Result setIndex(Long fileId) {
+        FileEntity entity = fileService.findById(fileId);
+        if (entity == null) {
+            return Result.failure("对象不存在: " + fileId);
+        }
+        Long goodId = entity.getModuleId();
+        fileService.indexDisable(goodId, entity.getModule());
+        fileService.indexEnabled(fileId);
+
+        // 设置缩略图
+        setThumbByIndex(goodId, entity.getFilePath());
+        return Result.success();
+    }
+
+    private void setIndex(Long fileId, String module, GoodsEntity entity) {
+        Long goodId = entity.getId();
+        fileService.indexDisable(goodId, module);
+        fileService.indexEnabled(fileId);
+
+    }
+
+    /**
+     * 将封面图更新为缩略图
+     */
+    private void setThumbByIndex(Long goodId, String thumb){
+        GoodsEntity entity = this.findById(goodId);
+        entity.setThumb(thumb);
+        entity.setUpdateTime(LocalDateTime.now());
+        this.update(entity);
+    }
+
+    @Override
+    public Result uploadImg(MultipartFile file, String code) {
+        if (!fileUtils.checkFile(file)) {
+            throw new BaseRuntimeException("非法文件, 请重新上传");
+        }
+
+        if ("null".equals(code) || StringUtils.isBlank(code)) {
+            code = DateUtil.format(LocalDateTime.now(), "yyyyMMdd_HHmmssSSS");
+        }
+
+        Map<String, Object> result = fileUtils.imgUploadMapAndCompress(file, "/goods/img/" + code, false);
+        FileEntity entity = new FileEntity();
+        entity.setModule(TypeCode.MODULE_GOODS);
+        entity.setName(result.get("fileName").toString());
+
+
+        entity.setFilePath(result.get("filePath").toString());
+        fileService.save(entity);
+        result.put("id", entity.getId());
+        result.put("code", code);
+        return Result.success(result);
+    }
+
+    @Override
+    public Result detail(Long id) {
+        GoodsEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.failure(MsgCode.e3001,"对象不存在,id: " + id);
+        }
+
+        List<FileEntity> files = fileService.findByModuleId(id, TypeCode.MODULE_GOODS);
+        HashMap<Object, Object> result = new HashMap<>();
+        result.put("entity", entity);
+        result.put("file", files);
+        return Result.success(result);
+    }
+
+
+    @Override
+    public Result display(Long id, Integer display) {
+        GoodsEntity entity = this.findById(id);
+        if (entity == null) {
+            log.error("对象id不存在 : {}", id);
+            return Result.failure("对象id不存在");
+        }
+
+        entity.setDisplay(display);
+        this.update(entity);
+        return Result.success(entity);
+    }
+
+    @Override
+    public void addVisit(Long id) {
+        entityMapper.addVisit(id);
+
+    }
+
+    @Override
+    public Result<SearchVo> searchGlobal(PageDto param) {
+        startPage(param);
+        return Result.success(new PageInfo<>(entityMapper.searchGlobal(param)));
+    }
+
+    @Override
+    public Result afreshUploadImg(MultipartFile file, String code, Long fileId) {
+
+        if (StringUtils.isBlank(code) || StringUtils.equals(code, "null")){
+            return Result.failure("目录码不能为空");
+        }
+
+        FileEntity entity = fileService.findById(fileId);
+        if (entity == null){
+            return Result.failure("对象不存在");
+        }
+
+
+
+        Map<String, Object> map = fileUtils.imgUploadMapAndCompress(file, "/goods/img/" + code, false);
+
+        String filePath = (String) map.get("filePath");
+        String fileName = (String) map.get("fileName");
+
+        if (!StringUtils.equals(filePath, entity.getFilePath())){
+            fileUtils.del(entity.getFilePath());
+        }
+        entity.setName(fileName);
+        entity.setFilePath(filePath);
+        fileService.update(entity);
+
+        // 更新封面图 (这里最终是否成功,要结合保存功能)
+        updateIndexImg(entity);
+
+        return Result.success(entity);
+    }
+
+    // 更新封面图
+    private void updateIndexImg(FileEntity entity){
+        if (entity.getIsIndex() == 1) {
+            GoodsEntity goods = this.findById(entity.getModuleId());
+            if (goods == null){
+                String errorMsg = "对象不存现,更新封面失败";
+                throw new RuntimeException(errorMsg);
+            }
+
+            goods.setThumb(entity.getFilePath());
+            this.update(goods);
+            log.info("更新封面完成");
+        }
+
+
+    }
+
+
+    @Override
+    public Result upload(MultipartFile file, String type) {
+
+        // 检查非法文件上传
+        boolean checkFile = fileUtils.checkFile(file);
+        if (!checkFile) {
+            return Result.failure("上传文件格式有误, 请重新上传");
+        }
+
+        // 判断后缀名,需要包含这以下四个
+        String [] typeCheck = {"video","model","thumb","audio","pdf"};
+        if (!Arrays.asList(typeCheck).contains(type)) {
+            return Result.failure("非法类型");
+        }
+
+        // 文件目录
+        String newName = "";
+        String fileName = file.getOriginalFilename();
+        String suffix = StringUtils.substringAfterLast(fileName, ".");
+
+
+        // 视频、模型使用原名存储(中文转拼音)
+        if ("video".equals(type) || "model".equals(type) || "audio".equals(type)) {
+            newName = RegexUtil.getPinyinName(fileName);
+        } else {
+            newName = DateUtil.format(LocalDateTime.now(), "yyyyMMdd_HHmmssSSS");
+            newName = newName + "." + suffix;
+        }
+        String urlPath = "/goods/" + type + "/" + newName;
+        String savePath = configConstant.serverBasePath + urlPath;
+        log.info("保存文件地址:{}", savePath);
+
+        try {
+            FileUtil.writeFromStream(file.getInputStream(), savePath);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("fileName", fileName);
+        result.put("filePath", urlPath);
+        return Result.success(result);
+    }
+
+
+}

+ 148 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/SensitiveServiceImpl.java

@@ -0,0 +1,148 @@
+package com.gis.cms.service.impl;
+
+import com.gis.cms.entity.dto.SensitiveDto;
+import com.gis.cms.entity.po.SensitiveEntity;
+import com.gis.cms.mapper.SensitiveMapper;
+import com.gis.common.base.entity.dto.PageDto;
+import com.gis.common.base.mapper.IBaseMapper;
+import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.Result;
+import com.gis.cms.service.SensitiveService;
+import com.github.pagehelper.PageInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.entity.Condition;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * Created by owen on 2021/6/25 0011 16:16
+ */
+@Slf4j
+@Service
+public class SensitiveServiceImpl extends IBaseServiceImpl<SensitiveEntity, Long> implements SensitiveService {
+
+    @Autowired
+    private SensitiveMapper entityMapper;
+
+    static String REDIS_FILTER = "filter";
+
+    @Override
+    public IBaseMapper<SensitiveEntity, Long> getBaseMapper() {
+        return this.entityMapper;
+    }
+
+    @Override
+    public Result<SensitiveEntity> search(PageDto param) {
+        startPage(param);
+        Condition condition = new Condition(SensitiveEntity.class);
+        String searchKey = param.getSearchKey();
+        if (StringUtils.isNotBlank(searchKey)) {
+            searchKey = StringUtils.trim(searchKey);
+            condition.and().orLike("name", "%" + searchKey + "%");
+        }
+        condition.orderBy("createTime").desc();
+        PageInfo<SensitiveEntity> pageInfo = this.findAll(condition, param.getPageNum(), param.getPageSize());
+        return Result.success(pageInfo);
+
+    }
+
+
+    @Override
+    public Result saveEntity(SensitiveDto param) {
+        Long id = param.getId();
+        SensitiveEntity entity = null;
+        if (id == null) {
+            entity = new SensitiveEntity();
+            BeanUtils.copyProperties(param, entity);
+            entity.setUserName(getTokenUserName());
+            this.save(entity);
+        } else {
+            entity = this.findById(id);
+            if (entity == null) {
+                return Result.failure("对象不存在: " + id);
+            }
+            BeanUtils.copyProperties(param, entity);
+            entity.setUpdateTime(LocalDateTime.now());
+            this.update(entity);
+        }
+        redisUtil.del(getRedisFilterKey());
+        return Result.success(entity);
+    }
+
+    @Override
+    public Result remove(Long id) {
+        SensitiveEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.success();
+        }
+        // db数据软删除, 物理数据真删除
+        entity.setIsDelete(1);
+        entity.setUpdateTime(LocalDateTime.now());
+        this.update(entity);
+        redisUtil.del(getRedisFilterKey());
+        return  Result.success();
+    }
+
+    @Override
+    public Result<SensitiveEntity> detail(Long id) {
+        SensitiveEntity entity = this.findById(id);
+        if (entity == null) {
+            return Result.failure("对象不存在");
+        }
+        return  Result.success(entity);
+    }
+
+    @Override
+    public Set<Object> getFilterKey(){
+        String redisFilterKey = getRedisFilterKey();
+        Set<Object> filterKey = redisUtil.getJsonSet(redisFilterKey);
+        if (filterKey == null) {
+            log.info("走数据库");
+            filterKey = entityMapper.getName();
+            // 86400s-> 24H
+            redisUtil.setObjectToJson(redisFilterKey, filterKey, 86400);
+        }
+        log.info("走缓存");
+        log.info("filterKey: {}", filterKey);
+
+        return filterKey;
+    }
+
+    @Override
+    public Result refreshRedis() {
+        redisUtil.del(getRedisFilterKey());
+        return Result.success();
+    }
+
+    private String getRedisFilterKey(){
+        return configConstant.redisPrefix+REDIS_FILTER;
+    }
+
+    @Test
+    public void test(){
+        String[] a = {"小米","小红"};
+        List<String> filterKey = Arrays.asList(a);
+        String msg = "我是小米, 很喜欢小红哈哈, 小米啊 , 小, 明, 小后果小红";
+        for (String s : filterKey) {
+            msg =  msg.replaceAll(s, "**");
+
+        }
+
+
+
+        for (String s : filterKey) {
+            msg =  msg.replaceAll(s, "**");
+        }
+        System.out.println(msg);
+    }
+
+}

+ 139 - 0
gis_cms/src/main/java/com/gis/cms/tree/CommentTreeUtil.java

@@ -0,0 +1,139 @@
+package com.gis.cms.tree;
+
+import com.gis.cms.entity.vo.CommentVo;
+import com.gis.cms.tree.vo.CommentTree;
+import com.gis.common.util.MyStrUtil;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+@Slf4j
+public class CommentTreeUtil {
+
+    private List<CommentTree> resultNodes = new ArrayList<CommentTree>();//树形结构排序之后list内容
+
+    private List<CommentTree> nodes = new ArrayList<CommentTree>();
+
+    /**
+     *
+     * @param nodesList 转换对象
+     * @param filterKey 敏感词集合
+     */
+    public CommentTreeUtil(List<CommentVo> nodesList, Set<Object> filterKey) {//通过构造函数初始化
+
+        for (CommentVo n : nodesList) {
+            CommentTree vo = new CommentTree();
+            vo.setId(n.getId());
+            vo.setContent(n.getContent());
+            // 过滤敏感内容
+            vo.setContent(MyStrUtil.getFilterMsg(filterKey, n.getContent()));
+
+
+//            vo.setRealName(n.getRealName());
+            vo.setCreateTime(n.getCreateTime());
+            vo.setUpdateTime(n.getUpdateTime());
+//            vo.setUnit(n.getUnit());
+//            vo.setNickName(n.getNickName());
+            vo.setDisplay(n.getDisplay());
+//            vo.setIsRealName(n.getIsRealName());
+
+
+
+
+            if (n.getParentId() != null) {
+                vo.setParentId(n.getParentId());
+            }
+            nodes.add(vo);
+        }
+    }
+
+    public CommentTreeUtil() {
+    }
+
+    /**
+     * 构建树形结构list
+     *
+     * @return 返回树形结构List列表
+     */
+    public List<CommentTree> buildTree() {
+        for (CommentTree node : nodes) {
+            Long id = node.getParentId();
+            if (id == null) {//通过循环一级节点 就可以通过递归获取二级以下节点
+                resultNodes.add(node);//添加一级节点
+                node.setLevel(1);
+                build(node, node.getLevel());//递归获取二级、三级、。。。节点
+            }
+        }
+        return resultNodes;
+    }
+
+    /**
+     * 递归循环子节点
+     *
+     * @param node 当前节点
+     */
+    private void build(CommentTree node, int level) {
+        List<CommentTree> children = getChildren(node);
+        if (!children.isEmpty()) {//如果存在子节点
+            node.setChildren(children);
+//        	level++;
+            for (CommentTree child : children) {//将子节点遍历加入返回值中
+        		child.setLevel(level);
+                build(child, child.getLevel());
+            }
+        }
+    }
+
+    /**
+     * @param node
+     * @return 返回
+     */
+    private List<CommentTree> getChildren(CommentTree node) {
+        List<CommentTree> children = new ArrayList<CommentTree>();
+        Long id = node.getId();
+        for (CommentTree child : nodes) {
+            if (id.equals(child.getParentId())) {//如果id等于父id
+                children.add(child);//将该节点加入循环列表中
+            }
+        }
+        return children;
+    }
+
+
+    /**
+     * 过滤敏感内容
+     * @param filterKey 敏感词集合
+     * @param content 过滤内容
+     * @return
+     */
+//    private String getFilterMsg(Set<Object> filterKey, String content){
+//        for (Object s : filterKey) {
+//            if (s != null){
+//                content =  content.replaceAll(s.toString(), "**");
+//            }
+//        }
+//        return content;
+//    }
+
+//    public List<CommentTree> buildTree(List<SysResourceEntity> all, List<SysResourceEntity> in) {
+//        for (SysResourceEntity n : all) {
+//            CommentTree treeGrid = new CommentTree();
+//            treeGrid.setId(n.getId());
+//            treeGrid.setMsg(n.getMsg());
+//            treeGrid.setUserName(n.getUserName());
+//            treeGrid.setCreateTime(n.getCreateTime());
+//            for (SysResourceEntity nin : in) {
+//                if (nin.getId().equals(n.getId())) {
+//                }
+//            }
+//            if (n.getParentId() != null) {
+//                treeGrid.setParentId(n.getParentId());
+//            }
+//            nodes.add(treeGrid);
+//        }
+//        return buildTree();
+//    }
+
+}

+ 44 - 0
gis_cms/src/main/java/com/gis/cms/tree/vo/CommentTree.java

@@ -0,0 +1,44 @@
+package com.gis.cms.tree.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class CommentTree {
+
+    private Long id;
+
+    private String realName;
+
+    private Long parentId;
+
+    private String content;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+
+    private String nickName;
+
+    private String unit;
+
+    private Integer display;
+
+    @ApiModelProperty(value = "是否显示真实姓名: 1:是, 0:否")
+    private Integer isRealName;
+
+
+    // 子菜单/或按钮
+    private List<CommentTree> children;
+
+    @JSONField(serialize = false)
+    private int level;
+
+
+
+
+}

+ 6 - 0
gis_cms/src/main/resources/db/resource.sql

@@ -0,0 +1,6 @@
+
+
+INSERT INTO `sys_resource` VALUES (400, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '沙盘管理', 'menu', 'sand', NULL, NULL, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (412, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '编辑', 'button', 'sand:edit', NULL, 400, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (413, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '删除', 'button', 'sand:remove', NULL, 400, 0, NULL, NULL);
+INSERT INTO `sys_resource` VALUES (414, '2021-07-05 15:49:29', '2021-07-05 15:49:29', '查看', 'button', 'sand:detail', NULL, 400, 0, NULL, NULL);

+ 0 - 0
gis_cms/src/main/resources/db/sys_admin.sql


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini