Pu Zhibing
2024-12-23 05e753e2a094de490d34a50a60571835217cd1b8
提交1.0版本
508个文件已添加
1个文件已修改
110148 ■■■■■ 已修改文件
.gitignore 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/pom.xml 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/GunsApplication.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/GunsServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/EhCacheConfig.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/SpringSessionConfig.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/SwaggerConfig.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/datasource/MultiDataSourceConfig.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/datasource/SingleDataSourceConfig.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/properties/BeetlProperties.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/properties/GunsProperties.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/web/BeetlConfig.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/web/ShiroConfig.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/config/web/WebConfig.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/aop/GlobalExceptionHandler.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/aop/LogAop.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/aop/PermissionAop.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/beetl/BeetlConfiguration.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/beetl/ShiroExt.java 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/annotion/BussinessLog.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/annotion/Permission.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/Const.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/DatasourceEnum.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/JwtConstants.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/cache/Cache.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/cache/CacheKey.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/DeleteDict.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/DeptDict.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/DictMap.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/LogDict.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/MenuDict.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/NoticeMap.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/RoleDict.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/UserDict.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/base/AbstractDictMap.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/base/SystemDict.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/factory/DictFieldWarpperFactory.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/ConstantFactory.java 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/IConstantFactory.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/MutiStrFactory.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/PageFactory.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/BizLogType.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/ExpenseState.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/LogSucceed.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/LogType.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/ManagerStatus.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/MenuOpenStatus.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/MenuStatus.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/Order.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/exception/BizExceptionEnum.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/common/exception/InvalidKaptchaException.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/intercept/GunsUserFilter.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/intercept/RestApiInteceptor.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/intercept/SessionHolderInterceptor.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/listener/ConfigListener.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/log/LogManager.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/log/LogObjectHolder.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/log/factory/LogFactory.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/log/factory/LogTaskFactory.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/ShiroDbRealm.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/ShiroKit.java 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/ShiroUser.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/check/ICheck.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/check/PermissionCheckFactory.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/check/PermissionCheckManager.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/factory/IShiro.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/factory/ShiroFactroy.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/tag/DictSelectorTag.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/util/ApiMenuFilter.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/util/Contrast.java 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/util/JwtTokenUtil.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/core/util/KaptchaUtil.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/api/ApiController.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/api/PatrolTaskController.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/code/controller/CodeController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/code/factory/DefaultTemplateFactory.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/code/service/TableService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/AuthIntercepter.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/AuthService.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/AuthenticationKit.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/Configuration.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/HMACSHA1.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/HashKit.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/UrlEncoderUtils.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/BlackboardController.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/DeptController.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/DictController.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/KaptchaController.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/LogController.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/LoginController.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/LoginLogController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/MenuController.java 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/NoticeController.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/RoleController.java 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/UserMgrController.java 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/DeptMapper.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/DictMapper.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/LoginLogMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/MenuMapper.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/NoticeMapper.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/OperationLogMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/PatrolTaskMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/RelationMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/RoleMapper.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailMapper.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailVehiclesChannelMapper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailVehiclesMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/UserMapper.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/DeptMapper.xml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/DictMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/LoginLogMapper.xml 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/MenuMapper.xml 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/NoticeMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/OperationLogMapper.xml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/PatrolTaskMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/RelationMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/RoleMapper.xml 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailMapper.xml 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailVehiclesChannelMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailVehiclesMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/UserMapper.xml 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/factory/UserFactory.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Dept.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Dict.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/LoginLog.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Menu.java 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Notice.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/OperationLog.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/PatrolTask.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Relation.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Role.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TaskDetail.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TaskDetailVehicles.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TaskDetailVehiclesChannel.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/User.java 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/enums/ImageModelEnum.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/enums/VideoChannelEnum.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/ManualAuditVo.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PatrolTaskVo.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PictureDetails.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PictureDetailsVehicle.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PictureDetailsVo.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskDetailList.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskDetailListVo.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskRecordInfo.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskRecordList.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskRecordListVo.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/VehicleVo.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IDeptService.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IDictService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ILoginLogService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IMenuService.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/INoticeService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IOperationLogService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IPatrolTaskService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IRelationService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IRoleService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailService.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailVehiclesChannelService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailVehiclesService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IUserService.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/DeptServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/DictServiceImpl.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/LoginLogServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/MenuServiceImpl.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/NoticeServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/OperationLogServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/PatrolTaskServiceImpl.java 340 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/RelationServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/RoleServiceImpl.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailServiceImpl.java 475 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailVehiclesChannelServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailVehiclesServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/UserServiceImpl.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/ManagerUser.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/ReqAddManager.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/ReqEditManager.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/UserDto.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/DateUtil.java 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/ExcelUtil.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/MD5AndKL.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/ResultUtil.java 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/SpringUtils.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/SystemException.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/UUIDUtil.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/imageModel/ImageModelUtil.java 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/quartz/QuartzUtil.java 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/quartz/jobs/PatrolTaskJob.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/quartz/model/QuartzEnum.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/VideoGateway.java 518 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/AccountLogin.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/SessionId.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/Ship.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/TrackInfo.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/Vehicle.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/VehicleOnline.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/ActivityWarpper.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/BalanceUsageRecord.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/BalanceUsageRecordList.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/BaseWarpper.java 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DeptWarpper.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DictWarpper.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DriverInfoWarpper.java 506 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DriverInviteInfoWarpper.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/EmailWarpper.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/HomeWarpper.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/LogWarpper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/LoginWarpper.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/MenuWarpper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/MoneyInfoWarpper.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/NoticeWrapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderEvaluateWarpper.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderInfoWarpper.java 598 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderListWarpper.java 271 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderStatusWarpper.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrdersWarpper.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/QueryHistoricalSettlement.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/QuerySettlementAmount.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/QuerySettlementAmountDetails.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/RegisteredWarpper.java 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/RoleWarpper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/SystemNoticeWarpper.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/UserWarpper.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/VersionWarpper.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/WithdrawalListWarpper.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/WithdrawalWarpper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/resources/META-INF/spring-devtools.properties 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/resources/application.yml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/resources/ehcache.xml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/resources/logback-spring.xml 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/404.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/blackboard.html 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/code/code.html 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/_container.html 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/_right.html 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/_tab.html 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/_theme.html 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/NameCon.tag 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/SelectCon.tag 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/TimeCon.tag 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/avatar.tag 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/button.tag 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/input.tag 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/select.tag 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/table.tag 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/common/tags/tag_tips 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/index.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/login.html 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/code/code.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept.html 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_add.html 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_edit.html 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict.html 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_add.html 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_edit.html 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/log/log.html 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/log/login_log.html 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_add.html 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_edit.html 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice.html 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_add.html 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_edit.html 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/role/role.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/role/role_add.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/role/role_assign.html 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/role/role_edit.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/user/user.html 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/user/user_add.html 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/user/user_chpwd.html 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/user/user_edit.html 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/user/user_roleassign.html 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/WEB-INF/view/system/user/user_view.html 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/_fstyle.css 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/bootstrap-rtl.css 1468 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/bootstrap.min.css 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/font-awesome.css 2026 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/font-awesome.min.css 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/login.css 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-1.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-3.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/patterns/header-profile.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/patterns/shattered.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/bootstrap-table/bootstrap-table.min.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/bootstrap-treetable/bootstrap-treetable.css 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/chosen/chosen.css 423 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/iCheck/custom.css 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/iCheck/green.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/iCheck/green@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/images/sprite-skin-flat.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/validate/bootstrapValidator.min.css 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/webuploader/webuploader.css 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/demo.css 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_close.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_open.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/2.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/3.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/4.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/5.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/6.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/7.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/8.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/9.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/line_conn.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/loading.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/plugins/ztree/zTreeStyle.css 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/css/style.css 7897 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/FontAwesome.otf 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.eot 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.svg 640 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.ttf 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff2 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.eot 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.svg 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.ttf 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff2 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/bg.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/boy.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/girl.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/icons.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/loading-upload.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/locked.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/img/user.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/bootstrap.min.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/DateUtils.js 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/Feng.js 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/ajax-object.js 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/bootstrap-table-object.js 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/select-list-object.js 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/tree-table-object.js 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/web-upload-object.js 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/common/ztree-object.js 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/contabs.js 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/content.js 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/hplus.js 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/jquery.min.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/jquery.min.map 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table.min.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/bootstrap-treetable/bootstrap-treetable.js 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/chosen/chosen.jquery.js 1211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/iCheck/icheck.min.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/laydate/laydate.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.eot 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.svg 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.ttf 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.woff 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/laydate.css 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/layer.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/mobile/layer.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/mobile/need/layer.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon-ext.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon.png 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/layer.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-0.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-1.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-2.gif 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/metisMenu/jquery.metisMenu.js 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/pace/pace.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/slimscroll/jquery.slimscroll.min.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/validate/additional-methods.min.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/validate/bootstrapValidator.min.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/validate/zh_CN.js 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/wangEditor/wangEditor.js 3967 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/Uploader.swf 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.css 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.js 6502 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.fis.js 8083 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.js 4622 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.js 6030 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.js 8106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.min.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.js 5026 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.js 8012 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.min.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.js 4993 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/js/plugins/ztree/jquery.ztree.all.min.js 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/code/gen.js 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/flowable/expense/expense.js 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/flowable/expense/expense_info.js 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/flowable/process/process.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/flowable/process/process_info.js 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/code/code.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/dept/dept.js 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/dept/dept_info.js 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/dict/dict.js 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/dict/dict_info.js 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/log/log.js 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/log/login_log.js 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/menu/menu.js 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/menu/menu_info.js 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/notice/notice.js 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/notice/notice_info.js 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/role/role.js 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/role/role_info.js 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/user/user.js 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/webapp/static/modular/system/user/user_info.js 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/test/java/com/stylefeng/guns/GunsApplicationTest.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/pom.xml 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java 508 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java 801 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java 1370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java 1060 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java 582 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/resources/META-INF/spring.factories 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-core/src/main/resources/default-config.properties 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/pom.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vehicle_inspection.sql 1266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -2,7 +2,7 @@
# Mobile Tools for Java (J2ME)
.mtj.tmp/
.idea/
# Package Files #
*.jar
*.war
@@ -10,3 +10,4 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
guns-admin/pom.xml
New file
@@ -0,0 +1,280 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.stylefeng</groupId>
        <artifactId>guns-parent</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>driver</artifactId>
    <name>guns-admin</name>
    <description>guns 的spring boot版本</description>
    <packaging>jar</packaging>
    <dependencies>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.stylefeng</groupId>
            <artifactId>guns-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.stylefeng</groupId>
            <artifactId>guns-generator</artifactId>
        </dependency>
        <!--spring boot依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk18on</artifactId>
            <version>1.78.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--shiro依赖-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <!--需要分布式session的话需要放开注释-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.session</groupId>-->
            <!--<artifactId>spring-session-data-redis</artifactId>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.boot</groupId>-->
            <!--<artifactId>spring-boot-starter-data-redis</artifactId>-->
        <!--</dependency>-->
        <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.13.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-codec</groupId>
                    <artifactId>commons-codec</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.13</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
        <!--任务调度框架-->
        <!--quartz依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.0.0</version>
        </dependency>
    </dependencies>
    <build>
        <!--打包jar包方式-->
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork><!-- 如果没有该项配置,肯呢个devtools不会起作用,即应用不会restart -->
                </configuration>
            </plugin>
        </plugins>
        <!--打包war包引入本地jar的打包方式-->
        <!--<plugins>-->
            <!--<plugin>-->
                <!--<groupId>org.apache.maven.plugins</groupId>-->
                <!--<artifactId>maven-war-plugin</artifactId>-->
                <!--<configuration>-->
                    <!--&lt;!&ndash; 设置成false,否则检查web.xml是否存在。因为springboot是没有web.xml的 &ndash;&gt;-->
                    <!--<failOnMissingWebXml>false</failOnMissingWebXml>-->
                    <!--&lt;!&ndash;打包后的项目名&ndash;&gt;-->
                    <!--&lt;!&ndash;<warName>example</warName>&ndash;&gt;-->
                    <!--&lt;!&ndash;<webResources>&ndash;&gt;-->
                        <!--&lt;!&ndash;<resource>&ndash;&gt;-->
                            <!--&lt;!&ndash;把本地lib里面的jar复制到lib&ndash;&gt;-->
                            <!--&lt;!&ndash;<directory>${project.basedir}/lib</directory>&ndash;&gt;-->
                            <!--&lt;!&ndash;<targetPath>WEB-INF/lib/</targetPath>&ndash;&gt;-->
                            <!--&lt;!&ndash;<includes>&ndash;&gt;-->
                                <!--&lt;!&ndash;<include>**/*.jar</include>&ndash;&gt;-->
                            <!--&lt;!&ndash;</includes>&ndash;&gt;-->
                        <!--&lt;!&ndash;</resource>&ndash;&gt;-->
                    <!--&lt;!&ndash;</webResources>&ndash;&gt;-->
                <!--</configuration>-->
            <!--</plugin>-->
        <!--</plugins>-->
        <resources>
            <resource>
                <directory>lib</directory>
                <targetPath>/BOOT-INF/lib/</targetPath>
                <includes>
                    <include>**/*.jar</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/webapp</directory>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>
guns-admin/src/main/java/com/stylefeng/guns/GunsApplication.java
New file
@@ -0,0 +1,39 @@
package com.stylefeng.guns;
import com.stylefeng.guns.modular.system.util.quartz.QuartzUtil;
import org.apache.http.client.HttpClient;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
/**
 * SpringBoot方式启动类
 *
 * @author stylefeng
 * @Date 2017/5/21 12:06
 */
@SpringBootApplication
@EnableScheduling//开启定时任务
@EnableTransactionManagement//启动事务功能
public class GunsApplication {
    private final static Logger logger = LoggerFactory.getLogger(GunsApplication.class);
    public static void main(String[] args) {
        SpringApplication.run(GunsApplication.class, args);
        logger.info("GunsApplication is success!");
    }
}
guns-admin/src/main/java/com/stylefeng/guns/GunsServletInitializer.java
New file
@@ -0,0 +1,18 @@
package com.stylefeng.guns;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
 * Guns Web程序启动类
 *
 * @author fengshuonan
 * @date 2017-05-21 9:43
 */
public class GunsServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(GunsApplication.class);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/EhCacheConfig.java
New file
@@ -0,0 +1,39 @@
package com.stylefeng.guns.config;
import net.sf.ehcache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
/**
 * ehcache配置
 *
 * @author fengshuonan
 * @date 2017-05-20 23:11
 */
@Configuration
@EnableCaching
public class EhCacheConfig {
    /**
     * EhCache的配置
     */
    @Bean
    public EhCacheCacheManager cacheManager(CacheManager cacheManager) {
        return new EhCacheCacheManager(cacheManager);
    }
    /**
     * EhCache的配置
     */
    @Bean
    public EhCacheManagerFactoryBean ehcache() {
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        ehCacheManagerFactoryBean.setShared(true);//共享缓存,避免tomcat启动报错
        return ehCacheManagerFactoryBean;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/SpringSessionConfig.java
New file
@@ -0,0 +1,15 @@
package com.stylefeng.guns.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
/**
 * spring session配置
 *
 * @author fengshuonan
 * @date 2017-07-13 21:05
 */
//@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)  //session过期时间  如果部署多机环境,需要打开注释
@ConditionalOnProperty(prefix = "guns", name = "spring-session-open", havingValue = "true")
public class SpringSessionConfig {
}
guns-admin/src/main/java/com/stylefeng/guns/config/SwaggerConfig.java
New file
@@ -0,0 +1,47 @@
package com.stylefeng.guns.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
 * swagger配置类
 *
 * @author fengshuonan
 * @date 2017年6月1日19:42:59
 */
@Configuration
@EnableSwagger2
@ConditionalOnProperty(prefix = "guns", name = "swagger-open", havingValue = "true")
public class SwaggerConfig{
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))                         //这里采用包含注解的方式来确定要显示的接口
                //.apis(RequestHandlerSelectors.basePackage("com.stylefeng.guns.modular.system.controller"))    //这里采用包扫描的方式来确定要显示的接口
                .paths(PathSelectors.any())
                .build();
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("喜望出行 Doc")
                .description("所有接口前需要加 /driver 前缀,例如:/driver/base/agreement/queryByType <br>所有以 /api/*** 路径的接口需要上传签名参数sign")
//                .termsOfServiceUrl("http://git.oschina.net/naan1993/guns")
                .contact("stylefeng")
                .version("1.0")
                .build();
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/datasource/MultiDataSourceConfig.java
New file
@@ -0,0 +1,125 @@
package com.stylefeng.guns.config.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.stylefeng.guns.core.config.properties.DruidProperties;
import com.stylefeng.guns.core.config.properties.MutiDataSourceProperties;
import com.stylefeng.guns.core.datascope.DataScopeInterceptor;
import com.stylefeng.guns.core.mutidatasource.DynamicDataSource;
import com.stylefeng.guns.core.mutidatasource.aop.MultiSourceExAop;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.sql.SQLException;
import java.util.HashMap;
/**
 * 多数据源配置<br/>
 * <p>
 * 注:由于引入多数据源,所以让spring事务的aop要在多数据源切换aop的后面
 *
 * @author stylefeng
 * @Date 2017/5/20 21:58
 */
@Configuration
@ConditionalOnProperty(prefix = "guns.muti-datasource", name = "open", havingValue = "true")
@EnableTransactionManagement(order = 2)
@MapperScan(basePackages = {"com.stylefeng.guns.modular.*.dao","com.stylefeng.guns.multi.mapper"})
public class MultiDataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "guns.muti-datasource")
    public MutiDataSourceProperties mutiDataSourceProperties() {
        return new MutiDataSourceProperties();
    }
    @Bean
    public MultiSourceExAop multiSourceExAop() {
        return new MultiSourceExAop();
    }
    /**
     * guns的数据源
     */
    private DruidDataSource dataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = new DruidDataSource();
        druidProperties.config(dataSource);
        return dataSource;
    }
    /**
     * 多数据源,第二个数据源
     */
    private DruidDataSource bizDataSource(DruidProperties druidProperties, MutiDataSourceProperties mutiDataSourceProperties) {
        DruidDataSource dataSource = new DruidDataSource();
        druidProperties.config(dataSource);
        mutiDataSourceProperties.config(dataSource);
        return dataSource;
    }
    /**
     * 多数据源连接池配置
     */
    @Bean
    public DynamicDataSource mutiDataSource(DruidProperties druidProperties, MutiDataSourceProperties mutiDataSourceProperties) {
        DruidDataSource dataSourceGuns = dataSource(druidProperties);
        DruidDataSource bizDataSource = bizDataSource(druidProperties, mutiDataSourceProperties);
        try {
            dataSourceGuns.init();
            bizDataSource.init();
        } catch (SQLException sql) {
            sql.printStackTrace();
        }
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put(mutiDataSourceProperties.getDataSourceNames()[0], dataSourceGuns);
        hashMap.put(mutiDataSourceProperties.getDataSourceNames()[1], bizDataSource);
        dynamicDataSource.setTargetDataSources(hashMap);
        dynamicDataSource.setDefaultTargetDataSource(dataSourceGuns);
        return dynamicDataSource;
    }
    /**
     * mybatis-plus分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
    /**
     * 数据范围mybatis插件
     */
    @Bean
    public DataScopeInterceptor dataScopeInterceptor() {
        return new DataScopeInterceptor();
    }
    /**
     * 乐观锁mybatis插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    /**
     * 事务配置
     *
     * @author stylefeng
     * @Date 2018/6/27 23:11
     */
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DynamicDataSource mutiDataSource) {
        return new DataSourceTransactionManager(mutiDataSource);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/datasource/SingleDataSourceConfig.java
New file
@@ -0,0 +1,61 @@
package com.stylefeng.guns.config.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.stylefeng.guns.core.config.properties.DruidProperties;
import com.stylefeng.guns.core.datascope.DataScopeInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
 * 多数据源配置
 *
 * @author stylefeng
 * @Date 2017/5/20 21:58
 */
@Configuration
@ConditionalOnProperty(prefix = "guns.muti-datasource", name = "open", havingValue = "false", matchIfMissing = true)
@EnableTransactionManagement
@MapperScan(basePackages = {"com.stylefeng.guns.modular.*.dao"})
public class SingleDataSourceConfig {
    /**
     * 单数据源连接池配置
     */
    @Bean
    public DruidDataSource dataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = new DruidDataSource();
        druidProperties.config(dataSource);
        return dataSource;
    }
    /**
     * mybatis-plus分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
    /**
     * 数据范围mybatis插件
     */
    @Bean
    public DataScopeInterceptor dataScopeInterceptor() {
        return new DataScopeInterceptor();
    }
    /**
     * 乐观锁mybatis插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/properties/BeetlProperties.java
New file
@@ -0,0 +1,103 @@
package com.stylefeng.guns.config.properties;
import com.stylefeng.guns.core.util.ToolUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
 * beetl配置(如果需要配置别的配置可参照这个形式自己添加)
 *
 * @author fengshuonan
 * @date 2017-05-24 20:37
 */
@Configuration
@ConfigurationProperties(prefix = BeetlProperties.BEETLCONF_PREFIX)
public class BeetlProperties {
    public static final String BEETLCONF_PREFIX = "beetl";
    private String delimiterStatementStart;
    private String delimiterStatementEnd;
    private String resourceTagroot;
    private String resourceTagsuffix;
    private String resourceAutoCheck;
    @Value("${spring.mvc.view.prefix}")
    private String prefix;
    public Properties getProperties(){
        Properties properties = new Properties();
        if(ToolUtil.isNotEmpty(delimiterStatementStart)){
            if(delimiterStatementStart.startsWith("\\")){
                delimiterStatementStart = delimiterStatementStart.substring(1);
            }
            properties.setProperty("DELIMITER_STATEMENT_START",delimiterStatementStart);
        }
        if(ToolUtil.isNotEmpty(delimiterStatementEnd)){
            properties.setProperty("DELIMITER_STATEMENT_END",delimiterStatementEnd);
        }else{
            properties.setProperty("DELIMITER_STATEMENT_END","null");
        }
        if(ToolUtil.isNotEmpty(resourceTagroot)){
            properties.setProperty("RESOURCE.tagRoot",resourceTagroot);
        }
        if(ToolUtil.isNotEmpty(resourceTagsuffix)){
            properties.setProperty("RESOURCE.tagSuffix",resourceTagsuffix);
        }
        if(ToolUtil.isNotEmpty(resourceAutoCheck)){
            properties.setProperty("RESOURCE.autoCheck",resourceAutoCheck);
        }
        return properties;
    }
    public String getPrefix() {
        return prefix;
    }
    public String getDelimiterStatementStart() {
        return delimiterStatementStart;
    }
    public void setDelimiterStatementStart(String delimiterStatementStart) {
        this.delimiterStatementStart = delimiterStatementStart;
    }
    public String getDelimiterStatementEnd() {
        return delimiterStatementEnd;
    }
    public void setDelimiterStatementEnd(String delimiterStatementEnd) {
        this.delimiterStatementEnd = delimiterStatementEnd;
    }
    public String getResourceTagroot() {
        return resourceTagroot;
    }
    public void setResourceTagroot(String resourceTagroot) {
        this.resourceTagroot = resourceTagroot;
    }
    public String getResourceTagsuffix() {
        return resourceTagsuffix;
    }
    public void setResourceTagsuffix(String resourceTagsuffix) {
        this.resourceTagsuffix = resourceTagsuffix;
    }
    public String getResourceAutoCheck() {
        return resourceAutoCheck;
    }
    public void setResourceAutoCheck(String resourceAutoCheck) {
        this.resourceAutoCheck = resourceAutoCheck;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/properties/GunsProperties.java
New file
@@ -0,0 +1,105 @@
package com.stylefeng.guns.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
import static com.stylefeng.guns.core.util.ToolUtil.getTempPath;
import static com.stylefeng.guns.core.util.ToolUtil.isEmpty;
/**
 * guns项目配置
 *
 * @author stylefeng
 * @Date 2017/5/23 22:31
 */
@Component
@ConfigurationProperties(prefix = GunsProperties.PREFIX)
public class GunsProperties {
    public static final String PREFIX = "guns";
    private Boolean kaptchaOpen = false;
    private Boolean swaggerOpen = false;
    private String fileUploadPath;
    private Boolean haveCreatePath = false;
    private Boolean springSessionOpen = false;
    /**
     * session 失效时间(默认为30分钟 单位:秒)
     */
    private Integer sessionInvalidateTime = 30 * 60;
    /**
     * session 验证失效时间(默认为15分钟 单位:秒)
     */
    private Integer sessionValidationInterval = 15 * 60;
    public String getFileUploadPath() {
        //如果没有写文件上传路径,保存到临时目录
        if (isEmpty(fileUploadPath)) {
            return getTempPath();
        } else {
            //判断有没有结尾符,没有得加上
            if (!fileUploadPath.endsWith(File.separator)) {
                fileUploadPath = fileUploadPath + File.separator;
            }
            //判断目录存不存在,不存在得加上
            if (!haveCreatePath) {
                File file = new File(fileUploadPath);
                file.mkdirs();
                haveCreatePath = true;
            }
            return fileUploadPath;
        }
    }
    public void setFileUploadPath(String fileUploadPath) {
        this.fileUploadPath = fileUploadPath;
    }
    public Boolean getKaptchaOpen() {
        return kaptchaOpen;
    }
    public void setKaptchaOpen(Boolean kaptchaOpen) {
        this.kaptchaOpen = kaptchaOpen;
    }
    public Boolean getSwaggerOpen() {
        return swaggerOpen;
    }
    public void setSwaggerOpen(Boolean swaggerOpen) {
        this.swaggerOpen = swaggerOpen;
    }
    public Boolean getSpringSessionOpen() {
        return springSessionOpen;
    }
    public void setSpringSessionOpen(Boolean springSessionOpen) {
        this.springSessionOpen = springSessionOpen;
    }
    public Integer getSessionInvalidateTime() {
        return sessionInvalidateTime;
    }
    public void setSessionInvalidateTime(Integer sessionInvalidateTime) {
        this.sessionInvalidateTime = sessionInvalidateTime;
    }
    public Integer getSessionValidationInterval() {
        return sessionValidationInterval;
    }
    public void setSessionValidationInterval(Integer sessionValidationInterval) {
        this.sessionValidationInterval = sessionValidationInterval;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/web/BeetlConfig.java
New file
@@ -0,0 +1,46 @@
package com.stylefeng.guns.config.web;
import com.stylefeng.guns.config.properties.BeetlProperties;
import com.stylefeng.guns.core.beetl.BeetlConfiguration;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.beetl.ext.spring.BeetlSpringViewResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * web 配置类
 *
 * @author fengshuonan
 * @date 2016年11月12日 下午5:03:32
 */
@Configuration
public class BeetlConfig {
    @Autowired
    BeetlProperties beetlProperties;
    /**
     * beetl的配置
     */
    @Bean(initMethod = "init")
    public BeetlConfiguration beetlConfiguration() {
        BeetlConfiguration beetlConfiguration = new BeetlConfiguration();
        beetlConfiguration.setResourceLoader(new ClasspathResourceLoader(BeetlConfig.class.getClassLoader(), beetlProperties.getPrefix()));
        beetlConfiguration.setConfigProperties(beetlProperties.getProperties());
        return beetlConfiguration;
    }
    /**
     * beetl的视图解析器
     */
    @Bean
    public BeetlSpringViewResolver beetlViewResolver() {
        BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver();
        beetlSpringViewResolver.setConfig(beetlConfiguration());
        beetlSpringViewResolver.setContentType("text/html;charset=UTF-8");
        beetlSpringViewResolver.setOrder(0);
        return beetlSpringViewResolver;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/web/ShiroConfig.java
New file
@@ -0,0 +1,214 @@
package com.stylefeng.guns.config.web;
import com.stylefeng.guns.config.properties.GunsProperties;
import com.stylefeng.guns.core.intercept.GunsUserFilter;
import com.stylefeng.guns.core.shiro.ShiroDbRealm;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.mgt.SessionManager;
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.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * shiro权限管理的配置
 *
 * @author fengshuonan
 * @date 2016年11月14日 下午3:03:44
 */
@Configuration
public class ShiroConfig {
    /**
     * 安全管理器
     */
    @Bean
    public DefaultWebSecurityManager securityManager(CookieRememberMeManager rememberMeManager, CacheManager cacheShiroManager, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(this.shiroDbRealm());
        securityManager.setCacheManager(cacheShiroManager);
        securityManager.setRememberMeManager(rememberMeManager);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }
    /**
     * spring session管理器(多机环境)
     */
    @Bean
    @ConditionalOnProperty(prefix = "guns", name = "spring-session-open", havingValue = "true")
    public ServletContainerSessionManager servletContainerSessionManager() {
        return new ServletContainerSessionManager();
    }
    /**
     * session管理器(单机环境)
     */
    @Bean
    @ConditionalOnProperty(prefix = "guns", name = "spring-session-open", havingValue = "false")
    public DefaultWebSessionManager defaultWebSessionManager(CacheManager cacheShiroManager, GunsProperties gunsProperties) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setCacheManager(cacheShiroManager);
        sessionManager.setSessionValidationInterval(gunsProperties.getSessionValidationInterval() * 1000);
        sessionManager.setGlobalSessionTimeout(gunsProperties.getSessionInvalidateTime() * 1000);
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
        cookie.setName("shiroCookie");
        cookie.setHttpOnly(true);
        sessionManager.setSessionIdCookie(cookie);
        return sessionManager;
    }
    /**
     * 缓存管理器 使用Ehcache实现
     */
    @Bean
    public CacheManager getCacheShiroManager(EhCacheManagerFactoryBean ehcache) {
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(ehcache.getObject());
        return ehCacheManager;
    }
    /**
     * 项目自定义的Realm
     */
    @Bean
    public ShiroDbRealm shiroDbRealm() {
        return new ShiroDbRealm();
    }
    /**
     * rememberMe管理器, cipherKey生成见{@code Base64Test.java}
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) {
        CookieRememberMeManager manager = new CookieRememberMeManager();
        manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA=="));
        manager.setCookie(rememberMeCookie);
        return manager;
    }
    /**
     * 记住密码Cookie
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        simpleCookie.setHttpOnly(true);
        simpleCookie.setMaxAge(7 * 24 * 60 * 60);//7天
        return simpleCookie;
    }
    /**
     * Shiro的过滤器链
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        /**
         * 默认的登陆访问url
         */
        shiroFilter.setLoginUrl("/login");
        /**
         * 登陆成功后跳转的url
         */
        shiroFilter.setSuccessUrl("/");
        /**
         * 没有权限跳转的url
         */
        shiroFilter.setUnauthorizedUrl("/global/error");
        /**
         * 覆盖默认的user拦截器(默认拦截器解决不了ajax请求 session超时的问题,若有更好的办法请及时反馈作者)
         */
        HashMap<String, Filter> myFilters = new HashMap<>();
        myFilters.put("user", new GunsUserFilter());
        shiroFilter.setFilters(myFilters);
        /**
         * 配置shiro拦截器链
         *
         * anon  不需要认证
         * authc 需要认证
         * user  验证通过或RememberMe登录的都可以
         *
         * 当应用开启了rememberMe时,用户下次访问时可以是一个user,但不会是authc,因为authc是需要重新认证的
         *
         * 顺序从上到下,优先级依次降低
         *
         * api开头的接口,走rest api鉴权,不走shiro鉴权
         *
         */
        Map<String, String> hashMap = new LinkedHashMap<>();
        hashMap.put("/swagger-ui.html", "anon");
        hashMap.put("/swagger-resources/**", "anon");
        hashMap.put("/v2/**", "anon");
        hashMap.put("/webjars/**", "anon");
        hashMap.put("/swagger-resources/configuration/ui/**", "anon");
        hashMap.put("/swagger-resources/configuration/security/**", "anon");
        hashMap.put("/base/**", "anon");
        hashMap.put("/api/**", "anon");
        hashMap.put("/static/**", "anon");
        hashMap.put("/gunsApi/**", "anon");
        hashMap.put("/login", "anon");
        hashMap.put("/global/sessionError", "anon");
        hashMap.put("/kaptcha", "anon");
        hashMap.put("/**", "user");
        shiroFilter.setFilterChainDefinitionMap(hashMap);
        return shiroFilter;
    }
    /**
     * 在方法中 注入 securityManager,进行代理控制
     */
    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean(DefaultWebSecurityManager securityManager) {
        MethodInvokingFactoryBean bean = new MethodInvokingFactoryBean();
        bean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        bean.setArguments(new Object[]{securityManager});
        return bean;
    }
    /**
     * Shiro生命周期处理器:
     * 用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调(例如:UserRealm)
     * 在实现了Destroyable接口的Shiro bean销毁时调用 Destroyable接口回调(例如:DefaultSecurityManager)
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    /**
     * 启用shrio授权注解拦截方式,AOP式方法级权限检查
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
                new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/config/web/WebConfig.java
New file
@@ -0,0 +1,174 @@
package com.stylefeng.guns.config.web;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.BeanTypeAutoProxyCreator;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.stylefeng.guns.config.properties.GunsProperties;
import com.stylefeng.guns.core.intercept.RestApiInteceptor;
import com.stylefeng.guns.core.listener.ConfigListener;
import com.stylefeng.guns.core.xss.XssFilter;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.Arrays;
import java.util.Properties;
/**
 * web 配置类
 *
 * @author fengshuonan
 * @date 2016年11月12日 下午5:03:32
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Autowired
    private GunsProperties gunsProperties;
    /**
     * 增加swagger的支持
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        if (gunsProperties.getSwaggerOpen()) {
            registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
    }
    /**
     * 增加对rest api鉴权的spring mvc拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RestApiInteceptor()).addPathPatterns("/api/**");
    }
    /**
     * druidServlet注册
     */
    @Bean
    public ServletRegistrationBean druidServletRegistration() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
        registration.addUrlMappings("/druid/*");
        return registration;
    }
    /**
     * druid监控 配置URI拦截策略
     */
    @Bean
    public FilterRegistrationBean druidStatFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        //添加过滤规则.
        filterRegistrationBean.addUrlPatterns("/*");
        //添加不需要忽略的格式信息.
        filterRegistrationBean.addInitParameter(
                "exclusions", "/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid,/druid/*");
        //用于session监控页面的用户名显示 需要登录后主动将username注入到session里
        filterRegistrationBean.addInitParameter("principalSessionName", "username");
        return filterRegistrationBean;
    }
    /**
     * druid数据库连接池监控
     */
    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        return new DruidStatInterceptor();
    }
    @Bean
    public JdkRegexpMethodPointcut druidStatPointcut() {
        JdkRegexpMethodPointcut druidStatPointcut = new JdkRegexpMethodPointcut();
        String patterns = "com.stylefeng.guns.modular.*.service.*";
        //可以set多个
        druidStatPointcut.setPatterns(patterns);
        return druidStatPointcut;
    }
    /**
     * druid数据库连接池监控
     */
    @Bean
    public BeanTypeAutoProxyCreator beanTypeAutoProxyCreator() {
        BeanTypeAutoProxyCreator beanTypeAutoProxyCreator = new BeanTypeAutoProxyCreator();
        beanTypeAutoProxyCreator.setTargetBeanType(DruidDataSource.class);
        beanTypeAutoProxyCreator.setInterceptorNames("druidStatInterceptor");
        return beanTypeAutoProxyCreator;
    }
    /**
     * druid 为druidStatPointcut添加拦截
     *
     * @return
     */
    @Bean
    public Advisor druidStatAdvisor() {
        return new DefaultPointcutAdvisor(druidStatPointcut(), druidStatInterceptor());
    }
    /**
     * xssFilter注册
     */
    @Bean
    public FilterRegistrationBean xssFilterRegistration() {
        XssFilter xssFilter = new XssFilter();
        xssFilter.setUrlExclusion(Arrays.asList("/notice/update", "/notice/add"));
        FilterRegistrationBean registration = new FilterRegistrationBean(xssFilter);
        registration.addUrlPatterns("/*");
        return registration;
    }
    /**
     * RequestContextListener注册
     */
    @Bean
    public ServletListenerRegistrationBean<RequestContextListener> requestContextListenerRegistration() {
        return new ServletListenerRegistrationBean<>(new RequestContextListener());
    }
    /**
     * ConfigListener注册
     */
    @Bean
    public ServletListenerRegistrationBean<ConfigListener> configListenerRegistration() {
        return new ServletListenerRegistrationBean<>(new ConfigListener());
    }
    /**
     * 验证码生成相关
     */
    @Bean
    public DefaultKaptcha kaptcha() {
        Properties properties = new Properties();
        properties.put("kaptcha.border", "no");
        properties.put("kaptcha.border.color", "105,179,90");
        properties.put("kaptcha.textproducer.font.color", "blue");
        properties.put("kaptcha.image.width", "125");
        properties.put("kaptcha.image.height", "45");
        properties.put("kaptcha.textproducer.font.size", "45");
        properties.put("kaptcha.session.key", "code");
        properties.put("kaptcha.textproducer.char.length", "4");
        properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/aop/GlobalExceptionHandler.java
New file
@@ -0,0 +1,123 @@
package com.stylefeng.guns.core.aop;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.common.exception.InvalidKaptchaException;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.log.factory.LogTaskFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.DisabledAccountException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.lang.reflect.UndeclaredThrowableException;
import static com.stylefeng.guns.core.support.HttpKit.getIp;
import static com.stylefeng.guns.core.support.HttpKit.getRequest;
/**
 * 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
 *
 * @author fengshuonan
 * @date 2016年11月12日 下午3:19:56
 */
@ControllerAdvice
@Order(-1)
public class GlobalExceptionHandler {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    /**
     * 拦截业务异常
     */
    @ExceptionHandler(GunsException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorTip notFount(GunsException e) {
        LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
        getRequest().setAttribute("tip", e.getMessage());
        log.error("业务异常:", e);
        return new ErrorTip(e.getCode(), e.getMessage());
    }
    /**
     * 用户未登录异常
     */
    @ExceptionHandler(AuthenticationException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public String unAuth(AuthenticationException e) {
        log.error("用户未登陆:", e);
        return "/login.html";
    }
    /**
     * 账号被冻结异常
     */
    @ExceptionHandler(DisabledAccountException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public String accountLocked(DisabledAccountException e, Model model) {
        String username = getRequest().getParameter("username");
        LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号被冻结", getIp()));
        model.addAttribute("tips", "账号被冻结");
        return "/login.html";
    }
    /**
     * 账号密码错误异常
     */
    @ExceptionHandler(CredentialsException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public String credentials(CredentialsException e, Model model) {
        String username = getRequest().getParameter("username");
        LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号密码错误", getIp()));
        model.addAttribute("tips", "账号密码错误");
        return "/login.html";
    }
    /**
     * 验证码错误异常
     */
    @ExceptionHandler(InvalidKaptchaException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String credentials(InvalidKaptchaException e, Model model) {
        String username = getRequest().getParameter("username");
        LogManager.me().executeLog(LogTaskFactory.loginLog(username, "验证码错误", getIp()));
        model.addAttribute("tips", "验证码错误");
        return "/login.html";
    }
    /**
     * 无权访问该资源异常
     */
    @ExceptionHandler(UndeclaredThrowableException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ResponseBody
    public ErrorTip credentials(UndeclaredThrowableException e) {
        getRequest().setAttribute("tip", "权限异常");
        log.error("权限异常!", e);
        return new ErrorTip(BizExceptionEnum.NO_PERMITION.getCode(), BizExceptionEnum.NO_PERMITION.getMessage());
    }
    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorTip notFount(RuntimeException e) {
        LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
        getRequest().setAttribute("tip", "服务器未知运行时异常");
        log.error("运行时异常:", e);
        return new ErrorTip(BizExceptionEnum.SERVER_ERROR.getCode(), BizExceptionEnum.SERVER_ERROR.getMessage());
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/aop/LogAop.java
New file
@@ -0,0 +1,105 @@
package com.stylefeng.guns.core.aop;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.log.factory.LogTaskFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.Contrast;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Map;
/**
 * 日志记录
 *
 * @author fengshuonan
 * @date 2016年12月6日 下午8:48:30
 */
@Aspect
@Component
public class LogAop {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Pointcut(value = "@annotation(com.stylefeng.guns.core.common.annotion.BussinessLog)")
    public void cutService() {
    }
    @Around("cutService()")
    public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {
        //先执行业务
        Object result = point.proceed();
        try {
            handle(point);
        } catch (Exception e) {
            log.error("日志记录出错!", e);
        }
        return result;
    }
    private void handle(ProceedingJoinPoint point) throws Exception {
        //获取拦截的方法名
        Signature sig = point.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = point.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        String methodName = currentMethod.getName();
        //如果当前用户未登录,不做日志
        ShiroUser user = ShiroKit.getUser();
        if (null == user) {
            return;
        }
        //获取拦截方法的参数
        String className = point.getTarget().getClass().getName();
        Object[] params = point.getArgs();
        //获取操作名称
        BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class);
        String bussinessName = annotation.value();
        String key = annotation.key();
        Class dictClass = annotation.dict();
        StringBuilder sb = new StringBuilder();
        for (Object param : params) {
            sb.append(param);
            sb.append(" & ");
        }
        //如果涉及到修改,比对变化
        String msg;
        if (bussinessName.indexOf("修改") != -1 || bussinessName.indexOf("编辑") != -1) {
            Object obj1 = LogObjectHolder.me().get();
            Map<String, String> obj2 = HttpKit.getRequestParameters();
            msg = Contrast.contrastObj(dictClass, key, obj1, obj2);
        } else {
            Map<String, String> parameters = HttpKit.getRequestParameters();
            AbstractDictMap dictMap = (AbstractDictMap) dictClass.newInstance();
            msg = Contrast.parseMutiKey(dictMap,key,parameters);
        }
        LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), bussinessName, className, methodName, msg));
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/aop/PermissionAop.java
New file
@@ -0,0 +1,70 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.aop;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.shiro.check.PermissionCheckManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.naming.NoPermissionException;
import java.lang.reflect.Method;
/**
 * AOP 权限自定义检查
 */
@Aspect
@Component
@Order(200)
public class PermissionAop {
    @Pointcut(value = "@annotation(com.stylefeng.guns.core.common.annotion.Permission)")
    private void cutPermission() {
    }
    @Around("cutPermission()")
    public Object doPermission(ProceedingJoinPoint point) throws Throwable {
        MethodSignature ms = (MethodSignature) point.getSignature();
        Method method = ms.getMethod();
        Permission permission = method.getAnnotation(Permission.class);
        Object[] permissions = permission.value();
        if (permissions == null || permissions.length == 0) {
            //检查全体角色
            boolean result = PermissionCheckManager.checkAll();
            if (result) {
                return point.proceed();
            } else {
                throw new NoPermissionException();
            }
        } else {
            //检查指定角色
            boolean result = PermissionCheckManager.check(permissions);
            if (result) {
                return point.proceed();
            } else {
                throw new NoPermissionException();
            }
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/beetl/BeetlConfiguration.java
New file
@@ -0,0 +1,71 @@
package com.stylefeng.guns.core.beetl;
import com.stylefeng.guns.core.tag.DictSelectorTag;
import com.stylefeng.guns.core.util.KaptchaUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import org.beetl.core.Context;
import org.beetl.core.Function;
import org.beetl.core.Tag;
import org.beetl.core.TagFactory;
import org.beetl.ext.spring.BeetlGroupUtilConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import java.io.UnsupportedEncodingException;
/**
 * beetl拓展配置,绑定一些工具类,方便在模板中直接调用
 *
 * @author stylefeng
 * @Date 2018/2/22 21:03
 */
public class BeetlConfiguration extends BeetlGroupUtilConfiguration {
    @Autowired
    Environment env;
    @Autowired
    ApplicationContext applicationContext;
    @Autowired
    DictSelectorTag dictSelectorTag;
    @Override
    public void initOther() {
        groupTemplate.registerFunctionPackage("shiro", new ShiroExt());
        groupTemplate.registerFunctionPackage("tool", new ToolUtil());
        groupTemplate.registerFunctionPackage("kaptcha", new KaptchaUtil());
        groupTemplate.registerTagFactory("dictSelector", new TagFactory() {
            @Override
            public Tag createTag() {
                return dictSelectorTag;
            }
        });
        groupTemplate.registerFunction("env", new Function() {
            @Override
            public String call(Object[] paras, Context ctx) {
                String key = (String)paras[0];
                String value =  env.getProperty(key);
                if(value!=null) {
                    return getStr(value);
                }
                if(paras.length==2) {
                    return (String)paras[1];
                }
                return null;
            }
            protected String getStr(String str) {
                try {
                    return new String(str.getBytes("iso8859-1"),"UTF-8");
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/beetl/ShiroExt.java
New file
@@ -0,0 +1,186 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.beetl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.beetl.core.GroupTemplate;
import com.stylefeng.guns.core.shiro.ShiroUser;
public class ShiroExt {
    private static final String NAMES_DELIMETER = ",";
    /**
     * 获取当前 Subject
     *
     * @return Subject
     */
    protected static Subject getSubject() {
        return SecurityUtils.getSubject();
    }
    /**
     * 获取封装的 ShiroUser
     *
     * @return ShiroUser
     */
    public ShiroUser getUser() {
        if (isGuest()) {
            return null;
        } else {
            return (ShiroUser) getSubject().getPrincipals().getPrimaryPrincipal();
        }
    }
    /**
     * 验证当前用户是否属于该角色?,使用时与lacksRole 搭配使用
     *
     * @param roleName 角色名
     * @return 属于该角色:true,否则false
     */
    public boolean hasRole(String roleName) {
        return getSubject() != null && roleName != null
                && roleName.length() > 0 && getSubject().hasRole(roleName);
    }
    /**
     * 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。
     *
     * @param roleName 角色名
     * @return 不属于该角色:true,否则false
     */
    public boolean lacksRole(String roleName) {
        return !hasRole(roleName);
    }
    /**
     * 验证当前用户是否属于以下任意一个角色。
     *
     * @param roleNames 角色列表
     * @return 属于:true,否则false
     */
    public boolean hasAnyRoles(String roleNames) {
        boolean hasAnyRole = false;
        Subject subject = getSubject();
        if (subject != null && roleNames != null && roleNames.length() > 0) {
            for (String role : roleNames.split(NAMES_DELIMETER)) {
                if (subject.hasRole(role.trim())) {
                    hasAnyRole = true;
                    break;
                }
            }
        }
        return hasAnyRole;
    }
    /**
     * 验证当前用户是否属于以下所有角色。
     *
     * @param roleNames 角色列表
     * @return 属于:true,否则false
     */
    public boolean hasAllRoles(String roleNames) {
        boolean hasAllRole = true;
        Subject subject = getSubject();
        if (subject != null && roleNames != null && roleNames.length() > 0) {
            for (String role : roleNames.split(NAMES_DELIMETER)) {
                if (!subject.hasRole(role.trim())) {
                    hasAllRole = false;
                    break;
                }
            }
        }
        return hasAllRole;
    }
    /**
     * 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用
     *
     * @param permission 权限名
     * @return 拥有权限:true,否则false
     */
    public boolean hasPermission(String permission) {
        return getSubject() != null && permission != null
                && permission.length() > 0
                && getSubject().isPermitted(permission);
    }
    /**
     * 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。
     *
     * @param permission 权限名
     * @return 拥有权限:true,否则false
     */
    public boolean lacksPermission(String permission) {
        return !hasPermission(permission);
    }
    /**
     * 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。与notAuthenticated搭配使用
     *
     * @return 通过身份验证:true,否则false
     */
    public boolean authenticated() {
        return getSubject() != null && getSubject().isAuthenticated();
    }
    /**
     * 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。。
     *
     * @return 没有通过身份验证:true,否则false
     */
    public boolean notAuthenticated() {
        return !authenticated();
    }
    /**
     * 认证通过或已记住的用户。与guset搭配使用。
     *
     * @return 用户:true,否则 false
     */
    public boolean isUser() {
        return getSubject() != null && getSubject().getPrincipal() != null;
    }
    /**
     * 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。用user搭配使用
     *
     * @return 访客:true,否则false
     */
    public boolean isGuest() {
        return !isUser();
    }
    /**
     * 输出当前用户信息,通常为登录帐号信息。
     *
     * @return 当前用户信息
     */
    public String principal() {
        if (getSubject() != null) {
            Object principal = getSubject().getPrincipal();
            return principal.toString();
        }
        return "";
    }
    public static void main(String[] args) {
        GroupTemplate gt = new GroupTemplate();
        gt.registerFunctionPackage("shiro", new ShiroExt());
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/annotion/BussinessLog.java
New file
@@ -0,0 +1,33 @@
package com.stylefeng.guns.core.common.annotion;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
import com.stylefeng.guns.core.common.constant.dictmap.base.SystemDict;
import java.lang.annotation.*;
/**
 * 标记需要做业务日志的方法
 *
 * @author fengshuonan
 * @date 2017-03-31 12:46
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface BussinessLog {
    /**
     * 业务的名称,例如:"修改菜单"
     */
    String value() default "";
    /**
     * 被修改的实体的唯一标识,例如:菜单实体的唯一标识为"id"
     */
    String key() default "id";
    /**
     * 字典(用于查找key的中文名称和字段的中文名称)
     */
    Class<? extends AbstractDictMap> dict() default SystemDict.class;
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/annotion/Permission.java
New file
@@ -0,0 +1,22 @@
package com.stylefeng.guns.core.common.annotion;
import java.lang.annotation.*;
/**
 * 权限注解 用于检查权限 规定访问权限
 *
 * @example @Permission({role1,role2})
 * @example @Permission
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Permission {
    /**
     * <p>角色英文名称</p>
     * <p>使用注解时加上这个值表示限制只有某个角色的才可以访问对应的资源</p>
     * <p>常用在某些资源限制只有超级管理员角色才可访问</p>
     */
    String[] value() default {};
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/Const.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.core.common.constant;
/**
 * 系统常量
 *
 * @author fengshuonan
 * @date 2017年2月12日 下午9:42:53
 */
public interface Const {
    /**
     * 系统默认的管理员密码
     */
    String DEFAULT_PWD = "111111";
    /**
     * 管理员角色的名字
     */
    String ADMIN_NAME = "administrator";
    /**
     * 管理员id
     */
    Integer ADMIN_ID = 1;
    /**
     * 超级管理员角色id
     */
    Integer ADMIN_ROLE_ID = 1;
    /**
     * 接口文档的菜单名
     */
    String API_MENU_NAME = "接口文档";
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/DatasourceEnum.java
New file
@@ -0,0 +1,15 @@
package com.stylefeng.guns.core.common.constant;
/**
 *
 * 多数据源的枚举
 *
 * @author fengshuonan
 * @date 2017年3月5日 上午10:15:02
 */
public interface DatasourceEnum {
    String DATA_SOURCE_GUNS = "dataSourceGuns";            //guns数据源
    String DATA_SOURCE_BIZ = "dataSourceBiz";            //其他业务的数据源
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/JwtConstants.java
New file
@@ -0,0 +1,19 @@
package com.stylefeng.guns.core.common.constant;
/**
 * jwt相关配置
 *
 * @author fengshuonan
 * @date 2017-08-23 9:23
 */
public interface JwtConstants {
    String AUTH_HEADER = "Authorization";
    String SECRET = "defaultSecret";
    Long EXPIRATION = 604800L;
    String AUTH_PATH = "/gunsApi/auth";
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/cache/Cache.java
New file
@@ -0,0 +1,15 @@
package com.stylefeng.guns.core.common.constant.cache;
/**
 * 所有缓存名称的集合
 *
 * @author fengshuonan
 * @date 2017-04-24 21:56
 */
public interface Cache {
    /**
     * 常量缓存
     */
    String CONSTANT = "CONSTANT";
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/cache/CacheKey.java
New file
@@ -0,0 +1,31 @@
package com.stylefeng.guns.core.common.constant.cache;
/**
 * 缓存标识前缀集合,常用在ConstantFactory类中
 *
 * @author fengshuonan
 * @date 2017-04-25 9:37
 */
public interface CacheKey {
    /**
     * 角色名称(多个)
     */
    String ROLES_NAME = "roles_name_";
    /**
     * 角色名称(单个)
     */
    String SINGLE_ROLE_NAME = "single_role_name_";
    /**
     * 角色英文名称
     */
    String SINGLE_ROLE_TIP = "single_role_tip_";
    /**
     * 部门名称
     */
    String DEPT_NAME = "dept_name_";
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/DeleteDict.java
New file
@@ -0,0 +1,31 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 用于删除业务的字典
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class DeleteDict extends AbstractDictMap {
    @Override
    public void init() {
        put("roleId","角色名称");
        put("deptId", "部门名称");
        put("menuId", "菜单名称");
        put("dictId", "字典名称");
        put("noticeId", "标题");
    }
    @Override
    protected void initBeWrapped() {
        putFieldWrapperMethodName("roleId","getCacheObject");
        putFieldWrapperMethodName("deptId","getCacheObject");
        putFieldWrapperMethodName("menuId","getCacheObject");
        putFieldWrapperMethodName("dictId","getCacheObject");
        putFieldWrapperMethodName("noticeId","getCacheObject");
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/DeptDict.java
New file
@@ -0,0 +1,28 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 部门的映射
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class DeptDict extends AbstractDictMap {
    @Override
    public void init() {
        put("deptId", "部门名称");
        put("num", "部门排序");
        put("pid", "上级名称");
        put("simplename", "部门简称");
        put("fullname", "部门全称");
        put("tips", "备注");
    }
    @Override
    protected void initBeWrapped() {
        putFieldWrapperMethodName("deptId", "getDeptName");
        putFieldWrapperMethodName("pid", "getDeptName");
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/DictMap.java
New file
@@ -0,0 +1,24 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 字典map
 *
 * @author fengshuonan
 * @date 2017-05-06 15:43
 */
public class DictMap extends AbstractDictMap {
    @Override
    public void init() {
        put("dictId","字典名称");
        put("dictName","字典名称");
        put("dictValues","字典内容");
    }
    @Override
    protected void initBeWrapped() {
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/LogDict.java
New file
@@ -0,0 +1,22 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 日志的字典
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class LogDict extends AbstractDictMap {
    @Override
    public void init() {
        put("tips","备注");
    }
    @Override
    protected void initBeWrapped() {
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/MenuDict.java
New file
@@ -0,0 +1,34 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 菜单的字典
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class MenuDict extends AbstractDictMap {
    @Override
    public void init() {
        put("menuId","菜单id");
        put("id","菜单id");
        put("code","菜单编号");
        put("pcode","菜单父编号");
        put("name","菜单名称");
        put("icon","菜单图标");
        put("url","url地址");
        put("num","菜单排序号");
        put("levels","菜单层级");
        put("tips","备注");
        put("status","菜单状态");
        put("isopen","是否打开");
        put("","");
    }
    @Override
    protected void initBeWrapped() {
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/NoticeMap.java
New file
@@ -0,0 +1,22 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 通知的映射
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class NoticeMap extends AbstractDictMap {
    @Override
    public void init() {
        put("title", "标题");
        put("content", "内容");
    }
    @Override
    protected void initBeWrapped() {
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/RoleDict.java
New file
@@ -0,0 +1,31 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 角色的字典
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class RoleDict extends AbstractDictMap {
    @Override
    public void init() {
        put("roleId","角色名称");
        put("num","角色排序");
        put("pid","角色的父级");
        put("name","角色名称");
        put("deptid","部门名称");
        put("tips","备注");
        put("ids","资源名称");
    }
    @Override
    protected void initBeWrapped() {
        putFieldWrapperMethodName("pid","getSingleRoleName");
        putFieldWrapperMethodName("deptid","getDeptName");
        putFieldWrapperMethodName("roleId","getSingleRoleName");
        putFieldWrapperMethodName("ids","getMenuNames");
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/UserDict.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.core.common.constant.dictmap;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
/**
 * 用户的字典
 *
 * @author fengshuonan
 * @date 2017-05-06 15:01
 */
public class UserDict extends AbstractDictMap {
    @Override
    public void init() {
        put("userId","账号");
        put("avatar","头像");
        put("account","账号");
        put("name","名字");
        put("birthday","生日");
        put("sex","性别");
        put("email","电子邮件");
        put("phone","电话");
        put("roleid","角色名称");
        put("deptid","部门名称");
        put("roleIds","角色名称集合");
    }
    @Override
    protected void initBeWrapped() {
        putFieldWrapperMethodName("sex","getSexName");
        putFieldWrapperMethodName("deptid","getDeptName");
        putFieldWrapperMethodName("roleid","getSingleRoleName");
        putFieldWrapperMethodName("userId","getUserAccountById");
        putFieldWrapperMethodName("roleIds","getRoleName");
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/base/AbstractDictMap.java
New file
@@ -0,0 +1,53 @@
package com.stylefeng.guns.core.common.constant.dictmap.base;
import java.util.HashMap;
/**
 * 字典映射抽象类
 *
 * @author fengshuonan
 * @date 2017-05-06 14:58
 */
public abstract class AbstractDictMap {
    protected HashMap<String, String> dictory = new HashMap<>();
    protected HashMap<String, String> fieldWarpperDictory = new HashMap<>();
    public AbstractDictMap(){
        put("id","主键id");
        init();
        initBeWrapped();
    }
    /**
     * 初始化字段英文名称和中文名称对应的字典
     *
     * @author stylefeng
     * @Date 2017/5/9 19:39
     */
    public abstract void init();
    /**
     * 初始化需要被包装的字段(例如:性别为1:男,2:女,需要被包装为汉字)
     *
     * @author stylefeng
     * @Date 2017/5/9 19:35
     */
    protected abstract void initBeWrapped();
    public String get(String key) {
        return this.dictory.get(key);
    }
    public void put(String key, String value) {
        this.dictory.put(key, value);
    }
    public String getFieldWarpperMethodName(String key){
        return this.fieldWarpperDictory.get(key);
    }
    public void putFieldWrapperMethodName(String key,String methodName){
        this.fieldWarpperDictory.put(key,methodName);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/base/SystemDict.java
New file
@@ -0,0 +1,20 @@
package com.stylefeng.guns.core.common.constant.dictmap.base;
/**
 * 系统相关的字典
 *
 * @author fengshuonan
 * @date 2017-05-06 15:48
 */
public class SystemDict extends AbstractDictMap {
    @Override
    public void init() {
    }
    @Override
    protected void initBeWrapped() {
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/dictmap/factory/DictFieldWarpperFactory.java
New file
@@ -0,0 +1,33 @@
package com.stylefeng.guns.core.common.constant.dictmap.factory;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.constant.factory.IConstantFactory;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import java.lang.reflect.Method;
/**
 * 字典字段的包装器(从ConstantFactory中获取包装值)
 *
 * @author fengshuonan
 * @date 2017-05-06 15:12
 */
public class DictFieldWarpperFactory {
    public static Object createFieldWarpper(Object parameter, String methodName) {
        IConstantFactory constantFactory = ConstantFactory.me();
        try {
            Method method = IConstantFactory.class.getMethod(methodName, parameter.getClass());
            return method.invoke(constantFactory, parameter);
        } catch (Exception e) {
            try {
                Method method = IConstantFactory.class.getMethod(methodName, Integer.class);
                return method.invoke(constantFactory, Integer.parseInt(parameter.toString()));
            } catch (Exception e1) {
                throw new GunsException(BizExceptionEnum.ERROR_WRAPPER_FIELD);
            }
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/ConstantFactory.java
New file
@@ -0,0 +1,333 @@
package com.stylefeng.guns.core.common.constant.factory;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.stylefeng.guns.core.common.constant.cache.Cache;
import com.stylefeng.guns.core.common.constant.cache.CacheKey;
import com.stylefeng.guns.core.common.constant.state.ManagerStatus;
import com.stylefeng.guns.core.common.constant.state.MenuStatus;
import com.stylefeng.guns.modular.system.dao.*;
import com.stylefeng.guns.modular.system.model.*;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.support.StrKit;
import com.stylefeng.guns.core.util.Convert;
import com.stylefeng.guns.core.util.SpringContextHolder;
import com.stylefeng.guns.core.util.ToolUtil;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
 * 常量的生产工厂
 *
 * @author fengshuonan
 * @date 2017年2月13日 下午10:55:21
 */
@Component
@DependsOn("springContextHolder")
public class ConstantFactory implements IConstantFactory {
    private RoleMapper roleMapper = SpringContextHolder.getBean(RoleMapper.class);
    private DeptMapper deptMapper = SpringContextHolder.getBean(DeptMapper.class);
    private DictMapper dictMapper = SpringContextHolder.getBean(DictMapper.class);
    private UserMapper userMapper = SpringContextHolder.getBean(UserMapper.class);
    private MenuMapper menuMapper = SpringContextHolder.getBean(MenuMapper.class);
    private NoticeMapper noticeMapper = SpringContextHolder.getBean(NoticeMapper.class);
    public static IConstantFactory me() {
        return SpringContextHolder.getBean("constantFactory");
    }
    /**
     * 根据用户id获取用户名称
     *
     * @author stylefeng
     * @Date 2017/5/9 23:41
     */
    @Override
    public String getUserNameById(Integer userId) {
        User user = userMapper.selectById(userId);
        if (user != null) {
            return user.getName();
        } else {
            return "--";
        }
    }
    /**
     * 根据用户id获取用户账号
     *
     * @author stylefeng
     * @date 2017年5月16日21:55:371
     */
    @Override
    public String getUserAccountById(Integer userId) {
        User user = userMapper.selectById(userId);
        if (user != null) {
            return user.getAccount();
        } else {
            return "--";
        }
    }
    /**
     * 通过角色ids获取角色名称
     */
    @Override
    @Cacheable(value = Cache.CONSTANT, key = "'" + CacheKey.ROLES_NAME + "'+#roleIds")
    public String getRoleName(String roleIds) {
        Integer[] roles = Convert.toIntArray(roleIds);
        StringBuilder sb = new StringBuilder();
        for (int role : roles) {
            Role roleObj = roleMapper.selectById(role);
            if (ToolUtil.isNotEmpty(roleObj) && ToolUtil.isNotEmpty(roleObj.getName())) {
                sb.append(roleObj.getName()).append(",");
            }
        }
        return StrKit.removeSuffix(sb.toString(), ",");
    }
    /**
     * 通过角色id获取角色名称
     */
    @Override
    @Cacheable(value = Cache.CONSTANT, key = "'" + CacheKey.SINGLE_ROLE_NAME + "'+#roleId")
    public String getSingleRoleName(Integer roleId) {
        if (0 == roleId) {
            return "--";
        }
        Role roleObj = roleMapper.selectById(roleId);
        if (ToolUtil.isNotEmpty(roleObj) && ToolUtil.isNotEmpty(roleObj.getName())) {
            return roleObj.getName();
        }
        return "";
    }
    /**
     * 通过角色id获取角色英文名称
     */
    @Override
    @Cacheable(value = Cache.CONSTANT, key = "'" + CacheKey.SINGLE_ROLE_TIP + "'+#roleId")
    public String getSingleRoleTip(Integer roleId) {
        if (0 == roleId) {
            return "--";
        }
        Role roleObj = roleMapper.selectById(roleId);
        if (ToolUtil.isNotEmpty(roleObj) && ToolUtil.isNotEmpty(roleObj.getName())) {
            return roleObj.getTips();
        }
        return "";
    }
    /**
     * 获取部门名称
     */
    @Override
    @Cacheable(value = Cache.CONSTANT, key = "'" + CacheKey.DEPT_NAME + "'+#deptId")
    public String getDeptName(Integer deptId) {
        Dept dept = deptMapper.selectById(deptId);
        if (ToolUtil.isNotEmpty(dept) && ToolUtil.isNotEmpty(dept.getFullname())) {
            return dept.getFullname();
        }
        return "";
    }
    /**
     * 获取菜单的名称们(多个)
     */
    @Override
    public String getMenuNames(String menuIds) {
        Integer[] menus = Convert.toIntArray(menuIds);
        StringBuilder sb = new StringBuilder();
        for (int menu : menus) {
            Menu menuObj = menuMapper.selectById(menu);
            if (ToolUtil.isNotEmpty(menuObj) && ToolUtil.isNotEmpty(menuObj.getName())) {
                sb.append(menuObj.getName()).append(",");
            }
        }
        return StrKit.removeSuffix(sb.toString(), ",");
    }
    /**
     * 获取菜单名称
     */
    @Override
    public String getMenuName(Long menuId) {
        if (ToolUtil.isEmpty(menuId)) {
            return "";
        } else {
            Menu menu = menuMapper.selectById(menuId);
            if (menu == null) {
                return "";
            } else {
                return menu.getName();
            }
        }
    }
    /**
     * 获取菜单名称通过编号
     */
    @Override
    public String getMenuNameByCode(String code) {
        if (ToolUtil.isEmpty(code)) {
            return "";
        } else {
            Menu param = new Menu();
            param.setCode(code);
            Menu menu = menuMapper.selectOne(param);
            if (menu == null) {
                return "";
            } else {
                return menu.getName();
            }
        }
    }
    /**
     * 获取字典名称
     */
    @Override
    public String getDictName(Integer dictId) {
        if (ToolUtil.isEmpty(dictId)) {
            return "";
        } else {
            Dict dict = dictMapper.selectById(dictId);
            if (dict == null) {
                return "";
            } else {
                return dict.getName();
            }
        }
    }
    /**
     * 获取通知标题
     */
    @Override
    public String getNoticeTitle(Integer dictId) {
        if (ToolUtil.isEmpty(dictId)) {
            return "";
        } else {
            Notice notice = noticeMapper.selectById(dictId);
            if (notice == null) {
                return "";
            } else {
                return notice.getTitle();
            }
        }
    }
    /**
     * 根据字典名称和字典中的值获取对应的名称
     */
    @Override
    public String getDictsByName(String name, Integer val) {
        Dict temp = new Dict();
        temp.setName(name);
        Dict dict = dictMapper.selectOne(temp);
        if (dict == null) {
            return "";
        } else {
            Wrapper<Dict> wrapper = new EntityWrapper<>();
            wrapper = wrapper.eq("pid", dict.getId());
            List<Dict> dicts = dictMapper.selectList(wrapper);
            for (Dict item : dicts) {
                if (item.getNum() != null && item.getNum().equals(val)) {
                    return item.getName();
                }
            }
            return "";
        }
    }
    /**
     * 获取性别名称
     */
    @Override
    public String getSexName(Integer sex) {
        return getDictsByName("性别", sex);
    }
    /**
     * 获取用户登录状态
     */
    @Override
    public String getStatusName(Integer status) {
        return ManagerStatus.valueOf(status);
    }
    /**
     * 获取菜单状态
     */
    @Override
    public String getMenuStatusName(Integer status) {
        return MenuStatus.valueOf(status);
    }
    /**
     * 查询字典
     */
    @Override
    public List<Dict> findInDict(Integer id) {
        if (ToolUtil.isEmpty(id)) {
            return null;
        } else {
            EntityWrapper<Dict> wrapper = new EntityWrapper<>();
            List<Dict> dicts = dictMapper.selectList(wrapper.eq("pid", id));
            if (dicts == null || dicts.size() == 0) {
                return null;
            } else {
                return dicts;
            }
        }
    }
    /**
     * 获取被缓存的对象(用户删除业务)
     */
    @Override
    public String getCacheObject(String para) {
        return LogObjectHolder.me().get().toString();
    }
    /**
     * 获取子部门id
     */
    @Override
    public List<Integer> getSubDeptId(Integer deptid) {
        Wrapper<Dept> wrapper = new EntityWrapper<>();
        wrapper = wrapper.like("pids", "%[" + deptid + "]%");
        List<Dept> depts = this.deptMapper.selectList(wrapper);
        ArrayList<Integer> deptids = new ArrayList<>();
        if(depts != null && depts.size() > 0){
            for (Dept dept : depts) {
                deptids.add(dept.getId());
            }
        }
        return deptids;
    }
    /**
     * 获取所有父部门id
     */
    @Override
    public List<Integer> getParentDeptIds(Integer deptid) {
        Dept dept = deptMapper.selectById(deptid);
        String pids = dept.getPids();
        String[] split = pids.split(",");
        ArrayList<Integer> parentDeptIds = new ArrayList<>();
        for (String s : split) {
            parentDeptIds.add(Integer.valueOf(StrKit.removeSuffix(StrKit.removePrefix(s, "["), "]")));
        }
        return parentDeptIds;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/IConstantFactory.java
New file
@@ -0,0 +1,116 @@
package com.stylefeng.guns.core.common.constant.factory;
import com.stylefeng.guns.modular.system.model.Dict;
import java.util.List;
/**
 * 常量生产工厂的接口
 *
 * @author fengshuonan
 * @date 2017-06-14 21:12
 */
public interface IConstantFactory {
    /**
     * 根据用户id获取用户名称
     *
     * @author stylefeng
     * @Date 2017/5/9 23:41
     */
    String getUserNameById(Integer userId);
    /**
     * 根据用户id获取用户账号
     *
     * @author stylefeng
     * @date 2017年5月16日21:55:371
     */
    String getUserAccountById(Integer userId);
    /**
     * 通过角色ids获取角色名称
     */
    String getRoleName(String roleIds);
    /**
     * 通过角色id获取角色名称
     */
    String getSingleRoleName(Integer roleId);
    /**
     * 通过角色id获取角色英文名称
     */
    String getSingleRoleTip(Integer roleId);
    /**
     * 获取部门名称
     */
    String getDeptName(Integer deptId);
    /**
     * 获取菜单的名称们(多个)
     */
    String getMenuNames(String menuIds);
    /**
     * 获取菜单名称
     */
    String getMenuName(Long menuId);
    /**
     * 获取菜单名称通过编号
     */
    String getMenuNameByCode(String code);
    /**
     * 获取字典名称
     */
    String getDictName(Integer dictId);
    /**
     * 获取通知标题
     */
    String getNoticeTitle(Integer dictId);
    /**
     * 根据字典名称和字典中的值获取对应的名称
     */
    String getDictsByName(String name, Integer val);
    /**
     * 获取性别名称
     */
    String getSexName(Integer sex);
    /**
     * 获取用户登录状态
     */
    String getStatusName(Integer status);
    /**
     * 获取菜单状态
     */
    String getMenuStatusName(Integer status);
    /**
     * 查询字典
     */
    List<Dict> findInDict(Integer id);
    /**
     * 获取被缓存的对象(用户删除业务)
     */
    String getCacheObject(String para);
    /**
     * 获取子部门id
     */
    List<Integer> getSubDeptId(Integer deptid);
    /**
     * 获取所有父部门id
     */
    List<Integer> getParentDeptIds(Integer deptid);
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/MutiStrFactory.java
New file
@@ -0,0 +1,96 @@
package com.stylefeng.guns.core.common.constant.factory;
import com.stylefeng.guns.core.support.StrKit;
import com.stylefeng.guns.core.util.ToolUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 组合字符串生产者
 *
 * @author fengshuonan
 * @date 2017-04-27 16:42
 */
public class MutiStrFactory {
    /**
     * 每个条目之间的分隔符
     */
    public static final String ITEM_SPLIT = ";";
    /**
     * 属性之间的分隔符
     */
    public static final String ATTR_SPLIT = ":";
    /**
     * 拼接字符串的id
     */
    public static final String MUTI_STR_ID = "ID";
    /**
     * 拼接字符串的CODE
     */
    public static final String MUTI_STR_CODE = "CODE";
    /**
     * 拼接字符串的NAME
     */
    public static final String MUTI_STR_NAME = "NAME";
    /**
     * 拼接字符串的NUM
     */
    public static final String MUTI_STR_NUM = "NUM";
    /**
     * 解析一个组合字符串(例如:  "1:启用;2:禁用;3:冻结"  这样的字符串)
     *
     * @author fengshuonan
     * @Date 2017/4/27 16:44
     */
    public static List<Map<String,String>> parseKeyValue(String mutiString){
        if(ToolUtil.isEmpty(mutiString)){
            return new ArrayList<>();
        }else{
            ArrayList<Map<String,String>> results = new ArrayList<>();
            String[] items = StrKit.split(StrKit.removeSuffix(mutiString, ITEM_SPLIT), ITEM_SPLIT);
            for (String item : items) {
                String[] attrs = item.split(ATTR_SPLIT);
                HashMap<String, String> itemMap = new HashMap<>();
                itemMap.put(MUTI_STR_CODE,attrs[0]);
                itemMap.put(MUTI_STR_NAME,attrs[1]);
                itemMap.put(MUTI_STR_NUM,attrs[2]);
                results.add(itemMap);
            }
            return results;
        }
    }
    /**
     * 解析id:key:value这样类型的字符串
     *
     * @author fengshuonan
     * @Date 2017/4/28 11:06
     */
    public static List<Map<String,String>> parseIdKeyValue(String mutiString){
        if(ToolUtil.isEmpty(mutiString)){
            return new ArrayList<>();
        }else{
            ArrayList<Map<String,String>> results = new ArrayList<>();
            String[] items = StrKit.split(StrKit.removeSuffix(mutiString, ITEM_SPLIT), ITEM_SPLIT);
            for (String item : items) {
                String[] attrs = item.split(ATTR_SPLIT);
                HashMap<String, String> itemMap = new HashMap<>();
                itemMap.put(MUTI_STR_CODE,attrs[0]);
                itemMap.put(MUTI_STR_NAME,attrs[1]);
                itemMap.put(MUTI_STR_NUM,attrs[2]);
                results.add(itemMap);
            }
            return results;
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/factory/PageFactory.java
New file
@@ -0,0 +1,38 @@
package com.stylefeng.guns.core.common.constant.factory;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.common.constant.state.Order;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.ToolUtil;
import javax.servlet.http.HttpServletRequest;
/**
 * BootStrap Table默认的分页参数创建
 *
 * @author fengshuonan
 * @date 2017-04-05 22:25
 */
public class PageFactory<T> {
    public Page<T> defaultPage() {
        HttpServletRequest request = HttpKit.getRequest();
        int limit = Integer.valueOf(request.getParameter("limit"));     //每页多少条数据
        int offset = Integer.valueOf(request.getParameter("offset"));   //每页的偏移量(本页当前有多少条)
        String sort = request.getParameter("sort");         //排序字段名称
        String order = request.getParameter("order");       //asc或desc(升序或降序)
        if (ToolUtil.isEmpty(sort)) {
            Page<T> page = new Page<>((offset / limit + 1), limit);
            page.setOpenSort(false);
            return page;
        } else {
            Page<T> page = new Page<>((offset / limit + 1), limit, sort);
            if (Order.ASC.getDes().equals(order)) {
                page.setAsc(true);
            } else {
                page.setAsc(false);
            }
            return page;
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/BizLogType.java
New file
@@ -0,0 +1,51 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 业务日志类型
 *
 * @author fengshuonan
 * @Date 2017年1月22日 下午12:14:59
 */
public enum BizLogType {
    ALL(0, null),//全部日志
    BUSSINESS(1, "业务日志"),
    EXCEPTION(2, "异常日志");
    Integer val;
    String message;
    BizLogType(Integer val, String message) {
        this.val = val;
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public Integer getVal() {
        return val;
    }
    public void setVal(Integer val) {
        this.val = val;
    }
    public static String valueOf(Integer value) {
        if (value == null) {
            return null;
        } else {
            for (BizLogType bizLogType : BizLogType.values()) {
                if (bizLogType.getVal().equals(value)) {
                    return bizLogType.getMessage();
                }
            }
            return null;
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/ExpenseState.java
New file
@@ -0,0 +1,52 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 是否是菜单的枚举
 *
 * @author fengshuonan
 * @date 2017年6月1日22:50:11
 */
public enum ExpenseState {
    SUBMITING(1, "待提交"),
    CHECKING(2, "待审核"),
    PASS(3, "审核通过"),
    UN_PASS(4, "未通过");
    int code;
    String message;
    ExpenseState(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public static String valueOf(Integer status) {
        if (status == null) {
            return "";
        } else {
            for (ExpenseState s : ExpenseState.values()) {
                if (s.getCode() == status) {
                    return s.getMessage();
                }
            }
            return "";
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/LogSucceed.java
New file
@@ -0,0 +1,27 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 业务是否成功的日志记录
 *
 * @author fengshuonan
 * @Date 2017年1月22日 下午12:14:59
 */
public enum LogSucceed {
    SUCCESS("成功"),
    FAIL("失败");
    String message;
    LogSucceed(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/LogType.java
New file
@@ -0,0 +1,30 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 日志类型
 *
 * @author fengshuonan
 * @Date 2017年1月22日 下午12:14:59
 */
public enum LogType {
    LOGIN("登录日志"),
    LOGIN_FAIL("登录失败日志"),
    EXIT("退出日志"),
    EXCEPTION("异常日志"),
    BUSSINESS("业务日志");
    String message;
    LogType(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/ManagerStatus.java
New file
@@ -0,0 +1,49 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 管理员的状态
 *
 * @author fengshuonan
 * @Date 2017年1月10日 下午9:54:13
 */
public enum ManagerStatus {
    OK(1, "启用"), FREEZED(2, "冻结"), DELETED(3, "被删除");
    int code;
    String message;
    ManagerStatus(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public static String valueOf(Integer value) {
        if (value == null) {
            return "";
        } else {
            for (ManagerStatus ms : ManagerStatus.values()) {
                if (ms.getCode() == value) {
                    return ms.getMessage();
                }
            }
            return "";
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/MenuOpenStatus.java
New file
@@ -0,0 +1,50 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 菜单是否打开的状态
 *
 * @author fengshuonan
 * @Date 2017年4月8日10:12:15
 */
public enum MenuOpenStatus {
    OPEN(1, "打开"),
    CLOSE(0, "关闭");
    int code;
    String message;
    MenuOpenStatus(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public static String valueOf(Integer status) {
        if (status == null) {
            return "";
        } else {
            for (MenuOpenStatus s : MenuOpenStatus.values()) {
                if (s.getCode() == status) {
                    return s.getMessage();
                }
            }
            return "";
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/MenuStatus.java
New file
@@ -0,0 +1,50 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 菜单的状态
 *
 * @author fengshuonan
 * @Date 2017年1月22日 下午12:14:59
 */
public enum MenuStatus {
    ENABLE(1, "启用"),
    DISABLE(0, "禁用");
    int code;
    String message;
    MenuStatus(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public static String valueOf(Integer status) {
        if (status == null) {
            return "";
        } else {
            for (MenuStatus s : MenuStatus.values()) {
                if (s.getCode() == status) {
                    return s.getMessage();
                }
            }
            return "";
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/state/Order.java
New file
@@ -0,0 +1,26 @@
package com.stylefeng.guns.core.common.constant.state;
/**
 * 数据库排序
 *
 * @author fengshuonan
 * @Date 2017年5月31日20:48:41
 */
public enum Order {
    ASC("asc"), DESC("desc");
    private String des;
    Order(String des) {
        this.des = des;
    }
    public String getDes() {
        return des;
    }
    public void setDes(String des) {
        this.des = des;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/exception/BizExceptionEnum.java
New file
@@ -0,0 +1,100 @@
package com.stylefeng.guns.core.common.exception;
import com.stylefeng.guns.core.exception.ServiceExceptionEnum;
/**
 * @author fengshuonan
 * @Description 所有业务异常的枚举
 * @date 2016年11月12日 下午5:04:51
 */
public enum BizExceptionEnum implements ServiceExceptionEnum {
    /**
     * 字典
     */
    DICT_EXISTED(400, "字典已经存在"),
    ERROR_CREATE_DICT(500, "创建字典失败"),
    ERROR_WRAPPER_FIELD(500, "包装字典属性失败"),
    ERROR_CODE_EMPTY(500, "字典类型不能为空"),
    /**
     * 文件上传
     */
    FILE_READING_ERROR(400, "FILE_READING_ERROR!"),
    FILE_NOT_FOUND(400, "FILE_NOT_FOUND!"),
    UPLOAD_ERROR(500, "上传图片出错"),
    /**
     * 权限和数据问题
     */
    DB_RESOURCE_NULL(400, "数据库中没有该资源"),
    NO_PERMITION(405, "权限异常"),
    REQUEST_INVALIDATE(400, "请求数据格式不正确"),
    INVALID_KAPTCHA(400, "验证码不正确"),
    CANT_DELETE_ADMIN(600, "不能删除超级管理员"),
    CANT_FREEZE_ADMIN(600, "不能冻结超级管理员"),
    CANT_CHANGE_ADMIN(600, "不能修改超级管理员角色"),
    /**
     * 账户问题
     */
    USER_ALREADY_REG(401, "该用户已经注册"),
    NO_THIS_USER(400, "没有此用户"),
    USER_NOT_EXISTED(400, "没有此用户"),
    ACCOUNT_FREEZED(401, "账号被冻结"),
    OLD_PWD_NOT_RIGHT(402, "原密码不正确"),
    TWO_PWD_NOT_MATCH(405, "两次输入密码不一致"),
    /**
     * 错误的请求
     */
    MENU_PCODE_COINCIDENCE(400, "菜单编号和副编号不能一致"),
    EXISTED_THE_MENU(400, "菜单编号重复,不能添加"),
    DICT_MUST_BE_NUMBER(400, "字典的值必须为数字"),
    REQUEST_NULL(400, "请求有错误"),
    SESSION_TIMEOUT(400, "会话超时"),
    SERVER_ERROR(500, "服务器异常"),
    /**
     * token异常
     */
    TOKEN_EXPIRED(600, "token过期"),
    TOKEN_ERROR(600, "token验证失败"),
    /**
     * 签名异常
     */
    SIGN_ERROR(700, "签名验证失败"),
    /**
     * 其他
     */
    AUTH_REQUEST_ERROR(400, "账号密码错误");
    BizExceptionEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }
    private Integer code;
    private String message;
    @Override
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    @Override
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/common/exception/InvalidKaptchaException.java
New file
@@ -0,0 +1,10 @@
package com.stylefeng.guns.core.common.exception;
/**
 * 验证码错误异常
 *
 * @author fengshuonan
 * @date 2017-05-05 23:52
 */
public class InvalidKaptchaException extends RuntimeException {
}
guns-admin/src/main/java/com/stylefeng/guns/core/intercept/GunsUserFilter.java
New file
@@ -0,0 +1,105 @@
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.stylefeng.guns.core.intercept;
import com.stylefeng.guns.core.shiro.ShiroKit;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * Filter that allows access to resources if the accessor is a known user, which is defined as
 * having a known principal.  This means that any user who is authenticated or remembered via a
 * 'remember me' feature will be allowed access from this filter.
 * <p/>
 * If the accessor is not a known user, then they will be redirected to the {@link #setLoginUrl(String) loginUrl}</p>
 *
 * @since 0.9
 */
public class GunsUserFilter extends AccessControlFilter {
    /**
     * Returns <code>true</code> if the request is a
     * {@link #isLoginRequest(javax.servlet.ServletRequest, javax.servlet.ServletResponse) loginRequest} or
     * if the current {@link #getSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) subject}
     * is not <code>null</code>, <code>false</code> otherwise.
     *
     * @return <code>true</code> if the request is a
     * {@link #isLoginRequest(javax.servlet.ServletRequest, javax.servlet.ServletResponse) loginRequest} or
     * if the current {@link #getSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) subject}
     * is not <code>null</code>, <code>false</code> otherwise.
     */
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (isLoginRequest(request, response)) {
            return true;
        } else {
            Subject subject = getSubject(request, response);
            // If principal is not null, then the user is known and should be allowed access.
            return subject.getPrincipal() != null;
        }
    }
    /**
     * This default implementation simply calls
     * {@link #saveRequestAndRedirectToLogin(javax.servlet.ServletRequest, javax.servlet.ServletResponse) saveRequestAndRedirectToLogin}
     * and then immediately returns <code>false</code>, thereby preventing the chain from continuing so the redirect may
     * execute.
     */
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
        /**
         * 如果是ajax请求则不进行跳转
         */
        if (httpServletRequest.getHeader("x-requested-with") != null
                && httpServletRequest.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
            httpServletResponse.setHeader("sessionstatus", "timeout");
            return false;
        } else {
            /**
             * 第一次点击页面
             */
            String referer = httpServletRequest.getHeader("Referer");
            if (referer == null) {
                saveRequestAndRedirectToLogin(request, response);
                return false;
            } else {
                /**
                 * 从别的页面跳转过来的
                 */
                if (ShiroKit.getSession().getAttribute("sessionFlag") == null) {
                    httpServletRequest.setAttribute("tips", "session超时");
                    httpServletRequest.getRequestDispatcher("/login").forward(request, response);
                    return false;
                } else {
                    saveRequestAndRedirectToLogin(request, response);
                    return false;
                }
            }
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/intercept/RestApiInteceptor.java
New file
@@ -0,0 +1,62 @@
package com.stylefeng.guns.core.intercept;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.common.constant.JwtConstants;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.core.util.RenderUtil;
import io.jsonwebtoken.JwtException;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * Rest Api接口鉴权
 *
 * @author stylefeng
 * @Date 2018/7/20 23:11
 */
public class RestApiInteceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof org.springframework.web.servlet.resource.ResourceHttpRequestHandler) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        return check(request, response, handlerMethod);
    }
    private boolean check(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) {
        if (request.getServletPath().equals(JwtConstants.AUTH_PATH)) {
            return true;
        }
        final String requestHeader = request.getHeader(JwtConstants.AUTH_HEADER);
        String authToken;
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            authToken = requestHeader.substring(7);
            //验证token是否过期,包含了验证jwt是否正确
            try {
                boolean flag = JwtTokenUtil.isTokenExpired(authToken);
                if (flag) {
                    RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_EXPIRED.getCode(), BizExceptionEnum.TOKEN_EXPIRED.getMessage()));
                    return false;
                }
            } catch (JwtException e) {
                //有异常就是token解析失败
                RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
                return false;
            }
        } else {
            //header没有带Bearer字段
            RenderUtil.renderJson(response, new ErrorTip(BizExceptionEnum.TOKEN_ERROR.getCode(), BizExceptionEnum.TOKEN_ERROR.getMessage()));
            return false;
        }
        return true;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/intercept/SessionHolderInterceptor.java
New file
@@ -0,0 +1,34 @@
package com.stylefeng.guns.core.intercept;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.util.HttpSessionHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
 * 静态调用session的拦截器
 *
 * @author fengshuonan
 * @date 2016年11月13日 下午10:15:42
 */
@Aspect
@Component
public class SessionHolderInterceptor extends BaseController {
    @Pointcut("execution(* com.stylefeng.guns.*..controller.*.*(..))")
    public void cutService() {
    }
    @Around("cutService()")
    public Object sessionKit(ProceedingJoinPoint point) throws Throwable {
        HttpSessionHolder.put(super.getHttpServletRequest().getSession());
        try {
            return point.proceed();
        } finally {
            HttpSessionHolder.remove();
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/listener/ConfigListener.java
New file
@@ -0,0 +1,54 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.HashMap;
import java.util.Map;
/**
 * ServletContext监听器
 *
 * @author stylefeng
 * @Date 2018/2/22 21:07
 */
public class ConfigListener implements ServletContextListener {
    private static Map<String, String> conf = new HashMap<>();
    public static Map<String, String> getConf() {
        return conf;
    }
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        conf.clear();
    }
    @Override
    public void contextInitialized(ServletContextEvent evt) {
        ServletContext sc = evt.getServletContext();
        //项目发布,当前运行环境的绝对路径
        conf.put("realPath", sc.getRealPath("/").replaceFirst("/", ""));
        //servletContextPath,默认""
        conf.put("contextPath", sc.getContextPath());
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/log/LogManager.java
New file
@@ -0,0 +1,33 @@
package com.stylefeng.guns.core.log;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * 日志管理器
 *
 * @author fengshuonan
 * @date 2017-03-30 16:29
 */
public class LogManager {
    //日志记录操作延时
    private final int OPERATE_DELAY_TIME = 10;
    //异步操作记录日志的线程池
    private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
    private LogManager() {
    }
    public static LogManager logManager = new LogManager();
    public static LogManager me() {
        return logManager;
    }
    public void executeLog(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/log/LogObjectHolder.java
New file
@@ -0,0 +1,34 @@
package com.stylefeng.guns.core.log;
import com.stylefeng.guns.core.util.SpringContextHolder;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import java.io.Serializable;
/**
 * 被修改的bean临时存放的地方
 *
 * @author fengshuonan
 * @date 2017-03-31 11:19
 */
@Component
@Scope(scopeName = WebApplicationContext.SCOPE_SESSION)
public class LogObjectHolder implements Serializable{
    private Object object = null;
    public void set(Object obj) {
        this.object = obj;
    }
    public Object get() {
        return object;
    }
    public static LogObjectHolder me(){
        LogObjectHolder bean = SpringContextHolder.getBean(LogObjectHolder.class);
        return bean;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/log/factory/LogFactory.java
New file
@@ -0,0 +1,47 @@
package com.stylefeng.guns.core.log.factory;
import com.stylefeng.guns.core.common.constant.state.LogSucceed;
import com.stylefeng.guns.core.common.constant.state.LogType;
import com.stylefeng.guns.modular.system.model.LoginLog;
import com.stylefeng.guns.modular.system.model.OperationLog;
import java.util.Date;
/**
 * 日志对象创建工厂
 *
 * @author fengshuonan
 * @date 2016年12月6日 下午9:18:27
 */
public class LogFactory {
    /**
     * 创建操作日志
     */
    public static OperationLog createOperationLog(LogType logType, Integer userId, String bussinessName, String clazzName, String methodName, String msg, LogSucceed succeed) {
        OperationLog operationLog = new OperationLog();
        operationLog.setLogtype(logType.getMessage());
        operationLog.setLogname(bussinessName);
        operationLog.setUserid(userId);
        operationLog.setClassname(clazzName);
        operationLog.setMethod(methodName);
        operationLog.setCreatetime(new Date());
        operationLog.setSucceed(succeed.getMessage());
        operationLog.setMessage(msg);
        return operationLog;
    }
    /**
     * 创建登录日志
     */
    public static LoginLog createLoginLog(LogType logType, Integer userId, String msg, String ip) {
        LoginLog loginLog = new LoginLog();
        loginLog.setLogname(logType.getMessage());
        loginLog.setUserid(userId);
        loginLog.setCreatetime(new Date());
        loginLog.setSucceed(LogSucceed.SUCCESS.getMessage());
        loginLog.setIp(ip);
        loginLog.setMessage(msg);
        return loginLog;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/log/factory/LogTaskFactory.java
New file
@@ -0,0 +1,102 @@
package com.stylefeng.guns.core.log.factory;
import com.stylefeng.guns.core.common.constant.state.LogSucceed;
import com.stylefeng.guns.core.common.constant.state.LogType;
import com.stylefeng.guns.modular.system.dao.LoginLogMapper;
import com.stylefeng.guns.modular.system.dao.OperationLogMapper;
import com.stylefeng.guns.modular.system.model.LoginLog;
import com.stylefeng.guns.modular.system.model.OperationLog;
import com.stylefeng.guns.core.db.Db;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.util.ToolUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.TimerTask;
/**
 * 日志操作任务创建工厂
 *
 * @author fengshuonan
 * @date 2016年12月6日 下午9:18:27
 */
public class LogTaskFactory {
    private static Logger logger = LoggerFactory.getLogger(LogManager.class);
    private static LoginLogMapper loginLogMapper = Db.getMapper(LoginLogMapper.class);
    private static OperationLogMapper operationLogMapper = Db.getMapper(OperationLogMapper.class);
    public static TimerTask loginLog(final Integer userId, final String ip) {
        return new TimerTask() {
            @Override
            public void run() {
                try {
                    LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null, ip);
                    loginLogMapper.insert(loginLog);
                } catch (Exception e) {
                    logger.error("创建登录日志异常!", e);
                }
            }
        };
    }
    public static TimerTask loginLog(final String username, final String msg, final String ip) {
        return new TimerTask() {
            @Override
            public void run() {
                LoginLog loginLog = LogFactory.createLoginLog(
                        LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg, ip);
                try {
                    loginLogMapper.insert(loginLog);
                } catch (Exception e) {
                    logger.error("创建登录失败异常!", e);
                }
            }
        };
    }
    public static TimerTask exitLog(final Integer userId, final String ip) {
        return new TimerTask() {
            @Override
            public void run() {
                LoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null,ip);
                try {
                    loginLogMapper.insert(loginLog);
                } catch (Exception e) {
                    logger.error("创建退出日志异常!", e);
                }
            }
        };
    }
    public static TimerTask bussinessLog(final Integer userId, final String bussinessName, final String clazzName, final String methodName, final String msg) {
        return new TimerTask() {
            @Override
            public void run() {
                OperationLog operationLog = LogFactory.createOperationLog(
                        LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS);
                try {
                    operationLogMapper.insert(operationLog);
                } catch (Exception e) {
                    logger.error("创建业务日志异常!", e);
                }
            }
        };
    }
    public static TimerTask exceptionLog(final Integer userId, final Exception exception) {
        return new TimerTask() {
            @Override
            public void run() {
                String msg = ToolUtil.getExceptionMsg(exception);
                OperationLog operationLog = LogFactory.createOperationLog(
                        LogType.EXCEPTION, userId, "", null, null, msg, LogSucceed.FAIL);
                try {
                    operationLogMapper.insert(operationLog);
                } catch (Exception e) {
                    logger.error("创建异常日志异常!", e);
                }
            }
        };
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/ShiroDbRealm.java
New file
@@ -0,0 +1,78 @@
package com.stylefeng.guns.core.shiro;
import com.stylefeng.guns.core.shiro.factory.IShiro;
import com.stylefeng.guns.core.shiro.factory.ShiroFactroy;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.User;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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 java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ShiroDbRealm extends AuthorizingRealm {
    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
            throws AuthenticationException {
        IShiro shiroFactory = ShiroFactroy.me();
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        User user = shiroFactory.user(token.getUsername());
        ShiroUser shiroUser = shiroFactory.shiroUser(user);
        return shiroFactory.info(shiroUser, user, super.getName());
    }
    /**
     * 权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        IShiro shiroFactory = ShiroFactroy.me();
        ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
        List<Integer> roleList = shiroUser.getRoleList();
        Set<String> permissionSet = new HashSet<>();
        Set<String> roleNameSet = new HashSet<>();
        for (Integer roleId : roleList) {
            List<String> permissions = shiroFactory.findPermissionsByRoleId(roleId);
            if (permissions != null) {
                for (String permission : permissions) {
                    if (ToolUtil.isNotEmpty(permission)) {
                        permissionSet.add(permission);
                    }
                }
            }
            String roleName = shiroFactory.findRoleNameByRoleId(roleId);
            roleNameSet.add(roleName);
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionSet);
        info.addRoles(roleNameSet);
        return info;
    }
    /**
     * 设置认证加密方式
     */
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher md5CredentialsMatcher = new HashedCredentialsMatcher();
        md5CredentialsMatcher.setHashAlgorithmName(ShiroKit.hashAlgorithmName);
        md5CredentialsMatcher.setHashIterations(ShiroKit.hashIterations);
        super.setCredentialsMatcher(md5CredentialsMatcher);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/ShiroKit.java
New file
@@ -0,0 +1,290 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.shiro;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.util.ToolUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import java.util.List;
/**
 * shiro工具类
 *
 * @author dafei, Chill Zhuang
 */
public class ShiroKit {
    private static final String NAMES_DELIMETER = ",";
    /**
     * 加盐参数
     */
    public final static String hashAlgorithmName = "MD5";
    /**
     * 循环次数
     */
    public final static int hashIterations = 1024;
    /**
     * shiro密码加密工具类
     *
     * @param credentials 密码
     * @param saltSource 密码盐
     * @return
     */
    public static String md5(String credentials, String saltSource) {
        ByteSource salt = new Md5Hash(saltSource);
        return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations).toString();
    }
    /**
     * 获取随机盐值
     * @param length
     * @return
     */
    public static String getRandomSalt(int length) {
        return ToolUtil.getRandomString(length);
    }
    /**
     * 获取当前 Subject
     *
     * @return Subject
     */
    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }
    /**
     * 获取封装的 ShiroUser
     *
     * @return ShiroUser
     */
    public static ShiroUser getUser() {
        if (isGuest()) {
            return null;
        } else {
            return (ShiroUser) getSubject().getPrincipals().getPrimaryPrincipal();
        }
    }
    /**
     * 从shiro获取session
     *
     */
    public static Session getSession() {
        return getSubject().getSession();
    }
    /**
     * 获取shiro指定的sessionKey
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getSessionAttr(String key) {
        Session session = getSession();
        return session != null ? (T) session.getAttribute(key) : null;
    }
    /**
     * 设置shiro指定的sessionKey
     *
     */
    public static void setSessionAttr(String key, Object value) {
        Session session = getSession();
        session.setAttribute(key, value);
    }
    /**
     * 移除shiro指定的sessionKey
     */
    public static void removeSessionAttr(String key) {
        Session session = getSession();
        if (session != null)
            session.removeAttribute(key);
    }
    /**
     * 验证当前用户是否属于该角色?,使用时与lacksRole 搭配使用
     *
     * @param roleName
     *            角色名
     * @return 属于该角色:true,否则false
     */
    public static boolean hasRole(String roleName) {
        return getSubject() != null && roleName != null
                && roleName.length() > 0 && getSubject().hasRole(roleName);
    }
    /**
     * 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。
     *
     * @param roleName
     *            角色名
     * @return 不属于该角色:true,否则false
     */
    public static boolean lacksRole(String roleName) {
        return !hasRole(roleName);
    }
    /**
     * 验证当前用户是否属于以下任意一个角色。
     *
     * @param roleNames
     *            角色列表
     * @return 属于:true,否则false
     */
    public static boolean hasAnyRoles(String roleNames) {
        boolean hasAnyRole = false;
        Subject subject = getSubject();
        if (subject != null && roleNames != null && roleNames.length() > 0) {
            for (String role : roleNames.split(NAMES_DELIMETER)) {
                if (subject.hasRole(role.trim())) {
                    hasAnyRole = true;
                    break;
                }
            }
        }
        return hasAnyRole;
    }
    /**
     * 验证当前用户是否属于以下所有角色。
     *
     * @param roleNames
     *            角色列表
     * @return 属于:true,否则false
     */
    public static boolean hasAllRoles(String roleNames) {
        boolean hasAllRole = true;
        Subject subject = getSubject();
        if (subject != null && roleNames != null && roleNames.length() > 0) {
            for (String role : roleNames.split(NAMES_DELIMETER)) {
                if (!subject.hasRole(role.trim())) {
                    hasAllRole = false;
                    break;
                }
            }
        }
        return hasAllRole;
    }
    /**
     * 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用
     *
     * @param permission
     *            权限名
     * @return 拥有权限:true,否则false
     */
    public static boolean hasPermission(String permission) {
        return getSubject() != null && permission != null
                && permission.length() > 0
                && getSubject().isPermitted(permission);
    }
    /**
     * 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。
     *
     * @param permission
     *            权限名
     * @return 拥有权限:true,否则false
     */
    public static boolean lacksPermission(String permission) {
        return !hasPermission(permission);
    }
    /**
     * 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。与notAuthenticated搭配使用
     *
     * @return 通过身份验证:true,否则false
     */
    public static boolean isAuthenticated() {
        return getSubject() != null && getSubject().isAuthenticated();
    }
    /**
     * 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。。
     *
     * @return 没有通过身份验证:true,否则false
     */
    public static boolean notAuthenticated() {
        return !isAuthenticated();
    }
    /**
     * 认证通过或已记住的用户。与guset搭配使用。
     *
     * @return 用户:true,否则 false
     */
    public static boolean isUser() {
        return getSubject() != null && getSubject().getPrincipal() != null;
    }
    /**
     * 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。用user搭配使用
     *
     * @return 访客:true,否则false
     */
    public static boolean isGuest() {
        return !isUser();
    }
    /**
     * 输出当前用户信息,通常为登录帐号信息。
     *
     * @return 当前用户信息
     */
    public static String principal() {
        if (getSubject() != null) {
            Object principal = getSubject().getPrincipal();
            return principal.toString();
        }
        return "";
    }
    /**
     * 获取当前用户的部门数据范围的集合
     */
    public static List<Integer> getDeptDataScope() {
        Integer deptId = getUser().getDeptId();
        List<Integer> subDeptIds = ConstantFactory.me().getSubDeptId(deptId);
        subDeptIds.add(deptId);
        return subDeptIds;
    }
    /**
     * 判断当前用户是否是超级管理员
     */
    public static boolean isAdmin() {
        List<Integer> roleList = ShiroKit.getUser().getRoleList();
        for (Integer integer : roleList) {
            String singleRoleTip = ConstantFactory.me().getSingleRoleTip(integer);
            if (singleRoleTip.equals(Const.ADMIN_NAME)) {
                return true;
            }
        }
        return false;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/ShiroUser.java
New file
@@ -0,0 +1,81 @@
package com.stylefeng.guns.core.shiro;
import java.io.Serializable;
import java.util.List;
/**
 * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息
 *
 * @author fengshuonan
 * @date 2016年12月5日 上午10:26:43
 */
public class ShiroUser implements Serializable {
    private static final long serialVersionUID = 1L;
    public Integer id;          // 主键ID
    public String account;      // 账号
    public String name;         // 姓名
    public Integer deptId;      // 部门id
    public List<Integer> roleList; // 角色集
    public String deptName;        // 部门名称
    public List<String> roleNames; // 角色名称集
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getDeptId() {
        return deptId;
    }
    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }
    public List<Integer> getRoleList() {
        return roleList;
    }
    public void setRoleList(List<Integer> roleList) {
        this.roleList = roleList;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    public List<String> getRoleNames() {
        return roleNames;
    }
    public void setRoleNames(List<String> roleNames) {
        this.roleNames = roleNames;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/check/ICheck.java
New file
@@ -0,0 +1,32 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.shiro.check;
/**
 * 检查用接口
 */
public interface ICheck {
    /**
     * 检查当前登录用户是否拥有指定的角色访问当
     */
    boolean check(Object[] permissions);
    /**
     * 检查当前登录用户是否拥有当前请求的servlet的权限
     */
    boolean checkAll();
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/check/PermissionCheckFactory.java
New file
@@ -0,0 +1,73 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.shiro.check;
import com.stylefeng.guns.core.listener.ConfigListener;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.support.CollectionKit;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.SpringContextHolder;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
/**
 * 权限自定义检查
 */
@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class PermissionCheckFactory implements ICheck {
    public static ICheck me() {
        return SpringContextHolder.getBean(ICheck.class);
    }
    @Override
    public boolean check(Object[] permissions) {
        ShiroUser user = ShiroKit.getUser();
        if (null == user) {
            return false;
        }
        String join = CollectionKit.join(permissions, ",");
        if (ShiroKit.hasAnyRoles(join)) {
            return true;
        }
        return false;
    }
    @Override
    public boolean checkAll() {
        HttpServletRequest request = HttpKit.getRequest();
        ShiroUser user = ShiroKit.getUser();
        if (null == user) {
            return false;
        }
        String requestURI = request.getRequestURI().replaceFirst(ConfigListener.getConf().get("contextPath"), "");
        String[] str = requestURI.split("/");
        if (str.length > 3) {
            requestURI = "/" + str[1] + "/" + str[2];
        }
        if (ShiroKit.hasPermission(requestURI)) {
            return true;
        }
        return false;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/check/PermissionCheckManager.java
New file
@@ -0,0 +1,50 @@
/**
 * Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stylefeng.guns.core.shiro.check;
import com.stylefeng.guns.core.util.SpringContextHolder;
/**
 * 权限检查管理器(入口)
 */
public class PermissionCheckManager {
    private final static PermissionCheckManager me = new PermissionCheckManager();
    private ICheck defaultCheckFactory = SpringContextHolder.getBean(ICheck.class);
    public static PermissionCheckManager me() {
        return me;
    }
    private PermissionCheckManager() {
    }
    public PermissionCheckManager(ICheck checkFactory) {
        this.defaultCheckFactory = checkFactory;
    }
    public void setDefaultCheckFactory(ICheck defaultCheckFactory) {
        this.defaultCheckFactory = defaultCheckFactory;
    }
    public static boolean check(Object[] permissions) {
        return me.defaultCheckFactory.check(permissions);
    }
    public static boolean checkAll() {
        return me.defaultCheckFactory.checkAll();
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/factory/IShiro.java
New file
@@ -0,0 +1,50 @@
package com.stylefeng.guns.core.shiro.factory;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.modular.system.model.User;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import java.util.List;
/**
 * 定义shirorealm所需数据的接口
 *
 * @author fengshuonan
 * @date 2016年12月5日 上午10:23:34
 */
public interface IShiro {
    /**
     * 根据账号获取登录用户
     *
     * @param account 账号
     */
    User user(String account);
    /**
     * 根据系统用户获取Shiro的用户
     *
     * @param user 系统用户
     */
    ShiroUser shiroUser(User user);
    /**
     * 获取权限列表通过角色id
     *
     * @param roleId 角色id
     */
    List<String> findPermissionsByRoleId(Integer roleId);
    /**
     * 根据角色id获取角色名称
     *
     * @param roleId 角色id
     */
    String findRoleNameByRoleId(Integer roleId);
    /**
     * 获取shiro的认证信息
     */
    SimpleAuthenticationInfo info(ShiroUser shiroUser, User user, String realmName);
}
guns-admin/src/main/java/com/stylefeng/guns/core/shiro/factory/ShiroFactroy.java
New file
@@ -0,0 +1,98 @@
package com.stylefeng.guns.core.shiro.factory;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.constant.state.ManagerStatus;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.Convert;
import com.stylefeng.guns.core.util.SpringContextHolder;
import com.stylefeng.guns.modular.system.dao.MenuMapper;
import com.stylefeng.guns.modular.system.dao.UserMapper;
import com.stylefeng.guns.modular.system.model.User;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class ShiroFactroy implements IShiro {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MenuMapper menuMapper;
    public static IShiro me() {
        return SpringContextHolder.getBean(IShiro.class);
    }
    @Override
    public User user(String account) {
        User user = userMapper.getByAccount(account);
        // 账号不存在
        if (null == user) {
            throw new CredentialsException();
        }
        // 账号被冻结
        if (user.getStatus() != ManagerStatus.OK.getCode()) {
            throw new LockedAccountException();
        }
        return user;
    }
    @Override
    public ShiroUser shiroUser(User user) {
        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setId(user.getId());
        shiroUser.setAccount(user.getAccount());
        shiroUser.setDeptId(user.getDeptid());
        shiroUser.setDeptName(ConstantFactory.me().getDeptName(user.getDeptid()));
        shiroUser.setName(user.getName());
        Integer[] roleArray = Convert.toIntArray(user.getRoleid());
        List<Integer> roleList = new ArrayList<Integer>();
        List<String> roleNameList = new ArrayList<String>();
        for (int roleId : roleArray) {
            roleList.add(roleId);
            roleNameList.add(ConstantFactory.me().getSingleRoleName(roleId));
        }
        shiroUser.setRoleList(roleList);
        shiroUser.setRoleNames(roleNameList);
        return shiroUser;
    }
    @Override
    public List<String> findPermissionsByRoleId(Integer roleId) {
        return menuMapper.getResUrlsByRoleId(roleId);
    }
    @Override
    public String findRoleNameByRoleId(Integer roleId) {
        return ConstantFactory.me().getSingleRoleTip(roleId);
    }
    @Override
    public SimpleAuthenticationInfo info(ShiroUser shiroUser, User user, String realmName) {
        String credentials = user.getPassword();
        // 密码加盐处理
        String source = user.getSalt();
        ByteSource credentialsSalt = new Md5Hash(source);
        return new SimpleAuthenticationInfo(shiroUser, credentials, credentialsSalt, realmName);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/tag/DictSelectorTag.java
New file
@@ -0,0 +1,201 @@
package com.stylefeng.guns.core.tag;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Dict;
import com.stylefeng.guns.modular.system.service.IDictService;
import org.beetl.core.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
 * 字典标签渲染
 *
 * @author zhangjiajia
 * @Date 2018年6月4日17:33:32
 */
@Component
@Scope("prototype")
public class DictSelectorTag extends Tag {
    @Autowired
    IDictService iDictService;
    @Override
    public void render(){
        //String tagName = (String) this.args[0];
        Map attrs = (Map) args[1];
        if(ToolUtil.isEmpty(attrs.get("code"))){
            throw new GunsException(BizExceptionEnum.ERROR_CODE_EMPTY);
        }
        //字典类型编码
        String code = attrs.get("code").toString();
        //控件显示类型select 选择框,radio 单选按钮,checkbox 多选按钮
        String type = ToolUtil.isNotEmpty(attrs.get("type"))?attrs.get("type").toString():"select";
        //开启多选
        String multiple = ToolUtil.isNotEmpty(attrs.get("multiple"))?attrs.get("multiple").toString():"";
        //字典名称
        String label = ToolUtil.isNotEmpty(attrs.get("label"))?attrs.get("label").toString():"";
        //提示
        String placeholder = (ToolUtil.isNotEmpty(attrs.get("placeholder"))?attrs.get("placeholder").toString():"");
        //宽度
        String width = ToolUtil.isNotEmpty(attrs.get("width"))?attrs.get("width").toString():"248";
        //默认值
        String value = ToolUtil.isNotEmpty(attrs.get("value"))?attrs.get("value").toString():"";
        //id
        String id = ToolUtil.isNotEmpty(attrs.get("id"))?attrs.get("id").toString():"";
        //name
        String name = ToolUtil.isNotEmpty(attrs.get("name"))?attrs.get("name").toString():"";
        //分割线
        String underline = ToolUtil.isNotEmpty(attrs.get("underline"))?attrs.get("underline").toString():"";
        //onchange事件
        String onchange = ToolUtil.isNotEmpty(attrs.get("onchange"))?attrs.get("onchange").toString():"";
        //readonly属性
        String readonly = ToolUtil.isNotEmpty(attrs.get("readonly"))?attrs.get("readonly").toString():"";
        //disabled属性
        String disabled = ToolUtil.isNotEmpty(attrs.get("disabled"))?attrs.get("disabled").toString():"";
        //searchnum 下拉选项数量达到多少启用搜索,默认10
        int searchnum = ToolUtil.isNum(attrs.get("searchnum"))?Integer.parseInt(attrs.get("searchnum").toString()):10;
        //根据code查询字典数据
        List<Dict>  list = iDictService.selectByParentCode(code);
        StringBuffer html = new StringBuffer();
        html.append("<div class=\"form-group\">\r\n");
        html.append("<label class=\"col-sm-3 control-label\">"+label+"</label>\r\n");
        html.append("<div class=\"col-sm-9\">\r\n");
        //单选按钮
        if("radio".equals(type)) {
            list.forEach(obj->{
                html.append("<label class=\"radio-inline i-checks\">\r\n<input type=\"radio\" ");
                //判断控件是否禁用
                if("true".equals(disabled)||"disabled".equals(disabled)) {
                    html.append("disabled ");
                }else{
                    if(ToolUtil.isNotEmpty(name)){
                        html.append("name=\""+name+"\" ");
                    }
                }
                if("true".equals(readonly)||"disabled".equals(readonly)) {
                    html.append("disabled ");
                }
                if(ToolUtil.isNotEmpty(value)&&value.equals(obj.getCode())){
                    html.append("checked ");
                }
                html.append("value=\""+obj.getCode()+"\" >"+obj.getName()+"</label>\r\n");
            });
        //多选按钮
        }else if("checkbox".equals(type)){
            list.forEach(obj->{
                html.append("<label class=\"checkbox-inline i-checks\">\r\n<input type=\"checkbox\" ");
                //判断控件是否禁用
                if("true".equals(disabled)||"disabled".equals(disabled)) {
                    html.append("disabled ");
                }else{
                    if(ToolUtil.isNotEmpty(name)){
                        html.append("name=\""+name+"\" ");
                    }
                }
                if("true".equals(readonly)||"disabled".equals(readonly)) {
                    html.append("disabled ");
                }
                if(ToolUtil.isNotEmpty(value)&&value.equals(obj.getCode())){
                    html.append("checked ");
                }
                html.append("value=\""+obj.getCode()+"\" >"+obj.getName()+"</label>\r\n");
            });
        //默认select
        }else{
            //开启多选
            if("true".equals(multiple)){
                if(list.size()>=searchnum) {
                    html.append("<select multiple ");
                }else{
                    html.append("<select multiple=\"multiple\" size=\"10\" ");
                }
            }else{
                html.append("<select ");
            }
            //判断控件是否启用提示
            if(ToolUtil.isNotEmpty(placeholder)){
                html.append(" data-placeholder=\""+placeholder+"\" ");
            }
            //判断控件是否禁用
            if("true".equals(disabled)||"disabled".equals(disabled)) {
                html.append("disabled=\"disabled\" ");
            }else{
                //启用
                if(ToolUtil.isNotEmpty(id)){
                    html.append("id=\""+id+"\" ");
                }
                if(ToolUtil.isNotEmpty(name)){
                    html.append("name=\""+name+"\" ");
                }
            }
            //判断是否启用搜索框
            //判断下拉数据,如果查询出来的条数达到启用搜索的数量就启用
            if(list.size()>=searchnum){
                html.append("class=\"form-control chosen-select\" style=\"width:"+width+"px\"  tabindex=\"1\" \r\n");
            } else{
                html.append("class=\"form-control\" style=\"width:"+width+"px\" \r\n");
            }
            //判断控件是否只读
            if("true".equals(readonly)||"readonly".equals(readonly)) {
                if(list.size()>=searchnum) {
                    html.append("disabled=\"disabled\" ");
                }else{
                    html.append("onfocus=\"this.defaultIndex=this.selectedIndex;\" onchange=\"this.selectedIndex=this.defaultIndex;\" ");
                }
            }
            //判断是否绑定onchange事件
            if(ToolUtil.isNotEmpty(onchange)){
                html.append("onchange=\""+onchange+"($(this).children('option:selected').val())\" ");
            }
            html.append(">");
            if(ToolUtil.isNotEmpty(placeholder)){
                html.append("<option value=\"\">"+placeholder+"</option>\r\n");
            }
            //将查询出来的数据添加到select中
            list.forEach(obj->{
                if(ToolUtil.isNotEmpty(value)&&value.equals(obj.getCode())){
                    html.append("<option selected value=\""+obj.getCode()+"\">"+obj.getName()+"</option>\r\n");
                }else{
                    html.append("<option value=\""+obj.getCode()+"\">"+obj.getName()+"</option>\r\n");
                }
            });
            html.append("</select>\r\n");
        }
        html.append("</div>\r\n</div>\r\n");
        //判断是否添加分割线
        if(ToolUtil.isNotEmpty(underline) && "true".equals(underline)) {
            html.append("<div class=\"hr-line-dashed\" ></div >\r\n");
        }
        try{
            this.ctx.byteWriter.writeString(html.toString());
        }catch (IOException e){
            throw new RuntimeException("输出字典标签错误");
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/util/ApiMenuFilter.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.core.util;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.config.properties.GunsProperties;
import com.stylefeng.guns.core.node.MenuNode;
import java.util.ArrayList;
import java.util.List;
/**
 * api接口文档显示过滤
 *
 * @author fengshuonan
 * @date 2017-08-17 16:55
 */
public class ApiMenuFilter extends MenuNode {
    public static List<MenuNode> build(List<MenuNode> nodes) {
        //如果关闭了接口文档,则不显示接口文档菜单
        GunsProperties gunsProperties = SpringContextHolder.getBean(GunsProperties.class);
        if (!gunsProperties.getSwaggerOpen()) {
            List<MenuNode> menuNodesCopy = new ArrayList<>();
            for (MenuNode menuNode : nodes) {
                if (Const.API_MENU_NAME.equals(menuNode.getName())) {
                    continue;
                } else {
                    menuNodesCopy.add(menuNode);
                }
            }
            nodes = menuNodesCopy;
        }
        return nodes;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/util/Contrast.java
New file
@@ -0,0 +1,211 @@
package com.stylefeng.guns.core.util;
import com.stylefeng.guns.core.common.constant.dictmap.base.AbstractDictMap;
import com.stylefeng.guns.core.common.constant.dictmap.factory.DictFieldWarpperFactory;
import com.stylefeng.guns.core.support.StrKit;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
/**
 * 对比两个对象的变化的工具类
 *
 * @author fengshuonan
 * @Date 2017/3/31 10:36
 */
public class Contrast {
    //记录每个修改字段的分隔符
    public static final String separator = ";;;";
    /**
     * 比较两个对象,并返回不一致的信息
     *
     * @author stylefeng
     * @Date 2017/5/9 19:34
     */
    public static String contrastObj(Object pojo1, Object pojo2) {
        String str = "";
        try {
            Class clazz = pojo1.getClass();
            Field[] fields = pojo1.getClass().getDeclaredFields();
            int i = 1;
            for (Field field : fields) {
                if ("serialVersionUID".equals(field.getName())) {
                    continue;
                }
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                Method getMethod = pd.getReadMethod();
                Object o1 = getMethod.invoke(pojo1);
                Object o2 = getMethod.invoke(pojo2);
                if (o1 == null || o2 == null) {
                    continue;
                }
                if (o1 instanceof Date) {
                    o1 = DateUtil.getDay((Date) o1);
                }
                if (!o1.toString().equals(o2.toString())) {
                    if (i != 1) {
                        str += separator;
                    }
                    str += "字段名称" + field.getName() + ",旧值:" + o1 + ",新值:" + o2;
                    i++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }
    /**
     * 比较两个对象pojo1和pojo2,并输出不一致信息
     *
     * @author stylefeng
     * @Date 2017/5/9 19:34
     */
    public static String contrastObj(Class dictClass, String key, Object pojo1, Map<String, String> pojo2) throws IllegalAccessException, InstantiationException {
        AbstractDictMap dictMap = (AbstractDictMap) dictClass.newInstance();
        String str = parseMutiKey(dictMap, key, pojo2) + separator;
        try {
            Class clazz = pojo1.getClass();
            Field[] fields = pojo1.getClass().getDeclaredFields();
            int i = 1;
            for (Field field : fields) {
                if ("serialVersionUID".equals(field.getName())) {
                    continue;
                }
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                Method getMethod = pd.getReadMethod();
                Object o1 = getMethod.invoke(pojo1);
                Object o2 = pojo2.get(StrKit.firstCharToLowerCase(getMethod.getName().substring(3)));
                if (o1 == null || o2 == null) {
                    continue;
                }
                if (o1 instanceof Date) {
                    o1 = DateUtil.getDay((Date) o1);
                } else if (o1 instanceof Integer) {
                    o2 = Integer.parseInt(o2.toString());
                }
                if (!o1.toString().equals(o2.toString())) {
                    if (i != 1) {
                        str += separator;
                    }
                    String fieldName = dictMap.get(field.getName());
                    String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(field.getName());
                    if (fieldWarpperMethodName != null) {
                        Object o1Warpper = DictFieldWarpperFactory.createFieldWarpper(o1, fieldWarpperMethodName);
                        Object o2Warpper = DictFieldWarpperFactory.createFieldWarpper(o2, fieldWarpperMethodName);
                        str += "字段名称:" + fieldName + ",旧值:" + o1Warpper + ",新值:" + o2Warpper;
                    } else {
                        str += "字段名称:" + fieldName + ",旧值:" + o1 + ",新值:" + o2;
                    }
                    i++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }
    /**
     * 比较两个对象pojo1和pojo2,并输出不一致信息
     *
     * @author stylefeng
     * @Date 2017/5/9 19:34
     */
    public static String contrastObjByName(Class dictClass, String key, Object pojo1, Map<String, String> pojo2) throws IllegalAccessException, InstantiationException {
        AbstractDictMap dictMap = (AbstractDictMap) dictClass.newInstance();
        String str = parseMutiKey(dictMap, key, pojo2) + separator;
        try {
            Class clazz = pojo1.getClass();
            Field[] fields = pojo1.getClass().getDeclaredFields();
            int i = 1;
            for (Field field : fields) {
                if ("serialVersionUID".equals(field.getName())) {
                    continue;
                }
                String prefix = "get";
                int prefixLength = 3;
                if (field.getType().getName().equals("java.lang.Boolean")) {
                    prefix = "is";
                    prefixLength = 2;
                }
                Method getMethod = null;
                try {
                    getMethod = clazz.getDeclaredMethod(prefix + StrKit.firstCharToUpperCase(field.getName()));
                } catch (java.lang.NoSuchMethodException e) {
                    System.err.println("this className:" + clazz.getName() + " is not methodName: " + e.getMessage());
                    continue;
                }
                Object o1 = getMethod.invoke(pojo1);
                Object o2 = pojo2.get(StrKit.firstCharToLowerCase(getMethod.getName().substring(prefixLength)));
                if (o1 == null || o2 == null) {
                    continue;
                }
                if (o1 instanceof Date) {
                    o1 = DateUtil.getDay((Date) o1);
                } else if (o1 instanceof Integer) {
                    o2 = Integer.parseInt(o2.toString());
                }
                if (!o1.toString().equals(o2.toString())) {
                    if (i != 1) {
                        str += separator;
                    }
                    String fieldName = dictMap.get(field.getName());
                    String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(field.getName());
                    if (fieldWarpperMethodName != null) {
                        Object o1Warpper = DictFieldWarpperFactory.createFieldWarpper(o1, fieldWarpperMethodName);
                        Object o2Warpper = DictFieldWarpperFactory.createFieldWarpper(o2, fieldWarpperMethodName);
                        str += "字段名称:" + fieldName + ",旧值:" + o1Warpper + ",新值:" + o2Warpper;
                    } else {
                        str += "字段名称:" + fieldName + ",旧值:" + o1 + ",新值:" + o2;
                    }
                    i++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }
    /**
     * 解析多个key(逗号隔开的)
     *
     * @author stylefeng
     * @Date 2017/5/16 22:19
     */
    public static String parseMutiKey(AbstractDictMap dictMap, String key, Map<String, String> requests) {
        StringBuilder sb = new StringBuilder();
        if (key.indexOf(",") != -1) {
            String[] keys = key.split(",");
            for (String item : keys) {
                String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(item);
                String value = requests.get(item);
                if (fieldWarpperMethodName != null) {
                    Object valueWarpper = DictFieldWarpperFactory.createFieldWarpper(value, fieldWarpperMethodName);
                    sb.append(dictMap.get(item) + "=" + valueWarpper + ",");
                } else {
                    sb.append(dictMap.get(item) + "=" + value + ",");
                }
            }
            return StrKit.removeSuffix(sb.toString(), ",");
        } else {
            String fieldWarpperMethodName = dictMap.getFieldWarpperMethodName(key);
            String value = requests.get(key);
            if (fieldWarpperMethodName != null) {
                Object valueWarpper = DictFieldWarpperFactory.createFieldWarpper(value, fieldWarpperMethodName);
                sb.append(dictMap.get(key) + "=" + valueWarpper);
            } else {
                sb.append(dictMap.get(key) + "=" + value);
            }
            return sb.toString();
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/util/JwtTokenUtil.java
New file
@@ -0,0 +1,128 @@
package com.stylefeng.guns.core.util;
import com.stylefeng.guns.core.common.constant.JwtConstants;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 * <p>jwt token工具类</p>
 * <pre>
 *     jwt的claim里一般包含以下几种数据:
 *         1. iss -- token的发行者
 *         2. sub -- 该JWT所面向的用户
 *         3. aud -- 接收该JWT的一方
 *         4. exp -- token的失效时间
 *         5. nbf -- 在此时间段之前,不会被处理
 *         6. iat -- jwt发布时间
 *         7. jti -- jwt唯一标识,防止重复使用
 * </pre>
 *
 * @author fengshuonan
 * @Date 2017/8/25 10:59
 */
@Component
public class JwtTokenUtil {
    /**
     * 获取用户名从token中
     */
    public static String getUsernameFromToken(String token) {
        return getClaimFromToken(token).getSubject();
    }
    /**
     * 获取jwt发布时间
     */
    public static Date getIssuedAtDateFromToken(String token) {
        return getClaimFromToken(token).getIssuedAt();
    }
    /**
     * 获取jwt失效时间
     */
    public static Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token).getExpiration();
    }
    /**
     * 获取jwt接收者
     */
    public static String getAudienceFromToken(String token) {
        return getClaimFromToken(token).getAudience();
    }
    /**
     * 获取私有的jwt claim
     */
    public static String getPrivateClaimFromToken(String token, String key) {
        return getClaimFromToken(token).get(key).toString();
    }
    /**
     * 获取jwt的payload部分
     */
    public static Claims getClaimFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(JwtConstants.SECRET)
                .parseClaimsJws(token)
                .getBody();
    }
    /**
     * 解析token是否正确,不正确会报异常<br>
     */
    public static void parseToken(String token) throws JwtException {
        Jwts.parser().setSigningKey(JwtConstants.SECRET).parseClaimsJws(token).getBody();
    }
    /**
     * <pre>
     *  验证token是否失效
     *  true:过期   false:没过期
     * </pre>
     */
    public static Boolean isTokenExpired(String token) {
        try {
            final Date expiration = getExpirationDateFromToken(token);
            return expiration.before(new Date());
        } catch (ExpiredJwtException expiredJwtException) {
            return true;
        }
    }
    /**
     * 生成token(通过用户名和签名时候用的随机数)
     */
    public static String generateToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        return doGenerateToken(claims, userId);
    }
    /**
     * 生成token
     */
    private static String doGenerateToken(Map<String, Object> claims, String subject) {
        final Date createdDate = new Date();
        final Date expirationDate = new Date(createdDate.getTime() + JwtConstants.EXPIRATION * 1000);
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(createdDate)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512, JwtConstants.SECRET)
                .compact();
    }
    /**
     * 获取混淆MD5签名用的随机字符串
     */
    public static String getRandomKey() {
        return ToolUtil.getRandomString(6);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/core/util/KaptchaUtil.java
New file
@@ -0,0 +1,16 @@
package com.stylefeng.guns.core.util;
import com.stylefeng.guns.config.properties.GunsProperties;
/**
 * 验证码工具类
 */
public class KaptchaUtil {
    /**
     * 获取验证码开关
     */
    public static Boolean getKaptchaOnOff() {
        return SpringContextHolder.getBean(GunsProperties.class).getKaptchaOpen();
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/api/ApiController.java
New file
@@ -0,0 +1,80 @@
package com.stylefeng.guns.modular.api;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.modular.system.dao.UserMapper;
import com.stylefeng.guns.modular.system.model.User;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
/**
 * 接口控制器提供
 *
 * @author stylefeng
 * @Date 2018/7/20 23:39
 */
@RestController
@RequestMapping("/base")
public class ApiController extends BaseController {
    @Autowired
    private UserMapper userMapper;
    /**
     * api登录接口,通过账号密码获取token
     */
    @RequestMapping("/auth")
    public Object auth(String username, String password) {
        //封装请求账号密码为shiro可验证的token
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password.toCharArray());
        //获取数据库中的账号密码,准备比对
        User user = userMapper.getByAccount(username);
        String credentials = user.getPassword();
        String salt = user.getSalt();
        ByteSource credentialsSalt = new Md5Hash(salt);
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                new ShiroUser(), credentials, credentialsSalt, "");
        //校验用户账号密码
        HashedCredentialsMatcher md5CredentialsMatcher = new HashedCredentialsMatcher();
        md5CredentialsMatcher.setHashAlgorithmName(ShiroKit.hashAlgorithmName);
        md5CredentialsMatcher.setHashIterations(ShiroKit.hashIterations);
        boolean passwordTrueFlag = md5CredentialsMatcher.doCredentialsMatch(
                usernamePasswordToken, simpleAuthenticationInfo);
        if (passwordTrueFlag) {
            String token = JwtTokenUtil.generateToken(String.valueOf(user.getId()));
            HashMap<String, Object> result = new HashMap<>();
            result.put("token", token);
            return result;
        } else {
            return new ErrorTip(500, "账号密码错误!");
        }
    }
    /**
     * 测试接口是否走鉴权
     */
    @RequestMapping(value = "/test", method = RequestMethod.POST)
    public Object test() {
        return SUCCESS_TIP;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/api/PatrolTaskController.java
New file
@@ -0,0 +1,190 @@
package com.stylefeng.guns.modular.api;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.constant.JwtConstants;
import com.stylefeng.guns.core.page.PageInfoBT;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.enums.ImageModelEnum;
import com.stylefeng.guns.modular.system.model.enums.VideoChannelEnum;
import com.stylefeng.guns.modular.system.model.vo.*;
import com.stylefeng.guns.modular.system.service.IPatrolTaskService;
import com.stylefeng.guns.modular.system.service.ITaskDetailService;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import com.stylefeng.guns.modular.system.util.videoGateway.VideoGateway;
import com.stylefeng.guns.modular.system.util.videoGateway.model.Ship;
import com.stylefeng.guns.modular.system.util.videoGateway.model.Vehicle;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:18
 */
@RestController
@RequestMapping("/base/patrolTask")
public class PatrolTaskController extends BaseController {
    @Resource
    private IPatrolTaskService patrolTaskService;
    @Resource
    private ITaskDetailService taskDetailService;
    @GetMapping("/getTaskDetailList")
    @ApiOperation(value = "获取任务列表数据", tags = {"任务管理"})
    public PageInfoBT<TaskDetailList> getTaskDetailList(TaskDetailListVo vo){
        Page<TaskDetailList> pageInfo = new Page(vo.getOffset(), vo.getPageSize());
        List<TaskDetailList> taskDetailList = taskDetailService.getTaskDetailList(pageInfo, vo);
        pageInfo.setRecords(taskDetailList);
        return super.packForBT(pageInfo);
    }
    @DeleteMapping("/delTaskDetail")
    @ApiOperation(value = "删除任务", tags = {"任务管理"})
    public ResultUtil delTaskDetail(List<Integer> ids){
        taskDetailService.delTaskDetail(ids);
        return ResultUtil.success();
    }
    @PostMapping("/addPatrolTask")
    @ApiOperation(value = "添加巡查任务", tags = {"任务管理"})
    public ResultUtil addPatrolTask(@RequestBody PatrolTaskVo vo, HttpServletRequest request){
        String token = request.getHeader(JwtConstants.AUTH_HEADER);
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(token.indexOf(" ") + 1);
        }
        String userId = JwtTokenUtil.getPrivateClaimFromToken(token, "userId");
        patrolTaskService.addPatrolTask(vo, userId);
        return ResultUtil.success();
    }
    @GetMapping("/getImageModel")
    @ApiOperation(value = "获取图片模型", tags = {"任务管理"})
    public ResultUtil<List<Map<String, Object>>> getImageModel(){
        ImageModelEnum[] values = ImageModelEnum.values();
        List<Map<String, Object>> list = new ArrayList<>();
        for (ImageModelEnum modelEnum : values) {
            String name = modelEnum.getName();
            String code = modelEnum.getCode();
            Map<String, Object> map = new HashMap<>();
            map.put("name", name);
            map.put("code", code);
            list.add(map);
        }
        return ResultUtil.success(list);
    }
    @GetMapping("/getVideoChannel")
    @ApiOperation(value = "获取视频通道", tags = {"任务管理"})
    public ResultUtil<List<Map<String, Object>>> getVideoChannel(){
        VideoChannelEnum[] values = VideoChannelEnum.values();
        List<Map<String, Object>> list = new ArrayList<>();
        for (VideoChannelEnum modelEnum : values) {
            String name = modelEnum.getName();
            Integer id = modelEnum.getId();
            Map<String, Object> map = new HashMap<>();
            map.put("name", name);
            map.put("id", id);
            list.add(map);
        }
        return ResultUtil.success(list);
    }
    @GetMapping("/getVehicleList")
    @ApiOperation(value = "获取车辆列表", tags = {"任务管理"})
    public ResultUtil<List<Vehicle>> getVehicleList(){
        List<Vehicle> vehicleList = VideoGateway.getVehicleList(null, null, null, 0);
        return ResultUtil.success(vehicleList);
    }
    @GetMapping("/getShipList")
    @ApiOperation(value = "获取船舶列表", tags = {"任务管理"})
    public ResultUtil<List<Ship>> getShipList(){
        List<Ship> shipList = VideoGateway.getShipList(null, null, null, 0);
        return ResultUtil.success(shipList);
    }
    @GetMapping("/getTaskRecordList")
    @ApiOperation(value = "获取任务记录列表", tags = {"任务记录"})
    public PageInfoBT<TaskRecordList> getTaskRecordList(TaskRecordListVo vo){
        Page<TaskRecordList> pageInfo = new Page(vo.getOffset(), vo.getPageSize());
        List<TaskRecordList> taskRecordList = taskDetailService.getTaskRecordList(pageInfo, vo);
        pageInfo.setRecords(taskRecordList);
        return super.packForBT(pageInfo);
    }
    @GetMapping("/getTaskRecordInfo")
    @ApiOperation(value = "获取任务记录详情", tags = {"任务记录"})
    public ResultUtil<TaskRecordInfo> getTaskRecordInfo(Integer id){
        TaskRecordInfo taskRecordInfo = taskDetailService.getTaskRecordInfo(id);
        return ResultUtil.success(taskRecordInfo);
    }
    @GetMapping("/getPictureDetailsVehicle")
    @ApiOperation(value = "获取任务记录详情中的车船数据", tags = {"任务记录"})
    public ResultUtil<PictureDetailsVehicle> getPictureDetailsVehicle(PictureDetailsVo vo){
        PictureDetailsVehicle pictureDetailsVehicle = taskDetailService.getPictureDetailsVehicle(vo);
        return ResultUtil.success(pictureDetailsVehicle);
    }
    @GetMapping("/getPictureDetails")
    @ApiOperation(value = "获取任务记录详情中的视频通道数据", tags = {"任务记录"})
    public PageInfoBT<PictureDetails> getPictureDetails(PictureDetailsVo vo){
        Page<PictureDetails> pageInfo = new Page(vo.getOffset(), vo.getPageSize());
        List<PictureDetails> pictureDetails = taskDetailService.getPictureDetails(pageInfo, vo);
        pageInfo.setRecords(pictureDetails);
        return super.packForBT(pageInfo);
    }
    @PostMapping("/manualAudit")
    @ApiOperation(value = "人工审核视频通道数据", tags = {"任务记录"})
    public ResultUtil manualAudit(@RequestBody ManualAuditVo vo){
        return taskDetailService.manualAudit(vo);
    }
    @GetMapping("/downloadTaskRecord")
    @ApiOperation(value = "下载任务记录数据", tags = {"任务记录"})
    @ApiImplicitParams({
            @ApiImplicitParam(value = "列表数据id,多个逗号分隔", name = "ids", dataType = "String"),
            @ApiImplicitParam(value = "状态(1=待执行,2=进行中,3=成功,4=失败)", name = "status", dataType = "int"),
            @ApiImplicitParam(value = "规则编号", name = "code", dataType = "String"),
    })
    public void downloadTaskRecord(String ids, String code, Integer status, HttpServletResponse response){
        List<String> id = null;
        if(ToolUtil.isNotEmpty(ids)){
            String[] split = ids.split(",");
            id = Arrays.asList(split);
        }
        taskDetailService.downloadTaskRecord(id, code, status, response);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/code/controller/CodeController.java
New file
@@ -0,0 +1,61 @@
package com.stylefeng.guns.modular.code.controller;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.config.properties.DruidProperties;
import com.stylefeng.guns.generator.action.config.WebGeneratorConfig;
import com.stylefeng.guns.generator.action.model.GenQo;
import com.stylefeng.guns.modular.code.factory.DefaultTemplateFactory;
import com.stylefeng.guns.modular.code.service.TableService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
 * 代码生成控制器
 *
 * @author fengshuonan
 * @Date 2017年11月30日16:39:19
 */
@Controller
@RequestMapping("/code")
public class CodeController extends BaseController {
    private static String PREFIX = "/code";
    @Autowired
    private TableService tableService;
    @Autowired
    private DruidProperties druidProperties;
    /**
     * 跳转到代码生成主页
     */
    @RequestMapping("")
    public String blackboard(Model model) {
        model.addAttribute("tables", tableService.getAllTables());
        model.addAttribute("params", DefaultTemplateFactory.getDefaultParams());
        model.addAttribute("templates", DefaultTemplateFactory.getDefaultTemplates());
        return PREFIX + "/code.html";
    }
    /**
     * 生成代码
     */
    @ApiOperation("生成代码")
    @RequestMapping(value = "/generate", method = RequestMethod.POST)
    @ResponseBody
    public Object generate(GenQo genQo) {
        genQo.setUrl(druidProperties.getUrl());
        genQo.setUserName(druidProperties.getUsername());
        genQo.setPassword(druidProperties.getPassword());
        WebGeneratorConfig webGeneratorConfig = new WebGeneratorConfig(genQo);
        webGeneratorConfig.doMpGeneration();
        webGeneratorConfig.doGunsGeneration();
        return SUCCESS_TIP;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/code/factory/DefaultTemplateFactory.java
New file
@@ -0,0 +1,61 @@
package com.stylefeng.guns.modular.code.factory;
import com.stylefeng.guns.GunsApplication;
import com.stylefeng.guns.core.CoreFlag;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.generator.action.model.GenQo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 模板种类构建器
 *
 * @author fengshuonan
 * @date 2017-12-04-下午2:59
 */
public class DefaultTemplateFactory {
    /**
     * 获取所有的模板种类
     */
    public static List<Map<String,Object>> getDefaultTemplates(){
        ArrayList<Map<String, Object>> templates = new ArrayList<>();
        templates.add(create("controllerSwitch","controller-控制器模板"));
        templates.add(create("entitySwitch","entity-实体模板"));
        templates.add(create("serviceSwitch","service-service模板"));
        templates.add(create("daoSwitch","dao-dao模板"));
        templates.add(create("indexPageSwitch","indexPage-首页模板"));
        templates.add(create("addPageSwitch","addPage-添加页面模板"));
        templates.add(create("editPageSwitch","editPage-编辑页面模板"));
        templates.add(create("jsSwitch","indexJs-主页js模板"));
        templates.add(create("infoJsSwitch","infoJs-详情页js模板"));
        templates.add(create("sqlSwitch","sql-sql语句模板"));
        return templates;
    }
    /**
     * 获取默认的参数
     */
    public static GenQo getDefaultParams(){
        GenQo genQo = new GenQo();
        genQo.setProjectPath(ToolUtil.getWebRootPath(null));
        genQo.setAuthor("stylefeng");
        genQo.setProjectPackage(GunsApplication.class.getPackage().getName());
        genQo.setCorePackage(CoreFlag.class.getPackage().getName());
        genQo.setIgnoreTabelPrefix("sys_");
        genQo.setModuleName("system");
        genQo.setParentMenuName("系统管理");
        return genQo;
    }
    private static Map<String,Object> create(String key,String desc){
        HashMap<String, Object> template = new HashMap<>();
        template.put("key",key);
        template.put("desc",desc);
        return template;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/code/service/TableService.java
New file
@@ -0,0 +1,29 @@
package com.stylefeng.guns.modular.code.service;
import com.baomidou.mybatisplus.mapper.SqlRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
 * 获取数据库所有的表
 *
 * @author fengshuonan
 * @date 2017-12-04-下午1:37
 */
@Service
public class TableService {
    @Value("${spring.datasource.db-name}")
    private String dbName;
    /**
     * 获取当前数据库所有的表信息
     */
    public List<Map<String, Object>> getAllTables() {
        String sql = "select TABLE_NAME as tableName,TABLE_COMMENT as tableComment from information_schema.`TABLES` where TABLE_SCHEMA = '" + dbName + "'";
        return SqlRunner.db().selectList(sql);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/AuthIntercepter.java
New file
@@ -0,0 +1,37 @@
package com.stylefeng.guns.modular.system.auth;
import com.alibaba.fastjson.JSON;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class AuthIntercepter implements HandlerInterceptor {
    private final static Logger log = LoggerFactory.getLogger(AuthIntercepter.class);
    @Autowired
    AuthService authService;
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws IOException {
        String appid = req.getParameter("appid");
        String sign = req.getParameter("sign");
        ResultUtil resultUtil = authService.checkSyncAuth(appid, sign, req);
        if (resultUtil.getCode() != 200) {
            res.setStatus(HttpStatus.OK.value());
            res.setHeader("Content-type", "text/html;charset=UTF-8");
            res.getWriter().print(JSON.toJSONString(resultUtil));//Res.Failure("req timeout, please try again")
            return false;
        }
        return true;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/AuthService.java
New file
@@ -0,0 +1,49 @@
package com.stylefeng.guns.modular.system.auth;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
@Service
public class AuthService {
    private final static Logger log = LoggerFactory.getLogger(AuthService.class);
    public static final AuthService me = new AuthService();
    /**
     * 鉴权
     * @param appid
     * @param sign
     * @param requset
     * @return
     */
    public ResultUtil checkSyncAuth(String appid, String sign, HttpServletRequest requset) {
        try {
            if (StringUtils.isBlank(sign)) {
                return ResultUtil.sign();
            }
            // 1.鉴权
            String signUrl = AuthenticationKit.getSignUrl(requset, "sign");
            signUrl = signUrl.replaceAll("& #40;", "\\(");
            signUrl = signUrl.replaceAll("& #41;", "\\)");
            String signUrlEncode = AuthenticationKit.signUrlEncode(signUrl, appid);
            if(sign.indexOf(" ") != -1 && signUrlEncode.indexOf("+") != -1){//处理前后端加密差异
                signUrlEncode = signUrlEncode.replaceAll("\\+", " ");
            }
            // 签名无
            if (StringUtils.isBlank(sign) || !sign.equals(signUrlEncode)) {
                return ResultUtil.sign();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.runErr();
        }
        return ResultUtil.success();
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/AuthenticationKit.java
New file
@@ -0,0 +1,232 @@
package com.stylefeng.guns.modular.system.auth;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
 *
 * 接口鉴权工具类
 *
 * @author gwx 2017-12-23
 *
 */
public class AuthenticationKit {
    public static final String utf8="UTF-8";
    /**
     * 返回64 位 token
     *
     * @param key 自定义安全字符
     * @return
     * @throws Exception
     */
    public static String getToken(String key) throws Exception {
        // 随机生成 32位字符
        String salt = HashKit.generateSaltForSha256();
        // 获取当前时间
        long cur = System.currentTimeMillis();
        // 生成64位token
        String access_token = getToken256(key, salt, cur);
        return access_token;
    }
    /**
     * 返回64 位 token
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String getToken256(String key, String salt, long cur) throws Exception {
        // 生成64位token
        String access_token = HashKit.sha256(salt + cur + key);
        return access_token;
    }
    /**
     * 返回到秒
     *
     * @return
     */
    public static String createTimestamp() {
        long l = System.currentTimeMillis();
        return Long.toString(l / 1000);
    }
    /**
     * 返回noce 不带 短杠"-"
     *
     * @return
     */
    public static String createNonceStr() {
        return getUUID();
    }
    public static String getUUID() {
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString();
        str = str.replaceAll("-", "");
        return str;
    }
    /**
     * 组装路径
     *
     * @param params
     * @return
     */
    public static String localSignParam(Map<String, String> params) {
        return localSignUrl(null, params, false);
    }
    /**
     * 组装签名路径
     * @param url
     * @param params
     * @return
     */
    public static String localSignUrl(String url, Map<String, String> params, boolean urlEncode) {
        StringBuilder strBuilder = new StringBuilder();
//        if(StringUtils.isNotBlank(url) && url.lastIndexOf("?")==-1){
//            strBuilder.append(url).append("?");
//        }
        Set es = params.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)) {
                strBuilder.append(k + "=" + v + "&");
            }
        }
        return strBuilder.substring(0, strBuilder.length() - 1);
//        for (String key : params.keySet()) {
//            if (params.get(key) != null) {
//                String lowerKey = key.toLowerCase();
//                String encodeKey = lowerKey;
//                String encodedValue = params.get(key);
//                if (urlEncode){
//                    encodeKey = UrlEncoderUtils.encode(lowerKey);
//                    encodedValue = UrlEncoderUtils.encode(encodedValue);
//                }
//                if (!seeOne) {
//                    seeOne = true;
//                } else {
//                    strBuilder.append("&");
//                }
//                strBuilder.append(encodeKey).append("=").append(encodedValue);
//            }
//        }
//        return strBuilder.toString();
    }
    /**
     * 加密签名路径生成签名
     *
     * @param signUrl
     *            /token?appid=12345&timestamp=1512440267&nonce=12345
     * @param encryptKey
     * @return
     * @throws Exception
     */
    public static String signUrlEncode(String signUrl, String encryptKey) throws Exception {
        byte[] signByte = HMACSHA1.HmacSHA1Encrypt(signUrl, encryptKey);
        String localSign = Base64.encodeBase64String(signByte);
        return localSign;
    }
    /**
     * 返回鉴权 签名路径
     *
     * @param req
     * @return
     */
    public static String getSignUrl(HttpServletRequest req) {
        return getSignUrl(req,"");
    }
    /**
     * 服务端 获取 客户端请求 组装验证签名
     * @param req
     * @param delParams 移除不相关 的签名参数
     * @return
     */
    public static String getSignUrl(HttpServletRequest req, String... delParams) {
        // 获取相对的访问路径
        String url = req.getServletPath();
        Map<String, String> paramMap = packageRequestGetParams(req);
        if (paramMap.size() > 0) {
            // 删除
            for (int i = 0, len = delParams.length; i < len; i++) {
                paramMap.remove(delParams[i]);
            }
            return localSignUrl(url, paramMap, false);
        }
        return null;
    }
    /**
     * 组装签名路径 客户端测试用
     * @param url api访问地址 "/apid"
     * @param appid
     * @return
     */
    public static String getSignUrl(String url, String appid, Map<String, String> queryParas) {
        Map<String, String> params = new TreeMap<String, String>();
        params.put("appid", appid);
        params.put("nonce", createNonceStr());
        params.put("timestamp", createTimestamp());
        if(queryParas!=null && queryParas.size()>0){
            params.putAll(queryParas);
        }
        return localSignUrl(url, params, false);
    }
    /**
     * 组装签名路径 客户端测试用
     * @param url api访问地址 "/apid"
     * @param appid
     * @return
     */
    public static String getSignUrl(String url, String appid) {
        return getSignUrl(url, appid, "");
    }
    /**
     *
     * @param url
     * @param appid
     * @param params
     * @return
     */
    public static String getSignUrl(String url, String appid, String params) {
        String urlTmp = getSignUrl(url, appid, new HashMap<String,String>());
        return urlTmp + UrlEncoderUtils.encode(params);
    }
    /**
     * 解析get参数返回treemap
     * @param req
     * @return
     */
    public static Map<String, String> packageRequestGetParams(
            HttpServletRequest req) {
        Map<String, String> paramMap = new TreeMap<String, String>();
        Enumeration pNames = req.getParameterNames();
        while (pNames.hasMoreElements()) {
            String key = (String) pNames.nextElement();
            String value = req.getParameter(key);
            paramMap.put(key, value);
        }
        return paramMap;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/Configuration.java
New file
@@ -0,0 +1,26 @@
package com.stylefeng.guns.modular.system.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class Configuration implements WebMvcConfigurer {
    @Autowired
    private AuthIntercepter authIntercepter;
    /**
     * 重写添加拦截器方法并添加配置拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(authIntercepter).addPathPatterns("/api/**")
//                .excludePathPatterns("/base/**");
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/HMACSHA1.java
New file
@@ -0,0 +1,63 @@
package com.stylefeng.guns.modular.system.auth;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HMACSHA1 {
    private static final String MAC_NAME = "HmacSHA1";
    private static final String ENCODING = "UTF-8";
    /*
     * 展示了一个生成指定算法密钥的过程 初始化HMAC密钥
     *
     * @return
     *
     * @throws Exception
     *
     * public static String initMacKey() throws Exception { //得到一个 指定算法密钥的密钥生成器
     * KeyGenerator KeyGenerator keyGenerator
     * =KeyGenerator.getInstance(MAC_NAME); //生成一个密钥 SecretKey secretKey
     * =keyGenerator.generateKey(); return null; }
     */
    /**
     * 使用 HMAC-SHA1 签名方法对对encryptText进行签名
     *
     * @param encryptText
     *            被签名的字符串
     * @param encryptKey
     *            密钥
     * @return
     * @throws Exception
     */
    public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception {
        byte[] data = encryptKey.getBytes(ENCODING);
        // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
        Mac mac = Mac.getInstance(MAC_NAME);
        SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
        // 生成一个指定 Mac 算法 的 Mac 对象
        // 用给定密钥初始化 Mac 对象
        mac.init(secretKey);
        byte[] text = encryptText.getBytes(ENCODING);
        // 完成 Mac 操作
        return mac.doFinal(text);
    }
    public static void main(String[] args) {
        String encryptText = "123";
        String encryptKey = "adc";
        try {
            byte[] b = HmacSHA1Encrypt(encryptText, encryptKey);
            String str = HashKit.toHex(b);
            String str2 = new String(Base64.encodeBase64(b));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/HashKit.java
New file
@@ -0,0 +1,109 @@
package com.stylefeng.guns.modular.system.auth;
/**
 * Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.security.MessageDigest;
public class HashKit {
    public static final long FNV_OFFSET_BASIS_64 = 0xcbf29ce484222325L;
    public static final long FNV_PRIME_64 = 0x100000001b3L;
    private static final java.security.SecureRandom random = new java.security.SecureRandom();
    private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
    private static final char[] CHAR_ARRAY = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            .toCharArray();
    public static long fnv1a64(String key) {
        long hash = FNV_OFFSET_BASIS_64;
        for (int i = 0, size = key.length(); i < size; i++) {
            hash ^= key.charAt(i);
            hash *= FNV_PRIME_64;
        }
        return hash;
    }
    public static String md5(String srcStr) {
        return hash("MD5", srcStr);
    }
    public static String sha1(String srcStr) {
        return hash("SHA-1", srcStr);
    }
    public static String sha256(String srcStr) {
        return hash("SHA-256", srcStr);
    }
    public static String sha384(String srcStr) {
        return hash("SHA-384", srcStr);
    }
    public static String sha512(String srcStr) {
        return hash("SHA-512", srcStr);
    }
    public static String hash(String algorithm, String srcStr) {
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            byte[] bytes = md.digest(srcStr.getBytes("utf-8"));
            return toHex(bytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static String toHex(byte[] bytes) {
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
        }
        return ret.toString();
    }
    /**
     * md5 128bit 16bytes sha1 160bit 20bytes sha256 256bit 32bytes sha384
     * 384bit 48bytes sha512 512bit 64bytes
     */
    public static String generateSalt(int saltLength) {
        StringBuilder salt = new StringBuilder(saltLength);
        for (int i = 0; i < saltLength; i++) {
            salt.append(CHAR_ARRAY[random.nextInt(CHAR_ARRAY.length)]);
        }
        return salt.toString();
    }
    public static String generateSaltForSha256() {
        return generateSalt(32);
    }
    public static String generateSaltForSha512() {
        return generateSalt(64);
    }
    public static boolean slowEquals(byte[] a, byte[] b) {
        if (a == null || b == null) {
            return false;
        }
        int diff = a.length ^ b.length;
        for (int i = 0; i < a.length && i < b.length; i++) {
            diff |= a[i] ^ b[i];
        }
        return diff == 0;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/auth/UrlEncoderUtils.java
New file
@@ -0,0 +1,44 @@
package com.stylefeng.guns.modular.system.auth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class UrlEncoderUtils {
    private static final String PATH_DELIMITER = "/";
    private static final Logger log = LoggerFactory.getLogger(UrlEncoderUtils.class);
    public static String encode(String originUrl) {
        try {
            return URLEncoder.encode(originUrl, "UTF-8").replace("+", "%20").replace("*", "%2A")
                    .replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            log.error("URLEncoder error, encode utf8, exception: {}", e);
        }
        return null;
    }
    // encode路径, 不包括分隔符
    public static String encodeEscapeDelimiter(String urlPath) {
        StringBuilder pathBuilder = new StringBuilder();
        String[] pathSegmentsArr = urlPath.split(PATH_DELIMITER);
        boolean isFirstSegMent = true;
        for (String pathSegment : pathSegmentsArr) {
            if (isFirstSegMent) {
                pathBuilder.append(encode(pathSegment));
                isFirstSegMent = false;
            } else {
                pathBuilder.append(PATH_DELIMITER).append(encode(pathSegment));
            }
        }
        if (urlPath.endsWith(PATH_DELIMITER)) {
            pathBuilder.append(PATH_DELIMITER);
        }
        return pathBuilder.toString();
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/BlackboardController.java
New file
@@ -0,0 +1,35 @@
package com.stylefeng.guns.modular.system.controller;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.modular.system.service.INoticeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import java.util.Map;
/**
 * 总览信息
 *
 * @author fengshuonan
 * @Date 2017年3月4日23:05:54
 */
@Controller
@RequestMapping("/blackboard")
public class BlackboardController extends BaseController {
    @Autowired
    private INoticeService noticeService;
    /**
     * 跳转到黑板
     */
    @RequestMapping("")
    public String blackboard(Model model) {
        List<Map<String, Object>> notices = noticeService.list(null);
        model.addAttribute("noticeList", notices);
        return "/blackboard.html";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/DeptController.java
New file
@@ -0,0 +1,164 @@
package com.stylefeng.guns.modular.system.controller;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.dictmap.DeptDict;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Dept;
import com.stylefeng.guns.modular.system.service.IDeptService;
import com.stylefeng.guns.modular.system.warpper.DeptWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
/**
 * 部门控制器
 *
 * @author fengshuonan
 * @Date 2017年2月17日20:27:22
 */
@Controller
@RequestMapping("/dept")
public class DeptController extends BaseController {
    private String PREFIX = "/system/dept/";
    @Autowired
    private IDeptService deptService;
    /**
     * 跳转到部门管理首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "dept.html";
    }
    /**
     * 跳转到添加部门
     */
    @RequestMapping("/dept_add")
    public String deptAdd() {
        return PREFIX + "dept_add.html";
    }
    /**
     * 跳转到修改部门
     */
    @Permission
    @RequestMapping("/dept_update/{deptId}")
    public String deptUpdate(@PathVariable Integer deptId, Model model) {
        Dept dept = deptService.selectById(deptId);
        model.addAttribute(dept);
        model.addAttribute("pName", ConstantFactory.me().getDeptName(dept.getPid()));
        LogObjectHolder.me().set(dept);
        return PREFIX + "dept_edit.html";
    }
    /**
     * 获取部门的tree列表
     */
    @RequestMapping(value = "/tree")
    @ResponseBody
    public List<ZTreeNode> tree() {
        List<ZTreeNode> tree = this.deptService.tree();
        tree.add(ZTreeNode.createParent());
        return tree;
    }
    /**
     * 新增部门
     */
    @BussinessLog(value = "添加部门", key = "simplename", dict = DeptDict.class)
    @RequestMapping(value = "/add")
    @Permission
    @ResponseBody
    public Object add(Dept dept) {
        if (ToolUtil.isOneEmpty(dept, dept.getSimplename())) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //完善pids,根据pid拿到pid的pids
        deptSetPids(dept);
        return this.deptService.insert(dept);
    }
    /**
     * 获取所有部门列表
     */
    @RequestMapping(value = "/list")
    @Permission
    @ResponseBody
    public Object list(String condition) {
        List<Map<String, Object>> list = this.deptService.list(condition);
        return super.warpObject(new DeptWarpper(list));
    }
    /**
     * 部门详情
     */
    @RequestMapping(value = "/detail/{deptId}")
    @Permission
    @ResponseBody
    public Object detail(@PathVariable("deptId") Integer deptId) {
        return deptService.selectById(deptId);
    }
    /**
     * 修改部门
     */
    @BussinessLog(value = "修改部门", key = "simplename", dict = DeptDict.class)
    @RequestMapping(value = "/update")
    @Permission
    @ResponseBody
    public Object update(Dept dept) {
        if (ToolUtil.isEmpty(dept) || dept.getId() == null) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        deptSetPids(dept);
        deptService.updateById(dept);
        return SUCCESS_TIP;
    }
    /**
     * 删除部门
     */
    @BussinessLog(value = "删除部门", key = "deptId", dict = DeptDict.class)
    @RequestMapping(value = "/delete")
    @Permission
    @ResponseBody
    public Object delete(@RequestParam Integer deptId) {
        //缓存被删除的部门名称
        LogObjectHolder.me().set(ConstantFactory.me().getDeptName(deptId));
        deptService.deleteDept(deptId);
        return SUCCESS_TIP;
    }
    private void deptSetPids(Dept dept) {
        if (ToolUtil.isEmpty(dept.getPid()) || dept.getPid().equals(0)) {
            dept.setPid(0);
            dept.setPids("[0],");
        } else {
            int pid = dept.getPid();
            Dept temp = deptService.selectById(pid);
            String pids = temp.getPids();
            dept.setPid(pid);
            dept.setPids(pids + "[" + pid + "],");
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/DictController.java
New file
@@ -0,0 +1,142 @@
package com.stylefeng.guns.modular.system.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.dictmap.DictMap;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Dict;
import com.stylefeng.guns.modular.system.service.IDictService;
import com.stylefeng.guns.modular.system.warpper.DictWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
/**
 * 字典控制器
 *
 * @author fengshuonan
 * @Date 2017年4月26日 12:55:31
 */
@Controller
@RequestMapping("/dict")
public class DictController extends BaseController {
    private String PREFIX = "/system/dict/";
    @Autowired
    private IDictService dictService;
    /**
     * 跳转到字典管理首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "dict.html";
    }
    /**
     * 跳转到添加字典
     */
    @RequestMapping("/dict_add")
    public String deptAdd() {
        return PREFIX + "dict_add.html";
    }
    /**
     * 跳转到修改字典
     */
    @Permission(Const.ADMIN_NAME)
    @RequestMapping("/dict_edit/{dictId}")
    public String deptUpdate(@PathVariable Integer dictId, Model model) {
        Dict dict = dictService.selectById(dictId);
        model.addAttribute("dict", dict);
        List<Dict> subDicts = dictService.selectList(new EntityWrapper<Dict>().eq("pid", dictId));
        model.addAttribute("subDicts", subDicts);
        LogObjectHolder.me().set(dict);
        return PREFIX + "dict_edit.html";
    }
    /**
     * 新增字典
     *
     * @param dictValues 格式例如   "1:启用;2:禁用;3:冻结"
     */
    @BussinessLog(value = "添加字典记录", key = "dictName,dictValues", dict = DictMap.class)
    @RequestMapping(value = "/add")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object add(String dictCode,String dictTips,String dictName, String dictValues) {
        if (ToolUtil.isOneEmpty(dictCode,dictName, dictValues)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        this.dictService.addDict(dictCode,dictName,dictTips,dictValues);
        return SUCCESS_TIP;
    }
    /**
     * 获取所有字典列表
     */
    @RequestMapping(value = "/list")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object list(String condition) {
        List<Map<String, Object>> list = this.dictService.list(condition);
        return super.warpObject(new DictWarpper(list));
    }
    /**
     * 字典详情
     */
    @RequestMapping(value = "/detail/{dictId}")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object detail(@PathVariable("dictId") Integer dictId) {
        return dictService.selectById(dictId);
    }
    /**
     * 修改字典
     */
    @BussinessLog(value = "修改字典", key = "dictName,dictValues", dict = DictMap.class)
    @RequestMapping(value = "/update")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object update(Integer dictId,String dictCode,String dictName, String dictTips,String dictValues) {
        if (ToolUtil.isOneEmpty(dictId, dictCode, dictName, dictValues)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        dictService.editDict(dictId, dictCode,dictName, dictTips,dictValues);
        return SUCCESS_TIP;
    }
    /**
     * 删除字典记录
     */
    @BussinessLog(value = "删除字典记录", key = "dictId", dict = DictMap.class)
    @RequestMapping(value = "/delete")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object delete(@RequestParam Integer dictId) {
        //缓存被删除的名称
        LogObjectHolder.me().set(ConstantFactory.me().getDictName(dictId));
        this.dictService.delteDict(dictId);
        return SUCCESS_TIP;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/KaptchaController.java
New file
@@ -0,0 +1,140 @@
package com.stylefeng.guns.modular.system.controller;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.stylefeng.guns.config.properties.GunsProperties;
import com.stylefeng.guns.core.util.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Properties;
/**
 * 验证码生成
 *
 * @author fengshuonan
 * @date 2017-05-05 23:10
 */
@Controller
@RequestMapping("/kaptcha")
public class KaptchaController {
    @Autowired
    private GunsProperties gunsProperties;
    @Autowired
    private Producer producer;
    /**
     * 生成验证码
     */
    @RequestMapping("")
    public void index(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        response.setDateHeader("Expires", 0);
        // Set standard HTTP/1.1 no-cache headers.
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        // Set standard HTTP/1.0 no-cache header.
        response.setHeader("Pragma", "no-cache");
        // return a jpeg
        response.setContentType("image/jpeg");
        // create the text for the image
        String capText = producer.createText();
        // store the text in the session
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        // create the image with the text
        Properties properties = new Properties();
        // 设置边框
        properties.setProperty("kaptcha.border", "no");
        // 设置颜色
        properties.setProperty("kaptcha.border.color", "105,179,90");
        // 设置字体颜色
        properties.setProperty("kaptcha.textproducer.font.color", "blue");
        // 设置宽度
        properties.setProperty("kaptcha.image.width", "125");
        // 高度
        properties.setProperty("kaptcha.image.height", "42");
        // 设置session.key
        properties.setProperty("kaptcha.session.key", "code");
        // 设置文本长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        // 设置字体
        properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
        //字体大小
        properties.setProperty("kaptcha.textproducer.font.size", "35");
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        BufferedImage bi = defaultKaptcha.createImage(capText);
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // write the data out
        try {
            ImageIO.write(bi, "jpg", out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            try {
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 返回图片
     *
     * @author stylefeng
     * @Date 2017/5/24 23:00
     */
    @RequestMapping("/{pictureId}")
    public void renderPicture(@PathVariable("pictureId") String pictureId, HttpServletResponse response) {
        String path = gunsProperties.getFileUploadPath() + pictureId;
        try {
            byte[] bytes = FileUtil.toByteArray(path);
            response.getOutputStream().write(bytes);
        } catch (Exception e) {
            //如果找不到图片就返回一个默认图片
            try {
                response.sendRedirect("/static/img/girl.gif");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/LogController.java
New file
@@ -0,0 +1,84 @@
package com.stylefeng.guns.modular.system.controller;
import com.baomidou.mybatisplus.mapper.SqlRunner;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.factory.PageFactory;
import com.stylefeng.guns.core.common.constant.state.BizLogType;
import com.stylefeng.guns.core.support.BeanKit;
import com.stylefeng.guns.modular.system.model.OperationLog;
import com.stylefeng.guns.modular.system.service.IOperationLogService;
import com.stylefeng.guns.modular.system.warpper.LogWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
/**
 * 日志管理的控制器
 *
 * @author fengshuonan
 * @Date 2017年4月5日 19:45:36
 */
@Controller
@RequestMapping("/log")
public class LogController extends BaseController {
    private static String PREFIX = "/system/log/";
    @Autowired
    private IOperationLogService operationLogService;
    /**
     * 跳转到日志管理的首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "log.html";
    }
    /**
     * 查询操作日志列表
     */
    @RequestMapping("/list")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object list(@RequestParam(required = false) String beginTime, @RequestParam(required = false) String endTime, @RequestParam(required = false) String logName, @RequestParam(required = false) Integer logType) {
        Page<OperationLog> page = new PageFactory<OperationLog>().defaultPage();
        List<Map<String, Object>> result = operationLogService.getOperationLogs(page, beginTime, endTime, logName, BizLogType.valueOf(logType), page.getOrderByField(), page.isAsc());
        page.setRecords((List<OperationLog>) new LogWarpper(result).warp());
        return super.packForBT(page);
    }
    /**
     * 查询操作日志详情
     */
    @RequestMapping("/detail/{id}")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object detail(@PathVariable Integer id) {
        OperationLog operationLog = operationLogService.selectById(id);
        Map<String, Object> stringObjectMap = BeanKit.beanToMap(operationLog);
        return super.warpObject(new LogWarpper(stringObjectMap));
    }
    /**
     * 清空日志
     */
    @BussinessLog(value = "清空业务日志")
    @RequestMapping("/delLog")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object delLog() {
        SqlRunner.db().delete("delete from sys_operation_log");
        return SUCCESS_TIP;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/LoginController.java
New file
@@ -0,0 +1,134 @@
package com.stylefeng.guns.modular.system.controller;
import com.google.code.kaptcha.Constants;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.exception.InvalidKaptchaException;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.log.factory.LogTaskFactory;
import com.stylefeng.guns.core.node.MenuNode;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.ApiMenuFilter;
import com.stylefeng.guns.core.util.KaptchaUtil;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.User;
import com.stylefeng.guns.modular.system.service.IMenuService;
import com.stylefeng.guns.modular.system.service.IUserService;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
import static com.stylefeng.guns.core.support.HttpKit.getIp;
/**
 * 登录控制器
 *
 * @author fengshuonan
 * @Date 2017年1月10日 下午8:25:24
 */
@Controller
public class LoginController extends BaseController {
    @Autowired
    private IMenuService menuService;
    @Autowired
    private IUserService userService;
    /**
     * 跳转到主页
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(Model model) {
        //获取菜单列表
        List<Integer> roleList = ShiroKit.getUser().getRoleList();
        if (roleList == null || roleList.size() == 0) {
            ShiroKit.getSubject().logout();
            model.addAttribute("tips", "该用户没有角色,无法登陆");
            return "/login.html";
        }
        List<MenuNode> menus = menuService.getMenusByRoleIds(roleList);
        List<MenuNode> titles = MenuNode.buildTitle(menus);
        titles = ApiMenuFilter.build(titles);
        model.addAttribute("titles", titles);
        //获取用户头像
        Integer id = ShiroKit.getUser().getId();
        User user = userService.selectById(id);
        String avatar = user.getAvatar();
        model.addAttribute("avatar", avatar);
        return "/index.html";
    }
    /**
     * 跳转到登录页面
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() {
        if (ShiroKit.isAuthenticated() || ShiroKit.getUser() != null) {
            return REDIRECT + "/";
        } else {
            return "/login.html";
        }
    }
    /**
     * 点击登录执行的动作
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String loginVali() {
        String username = super.getPara("username").trim();
        String password = super.getPara("password").trim();
        String remember = super.getPara("remember");
        //验证验证码是否正确
        if (KaptchaUtil.getKaptchaOnOff()) {
            String kaptcha = super.getPara("kaptcha").trim();
            String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
            if (ToolUtil.isEmpty(kaptcha) || !kaptcha.equalsIgnoreCase(code)) {
                throw new InvalidKaptchaException();
            }
        }
        Subject currentUser = ShiroKit.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray());
        if ("on".equals(remember)) {
            token.setRememberMe(true);
        } else {
            token.setRememberMe(false);
        }
        currentUser.login(token);
        ShiroUser shiroUser = ShiroKit.getUser();
        super.getSession().setAttribute("shiroUser", shiroUser);
        super.getSession().setAttribute("username", shiroUser.getAccount());
        LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp()));
        ShiroKit.getSession().setAttribute("sessionFlag", true);
        return REDIRECT + "/";
    }
    /**
     * 退出登录
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logOut() {
        LogManager.me().executeLog(LogTaskFactory.exitLog(ShiroKit.getUser().getId(), getIp()));
        ShiroKit.getSubject().logout();
        deleteAllCookie();
        return REDIRECT + "/login";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/LoginLogController.java
New file
@@ -0,0 +1,69 @@
package com.stylefeng.guns.modular.system.controller;
import com.baomidou.mybatisplus.mapper.SqlRunner;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.factory.PageFactory;
import com.stylefeng.guns.modular.system.model.LoginLog;
import com.stylefeng.guns.modular.system.service.ILoginLogService;
import com.stylefeng.guns.modular.system.warpper.LogWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
/**
 * 日志管理的控制器
 *
 * @author fengshuonan
 * @Date 2017年4月5日 19:45:36
 */
@Controller
@RequestMapping("/loginLog")
public class LoginLogController extends BaseController {
    private static String PREFIX = "/system/log/";
    @Autowired
    private ILoginLogService loginLogService;
    /**
     * 跳转到日志管理的首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "login_log.html";
    }
    /**
     * 查询登录日志列表
     */
    @RequestMapping("/list")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object list(@RequestParam(required = false) String beginTime, @RequestParam(required = false) String endTime, @RequestParam(required = false) String logName) {
        Page<LoginLog> page = new PageFactory<LoginLog>().defaultPage();
        List<Map<String, Object>> result = loginLogService.getLoginLogs(page, beginTime, endTime, logName, page.getOrderByField(), page.isAsc());
        page.setRecords((List<LoginLog>) new LogWarpper(result).warp());
        return super.packForBT(page);
    }
    /**
     * 清空日志
     */
    @BussinessLog("清空登录日志")
    @RequestMapping("/delLoginLog")
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Object delLog() {
        SqlRunner.db().delete("delete from sys_login_log");
        return SUCCESS_TIP;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/MenuController.java
New file
@@ -0,0 +1,244 @@
package com.stylefeng.guns.modular.system.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.Tip;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.dictmap.MenuDict;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.constant.state.MenuStatus;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.core.support.BeanKit;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Menu;
import com.stylefeng.guns.modular.system.service.IMenuService;
import com.stylefeng.guns.modular.system.warpper.MenuWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
 * 菜单控制器
 *
 * @author fengshuonan
 * @Date 2017年2月12日21:59:14
 */
@Controller
@RequestMapping("/menu")
public class MenuController extends BaseController {
    private static String PREFIX = "/system/menu/";
    @Autowired
    private IMenuService menuService;
    /**
     * 跳转到菜单列表列表页面
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "menu.html";
    }
    /**
     * 跳转到菜单列表列表页面
     */
    @RequestMapping(value = "/menu_add")
    public String menuAdd() {
        return PREFIX + "menu_add.html";
    }
    /**
     * 跳转到菜单详情列表页面
     */
    @Permission(Const.ADMIN_NAME)
    @RequestMapping(value = "/menu_edit/{menuId}")
    public String menuEdit(@PathVariable Long menuId, Model model) {
        if (ToolUtil.isEmpty(menuId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        Menu menu = this.menuService.selectById(menuId);
        //获取父级菜单的id
        Menu temp = new Menu();
        temp.setCode(menu.getPcode());
        Menu pMenu = this.menuService.selectOne(new EntityWrapper<>(temp));
        //如果父级是顶级菜单
        if (pMenu == null) {
            menu.setPcode("0");
        } else {
            //设置父级菜单的code为父级菜单的id
            menu.setPcode(String.valueOf(pMenu.getId()));
        }
        Map<String, Object> menuMap = BeanKit.beanToMap(menu);
        menuMap.put("pcodeName", ConstantFactory.me().getMenuNameByCode(temp.getCode()));
        model.addAttribute("menu", menuMap);
        LogObjectHolder.me().set(menu);
        return PREFIX + "menu_edit.html";
    }
    /**
     * 修该菜单
     */
    @Permission(Const.ADMIN_NAME)
    @RequestMapping(value = "/edit")
    @BussinessLog(value = "修改菜单", key = "name", dict = MenuDict.class)
    @ResponseBody
    public Tip edit(@Valid Menu menu, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //设置父级菜单编号
        menuSetPcode(menu);
        this.menuService.updateById(menu);
        return SUCCESS_TIP;
    }
    /**
     * 获取菜单列表
     */
    @Permission(Const.ADMIN_NAME)
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(@RequestParam(required = false) String menuName, @RequestParam(required = false) String level) {
        List<Map<String, Object>> menus = this.menuService.selectMenus(menuName, level);
        return super.warpObject(new MenuWarpper(menus));
    }
    /**
     * 新增菜单
     */
    @Permission(Const.ADMIN_NAME)
    @RequestMapping(value = "/add")
    @BussinessLog(value = "菜单新增", key = "name", dict = MenuDict.class)
    @ResponseBody
    public Tip add(@Valid Menu menu, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //判断是否存在该编号
        String existedMenuName = ConstantFactory.me().getMenuNameByCode(menu.getCode());
        if (ToolUtil.isNotEmpty(existedMenuName)) {
            throw new GunsException(BizExceptionEnum.EXISTED_THE_MENU);
        }
        //设置父级菜单编号
        menuSetPcode(menu);
        menu.setStatus(MenuStatus.ENABLE.getCode());
        this.menuService.insert(menu);
        return SUCCESS_TIP;
    }
    /**
     * 删除菜单
     */
    @Permission(Const.ADMIN_NAME)
    @RequestMapping(value = "/remove")
    @BussinessLog(value = "删除菜单", key = "menuId", dict = MenuDict.class)
    @ResponseBody
    public Tip remove(@RequestParam Long menuId) {
        if (ToolUtil.isEmpty(menuId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //缓存菜单的名称
        LogObjectHolder.me().set(ConstantFactory.me().getMenuName(menuId));
        this.menuService.delMenuContainSubMenus(menuId);
        return SUCCESS_TIP;
    }
    /**
     * 查看菜单
     */
    @RequestMapping(value = "/view/{menuId}")
    @ResponseBody
    public Tip view(@PathVariable Long menuId) {
        if (ToolUtil.isEmpty(menuId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        this.menuService.selectById(menuId);
        return SUCCESS_TIP;
    }
    /**
     * 获取菜单列表(首页用)
     */
    @RequestMapping(value = "/menuTreeList")
    @ResponseBody
    public List<ZTreeNode> menuTreeList() {
        List<ZTreeNode> roleTreeList = this.menuService.menuTreeList();
        return roleTreeList;
    }
    /**
     * 获取菜单列表(选择父级菜单用)
     */
    @RequestMapping(value = "/selectMenuTreeList")
    @ResponseBody
    public List<ZTreeNode> selectMenuTreeList() {
        List<ZTreeNode> roleTreeList = this.menuService.menuTreeList();
        roleTreeList.add(ZTreeNode.createParent());
        return roleTreeList;
    }
    /**
     * 获取角色列表
     */
    @RequestMapping(value = "/menuTreeListByRoleId/{roleId}")
    @ResponseBody
    public List<ZTreeNode> menuTreeListByRoleId(@PathVariable Integer roleId) {
        List<Long> menuIds = this.menuService.getMenuIdsByRoleId(roleId);
        if (ToolUtil.isEmpty(menuIds)) {
            List<ZTreeNode> roleTreeList = this.menuService.menuTreeList();
            return roleTreeList;
        } else {
            List<ZTreeNode> roleTreeListByUserId = this.menuService.menuTreeListByMenuIds(menuIds);
            return roleTreeListByUserId;
        }
    }
    /**
     * 根据请求的父级菜单编号设置pcode和层级
     */
    private void menuSetPcode(@Valid Menu menu) {
        if (ToolUtil.isEmpty(menu.getPcode()) || menu.getPcode().equals("0")) {
            menu.setPcode("0");
            menu.setPcodes("[0],");
            menu.setLevels(1);
        } else {
            long code = Long.parseLong(menu.getPcode());
            Menu pMenu = menuService.selectById(code);
            Integer pLevels = pMenu.getLevels();
            menu.setPcode(pMenu.getCode());
            //如果编号和父编号一致会导致无限递归
            if (menu.getCode().equals(menu.getPcode())) {
                throw new GunsException(BizExceptionEnum.MENU_PCODE_COINCIDENCE);
            }
            menu.setLevels(pLevels + 1);
            menu.setPcodes(pMenu.getPcodes() + "[" + pMenu.getCode() + "],");
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/NoticeController.java
New file
@@ -0,0 +1,138 @@
package com.stylefeng.guns.modular.system.controller;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.constant.dictmap.NoticeMap;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Notice;
import com.stylefeng.guns.modular.system.service.INoticeService;
import com.stylefeng.guns.modular.system.warpper.NoticeWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * 通知控制器
 *
 * @author fengshuonan
 * @Date 2017-05-09 23:02:21
 */
@Controller
@RequestMapping("/notice")
public class NoticeController extends BaseController {
    private String PREFIX = "/system/notice/";
    @Autowired
    private INoticeService noticeService;
    /**
     * 跳转到通知列表首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "notice.html";
    }
    /**
     * 跳转到添加通知
     */
    @RequestMapping("/notice_add")
    public String noticeAdd() {
        return PREFIX + "notice_add.html";
    }
    /**
     * 跳转到修改通知
     */
    @RequestMapping("/notice_update/{noticeId}")
    public String noticeUpdate(@PathVariable Integer noticeId, Model model) {
        Notice notice = this.noticeService.selectById(noticeId);
        model.addAttribute("notice",notice);
        LogObjectHolder.me().set(notice);
        return PREFIX + "notice_edit.html";
    }
    /**
     * 跳转到首页通知
     */
    @RequestMapping("/hello")
    public String hello() {
        List<Map<String, Object>> notices = noticeService.list(null);
        super.setAttr("noticeList",notices);
        return "/blackboard.html";
    }
    /**
     * 获取通知列表
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(String condition) {
        List<Map<String, Object>> list = this.noticeService.list(condition);
        return super.warpObject(new NoticeWrapper(list));
    }
    /**
     * 新增通知
     */
    @RequestMapping(value = "/add")
    @ResponseBody
    @BussinessLog(value = "新增通知",key = "title",dict = NoticeMap.class)
    public Object add(Notice notice) {
        if (ToolUtil.isOneEmpty(notice, notice.getTitle(), notice.getContent())) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        notice.setCreater(ShiroKit.getUser().getId());
        notice.setCreatetime(new Date());
        notice.insert();
        return SUCCESS_TIP;
    }
    /**
     * 删除通知
     */
    @RequestMapping(value = "/delete")
    @ResponseBody
    @BussinessLog(value = "删除通知",key = "noticeId",dict = NoticeMap.class)
    public Object delete(@RequestParam Integer noticeId) {
        //缓存通知名称
        LogObjectHolder.me().set(ConstantFactory.me().getNoticeTitle(noticeId));
        this.noticeService.deleteById(noticeId);
        return SUCCESS_TIP;
    }
    /**
     * 修改通知
     */
    @RequestMapping(value = "/update")
    @ResponseBody
    @BussinessLog(value = "修改通知",key = "title",dict = NoticeMap.class)
    public Object update(Notice notice) {
        if (ToolUtil.isOneEmpty(notice, notice.getId(), notice.getTitle(), notice.getContent())) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        Notice old = this.noticeService.selectById(notice.getId());
        old.setTitle(notice.getTitle());
        old.setContent(notice.getContent());
        old.updateById();
        return SUCCESS_TIP;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/RoleController.java
New file
@@ -0,0 +1,230 @@
package com.stylefeng.guns.modular.system.controller;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.Tip;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.cache.Cache;
import com.stylefeng.guns.core.common.constant.dictmap.RoleDict;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.core.util.Convert;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.Role;
import com.stylefeng.guns.modular.system.model.User;
import com.stylefeng.guns.modular.system.service.IRoleService;
import com.stylefeng.guns.modular.system.service.IUserService;
import com.stylefeng.guns.modular.system.warpper.RoleWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
 * 角色控制器
 *
 * @author fengshuonan
 * @Date 2017年2月12日21:59:14
 */
@Controller
@RequestMapping("/role")
public class RoleController extends BaseController {
    private static String PREFIX = "/system/role";
    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;
    /**
     * 跳转到角色列表页面
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "/role.html";
    }
    /**
     * 跳转到添加角色
     */
    @RequestMapping(value = "/role_add")
    public String roleAdd() {
        return PREFIX + "/role_add.html";
    }
    /**
     * 跳转到修改角色
     */
    @Permission
    @RequestMapping(value = "/role_edit/{roleId}")
    public String roleEdit(@PathVariable Integer roleId, Model model) {
        if (ToolUtil.isEmpty(roleId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        Role role = this.roleService.selectById(roleId);
        model.addAttribute(role);
        model.addAttribute("pName", ConstantFactory.me().getSingleRoleName(role.getPid()));
        model.addAttribute("deptName", ConstantFactory.me().getDeptName(role.getDeptid()));
        LogObjectHolder.me().set(role);
        return PREFIX + "/role_edit.html";
    }
    /**
     * 跳转到角色分配
     */
    @Permission
    @RequestMapping(value = "/role_assign/{roleId}")
    public String roleAssign(@PathVariable("roleId") Integer roleId, Model model) {
        if (ToolUtil.isEmpty(roleId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        model.addAttribute("roleId", roleId);
        model.addAttribute("roleName", ConstantFactory.me().getSingleRoleName(roleId));
        return PREFIX + "/role_assign.html";
    }
    /**
     * 获取角色列表
     */
    @Permission
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(@RequestParam(required = false) String roleName) {
        List<Map<String, Object>> roles = this.roleService.selectRoles(super.getPara("roleName"));
        return super.warpObject(new RoleWarpper(roles));
    }
    /**
     * 角色新增
     */
    @RequestMapping(value = "/add")
    @BussinessLog(value = "添加角色", key = "name", dict = RoleDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip add(@Valid Role role, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        role.setId(null);
        this.roleService.insert(role);
        return SUCCESS_TIP;
    }
    /**
     * 角色修改
     */
    @RequestMapping(value = "/edit")
    @BussinessLog(value = "修改角色", key = "name", dict = RoleDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip edit(@Valid Role role, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        this.roleService.updateById(role);
        //删除缓存
        CacheKit.removeAll(Cache.CONSTANT);
        return SUCCESS_TIP;
    }
    /**
     * 删除角色
     */
    @RequestMapping(value = "/remove")
    @BussinessLog(value = "删除角色", key = "roleId", dict = RoleDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip remove(@RequestParam Integer roleId) {
        if (ToolUtil.isEmpty(roleId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能删除超级管理员角色
        if (roleId.equals(Const.ADMIN_ROLE_ID)) {
            throw new GunsException(BizExceptionEnum.CANT_DELETE_ADMIN);
        }
        //缓存被删除的角色名称
        LogObjectHolder.me().set(ConstantFactory.me().getSingleRoleName(roleId));
        this.roleService.delRoleById(roleId);
        //删除缓存
        CacheKit.removeAll(Cache.CONSTANT);
        return SUCCESS_TIP;
    }
    /**
     * 查看角色
     */
    @RequestMapping(value = "/view/{roleId}")
    @ResponseBody
    public Tip view(@PathVariable Integer roleId) {
        if (ToolUtil.isEmpty(roleId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        this.roleService.selectById(roleId);
        return SUCCESS_TIP;
    }
    /**
     * 配置权限
     */
    @RequestMapping("/setAuthority")
    @BussinessLog(value = "配置权限", key = "roleId,ids", dict = RoleDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip setAuthority(@RequestParam("roleId") Integer roleId, @RequestParam("ids") String ids) {
        if (ToolUtil.isOneEmpty(roleId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        this.roleService.setAuthority(roleId, ids);
        return SUCCESS_TIP;
    }
    /**
     * 获取角色列表
     */
    @RequestMapping(value = "/roleTreeList")
    @ResponseBody
    public List<ZTreeNode> roleTreeList() {
        List<ZTreeNode> roleTreeList = this.roleService.roleTreeList();
        roleTreeList.add(ZTreeNode.createParent());
        return roleTreeList;
    }
    /**
     * 获取角色列表
     */
    @RequestMapping(value = "/roleTreeListByUserId/{userId}")
    @ResponseBody
    public List<ZTreeNode> roleTreeListByUserId(@PathVariable Integer userId) {
        User theUser = this.userService.selectById(userId);
        String roleid = theUser.getRoleid();
        if (ToolUtil.isEmpty(roleid)) {
            List<ZTreeNode> roleTreeList = this.roleService.roleTreeList();
            return roleTreeList;
        } else {
            String[] strArray = Convert.toStrArray(",", roleid);
            List<ZTreeNode> roleTreeListByUserId = this.roleService.roleTreeListByRoleId(strArray);
            return roleTreeListByUserId;
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/UserMgrController.java
New file
@@ -0,0 +1,373 @@
package com.stylefeng.guns.modular.system.controller;
import com.stylefeng.guns.config.properties.GunsProperties;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.Tip;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.annotion.Permission;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.dictmap.UserDict;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.common.constant.state.ManagerStatus;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.datascope.DataScope;
import com.stylefeng.guns.core.db.Db;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.dao.UserMapper;
import com.stylefeng.guns.modular.system.factory.UserFactory;
import com.stylefeng.guns.modular.system.model.User;
import com.stylefeng.guns.modular.system.service.IUserService;
import com.stylefeng.guns.modular.system.transfer.UserDto;
import com.stylefeng.guns.modular.system.warpper.UserWarpper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.naming.NoPermissionException;
import javax.validation.Valid;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
 * 系统管理员控制器
 *
 * @author fengshuonan
 * @Date 2017年1月11日 下午1:08:17
 */
@Controller
@RequestMapping("/mgr")
public class UserMgrController extends BaseController {
    private static String PREFIX = "/system/user/";
    @Autowired
    private GunsProperties gunsProperties;
    @Autowired
    private IUserService userService;
    /**
     * 跳转到查看管理员列表的页面
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "user.html";
    }
    /**
     * 跳转到查看管理员列表的页面
     */
    @RequestMapping("/user_add")
    public String addView() {
        return PREFIX + "user_add.html";
    }
    /**
     * 跳转到角色分配页面
     */
    //@RequiresPermissions("/mgr/role_assign")  //利用shiro自带的权限检查
    @Permission
    @RequestMapping("/role_assign/{userId}")
    public String roleAssign(@PathVariable Integer userId, Model model) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        User user = (User) Db.create(UserMapper.class).selectOneByCon("id", userId);
        model.addAttribute("userId", userId);
        model.addAttribute("userAccount", user.getAccount());
        return PREFIX + "user_roleassign.html";
    }
    /**
     * 跳转到编辑管理员页面
     */
    @Permission
    @RequestMapping("/user_edit/{userId}")
    public String userEdit(@PathVariable Integer userId, Model model) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        assertAuth(userId);
        User user = this.userService.selectById(userId);
        model.addAttribute(user);
        model.addAttribute("roleName", ConstantFactory.me().getRoleName(user.getRoleid()));
        model.addAttribute("deptName", ConstantFactory.me().getDeptName(user.getDeptid()));
        LogObjectHolder.me().set(user);
        return PREFIX + "user_edit.html";
    }
    /**
     * 跳转到查看用户详情页面
     */
    @RequestMapping("/user_info")
    public String userInfo(Model model) {
        Integer userId = ShiroKit.getUser().getId();
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        User user = this.userService.selectById(userId);
        model.addAttribute(user);
        model.addAttribute("roleName", ConstantFactory.me().getRoleName(user.getRoleid()));
        model.addAttribute("deptName", ConstantFactory.me().getDeptName(user.getDeptid()));
        LogObjectHolder.me().set(user);
        return PREFIX + "user_view.html";
    }
    /**
     * 跳转到修改密码界面
     */
    @RequestMapping("/user_chpwd")
    public String chPwd() {
        return PREFIX + "user_chpwd.html";
    }
    /**
     * 修改当前用户的密码
     */
    @RequestMapping("/changePwd")
    @ResponseBody
    public Object changePwd(@RequestParam String oldPwd, @RequestParam String newPwd, @RequestParam String rePwd) {
        if (!newPwd.equals(rePwd)) {
            throw new GunsException(BizExceptionEnum.TWO_PWD_NOT_MATCH);
        }
        Integer userId = ShiroKit.getUser().getId();
        User user = userService.selectById(userId);
        String oldMd5 = ShiroKit.md5(oldPwd, user.getSalt());
        if (user.getPassword().equals(oldMd5)) {
            String newMd5 = ShiroKit.md5(newPwd, user.getSalt());
            user.setPassword(newMd5);
            user.updateById();
            return SUCCESS_TIP;
        } else {
            throw new GunsException(BizExceptionEnum.OLD_PWD_NOT_RIGHT);
        }
    }
    /**
     * 查询管理员列表
     */
    @RequestMapping("/list")
    @Permission
    @ResponseBody
    public Object list(@RequestParam(required = false) String name, @RequestParam(required = false) String beginTime, @RequestParam(required = false) String endTime, @RequestParam(required = false) Integer deptid) {
        if (ShiroKit.isAdmin()) {
            List<Map<String, Object>> users = userService.selectUsers(null, name, beginTime, endTime, deptid);
            return new UserWarpper(users).warp();
        } else {
            DataScope dataScope = new DataScope(ShiroKit.getDeptDataScope());
            List<Map<String, Object>> users = userService.selectUsers(dataScope, name, beginTime, endTime, deptid);
            return new UserWarpper(users).warp();
        }
    }
    /**
     * 添加管理员
     */
    @RequestMapping("/add")
    @BussinessLog(value = "添加管理员", key = "account", dict = UserDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip add(@Valid UserDto user, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        // 判断账号是否重复
        User theUser = userService.getByAccount(user.getAccount());
        if (theUser != null) {
            throw new GunsException(BizExceptionEnum.USER_ALREADY_REG);
        }
        // 完善账号信息
        user.setSalt(ShiroKit.getRandomSalt(5));
        user.setPassword(ShiroKit.md5(user.getPassword(), user.getSalt()));
        user.setStatus(ManagerStatus.OK.getCode());
        user.setCreatetime(new Date());
        this.userService.insert(UserFactory.createUser(user));
        return SUCCESS_TIP;
    }
    /**
     * 修改管理员
     *
     * @throws NoPermissionException
     */
    @RequestMapping("/edit")
    @BussinessLog(value = "修改管理员", key = "account", dict = UserDict.class)
    @ResponseBody
    public Tip edit(@Valid UserDto user, BindingResult result) throws NoPermissionException {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        User oldUser = userService.selectById(user.getId());
        if (ShiroKit.hasRole(Const.ADMIN_NAME)) {
            this.userService.updateById(UserFactory.editUser(user, oldUser));
            return SUCCESS_TIP;
        } else {
            assertAuth(user.getId());
            ShiroUser shiroUser = ShiroKit.getUser();
            if (shiroUser.getId().equals(user.getId())) {
                this.userService.updateById(UserFactory.editUser(user, oldUser));
                return SUCCESS_TIP;
            } else {
                throw new GunsException(BizExceptionEnum.NO_PERMITION);
            }
        }
    }
    /**
     * 删除管理员(逻辑删除)
     */
    @RequestMapping("/delete")
    @BussinessLog(value = "删除管理员", key = "userId", dict = UserDict.class)
    @Permission
    @ResponseBody
    public Tip delete(@RequestParam Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能删除超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            throw new GunsException(BizExceptionEnum.CANT_DELETE_ADMIN);
        }
        assertAuth(userId);
        this.userService.setStatus(userId, ManagerStatus.DELETED.getCode());
        return SUCCESS_TIP;
    }
    /**
     * 查看管理员详情
     */
    @RequestMapping("/view/{userId}")
    @ResponseBody
    public User view(@PathVariable Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        assertAuth(userId);
        return this.userService.selectById(userId);
    }
    /**
     * 重置管理员的密码
     */
    @RequestMapping("/reset")
    @BussinessLog(value = "重置管理员密码", key = "userId", dict = UserDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip reset(@RequestParam Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        assertAuth(userId);
        User user = this.userService.selectById(userId);
        user.setSalt(ShiroKit.getRandomSalt(5));
        user.setPassword(ShiroKit.md5(Const.DEFAULT_PWD, user.getSalt()));
        this.userService.updateById(user);
        return SUCCESS_TIP;
    }
    /**
     * 冻结用户
     */
    @RequestMapping("/freeze")
    @BussinessLog(value = "冻结用户", key = "userId", dict = UserDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip freeze(@RequestParam Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能冻结超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            throw new GunsException(BizExceptionEnum.CANT_FREEZE_ADMIN);
        }
        assertAuth(userId);
        this.userService.setStatus(userId, ManagerStatus.FREEZED.getCode());
        return SUCCESS_TIP;
    }
    /**
     * 解除冻结用户
     */
    @RequestMapping("/unfreeze")
    @BussinessLog(value = "解除冻结用户", key = "userId", dict = UserDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip unfreeze(@RequestParam Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        assertAuth(userId);
        this.userService.setStatus(userId, ManagerStatus.OK.getCode());
        return SUCCESS_TIP;
    }
    /**
     * 分配角色
     */
    @RequestMapping("/setRole")
    @BussinessLog(value = "分配角色", key = "userId,roleIds", dict = UserDict.class)
    @Permission(Const.ADMIN_NAME)
    @ResponseBody
    public Tip setRole(@RequestParam("userId") Integer userId, @RequestParam("roleIds") String roleIds) {
        if (ToolUtil.isOneEmpty(userId, roleIds)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能修改超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            throw new GunsException(BizExceptionEnum.CANT_CHANGE_ADMIN);
        }
        assertAuth(userId);
        this.userService.setRoles(userId, roleIds);
        return SUCCESS_TIP;
    }
    /**
     * 上传图片
     */
    @RequestMapping(method = RequestMethod.POST, path = "/upload")
    @ResponseBody
    public String upload(@RequestPart("file") MultipartFile picture) {
        String pictureName = UUID.randomUUID().toString() + "." + ToolUtil.getFileSuffix(picture.getOriginalFilename());
        try {
            String fileSavePath = gunsProperties.getFileUploadPath();
            picture.transferTo(new File(fileSavePath + pictureName));
        } catch (Exception e) {
            throw new GunsException(BizExceptionEnum.UPLOAD_ERROR);
        }
        return pictureName;
    }
    /**
     * 判断当前登录的用户是否有操作这个用户的权限
     */
    private void assertAuth(Integer userId) {
        if (ShiroKit.isAdmin()) {
            return;
        }
        List<Integer> deptDataScope = ShiroKit.getDeptDataScope();
        User user = this.userService.selectById(userId);
        Integer deptid = user.getDeptid();
        if (deptDataScope.contains(deptid)) {
            return;
        } else {
            throw new GunsException(BizExceptionEnum.NO_PERMITION);
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/DeptMapper.java
New file
@@ -0,0 +1,31 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.model.Dept;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 部门表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface DeptMapper extends BaseMapper<Dept> {
    /**
     * 获取ztree的节点列表
     */
    List<ZTreeNode> tree();
    /**
     * 获取所有部门列表
     */
    List<Map<String, Object>> list(@Param("condition") String condition);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/DictMapper.java
New file
@@ -0,0 +1,34 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.modular.system.model.Dict;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 字典表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface DictMapper extends BaseMapper<Dict> {
    /**
     * 根据编码获取词典列表
     */
    List<Dict> selectByCode(@Param("code") String code);
    /**
     * 查询字典列表
     */
    List<Map<String, Object>> list(@Param("condition") String conditiion);
    /**
     * 根据父类编码获取词典列表
     */
    List<Dict> selectByParentCode(@Param("code") String code);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/LoginLogMapper.java
New file
@@ -0,0 +1,27 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.modular.system.model.LoginLog;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 登录记录 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface LoginLogMapper extends BaseMapper<LoginLog> {
    /**
     * 获取登录日志
     */
    List<Map<String, Object>> getLoginLogs(@Param("page") Page<LoginLog> page, @Param("beginTime") String beginTime,
                                           @Param("endTime") String endTime, @Param("logName") String logName, @Param("orderByField") String orderByField, @Param("isAsc") boolean isAsc);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/MenuMapper.java
New file
@@ -0,0 +1,80 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.core.node.MenuNode;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.model.Menu;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
  * 菜单表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface MenuMapper extends BaseMapper<Menu> {
    /**
     * 根据条件查询菜单
     *
     * @return
     * @date 2017年2月12日 下午9:14:34
     */
    List<Map<String, Object>> selectMenus(@Param("condition") String condition, @Param("level") String level);
    /**
     * 根据条件查询菜单
     *
     * @return
     * @date 2017年2月12日 下午9:14:34
     */
    List<Long> getMenuIdsByRoleId(@Param("roleId") Integer roleId);
    /**
     * 获取菜单列表树
     *
     * @return
     * @date 2017年2月19日 下午1:33:51
     */
    List<ZTreeNode> menuTreeList();
    /**
     * 获取菜单列表树
     *
     * @return
     * @date 2017年2月19日 下午1:33:51
     */
    List<ZTreeNode> menuTreeListByMenuIds(List<Long> menuIds);
    /**
     * 删除menu关联的relation
     *
     * @param menuId
     * @return
     * @date 2017年2月19日 下午4:10:59
     */
    int deleteRelationByMenu(Long menuId);
    /**
     * 获取资源url通过角色id
     *
     * @param roleId
     * @return
     * @date 2017年2月19日 下午7:12:38
     */
    List<String> getResUrlsByRoleId(Integer roleId);
    /**
     * 根据角色获取菜单
     *
     * @param roleIds
     * @return
     * @date 2017年2月19日 下午10:35:40
     */
    List<MenuNode> getMenusByRoleIds(List<Integer> roleIds);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/NoticeMapper.java
New file
@@ -0,0 +1,25 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.modular.system.model.Notice;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 通知表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface NoticeMapper extends BaseMapper<Notice> {
    /**
     * 获取通知列表
     */
    List<Map<String, Object>> list(@Param("condition") String condition);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/OperationLogMapper.java
New file
@@ -0,0 +1,26 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.modular.system.model.OperationLog;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 操作日志 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface OperationLogMapper extends BaseMapper<OperationLog> {
    /**
     * 获取操作日志
     */
    List<Map<String, Object>> getOperationLogs(@Param("page") Page<OperationLog> page, @Param("beginTime") String beginTime, @Param("endTime") String endTime, @Param("logName") String logName, @Param("logType") String logType, @Param("orderByField") String orderByField, @Param("isAsc") boolean isAsc);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/PatrolTaskMapper.java
New file
@@ -0,0 +1,11 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.modular.system.model.PatrolTask;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:17
 */
public interface PatrolTaskMapper extends BaseMapper<PatrolTask> {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/RelationMapper.java
New file
@@ -0,0 +1,16 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.modular.system.model.Relation;
/**
 * <p>
  * 角色和菜单关联表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface RelationMapper extends BaseMapper<Relation> {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/RoleMapper.java
New file
@@ -0,0 +1,53 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.model.Role;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
  * 角色表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface RoleMapper extends BaseMapper<Role> {
    /**
     * 根据条件查询角色列表
     *
     * @return
     * @date 2017年2月12日 下午9:14:34
     */
    List<Map<String, Object>> selectRoles(@Param("condition") String condition);
    /**
     * 删除某个角色的所有权限
     *
     * @param roleId 角色id
     * @return
     * @date 2017年2月13日 下午7:57:51
     */
    int deleteRolesById(@Param("roleId") Integer roleId);
    /**
     * 获取角色列表树
     *
     * @return
     * @date 2017年2月18日 上午10:32:04
     */
    List<ZTreeNode> roleTreeList();
    /**
     * 获取角色列表树
     *
     * @return
     * @date 2017年2月18日 上午10:32:04
     */
    List<ZTreeNode> roleTreeListByRoleId(String[] roleId);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailMapper.java
New file
@@ -0,0 +1,46 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.modular.system.model.TaskDetail;
import com.stylefeng.guns.modular.system.model.vo.TaskDetailList;
import com.stylefeng.guns.modular.system.model.vo.TaskDetailListVo;
import com.stylefeng.guns.modular.system.model.vo.TaskRecordList;
import com.stylefeng.guns.modular.system.model.vo.TaskRecordListVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:22
 */
public interface TaskDetailMapper extends BaseMapper<TaskDetail> {
    /**
     * 获取巡查任务列表数据
     * @param vo
     * @return
     */
    List<TaskDetailList> getTaskDetailList(Page<TaskDetailList> pageInfo, @Param("item") TaskDetailListVo vo);
    /**
     * 获取任务记录列表
     * @param pageInfo
     * @param vo
     * @return
     */
    List<TaskRecordList> getTaskRecordList(Page<TaskRecordList> pageInfo, @Param("item") TaskRecordListVo vo);
    /**
     * 获取下载任务记录数据
     * @param ids
     * @param code
     * @param status
     * @return
     */
    List<Map<String, Object>> getDownloadTaskRecord(@Param("ids") List<String> ids, @Param("code") String code, @Param("status") Integer status);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailVehiclesChannelMapper.java
New file
@@ -0,0 +1,28 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.modular.system.model.TaskDetailVehiclesChannel;
import com.stylefeng.guns.modular.system.model.vo.PictureDetails;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:34
 */
public interface TaskDetailVehiclesChannelMapper extends BaseMapper<TaskDetailVehiclesChannel> {
    /**
     * 根据任务车船关系数据id获取通道数据
     * @param pageInfo
     * @param taskDetailVehiclesIdList
     * @param sysStatus
     * @param artificialStatus
     * @return
     */
    List<PictureDetails> getPictureDetails(Page<PictureDetails> pageInfo, @Param("taskDetailVehiclesIdList") List<Integer> taskDetailVehiclesIdList,
                                           @Param("sysStatus") Integer sysStatus, @Param("artificialStatus") Integer artificialStatus);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailVehiclesMapper.java
New file
@@ -0,0 +1,11 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.modular.system.model.TaskDetailVehicles;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:28
 */
public interface TaskDetailVehiclesMapper extends BaseMapper<TaskDetailVehicles> {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/UserMapper.java
New file
@@ -0,0 +1,45 @@
package com.stylefeng.guns.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.stylefeng.guns.core.datascope.DataScope;
import com.stylefeng.guns.modular.system.model.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 管理员表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface UserMapper extends BaseMapper<User> {
    /**
     * 修改用户状态
     */
    int setStatus(@Param("userId") Integer userId, @Param("status") int status);
    /**
     * 修改密码
     */
    int changePwd(@Param("userId") Integer userId, @Param("pwd") String pwd);
    /**
     * 根据条件查询用户列表
     */
    List<Map<String, Object>> selectUsers(@Param("dataScope") DataScope dataScope, @Param("name") String name, @Param("beginTime") String beginTime, @Param("endTime") String endTime, @Param("deptid") Integer deptid);
    /**
     * 设置用户的角色
     */
    int setRoles(@Param("userId") Integer userId, @Param("roleIds") String roleIds);
    /**
     * 通过账号获取用户
     */
    User getByAccount(@Param("account") String account);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/DeptMapper.xml
New file
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.DeptMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.Dept">
        <id column="id" property="id"/>
        <result column="num" property="num"/>
        <result column="pid" property="pid"/>
        <result column="pids" property="pids"/>
        <result column="simplename" property="simplename"/>
        <result column="fullname" property="fullname"/>
        <result column="tips" property="tips"/>
        <result column="version" property="version"/>
    </resultMap>
    <select id="tree" resultType="com.stylefeng.guns.core.node.ZTreeNode">
        select id,pid as pId,simplename as name,
        (
        CASE
        WHEN (pId = 0 OR pId IS NULL) THEN
        'true'
        ELSE
        'false'
        END
        ) as isOpen from sys_dept
    </select>
    <select id="list" resultType="map">
        select * from sys_dept
        <if test="condition != null and condition != ''">
            where simplename like CONCAT('%',#{condition},'%') or fullname like CONCAT('%',#{condition},'%')
        </if>
        order by num ASC
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/DictMapper.xml
New file
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.DictMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.Dict">
        <id column="id" property="id"/>
        <result column="num" property="num"/>
        <result column="pid" property="pid"/>
        <result column="name" property="name"/>
        <result column="code" property="code"/>
        <result column="tips" property="tips"/>
    </resultMap>
    <sql id="Base_Column_List">
        id, num, pid, name,code,tips
    </sql>
    <select id="selectByCode" resultType="dict">
        select
        <include refid="Base_Column_List"/>
        from sys_dict
        where code = #{code}
    </select>
    <select id="selectByParentCode" resultType="dict">
        select
        <include refid="Base_Column_List"/>
        from sys_dict
        where pid in(select id  from sys_dict where code = #{code}) order by num asc
    </select>
    <select id="list" resultType="map">
        select * from sys_dict
        where pid = 0
        <if test="condition != null and condition != ''">
            AND name like CONCAT('%',#{condition},'%')
        </if>
        order by id ASC
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/LoginLogMapper.xml
New file
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.LoginLogMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.LoginLog">
        <id column="id" property="id" />
        <result column="logname" property="logname" />
        <result column="userid" property="userid" />
        <result column="createtime" property="createtime" />
        <result column="succeed" property="succeed" />
        <result column="message" property="message" />
        <result column="ip" property="ip" />
    </resultMap>
    <select id="getLoginLogs" resultType="map" parameterType="com.baomidou.mybatisplus.plugins.Page">
        select * from sys_login_log where 1 = 1
        <if test="beginTime != null and beginTime !='' and endTime != null and endTime != ''">
            and (createTime between CONCAT(#{beginTime},' 00:00:00') and CONCAT(#{endTime},' 23:59:59'))
        </if>
        <if test="logName != null and logName !=''">
            and logname like CONCAT('%',#{logName},'%')
        </if>
        <choose>
            <when test="orderByField != null and orderByField !=''">
                <choose>
                    <when test="isAsc == true">
                        order by ${orderByField} ASC
                    </when>
                    <otherwise>
                        order by ${orderByField} DESC
                    </otherwise>
                </choose>
            </when>
            <otherwise>
                order by createtime DESC
            </otherwise>
        </choose>
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/MenuMapper.xml
New file
@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.MenuMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.Menu">
        <id column="id" property="id" />
        <result column="code" property="code" />
        <result column="pcode" property="pcode" />
        <result column="pcodes" property="pcodes" />
        <result column="name" property="name" />
        <result column="icon" property="icon" />
        <result column="url" property="url" />
        <result column="num" property="num" />
        <result column="levels" property="levels" />
        <result column="ismenu" property="ismenu" />
        <result column="tips" property="tips" />
        <result column="status" property="status" />
        <result column="isopen" property="isopen" />
    </resultMap>
    <sql id="Base_Column_List">
        id, code, pcode, name, icon, url, num, levels,pcodes,
        tips, status,isopen,ismenu
    </sql>
    <select id="selectMenus" resultType="map">
        select
        <include refid="Base_Column_List" />
        from sys_menu
        where status = 1
        <if test="condition != null and condition != ''">
            and (name like CONCAT('%',#{condition},'%') or code like CONCAT('%',#{condition},'%'))
        </if>
        <if test="level != null and level != ''">
            and levels = #{level}
        </if>
    </select>
    <select id="getMenuIdsByRoleId" resultType="long">
        select menuid from
        sys_relation where roleid = #{roleId}
    </select>
    <select id="menuTreeList" resultType="com.stylefeng.guns.core.node.ZTreeNode">
        SELECT
        m1.id AS id,
        (
        CASE
        WHEN (m2.id = 0 OR m2.id IS NULL) THEN
        0
        ELSE
        m2.id
        END
        ) AS pId,
        m1. NAME
        AS NAME,
        (
        CASE
        WHEN (m2.id = 0 OR m2.id IS NULL) THEN
        'true'
        ELSE
        'false'
        END
        ) as isOpen
        FROM
        sys_menu m1
        LEFT join sys_menu m2 ON m1.pcode = m2. CODE
        ORDER BY
        m1.id ASC
    </select>
    <select id="menuTreeListByMenuIds" resultType="com.stylefeng.guns.core.node.ZTreeNode">
        SELECT
        m1.id AS id,
        (
        CASE
        WHEN (m2.id = 0 OR m2.id IS NULL) THEN
        0
        ELSE
        m2.id
        END
        ) AS pId,
        m1. NAME AS NAME,
        (
        CASE
        WHEN (m2.id = 0 OR m2.id IS
        NULL) THEN
        'true'
        ELSE
        'false'
        END
        ) as isOpen,
        (
        CASE
        WHEN (m3.ID = 0 OR m3.ID
        IS NULL) THEN
        'false'
        ELSE
        'true'
        END
        ) "checked"
        FROM
        sys_menu m1
        LEFT JOIN
        sys_menu m2
        ON m1.pcode = m2. CODE
        left join (
        SELECT
        ID
        FROM
        sys_menu
        WHERE
        ID IN
        <foreach collection="list" index="index" item="i" open="("
                 separator="," close=")">
            #{i}
        </foreach>
        ) m3 on m1.id = m3.id
        ORDER BY
        m1.id ASC
    </select>
    <delete id="deleteRelationByMenu">
        delete from sys_relation where menuid = #{menuId}
    </delete>
    <select id="getResUrlsByRoleId" resultType="string">
        select url from
        sys_relation rel
        inner join sys_menu m on rel.menuid = m.id
        where rel.roleid = #{roleId}
    </select>
    <select id="getMenusByRoleIds" resultType="com.stylefeng.guns.core.node.MenuNode">
        SELECT
        m1.id AS id,
        m1.icon AS icon,
        (
        CASE
        WHEN (m2.id = 0 OR m2.id IS NULL) THEN
        0
        ELSE
        m2.id
        END
        ) AS parentId,
        m1.NAME as name,
        m1.url as url,
        m1.levels as levels,
        m1.ismenu as ismenu,
        m1.num as num
        FROM
        sys_menu m1
        LEFT join sys_menu m2 ON m1.pcode = m2. CODE
        INNER JOIN (
        SELECT
        ID
        FROM
        sys_menu
        WHERE
        ID IN (
        SELECT
        menuid
        FROM
        sys_relation rela
        WHERE
        rela.roleid IN
        <foreach collection="list" index="index" item="i" open="(" separator="," close=")">
            #{i}
        </foreach>
        )
        ) m3 ON m1.id = m3.id
        where m1.ismenu = 1
        order by levels,num asc
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/NoticeMapper.xml
New file
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.NoticeMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.Notice">
        <id column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="type" property="type"/>
        <result column="content" property="content"/>
        <result column="createtime" property="createtime"/>
        <result column="creater" property="creater"/>
    </resultMap>
    <select id="list" resultType="map">
        select * from sys_notice
        <if test="condition != null and condition != ''">
            where title like CONCAT('%',#{condition},'%') or content like CONCAT('%',#{condition},'%')
        </if>
        order by createtime DESC
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/OperationLogMapper.xml
New file
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.OperationLogMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.OperationLog">
        <id column="id" property="id" />
        <result column="logtype" property="logtype" />
        <result column="logname" property="logname" />
        <result column="userid" property="userid" />
        <result column="classname" property="classname" />
        <result column="method" property="method" />
        <result column="createtime" property="createtime" />
        <result column="succeed" property="succeed" />
        <result column="message" property="message" />
    </resultMap>
    <select id="getOperationLogs" resultType="map">
        select * from sys_operation_log where 1 = 1
        <if test="beginTime != null and beginTime !='' and endTime != null and endTime != ''">
            and (createTime between CONCAT(#{beginTime},' 00:00:00') and CONCAT(#{endTime},' 23:59:59'))
        </if>
        <if test="logName != null and logName !=''">
            and logname like CONCAT('%',#{logName},'%')
        </if>
        <if test="logType != null and logType !=''">
            and logtype like CONCAT('%',#{logType},'%')
        </if>
        <choose>
            <when test="orderByField != null and orderByField !=''">
                <choose>
                    <when test="isAsc == true">
                        order by ${orderByField} ASC
                    </when>
                    <otherwise>
                        order by ${orderByField} DESC
                    </otherwise>
                </choose>
            </when>
            <otherwise>
                order by createtime DESC
            </otherwise>
        </choose>
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/PatrolTaskMapper.xml
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.PatrolTaskMapper">
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/RelationMapper.xml
New file
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.RelationMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.Relation">
        <id column="id" property="id" />
        <result column="menuid" property="menuid" />
        <result column="roleid" property="roleid" />
    </resultMap>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/RoleMapper.xml
New file
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.RoleMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.Role">
        <id column="id" property="id" />
        <result column="num" property="num" />
        <result column="pid" property="pid" />
        <result column="name" property="name" />
        <result column="deptid" property="deptid" />
        <result column="tips" property="tips" />
        <result column="version" property="version" />
    </resultMap>
    <sql id="Base_Column_List">
        id, num, pid, name, deptid, tips, version
    </sql>
    <select id="selectRoles" resultType="map">
        select
        <include refid="Base_Column_List" />
        from sys_role
        <if test="condition != null">
            where name like CONCAT('%',#{condition},'%')
        </if>
    </select>
    <delete id="deleteRolesById">
        delete from sys_relation where roleid = #{roleId}
    </delete>
    <select id="roleTreeList" resultType="com.stylefeng.guns.core.node.ZTreeNode">
        select id "id",pId
        "pId",name as "name",(case when (pId=0 or pId is null) then 'true'
        else 'false' end) "open" from sys_role
    </select>
    <select id="roleTreeListByRoleId" resultType="com.stylefeng.guns.core.node.ZTreeNode">
        SELECT
        r.id "id",
        pId "pId",
        NAME AS "name",
        (
        CASE
        WHEN (pId = 0 OR pId IS NULL) THEN
        'true'
        ELSE
        'false'
        END
        ) "open",
        (
        CASE
        WHEN (r1.ID = 0 OR r1.ID IS NULL) THEN
        'false'
        ELSE
        'true'
        END
        ) "checked"
        FROM
        sys_role r
        LEFT JOIN (
        SELECT
        ID
        FROM
        sys_role
        WHERE
        ID IN
        <foreach collection="array" index="index" item="i" open="(" separator="," close=")">
            #{i}
        </foreach>
        ) r1 ON r.ID = r1.ID
        ORDER BY
        pId,
        num ASC
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailMapper.xml
New file
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.TaskDetailMapper">
    <select id="getTaskDetailList" resultType="com.stylefeng.guns.modular.system.model.vo.TaskDetailList">
        select
            a.id,
            a.code,
            b.`name`,
            b.type,
            a.status,
            DATE_FORMAT(a.execution_time, '%Y-%m-%d %H:%i:%s') as executionTime
        from t_task_detail a
        left join t_patrol_task b on (a.patrol_task_id = b.id)
        where a.del_flag = 0
        <if test="null != item.code and '' != item.code">
            and a.code like CONCAT('%', #{item.code}, '%')
        </if>
        <if test="null != item.status">
            and a.status = #{item.status}
        </if>
    </select>
    <select id="getTaskRecordList" resultType="com.stylefeng.guns.modular.system.model.vo.TaskRecordList">
        select
            a.id,
            b.type,
            b.`name`,
            a.`status`,
            a.execution_time as executionTime,
            c.num as vehicleNum,
            d.num as unexecutedQuantity,
            e.num as offlineNum,
            f.num as normalNum,
            g.num as abnormalNum,
            if(h.num > 0, 0, 1) as authStatus
        from t_task_detail a
         left join t_patrol_task b on (a.patrol_task_id = b.id)
         left join (select task_detail_id, count(1) as num from t_task_detail_vehicles group by task_detail_id) c on (a.id = c.task_detail_id)
         left join (select task_detail_id, count(1) as num from t_task_detail_vehicles where `status` = 1 group by task_detail_id) d on (a.id = d.task_detail_id)
         left join (select task_detail_id, count(1) as num from t_task_detail_vehicles where `status` = 3 group by task_detail_id) e on (a.id = e.task_detail_id)
         left join (select task_detail_id, count(1) as num from t_task_detail_vehicles where `status` = 2 group by task_detail_id) f on (a.id = f.task_detail_id)
         left join (select task_detail_id, count(1) as num from t_task_detail_vehicles where `status` = 4 group by task_detail_id) g on (a.id = g.task_detail_id)
         left join (select task_detail_id, count(1) as num from t_task_detail_vehicles_channel where artificial_status = 1 group by task_detail_id) h on (a.id = h.task_detail_id)
        where a.del_flag = 0
        <if test="null != item.code and '' != item.code">
            and a.code like CONCAT('%', #{item.code}, '%')
        </if>
        <if test="null != item.status">
            and a.status = #{item.status}
        </if>
    </select>
    <select id="getDownloadTaskRecord" resultType="map">
        select
        c.`name`,
        if(c.type = 1, '定时任务', '实时任务') as taskType,
        DATE_FORMAT(b.execution_time, '%Y-%m-%d %H:%i:%s') as executionTime,
        a.`status`,
        a.vehicleNum,
        a.companyName,
        if(d.artificial_status = 1, d.sys_status, d.artificial_status) as vehiclesStatus,
        d.image_url as imageUrl,
        d.sys_status as sysStatus,
        DATE_FORMAT(d.sys_create_time, '%Y-%m-%d %H:%i:%s') as sysCreateTime,
        d.artificial_status as artificialStatus,
        d.remark,
        e.`name` as artificialUser,
        DATE_FORMAT(d.artificial_create_time, '%Y-%m-%d %H:%i:%s') as artificialCreateTime
        from t_task_detail_vehicles a
        left join t_task_detail b on (a.task_detail_id = b.id)
        left join t_patrol_task c on (a.patrol_task_id = c.id)
        left join t_task_detail_vehicles_channel d on (a.id = d.task_detail_vehicles_id and d.video_channel = 1)
        left join sys_user e on (d.artificial_user_id = e.id)
        where b.del_flag = 0
        <if test="null != ids and ids.size() > 0">
            and d.id in
            <foreach collection="ids" item="item" index="index" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
        <if test="null != code and '' != code">
            and b.code like CONCAT('%', #{code}, '%')
        </if>
        <if test="null != status">
            and b.status = #{status}
        </if>
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailVehiclesChannelMapper.xml
New file
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.TaskDetailVehiclesChannelMapper">
    <select id="getPictureDetails" resultType="com.stylefeng.guns.modular.system.model.vo.PictureDetails">
        select
            a.id,
            a.video_channel as videoChannel,
            a.image_url as imageUrl,
            a.sys_status as sysStatus,
            DATE_FORMAT(a.sys_create_time, '%Y-%m-%d %H:%i:%s') as sysCreateTime,
            a.artificial_status as artificialStatus,
            DATE_FORMAT(a.artificial_create_time, '%Y-%m-%d %H:%i:%s') as artificialCreateTime,
            b.`name` as artificialUserName,
            a.verify
        from t_task_detail_vehicles_channel a
        left join sys_user b on (a.artificial_user_id = b.id)
        where 1 = 1
        <if test="null != taskDetailVehiclesIdList and taskDetailVehiclesIdList.size() > 0">
            and a.task_detail_vehicles_id in
            <foreach collection="taskDetailVehiclesIdList" item="item" index="index" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
        <if test="null != sysStatus">
            and a.sys_status = #{sysStatus}
        </if>
        <if test="null != artificialStatus">
            and a.artificial_status = #{artificialStatus}
        </if>
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailVehiclesMapper.xml
New file
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.TaskDetailVehiclesMapper">
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/UserMapper.xml
New file
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.stylefeng.guns.modular.system.dao.UserMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.User">
        <id column="id" property="id" />
        <result column="avatar" property="avatar" />
        <result column="account" property="account" />
        <result column="password" property="password" />
        <result column="salt" property="salt" />
        <result column="birthday" property="birthday" />
        <result column="sex" property="sex" />
        <result column="email" property="email" />
        <result column="phone" property="phone" />
        <result column="roleid" property="roleid" />
        <result column="deptid" property="deptid" />
        <result column="status" property="status" />
        <result column="createtime" property="createtime" />
        <result column="version" property="version" />
    </resultMap>
    <sql id="Base_Column_List">
        id, account, birthday, sex, email, avatar,
        phone, roleid,
        deptid, status,
        createtime, version
    </sql>
    <sql id="Base_Column_List_With_Pwd">
        id, account, birthday,password, sex, email, avatar,
        phone, roleid,salt,
        deptid, status,
        createtime, version
    </sql>
    <select id="selectUsers" resultType="map">
        select
        <include refid="Base_Column_List" />
        from sys_user
        where status != 3
        <if test="name != null and name != ''">
            and (phone like CONCAT('%',#{name},'%')
            or account like CONCAT('%',#{name},'%')
            or lastName like CONCAT('%',#{name},'%')
            or firstName like CONCAT('%',#{name},'%'))
        </if>
        <if test="deptid != null and deptid != 0">
            and (deptid = #{deptid} or deptid in ( select id from sys_dept where pids like CONCAT('%[', #{deptid}, ']%') ))
        </if>
        <if test="beginTime != null and beginTime != '' and endTime != null and endTime != ''">
            and (createTime between CONCAT(#{beginTime},' 00:00:00') and CONCAT(#{endTime},' 23:59:59'))
        </if>
    </select>
    <update id="setStatus">
        update sys_user set status = #{status} where id =
        #{userId}
    </update>
    <update id="changePwd">
        update sys_user set password = #{pwd} where id =
        #{userId}
    </update>
    <update id="setRoles">
        update sys_user set roleid = #{roleIds} where id =
        #{userId}
    </update>
    <select id="getByAccount" resultType="user">
        select
        <include refid="Base_Column_List_With_Pwd" />
        from sys_user where account = #{account} and status != 3
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/factory/UserFactory.java
New file
@@ -0,0 +1,54 @@
package com.stylefeng.guns.modular.system.factory;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.model.User;
import com.stylefeng.guns.modular.system.transfer.UserDto;
import org.springframework.beans.BeanUtils;
/**
 * 用户创建工厂
 *
 * @author fengshuonan
 * @date 2017-05-05 22:43
 */
public class UserFactory {
    public static User createUser(UserDto userDto) {
        if (userDto == null) {
            return null;
        } else {
            User user = new User();
            BeanUtils.copyProperties(userDto, user);
            return user;
        }
    }
    public static User editUser(UserDto newUser, User oldUser) {
        if (newUser == null || oldUser == null) {
            return oldUser;
        } else {
            if (ToolUtil.isNotEmpty(newUser.getAvatar())) {
                oldUser.setAvatar(newUser.getAvatar());
            }
            if (ToolUtil.isNotEmpty(newUser.getName())) {
                oldUser.setName(newUser.getName());
            }
            if (ToolUtil.isNotEmpty(newUser.getBirthday())) {
                oldUser.setBirthday(newUser.getBirthday());
            }
            if (ToolUtil.isNotEmpty(newUser.getDeptid())) {
                oldUser.setDeptid(newUser.getDeptid());
            }
            if (ToolUtil.isNotEmpty(newUser.getSex())) {
                oldUser.setSex(newUser.getSex());
            }
            if (ToolUtil.isNotEmpty(newUser.getEmail())) {
                oldUser.setEmail(newUser.getEmail());
            }
            if (ToolUtil.isNotEmpty(newUser.getPhone())) {
                oldUser.setPhone(newUser.getPhone());
            }
            return oldUser;
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Dept.java
New file
@@ -0,0 +1,140 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
/**
 * <p>
 * 部门表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_dept")
public class Dept extends Model<Dept> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键id
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 排序
     */
    private Integer num;
    /**
     * 父部门id
     */
    private Integer pid;
    /**
     * 父级ids
     */
    private String pids;
    /**
     * 简称
     */
    private String simplename;
    /**
     * 全称
     */
    private String fullname;
    /**
     * 提示
     */
    private String tips;
    /**
     * 版本(乐观锁保留字段)
     */
    private Integer version;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getNum() {
        return num;
    }
    public void setNum(Integer num) {
        this.num = num;
    }
    public Integer getPid() {
        return pid;
    }
    public void setPid(Integer pid) {
        this.pid = pid;
    }
    public String getPids() {
        return pids;
    }
    public void setPids(String pids) {
        this.pids = pids;
    }
    public String getSimplename() {
        return simplename;
    }
    public void setSimplename(String simplename) {
        this.simplename = simplename;
    }
    public String getFullname() {
        return fullname;
    }
    public void setFullname(String fullname) {
        this.fullname = fullname;
    }
    public String getTips() {
        return tips;
    }
    public void setTips(String tips) {
        this.tips = tips;
    }
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "Dept{" +
            "id=" + id +
            ", num=" + num +
            ", pid=" + pid +
            ", pids=" + pids +
            ", simplename=" + simplename +
            ", fullname=" + fullname +
            ", tips=" + tips +
            ", version=" + version +
            "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Dict.java
New file
@@ -0,0 +1,116 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
/**
 * <p>
 * 字典表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_dict")
public class Dict extends Model<Dict> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键id
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 排序
     */
    private Integer num;
    /**
     * 父级字典
     */
    private Integer pid;
    /**
     * 名称
     */
    private String name;
    /**
     * 编码
     */
    private String code;
    /**
     * 提示
     */
    private String tips;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getNum() {
        return num;
    }
    public void setNum(Integer num) {
        this.num = num;
    }
    public Integer getPid() {
        return pid;
    }
    public void setPid(Integer pid) {
        this.pid = pid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTips() {
        return tips;
    }
    public void setTips(String tips) {
        this.tips = tips;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    @Override
    public String toString() {
        return "Dict{" +
                "id=" + id +
                ", num=" + num +
                ", pid=" + pid +
                ", name='" + name + '\'' +
                ", code='" + code + '\'' +
                ", tips='" + tips + '\'' +
                '}';
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/LoginLog.java
New file
@@ -0,0 +1,128 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 * 登录记录
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_login_log")
public class LoginLog extends Model<LoginLog> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 日志名称
     */
    private String logname;
    /**
     * 管理员id
     */
    private Integer userid;
    /**
     * 创建时间
     */
    private Date createtime;
    /**
     * 是否执行成功
     */
    private String succeed;
    /**
     * 具体消息
     */
    private String message;
    /**
     * 登录ip
     */
    private String ip;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getLogname() {
        return logname;
    }
    public void setLogname(String logname) {
        this.logname = logname;
    }
    public Integer getUserid() {
        return userid;
    }
    public void setUserid(Integer userid) {
        this.userid = userid;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public String getSucceed() {
        return succeed;
    }
    public void setSucceed(String succeed) {
        this.succeed = succeed;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "LoginLog{" +
            "id=" + id +
            ", logname=" + logname +
            ", userid=" + userid +
            ", createtime=" + createtime +
            ", succeed=" + succeed +
            ", message=" + message +
            ", ip=" + ip +
            "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Menu.java
New file
@@ -0,0 +1,208 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import org.hibernate.validator.constraints.NotBlank;
import java.io.Serializable;
/**
 * <p>
 * 菜单表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_menu")
public class Menu extends Model<Menu> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键id
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 菜单编号
     */
    private String code;
    /**
     * 菜单父编号
     */
    private String pcode;
    /**
     * 当前菜单的所有父菜单编号
     */
    private String pcodes;
    /**
     * 菜单名称
     */
    @NotBlank
    private String name;
    /**
     * 菜单图标
     */
    private String icon;
    /**
     * url地址
     */
    @NotBlank
    private String url;
    /**
     * 菜单排序号
     */
    private Integer num;
    /**
     * 菜单层级
     */
    private Integer levels;
    /**
     * 是否是菜单(1:是  0:不是)
     */
    private Integer ismenu;
    /**
     * 备注
     */
    private String tips;
    /**
     * 菜单状态 :  1:启用   0:不启用
     */
    private Integer status;
    /**
     * 是否打开:    1:打开   0:不打开
     */
    private Integer isopen;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getPcode() {
        return pcode;
    }
    public void setPcode(String pcode) {
        this.pcode = pcode;
    }
    public String getPcodes() {
        return pcodes;
    }
    public void setPcodes(String pcodes) {
        this.pcodes = pcodes;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getIcon() {
        return icon;
    }
    public void setIcon(String icon) {
        this.icon = icon;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public Integer getNum() {
        return num;
    }
    public void setNum(Integer num) {
        this.num = num;
    }
    public Integer getLevels() {
        return levels;
    }
    public void setLevels(Integer levels) {
        this.levels = levels;
    }
    public Integer getIsmenu() {
        return ismenu;
    }
    public void setIsmenu(Integer ismenu) {
        this.ismenu = ismenu;
    }
    public String getTips() {
        return tips;
    }
    public void setTips(String tips) {
        this.tips = tips;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public Integer getIsopen() {
        return isopen;
    }
    public void setIsopen(Integer isopen) {
        this.isopen = isopen;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "Menu{" +
                "id=" + id +
                ", code=" + code +
                ", pcode=" + pcode +
                ", pcodes=" + pcodes +
                ", name=" + name +
                ", icon=" + icon +
                ", url=" + url +
                ", num=" + num +
                ", levels=" + levels +
                ", ismenu=" + ismenu +
                ", tips=" + tips +
                ", status=" + status +
                ", isopen=" + isopen +
                "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Notice.java
New file
@@ -0,0 +1,115 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 * 通知表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_notice")
public class Notice extends Model<Notice> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 标题
     */
    private String title;
    /**
     * 类型
     */
    private Integer type;
    /**
     * 内容
     */
    private String content;
    /**
     * 创建时间
     */
    private Date createtime;
    /**
     * 创建人
     */
    private Integer creater;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public Integer getCreater() {
        return creater;
    }
    public void setCreater(Integer creater) {
        this.creater = creater;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "Notice{" +
            "id=" + id +
            ", title=" + title +
            ", type=" + type +
            ", content=" + content +
            ", createtime=" + createtime +
            ", creater=" + creater +
            "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/OperationLog.java
New file
@@ -0,0 +1,154 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 * 操作日志
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_operation_log")
public class OperationLog extends Model<OperationLog> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 日志类型
     */
    private String logtype;
    /**
     * 日志名称
     */
    private String logname;
    /**
     * 用户id
     */
    private Integer userid;
    /**
     * 类名称
     */
    private String classname;
    /**
     * 方法名称
     */
    private String method;
    /**
     * 创建时间
     */
    private Date createtime;
    /**
     * 是否成功
     */
    private String succeed;
    /**
     * 备注
     */
    private String message;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getLogtype() {
        return logtype;
    }
    public void setLogtype(String logtype) {
        this.logtype = logtype;
    }
    public String getLogname() {
        return logname;
    }
    public void setLogname(String logname) {
        this.logname = logname;
    }
    public Integer getUserid() {
        return userid;
    }
    public void setUserid(Integer userid) {
        this.userid = userid;
    }
    public String getClassname() {
        return classname;
    }
    public void setClassname(String classname) {
        this.classname = classname;
    }
    public String getMethod() {
        return method;
    }
    public void setMethod(String method) {
        this.method = method;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public String getSucceed() {
        return succeed;
    }
    public void setSucceed(String succeed) {
        this.succeed = succeed;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "OperationLog{" +
            "id=" + id +
            ", logtype=" + logtype +
            ", logname=" + logname +
            ", userid=" + userid +
            ", classname=" + classname +
            ", method=" + method +
            ", createtime=" + createtime +
            ", succeed=" + succeed +
            ", message=" + message +
            "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/PatrolTask.java
New file
@@ -0,0 +1,84 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:10
 */
@Data
@ApiModel
@TableName("t_patrol_task")
public class PatrolTask {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 任务名称
     */
    @TableField("name")
    @ApiModelProperty("任务名称")
    private String name;
    /**
     * 任务类型(1=定时任务,2=实时任务)
     */
    @TableField("type")
    @ApiModelProperty("任务类型(1=定时任务,2=实时任务)")
    private Integer type;
    /**
     * 数据模型编号
     */
    @TableField("image_model")
    @ApiModelProperty("数据模型编号")
    private String imageModel;
    /**
     * 定时周期json
     */
    @TableField("weeks")
    @ApiModelProperty("定时周期json[1,2,3,4,5,6,7]")
    private String weeks;
    /**
     * 执行时间
     */
    @TableField("execution_time")
    @ApiModelProperty("执行时间")
    private String executionTime;
    /**
     * 开始执行时间
     */
    @TableField("start_time")
    @ApiModelProperty("开始执行时间")
    private LocalDateTime startTime;
    /**
     * 执行结束时间
     */
    @TableField("end_time")
    @ApiModelProperty("执行结束时间")
    private LocalDateTime endTime;
    /**
     * 备注
     */
    @TableField("remark")
    @ApiModelProperty("备注")
    private String remark;
    /**
     * 添加时间
     */
    @TableField("create_time")
    private LocalDateTime createTime;
    /**
     * 添加人id
     */
    @TableField("create_user_id")
    private Integer createUserId;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Relation.java
New file
@@ -0,0 +1,75 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
/**
 * <p>
 * 角色和菜单关联表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_relation")
public class Relation extends Model<Relation> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 菜单id
     */
    private Long menuid;
    /**
     * 角色id
     */
    private Integer roleid;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Long getMenuid() {
        return menuid;
    }
    public void setMenuid(Long menuid) {
        this.menuid = menuid;
    }
    public Integer getRoleid() {
        return roleid;
    }
    public void setRoleid(Integer roleid) {
        this.roleid = roleid;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "Relation{" +
                "id=" + id +
                ", menuid=" + menuid +
                ", roleid=" + roleid +
                "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/Role.java
New file
@@ -0,0 +1,127 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
/**
 * <p>
 * 角色表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_role")
public class Role extends Model<Role> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键id
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 序号
     */
    private Integer num;
    /**
     * 父角色id
     */
    private Integer pid;
    /**
     * 角色名称
     */
    private String name;
    /**
     * 部门名称
     */
    private Integer deptid;
    /**
     * 提示
     */
    private String tips;
    /**
     * 保留字段(暂时没用)
     */
    private Integer version;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getNum() {
        return num;
    }
    public void setNum(Integer num) {
        this.num = num;
    }
    public Integer getPid() {
        return pid;
    }
    public void setPid(Integer pid) {
        this.pid = pid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getDeptid() {
        return deptid;
    }
    public void setDeptid(Integer deptid) {
        this.deptid = deptid;
    }
    public String getTips() {
        return tips;
    }
    public void setTips(String tips) {
        this.tips = tips;
    }
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "Role{" +
            "id=" + id +
            ", num=" + num +
            ", pid=" + pid +
            ", name=" + name +
            ", deptid=" + deptid +
            ", tips=" + tips +
            ", version=" + version +
            "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TaskDetail.java
New file
@@ -0,0 +1,48 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:20
 */
@Data
@TableName("t_task_detail")
public class TaskDetail {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 任务编号
     */
    @TableField("code")
    private String code;
    /**
     * 任务id
     */
    @TableField("patrol_task_id")
    private Integer patrolTaskId;
    /**
     * 执行状态(1=待执行,2=进行中,3=成功,4=失败)
     */
    @TableField("status")
    private Integer status;
    /**
     * 执行时间
     */
    @TableField("execution_time")
    private LocalDateTime executionTime;
    /**
     * 删除(0=否,1=是)
     */
    @TableField("del_flag")
    private Integer delFlag;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TaskDetailVehicles.java
New file
@@ -0,0 +1,88 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:24
 */
@Data
@TableName("t_task_detail_vehicles")
public class TaskDetailVehicles {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 任务id
     */
    @TableField("patrol_task_id")
    private Integer patrolTaskId;
    /**
     * 任务明细id
     */
    @TableField("task_detail_id")
    private Integer taskDetailId;
    /**
     * 车辆id
     */
    @TableField("vehicleId")
    private Integer vehicleId;
    /**
     * 车牌号
     */
    @TableField("vehicleNum")
    private String vehicleNum;
    /**
     * 车船类型:1 车辆设备 2 船舶设备
     */
    @TableField("vehicleType")
    private Integer vehicleType;
    /**
     * 车船唯一码(车辆id+车船类型)
     */
    @TableField("vehicleIdUnique")
    private String vehicleIdUnique;
    /**
     * 公司id
     */
    @TableField("companyId")
    private String companyId;
    /**
     * 公司名称
     */
    @TableField("companyName")
    private String companyName;
    /**
     * 年审开始时间,格式:yyyy-MM-dd
     */
    @TableField("inspectPeriodStart")
    private String inspectPeriodStart;
    /**
     * 年审结束时间,格式:yyyy-MM-dd
     */
    @TableField("inspectPeriodEnd")
    private String inspectPeriodEnd;
    /**
     * 执行状态(1=待执行,2=执行中,3=成功,4=离线,5=失败)
     */
    @TableField("status")
    private Integer status;
    /**
     * 开始执行时间
     */
    @TableField("start_execution_time")
    private LocalDateTime startExecutionTime;
    /**
     * 结束执行时间
     */
    @TableField("end_execution_time")
    private LocalDateTime endExecutionTime;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TaskDetailVehiclesChannel.java
New file
@@ -0,0 +1,78 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:30
 */
@Data
@TableName("t_task_detail_vehicles_channel")
public class TaskDetailVehiclesChannel {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 任务id
     */
    @TableField("patrol_task_id")
    private Integer patrolTaskId;
    /**
     * 任务明细id
     */
    @TableField("task_detail_id")
    private Integer taskDetailId;
    /**
     * 任务车船明细id
     */
    @TableField("task_detail_vehicles_id")
    private Integer taskDetailVehiclesId;
    /**
     * 视频通道
     */
    @TableField("video_channel")
    private Integer videoChannel;
    /**
     * 图片地址
     */
    @TableField("image_url")
    private String imageUrl;
    /**
     * 系统审核状态(1=未执行,2=正常,3=异常)
     */
    @TableField("sys_status")
    private Integer sysStatus;
    /**
     * 系统审核时间
     */
    @TableField("sys_create_time")
    private LocalDateTime sysCreateTime;
    /**
     * 人工审核状态(1=未执行,2=正常,3=异常)
     */
    @TableField("artificial_status")
    private Integer artificialStatus;
    /**
     * 人工审核时间
     */
    @TableField("artificial_create_time")
    private LocalDateTime artificialCreateTime;
    /**
     * 人工审核人id
     */
    @TableField("artificial_user_id")
    private Integer artificialUserId;
    /**
     * 人工审核备注
     */
    @TableField("remark")
    private String remark;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/User.java
New file
@@ -0,0 +1,234 @@
package com.stylefeng.guns.modular.system.model;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 * 管理员表
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
@TableName("sys_user")
public class User extends Model<User> {
    private static final long serialVersionUID = 1L;
    /**
     * 主键id
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 头像
     */
    private String avatar;
    /**
     * 账号
     */
    private String account;
    /**
     * 密码
     */
    private String password;
    /**
     * md5密码盐
     */
    private String salt;
    /**
     * 名字
     */
    private String name;
    /**
     * 生日
     */
    private Date birthday;
    /**
     * 性别(1:男 2:女)
     */
    private Integer sex;
    /**
     * 电子邮件
     */
    private String email;
    /**
     * 电话
     */
    private String phone;
    /**
     * 角色id
     */
    private String roleid;
    /**
     * 部门id
     */
    private Integer deptid;
    /**
     * 状态(1:启用  2:冻结  3:删除)
     */
    private Integer status;
    /**
     * 创建时间
     */
    private Date createtime;
    /**
     * 保留字段
     */
    private Integer version;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getAvatar() {
        return avatar;
    }
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getSalt() {
        return salt;
    }
    public void setSalt(String salt) {
        this.salt = salt;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public Integer getSex() {
        return sex;
    }
    public void setSex(Integer sex) {
        this.sex = sex;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getRoleid() {
        return roleid;
    }
    public void setRoleid(String roleid) {
        this.roleid = roleid;
    }
    public Integer getDeptid() {
        return deptid;
    }
    public void setDeptid(Integer deptid) {
        this.deptid = deptid;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "User{" +
            "id=" + id +
            ", avatar=" + avatar +
            ", account=" + account +
            ", password=" + password +
            ", salt=" + salt +
            ", name=" + name +
            ", birthday=" + birthday +
            ", sex=" + sex +
            ", email=" + email +
            ", phone=" + phone +
            ", roleid=" + roleid +
            ", deptid=" + deptid +
            ", status=" + status +
            ", createtime=" + createtime +
            ", version=" + version +
            "}";
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/enums/ImageModelEnum.java
New file
@@ -0,0 +1,59 @@
package com.stylefeng.guns.modular.system.model.enums;
/**
 * 图片模型枚举类
 * @author zhibing.pu
 * @Date 2024/12/17 20:50
 */
public enum ImageModelEnum {
    TOP_SEAL("顶盖密闭巡查", "TOP_SEAL"),
    CAMERA_FAULT("摄像头图章巡查", "CAMERA_FAULT"),
    CONSTRUCTION_WASTE_LOAD("建筑垃圾装载巡查", "CONSTRUCTION_WASTE_LOAD")
    ;
    /**
     * 模型名称
     */
    private String name;
    /**
     * 模型编号
     */
    private String code;
    ImageModelEnum(String name, String code) {
        this.name = name;
        this.code = code;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    /**
     * 根据编号获取枚举对象
     * @param code
     * @return
     */
    public static ImageModelEnum getImageModelEnum(String code){
        ImageModelEnum[] values = ImageModelEnum.values();
        for (ImageModelEnum modelEnum : values) {
            if(modelEnum.getCode().equals(code)){
                return modelEnum;
            }
        }
        return null;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/enums/VideoChannelEnum.java
New file
@@ -0,0 +1,58 @@
package com.stylefeng.guns.modular.system.model.enums;
/**
 * 视频通道枚举类
 * @author zhibing.pu
 * @Date 2024/12/18 18:42
 */
public enum VideoChannelEnum {
    CONTAINER("货箱", 1),
    CAB("驾驶室", 2),
    ROAD_AHEAD("前方路面", 3),
    RIGHT_BLIND_AREA("右侧盲区", 4),
    BACK_UP("倒车", 5),
    DRIVER("驾驶员", 6)
    ;
    //车船协议分两类,2018协议和2023协议,2018协议有5个通道(1-5),2023协议有6个通道(1-6)
    /**
     * 通道名称
     */
    private String name;
    /**
     * 通道id
     */
    private Integer id;
    VideoChannelEnum(String name, Integer id) {
        this.name = name;
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public static String getName(Integer id){
        VideoChannelEnum[] values = VideoChannelEnum.values();
        for (VideoChannelEnum channelEnum : values) {
            if(channelEnum.getId().equals(id)){
                return channelEnum.getName();
            }
        }
        return null;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/ManualAuditVo.java
New file
@@ -0,0 +1,22 @@
package com.stylefeng.guns.modular.system.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 11:33
 */
@Data
@ApiModel
public class ManualAuditVo {
    @ApiModelProperty("数据id数组")
    private List<Integer> id;
    @ApiModelProperty("审核状态(2=正常,3=异常)")
    private Integer status;
    @ApiModelProperty("审核注释")
    private String remark;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PatrolTaskVo.java
New file
@@ -0,0 +1,21 @@
package com.stylefeng.guns.modular.system.model.vo;
import com.stylefeng.guns.modular.system.model.PatrolTask;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/18 18:39
 */
@Data
@ApiModel
public class PatrolTaskVo extends PatrolTask {
    @ApiModelProperty("视频通道编号数组")
    private List<Integer> videoChannel;
    @ApiModelProperty("船舶数据")
    private List<VehicleVo> vehicle;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PictureDetails.java
New file
@@ -0,0 +1,34 @@
package com.stylefeng.guns.modular.system.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 10:09
 */
@Data
@ApiModel
public class PictureDetails {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("图片通道")
    private String videoChannel;
    @ApiModelProperty("图片地址")
    private String imageUrl;
    @ApiModelProperty("系统审核状态(1=未执行,2=正常,3=异常)")
    private Integer sysStatus;
    @ApiModelProperty("系统审核时间")
    private String sysCreateTime;
    @ApiModelProperty("人工审核状态(1=未执行,2=正常,3=异常)")
    private Integer artificialStatus;
    @ApiModelProperty("人工审核时间")
    private String artificialCreateTime;
    @ApiModelProperty("人工审核人")
    private String artificialUserName;
    @ApiModelProperty("是否确认(0=否,1=是)")
    private Integer verify;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PictureDetailsVehicle.java
New file
@@ -0,0 +1,20 @@
package com.stylefeng.guns.modular.system.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 10:49
 */
@Data
@ApiModel
public class PictureDetailsVehicle {
    @ApiModelProperty("车辆列表")
    private List<VehicleVo> vehicle;
    @ApiModelProperty("船舶列表")
    private List<VehicleVo> ship;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/PictureDetailsVo.java
New file
@@ -0,0 +1,25 @@
package com.stylefeng.guns.modular.system.model.vo;
import com.stylefeng.guns.core.page.PageBT;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 10:32
 */
@Data
@ApiModel
public class PictureDetailsVo extends PageBT {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("车船对象数据[{\"vehicleType\":1,\"vehicleId\":123},{\"vehicleType\":2,\"vehicleId\":456}]")
    private String vehicle;
    @ApiModelProperty("执行状态(1=待执行,2=执行中,3=成功,4=离线,5=失败)")
    private Integer status;
    @ApiModelProperty("系统审核(1=未执行,2=正常,3=异常)")
    private Integer sysStatus;
    @ApiModelProperty("系统审核(1=未执行,2=正常,3=异常)")
    private Integer artificialStatus;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskDetailList.java
New file
@@ -0,0 +1,24 @@
package com.stylefeng.guns.modular.system.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:57
 */
@Data
@ApiModel
public class TaskDetailList {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("规则编号")
    private String code;
    @ApiModelProperty("任务名称")
    private String name;
    @ApiModelProperty("任务类型(1=定时任务,2=实时任务)")
    private Integer type;
    @ApiModelProperty("执行时间")
    private String executionTime;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskDetailListVo.java
New file
@@ -0,0 +1,19 @@
package com.stylefeng.guns.modular.system.model.vo;
import com.stylefeng.guns.core.page.PageBT;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:46
 */
@Data
@ApiModel
public class TaskDetailListVo extends PageBT {
    @ApiModelProperty("规则编号")
    private String code;
    @ApiModelProperty("状态(1=待执行,2=进行中,3=成功,4=失败)")
    private Integer status;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskRecordInfo.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.modular.system.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 10:04
 */
@Data
@ApiModel
public class TaskRecordInfo {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("执行车辆")
    private Integer vehicleNum;
    @ApiModelProperty("未执行数量")
    private Long unexecutedQuantity;
    @ApiModelProperty("任务类型(1=定时任务,2=实时任务)")
    private Integer type;
    @ApiModelProperty("任务名称")
    private String name;
    @ApiModelProperty("任务状态(1=待执行,2=进行中,3=成功,4=失败)")
    private Integer status;
    @ApiModelProperty("执行时间")
    private String executionTime;
    @ApiModelProperty("离线数量")
    private Long offlineNum;
    @ApiModelProperty("正常数量")
    private Long normalNum;
    @ApiModelProperty("异常数量")
    private Long abnormalNum;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskRecordList.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.modular.system.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 9:12
 */
@Data
@ApiModel
public class TaskRecordList {
    @ApiModelProperty("数据id")
    private Integer id;
    @ApiModelProperty("任务类型(1=定时任务,2=实时任务)")
    private Integer type;
    @ApiModelProperty("任务名称")
    private String name;
    @ApiModelProperty("任务状态(1=待执行,2=进行中,3=成功,4=失败)")
    private Integer status;
    @ApiModelProperty("执行时间")
    private String executionTime;
    @ApiModelProperty("执行车辆")
    private Integer vehicleNum;
    @ApiModelProperty("未执行数量")
    private Integer unexecutedQuantity;
    @ApiModelProperty("离线数量")
    private Integer offlineNum;
    @ApiModelProperty("正常数量")
    private Integer normalNum;
    @ApiModelProperty("异常数量")
    private Integer abnormalNum;
    @ApiModelProperty("人工审核状态(0=未审核,1=已审核)")
    private Integer authStatus;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/TaskRecordListVo.java
New file
@@ -0,0 +1,19 @@
package com.stylefeng.guns.modular.system.model.vo;
import com.stylefeng.guns.core.page.PageBT;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 9:59
 */
@Data
@ApiModel
public class TaskRecordListVo extends PageBT {
    @ApiModelProperty("规则编号")
    private String code;
    @ApiModelProperty("状态(1=待执行,2=进行中,3=成功,4=失败)")
    private Integer status;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/vo/VehicleVo.java
New file
@@ -0,0 +1,29 @@
package com.stylefeng.guns.modular.system.model.vo;
import com.baomidou.mybatisplus.annotations.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/18 19:15
 */
@Data
@ApiModel
public class VehicleVo {
    @ApiModelProperty("车辆id")
    private Integer vehicleId;
    @ApiModelProperty("车牌号")
    private String vehicleNum;
    @ApiModelProperty("车船类型:1 车辆设备 2 船舶设备")
    private Integer vehicleType;
    @ApiModelProperty("公司id")
    private String companyId;
    @ApiModelProperty("公司名称")
    private String companyName;
    @ApiModelProperty("年审开始时间,格式:yyyy-MM-dd")
    private String inspectPeriodStart;
    @ApiModelProperty("年审结束时间,格式:yyyy-MM-dd")
    private String inspectPeriodEnd;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IDeptService.java
New file
@@ -0,0 +1,33 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.model.Dept;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * 部门服务
 *
 * @author fengshuonan
 * @date 2017-04-27 17:00
 */
public interface IDeptService extends IService<Dept> {
    /**
     * 删除部门
     */
    void deleteDept(Integer deptId);
    /**
     * 获取ztree的节点列表
     */
    List<ZTreeNode> tree();
    /**
     * 获取所有部门列表
     */
    List<Map<String, Object>> list(@Param("condition") String condition);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IDictService.java
New file
@@ -0,0 +1,48 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.Dict;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * 字典服务
 *
 * @author fengshuonan
 * @date 2017-04-27 17:00
 */
public interface IDictService extends IService<Dict> {
    /**
     * 添加字典
     */
    void addDict(String dictCode,String dictName,String dictTips, String dictValues);
    /**
     * 编辑字典
     */
    void editDict(Integer dictId,String dictCode, String dictName,String dictTips, String dicts);
    /**
     * 删除字典
     */
    void delteDict(Integer dictId);
    /**
     * 根据编码获取词典列表
     */
    List<Dict> selectByCode(@Param("code") String code);
    /**
     * 根据父类编码获取词典列表
     */
    List<Dict> selectByParentCode(@Param("code") String code);
    /**
     * 查询字典列表
     */
    List<Map<String, Object>> list(@Param("condition") String conditiion);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ILoginLogService.java
New file
@@ -0,0 +1,24 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.LoginLog;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 登录记录 服务类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
public interface ILoginLogService extends IService<LoginLog> {
    /**
     * 获取登录日志列表
     */
    List<Map<String, Object>> getLoginLogs(Page<LoginLog> page, String beginTime, String endTime, String logName, String orderByField, boolean asc);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IMenuService.java
New file
@@ -0,0 +1,94 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.core.node.MenuNode;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.model.Menu;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * 菜单服务
 *
 * @author fengshuonan
 * @date 2017-05-05 22:19
 */
public interface IMenuService extends IService<Menu> {
    /**
     * 删除菜单
     *
     * @author stylefeng
     * @Date 2017/5/5 22:20
     */
    void delMenu(Long menuId);
    /**
     * 删除菜单包含所有子菜单
     *
     * @author stylefeng
     * @Date 2017/6/13 22:02
     */
    void delMenuContainSubMenus(Long menuId);
    /**
     * 根据条件查询菜单
     *
     * @return
     * @date 2017年2月12日 下午9:14:34
     */
    List<Map<String, Object>> selectMenus(@Param("condition") String condition, @Param("level") String level);
    /**
     * 根据条件查询菜单
     *
     * @return
     * @date 2017年2月12日 下午9:14:34
     */
    List<Long> getMenuIdsByRoleId(@Param("roleId") Integer roleId);
    /**
     * 获取菜单列表树
     *
     * @return
     * @date 2017年2月19日 下午1:33:51
     */
    List<ZTreeNode> menuTreeList();
    /**
     * 获取菜单列表树
     *
     * @return
     * @date 2017年2月19日 下午1:33:51
     */
    List<ZTreeNode> menuTreeListByMenuIds(List<Long> menuIds);
    /**
     * 删除menu关联的relation
     *
     * @param menuId
     * @return
     * @date 2017年2月19日 下午4:10:59
     */
    int deleteRelationByMenu(Long menuId);
    /**
     * 获取资源url通过角色id
     *
     * @param roleId
     * @return
     * @date 2017年2月19日 下午7:12:38
     */
    List<String> getResUrlsByRoleId(Integer roleId);
    /**
     * 根据角色获取菜单
     *
     * @param roleIds
     * @return
     * @date 2017年2月19日 下午10:35:40
     */
    List<MenuNode> getMenusByRoleIds(List<Integer> roleIds);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/INoticeService.java
New file
@@ -0,0 +1,23 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.Notice;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 通知表 服务类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
public interface INoticeService extends IService<Notice> {
    /**
     * 获取通知列表
     */
    List<Map<String, Object>> list(String condition);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IOperationLogService.java
New file
@@ -0,0 +1,24 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.OperationLog;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 操作日志 服务类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
public interface IOperationLogService extends IService<OperationLog> {
    /**
     * 获取操作日志列表
     */
    List<Map<String, Object>> getOperationLogs(Page<OperationLog> page, String beginTime, String endTime, String logName, String s, String orderByField, boolean asc);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IPatrolTaskService.java
New file
@@ -0,0 +1,26 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.PatrolTask;
import com.stylefeng.guns.modular.system.model.vo.PatrolTaskVo;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:17
 */
public interface IPatrolTaskService extends IService<PatrolTask> {
    /**
     * 添加新的任务数据
     * @param vo
     */
    void addPatrolTask(PatrolTaskVo vo, String userId);
    /**
     * 定时任务执行逻辑
     * @param id
     */
    void execute(Integer id);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IRelationService.java
New file
@@ -0,0 +1,16 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.Relation;
/**
 * <p>
 * 角色和菜单关联表 服务类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
public interface IRelationService extends IService<Relation> {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IRoleService.java
New file
@@ -0,0 +1,68 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.model.Role;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * 角色相关业务
 *
 * @author fengshuonan
 * @Date 2017年1月10日 下午9:11:57
 */
public interface IRoleService extends IService<Role> {
    /**
     * 设置某个角色的权限
     *
     * @param roleId 角色id
     * @param ids    权限的id
     * @date 2017年2月13日 下午8:26:53
     */
    void setAuthority(Integer roleId, String ids);
    /**
     * 删除角色
     *
     * @author stylefeng
     * @Date 2017/5/5 22:24
     */
    void delRoleById(Integer roleId);
    /**
     * 根据条件查询角色列表
     *
     * @return
     * @date 2017年2月12日 下午9:14:34
     */
    List<Map<String, Object>> selectRoles(@Param("condition") String condition);
    /**
     * 删除某个角色的所有权限
     *
     * @param roleId 角色id
     * @return
     * @date 2017年2月13日 下午7:57:51
     */
    int deleteRolesById(@Param("roleId") Integer roleId);
    /**
     * 获取角色列表树
     *
     * @return
     * @date 2017年2月18日 上午10:32:04
     */
    List<ZTreeNode> roleTreeList();
    /**
     * 获取角色列表树
     *
     * @return
     * @date 2017年2月18日 上午10:32:04
     */
    List<ZTreeNode> roleTreeListByRoleId(String[] roleId);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailService.java
New file
@@ -0,0 +1,81 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.TaskDetail;
import com.stylefeng.guns.modular.system.model.vo.*;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:23
 */
public interface ITaskDetailService extends IService<TaskDetail> {
    /**
     * 获取巡查任务列表数据
     * @param vo
     * @return
     */
    List<TaskDetailList> getTaskDetailList(Page<TaskDetailList> pageInfo, TaskDetailListVo vo);
    /**
     * 删除任务
     * @param ids
     */
    void delTaskDetail(List<Integer> ids);
    /**
     * 获取任务记录列表
     * @param pageInfo
     * @param vo
     * @return
     */
    List<TaskRecordList> getTaskRecordList(Page<TaskRecordList> pageInfo, TaskRecordListVo vo);
    /**
     * 获取任务记录详情
     * @param id
     * @return
     */
    TaskRecordInfo getTaskRecordInfo(Integer id);
    /**
     * 获取任务记录中的车船数据
     * @param vo
     * @return
     */
    PictureDetailsVehicle getPictureDetailsVehicle(PictureDetailsVo vo);
    /**
     * 获取任务记录详情中的通道数据
     * @param vo
     * @return
     */
    List<PictureDetails> getPictureDetails(Page<PictureDetails> pageInfo, PictureDetailsVo vo);
    /**
     * 人工审核
     * @return
     */
    ResultUtil manualAudit(ManualAuditVo vo);
    /**
     * 下载任务记录数据
     * @param ids
     * @param code
     * @param status
     * @param response
     */
    void downloadTaskRecord(List<String> ids, String code, Integer status, HttpServletResponse response);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailVehiclesChannelService.java
New file
@@ -0,0 +1,23 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.TaskDetailVehiclesChannel;
import com.stylefeng.guns.modular.system.model.vo.PictureDetails;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:35
 */
public interface ITaskDetailVehiclesChannelService extends IService<TaskDetailVehiclesChannel> {
    /**
     * 根据任务车船关系数据id获取通道数据
     * @param taskDetailVehiclesIdList
     * @return
     */
    List<PictureDetails> getPictureDetails(Page<PictureDetails> pageInfo, List<Integer> taskDetailVehiclesIdList, Integer sysStatus, Integer artificialStatus);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailVehiclesService.java
New file
@@ -0,0 +1,11 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.modular.system.model.TaskDetailVehicles;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:28
 */
public interface ITaskDetailVehiclesService extends IService<TaskDetailVehicles> {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/IUserService.java
New file
@@ -0,0 +1,46 @@
package com.stylefeng.guns.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.stylefeng.guns.core.datascope.DataScope;
import com.stylefeng.guns.modular.system.model.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 管理员表 服务类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
public interface IUserService extends IService<User> {
    /**
     * 修改用户状态
     */
    int setStatus(@Param("userId") Integer userId, @Param("status") int status);
    /**
     * 修改密码
     */
    int changePwd(@Param("userId") Integer userId, @Param("pwd") String pwd);
    /**
     * 根据条件查询用户列表
     */
    List<Map<String, Object>> selectUsers(@Param("dataScope") DataScope dataScope, @Param("name") String name, @Param("beginTime") String beginTime, @Param("endTime") String endTime, @Param("deptid") Integer deptid);
    /**
     * 设置用户的角色
     */
    int setRoles(@Param("userId") Integer userId, @Param("roleIds") String roleIds);
    /**
     * 通过账号获取用户
     */
    User getByAccount(@Param("account") String account);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/DeptServiceImpl.java
New file
@@ -0,0 +1,47 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.dao.DeptMapper;
import com.stylefeng.guns.modular.system.model.Dept;
import com.stylefeng.guns.modular.system.service.IDeptService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Service
@Transactional
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    public void deleteDept(Integer deptId) {
        Dept dept = deptMapper.selectById(deptId);
        Wrapper<Dept> wrapper = new EntityWrapper<>();
        wrapper = wrapper.like("pids", "%[" + dept.getId() + "]%");
        List<Dept> subDepts = deptMapper.selectList(wrapper);
        for (Dept temp : subDepts) {
            temp.deleteById();
        }
        dept.deleteById();
    }
    @Override
    public List<ZTreeNode> tree() {
        return this.baseMapper.tree();
    }
    @Override
    public List<Map<String, Object>> list(String condition) {
        return this.baseMapper.list(condition);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/DictServiceImpl.java
New file
@@ -0,0 +1,101 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.modular.system.dao.DictMapper;
import com.stylefeng.guns.modular.system.model.Dict;
import com.stylefeng.guns.modular.system.service.IDictService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import static com.stylefeng.guns.core.common.constant.factory.MutiStrFactory.*;
@Service
@Transactional
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements IDictService {
    @Resource
    private DictMapper dictMapper;
    @Override
    public void addDict(String dictCode,String dictName,String dictTips, String dictValues) {
        //判断有没有该字典
        List<Dict> dicts = dictMapper.selectList(new EntityWrapper<Dict>().eq("code", dictCode).and().eq("pid", 0));
        if (dicts != null && dicts.size() > 0) {
            throw new GunsException(BizExceptionEnum.DICT_EXISTED);
        }
        //解析dictValues
        List<Map<String, String>> items = parseKeyValue(dictValues);
        //添加字典
        Dict dict = new Dict();
        dict.setName(dictName);
        dict.setCode(dictCode);
        dict.setTips(dictTips);
        dict.setNum(0);
        dict.setPid(0);
        this.dictMapper.insert(dict);
        //添加字典条目
        for (Map<String, String> item : items) {
            String code = item.get(MUTI_STR_CODE);
            String name = item.get(MUTI_STR_NAME);
            String num = item.get(MUTI_STR_NUM);
            Dict itemDict = new Dict();
            itemDict.setPid(dict.getId());
            itemDict.setCode(code);
            itemDict.setName(name);
            try {
                itemDict.setNum(Integer.valueOf(num));
            } catch (NumberFormatException e) {
                throw new GunsException(BizExceptionEnum.DICT_MUST_BE_NUMBER);
            }
            this.dictMapper.insert(itemDict);
        }
    }
    @Override
    public void editDict(Integer dictId,String dictCode, String dictName,String dictTips, String dicts) {
        //删除之前的字典
        this.delteDict(dictId);
        //重新添加新的字典
        this.addDict(dictCode,dictName,dictTips, dicts);
    }
    @Override
    public void delteDict(Integer dictId) {
        //删除这个字典的子词典
        Wrapper<Dict> dictEntityWrapper = new EntityWrapper<>();
        dictEntityWrapper = dictEntityWrapper.eq("pid", dictId);
        dictMapper.delete(dictEntityWrapper);
        //删除这个词典
        dictMapper.deleteById(dictId);
    }
    @Override
    public List<Dict> selectByCode(String code) {
        return this.baseMapper.selectByCode(code);
    }
    @Override
    public List<Dict> selectByParentCode(String code) {
        return this.baseMapper.selectByParentCode(code);
    }
    @Override
    public List<Map<String, Object>> list(String conditiion) {
        return this.baseMapper.list(conditiion);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/LoginLogServiceImpl.java
New file
@@ -0,0 +1,28 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.LoginLogMapper;
import com.stylefeng.guns.modular.system.model.LoginLog;
import com.stylefeng.guns.modular.system.service.ILoginLogService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 登录记录 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
@Service
public class LoginLogServiceImpl extends ServiceImpl<LoginLogMapper, LoginLog> implements ILoginLogService {
    @Override
    public List<Map<String, Object>> getLoginLogs(Page<LoginLog> page, String beginTime, String endTime, String logName, String orderByField, boolean asc) {
        return this.baseMapper.getLoginLogs(page, beginTime, endTime, logName, orderByField, asc);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/MenuServiceImpl.java
New file
@@ -0,0 +1,90 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.node.MenuNode;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.modular.system.dao.MenuMapper;
import com.stylefeng.guns.modular.system.model.Menu;
import com.stylefeng.guns.modular.system.service.IMenuService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
 * 菜单服务
 *
 * @author fengshuonan
 * @date 2017-05-05 22:20
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
    @Resource
    private MenuMapper menuMapper;
    @Override
    public void delMenu(Long menuId) {
        //删除菜单
        this.menuMapper.deleteById(menuId);
        //删除关联的relation
        this.menuMapper.deleteRelationByMenu(menuId);
    }
    @Override
    public void delMenuContainSubMenus(Long menuId) {
        Menu menu = menuMapper.selectById(menuId);
        //删除当前菜单
        delMenu(menuId);
        //删除所有子菜单
        Wrapper<Menu> wrapper = new EntityWrapper<>();
        wrapper = wrapper.like("pcodes", "%[" + menu.getCode() + "]%");
        List<Menu> menus = menuMapper.selectList(wrapper);
        for (Menu temp : menus) {
            delMenu(temp.getId());
        }
    }
    @Override
    public List<Map<String, Object>> selectMenus(String condition, String level) {
        return this.baseMapper.selectMenus(condition, level);
    }
    @Override
    public List<Long> getMenuIdsByRoleId(Integer roleId) {
        return this.baseMapper.getMenuIdsByRoleId(roleId);
    }
    @Override
    public List<ZTreeNode> menuTreeList() {
        return this.baseMapper.menuTreeList();
    }
    @Override
    public List<ZTreeNode> menuTreeListByMenuIds(List<Long> menuIds) {
        return this.baseMapper.menuTreeListByMenuIds(menuIds);
    }
    @Override
    public int deleteRelationByMenu(Long menuId) {
        return this.baseMapper.deleteRelationByMenu(menuId);
    }
    @Override
    public List<String> getResUrlsByRoleId(Integer roleId) {
        return this.baseMapper.getResUrlsByRoleId(roleId);
    }
    @Override
    public List<MenuNode> getMenusByRoleIds(List<Integer> roleIds) {
        return this.baseMapper.getMenusByRoleIds(roleIds);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/NoticeServiceImpl.java
New file
@@ -0,0 +1,27 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.NoticeMapper;
import com.stylefeng.guns.modular.system.model.Notice;
import com.stylefeng.guns.modular.system.service.INoticeService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 通知表 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
@Service
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements INoticeService {
    @Override
    public List<Map<String, Object>> list(String condition) {
        return this.baseMapper.list(condition);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/OperationLogServiceImpl.java
New file
@@ -0,0 +1,28 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.OperationLogMapper;
import com.stylefeng.guns.modular.system.model.OperationLog;
import com.stylefeng.guns.modular.system.service.IOperationLogService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 操作日志 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
@Service
public class OperationLogServiceImpl extends ServiceImpl<OperationLogMapper, OperationLog> implements IOperationLogService {
    @Override
    public List<Map<String, Object>> getOperationLogs(Page<OperationLog> page, String beginTime, String endTime, String logName, String s, String orderByField, boolean asc) {
        return this.baseMapper.getOperationLogs(page, beginTime, endTime, logName, s, orderByField, asc);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/PatrolTaskServiceImpl.java
New file
@@ -0,0 +1,340 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.modular.system.model.PatrolTask;
import com.stylefeng.guns.modular.system.model.TaskDetail;
import com.stylefeng.guns.modular.system.model.TaskDetailVehicles;
import com.stylefeng.guns.modular.system.model.TaskDetailVehiclesChannel;
import com.stylefeng.guns.modular.system.model.enums.ImageModelEnum;
import com.stylefeng.guns.modular.system.model.vo.PatrolTaskVo;
import com.stylefeng.guns.modular.system.model.vo.VehicleVo;
import com.stylefeng.guns.modular.system.service.ITaskDetailService;
import com.stylefeng.guns.modular.system.service.ITaskDetailVehiclesChannelService;
import com.stylefeng.guns.modular.system.service.ITaskDetailVehiclesService;
import com.stylefeng.guns.modular.system.util.UUIDUtil;
import com.stylefeng.guns.modular.system.util.imageModel.ImageModelUtil;
import com.stylefeng.guns.modular.system.util.quartz.QuartzUtil;
import com.stylefeng.guns.modular.system.util.quartz.jobs.PatrolTaskJob;
import com.stylefeng.guns.modular.system.util.quartz.model.QuartzEnum;
import com.stylefeng.guns.modular.system.util.videoGateway.VideoGateway;
import com.stylefeng.guns.modular.system.util.videoGateway.model.VehicleOnline;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.stylefeng.guns.modular.system.dao.PatrolTaskMapper;
import com.stylefeng.guns.modular.system.service.IPatrolTaskService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:18
 */
@Slf4j
@Service
public class PatrolTaskServiceImpl extends ServiceImpl<PatrolTaskMapper, PatrolTask> implements IPatrolTaskService {
    @Autowired
    private ITaskDetailService taskDetailService;
    @Autowired
    private ITaskDetailVehiclesService taskDetailVehiclesService;
    @Autowired
    private ITaskDetailVehiclesChannelService taskDetailVehiclesChannelService;
    @Autowired
    private QuartzUtil quartzUtil;
    /**
     * 添加新的任务数据
     * @param vo
     */
    @Override
    public void addPatrolTask(PatrolTaskVo vo, String userId) {
        if(vo.getStartTime().isAfter(vo.getEndTime())){
            throw new RuntimeException("结束时间不能小于开始时间");
        }
        //构建主数据
        PatrolTask patrolTask = new PatrolTask();
        BeanUtils.copyProperties(vo, patrolTask);
        patrolTask.setCreateTime(LocalDateTime.now());
        patrolTask.setCreateUserId(Integer.valueOf(userId));
        this.insert(patrolTask);
        if(vo.getType() == 2){
            //实时任务,手动添加后续逻辑中需要的数据
            LocalDateTime now = LocalDateTime.now();
            vo.setWeeks("[" + now.getDayOfWeek().getValue() + "]");
            vo.setStartTime(now);
            vo.setExecutionTime(now.plusSeconds(5).format(DateTimeFormatter.ofPattern("HH:mm:ss")));
            vo.setEndTime(now.plusSeconds(10));
        }
        String weeks = vo.getWeeks();
        List<Integer> week = JSON.parseArray(weeks, Integer.class);
        //构建明细任务
        LocalDateTime startTime = vo.getStartTime();
        LocalDateTime endTime = vo.getEndTime();
        while (true){
            if(startTime.compareTo(endTime) >= 0){
                break;
            }
            int value = startTime.getDayOfWeek().getValue();
            if(week.contains(value)){
                TaskDetail taskDetail = new TaskDetail();
                taskDetail.setCode(UUIDUtil.getTimeStr());
                taskDetail.setPatrolTaskId(patrolTask.getId());
                taskDetail.setStatus(1);
                String executionTime = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + vo.getExecutionTime();
                taskDetail.setExecutionTime(LocalDateTime.parse(executionTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                taskDetail.setDelFlag(0);
                taskDetailService.insert(taskDetail);
                //添加任务和车船关系数据
                List<VehicleVo> vehicle = vo.getVehicle();
                for (VehicleVo vehicleVo : vehicle) {
                    TaskDetailVehicles taskDetailVehicles = new TaskDetailVehicles();
                    taskDetailVehicles.setPatrolTaskId(patrolTask.getId());
                    taskDetailVehicles.setTaskDetailId(taskDetail.getId());
                    taskDetailVehicles.setVehicleId(vehicleVo.getVehicleId());
                    taskDetailVehicles.setVehicleNum(vehicleVo.getVehicleNum());
                    taskDetailVehicles.setVehicleType(vehicleVo.getVehicleType());
                    taskDetailVehicles.setVehicleIdUnique(vehicleVo.getVehicleId() + "_" + vehicleVo.getVehicleType());
                    taskDetailVehicles.setCompanyId(vehicleVo.getCompanyId());
                    taskDetailVehicles.setCompanyName(vehicleVo.getCompanyName());
                    taskDetailVehicles.setInspectPeriodStart(vehicleVo.getInspectPeriodStart());
                    taskDetailVehicles.setInspectPeriodEnd(vehicleVo.getInspectPeriodEnd());
                    taskDetailVehicles.setStatus(1);
                    taskDetailVehiclesService.insert(taskDetailVehicles);
                    //添加任务车船视频通道关系数据
                    List<Integer> videoChannel = vo.getVideoChannel();
                    for (Integer s : videoChannel) {
                        TaskDetailVehiclesChannel taskDetailVehiclesChannel = new TaskDetailVehiclesChannel();
                        taskDetailVehiclesChannel.setPatrolTaskId(patrolTask.getId());
                        taskDetailVehiclesChannel.setTaskDetailId(taskDetail.getId());
                        taskDetailVehiclesChannel.setTaskDetailVehiclesId(taskDetailVehicles.getId());
                        taskDetailVehiclesChannel.setVideoChannel(s);
                        taskDetailVehiclesChannel.setSysStatus(1);
                        taskDetailVehiclesChannelService.insert(taskDetailVehiclesChannel);
                    }
                }
                //添加定时任务
                JobDataMap jobDataMap = new JobDataMap();
                jobDataMap.put("id", taskDetail.getId());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    quartzUtil.addSimpleQuartzTask(PatrolTaskJob.class,patrolTask.getName() + "_" + taskDetail.getId(), QuartzEnum.DEFAULT_GROUP.getValue(), jobDataMap
                            , sdf.parse(executionTime), 0, 0);
                } catch (SchedulerException e) {
                    throw new RuntimeException(e);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
            //添加一天
            startTime = startTime.plusDays(1);
        }
    }
    /**
     * 定时任务执行逻辑
     * @param id
     */
    @Override
    public void execute(Integer id){
        //修改状态为执行中
        TaskDetail taskDetail = taskDetailService.selectById(id);
        taskDetail.setStatus(2);
        taskDetailService.updateById(taskDetail);
        PatrolTask patrolTask = this.selectById(taskDetail.getPatrolTaskId());
        //获取所有在线车船
        //2018年协议车辆在线
        List<VehicleOnline> vehicleOnlines2018 = VideoGateway.queryRuntimeInfoByCache(0);
        //2023年协议车辆在线
        List<VehicleOnline> vehicleOnlines203 = VideoGateway.locationRealTimeInfoCache(0);
        //获取当前任务中的车船信息
        List<TaskDetailVehicles> taskDetailVehicles = taskDetailVehiclesService.selectList(new EntityWrapper<TaskDetailVehicles>().eq("task_detail_id", id));
        int errNum = 0;
        for (TaskDetailVehicles taskDetailVehicle : taskDetailVehicles) {
            try {
                taskDetailVehicle.setStartExecutionTime(LocalDateTime.now());
                Integer taskDetailVehicleId = taskDetailVehicle.getId();
                //车船类型:1 车辆设备 2 船舶设备
                Integer vehicleType = taskDetailVehicle.getVehicleType();
                //车船id
                Integer vehicleId = taskDetailVehicle.getVehicleId();
                VehicleOnline vehicleOnline1 = null;
                for (VehicleOnline vehicleOnline : vehicleOnlines2018) {
                    if(vehicleOnline.getVehicleId().equals(vehicleId) && vehicleOnline.getVehicleType().equals(vehicleType)){
                        vehicleOnline1 = vehicleOnline;
                        String vehicleGpsProtocol = vehicleOnline.getVehicleGpsProtocol();
                        vehicleOnline1.setVehicleGpsProtocol("808-guangzhou".equals(vehicleGpsProtocol) ? "1" : "2");
                        break;
                    }
                }
                if(null == vehicleOnline1){
                    for (VehicleOnline vehicleOnline : vehicleOnlines203) {
                        if(vehicleOnline.getVehicleId().equals(vehicleId) && vehicleOnline.getVehicleType().equals(vehicleType)){
                            vehicleOnline1 = vehicleOnline;
                            vehicleOnline1.setVehicleGpsProtocol(vehicleOnline.getVehicleGpsProtocol());
                            break;
                        }
                    }
                }
                //不在线
                if(null == vehicleOnline1){
                    taskDetailVehicle.setEndExecutionTime(LocalDateTime.now());
                    taskDetailVehicle.setStatus(4);
                    taskDetailVehiclesService.updateById(taskDetailVehicle);
                    continue;
                }
                taskDetailVehicle.setStatus(2);
                taskDetailVehiclesService.updateById(taskDetailVehicle);
                //成功
                List<TaskDetailVehiclesChannel> taskDetailVehiclesChannels = taskDetailVehiclesChannelService.selectList(new EntityWrapper<TaskDetailVehiclesChannel>().eq("task_detail_vehicles_id", taskDetailVehicleId));
                //开始发送拍照指令,获取照片地址
                String vehicleGpsProtocol = vehicleOnline1.getVehicleGpsProtocol();
                String terminalId = vehicleOnline1.getTerminalId();
                for (TaskDetailVehiclesChannel taskDetailVehiclesChannel : taskDetailVehiclesChannels) {
                    Integer videoChannel = taskDetailVehiclesChannel.getVideoChannel();
                    if("1".equals(vehicleGpsProtocol)){
                        //2018 协议
                        String fileId = VideoGateway.cameraShot2018(terminalId, videoChannel, 0);
                        if(null == fileId){
                            log.error("2018年协议发送拍摄指令失败:terminalId-->{},videoChannel-->{}", terminalId, videoChannel);
                            throw new RuntimeException();
                        }else{
                            //等待15秒
                            Thread.sleep(15000);
                            String fileUrl = VideoGateway.getCameraShotByFileId2018(terminalId, fileId, 0);
                            if(null == fileUrl){
                                log.error("2018年协议车辆获取拍摄图片失败:terminalId-->{},fileId-->{}", terminalId, fileId);
                                //重新发送拍摄指令,如果还是没有获取到图片,标注失败
                                fileId = VideoGateway.cameraShot2018(terminalId, videoChannel, 0);
                                if(null == fileId){
                                    log.error("2018年协议发送拍摄指令失败:terminalId-->{},videoChannel-->{}", terminalId, videoChannel);
                                    throw new Exception();
                                }else{
                                    //等待15秒
                                    Thread.sleep(15000);
                                    fileUrl = VideoGateway.getCameraShotByFileId2018(terminalId, fileId, 0);
                                    if(null == fileUrl){
                                        log.error("2018年协议车辆获取拍摄图片失败:terminalId-->{},fileId-->{}", terminalId, fileId);
                                        throw new Exception();
                                    }else{
                                        taskDetailVehiclesChannel.setImageUrl(fileUrl);
                                        taskDetailVehiclesChannel.setSysCreateTime(LocalDateTime.now());
                                        taskDetailVehiclesChannel.setArtificialStatus(1);
                                        //开始调模型接口得出结果
                                        boolean b = ImageModelUtil.modelCheck(fileUrl, ImageModelEnum.getImageModelEnum(patrolTask.getImageModel()));
                                        taskDetailVehiclesChannel.setSysStatus(b ? 2 : 3);
                                        taskDetailVehiclesChannelService.updateById(taskDetailVehiclesChannel);
                                    }
                                }
                            }else{
                                taskDetailVehiclesChannel.setImageUrl(fileUrl);
                                taskDetailVehiclesChannel.setSysCreateTime(LocalDateTime.now());
                                taskDetailVehiclesChannel.setArtificialStatus(1);
                                //开始调模型接口得出结果
                                boolean b = ImageModelUtil.modelCheck(fileUrl, ImageModelEnum.getImageModelEnum(patrolTask.getImageModel()));
                                taskDetailVehiclesChannel.setSysStatus(b ? 2 : 3);
                                taskDetailVehiclesChannelService.updateById(taskDetailVehiclesChannel);
                            }
                        }
                    }else{
                        //2023 协议
                        String fileId = VideoGateway.cameraShot2023(vehicleId, vehicleType, terminalId, videoChannel, 0);
                        if(null == fileId){
                            log.error("2023年协议发送拍摄指令失败:terminalId-->{},videoChannel-->{}", terminalId, videoChannel);
                            throw new Exception();
                        }else{
                            //等待15秒
                            Thread.sleep(15000);
                            String fileUrl = VideoGateway.getCameraShotByFileId2023(fileId, 0);
                            if(null == fileUrl){
                                log.error("2023年协议车辆获取拍摄图片失败:terminalId-->{},fileId-->{}", terminalId, fileId);
                                //重新发送拍摄指令,如果还是没有获取图片,标注异常
                                fileId = VideoGateway.cameraShot2023(vehicleId, vehicleType, terminalId, videoChannel, 0);
                                if(null == fileId){
                                    log.error("2023年协议发送拍摄指令失败:terminalId-->{},videoChannel-->{}", terminalId, videoChannel);
                                    throw new Exception();
                                }else{
                                    //等待15秒
                                    Thread.sleep(15000);
                                    fileUrl = VideoGateway.getCameraShotByFileId2023(fileId, 0);
                                    if(null == fileUrl){
                                        log.error("2023年协议车辆获取拍摄图片失败:terminalId-->{},fileId-->{}", terminalId, fileId);
                                        throw new Exception();
                                    }else{
                                        taskDetailVehiclesChannel.setImageUrl(fileUrl);
                                        taskDetailVehiclesChannel.setSysCreateTime(LocalDateTime.now());
                                        taskDetailVehiclesChannel.setArtificialStatus(1);
                                        //开始调模型接口得出结果
                                        boolean b = ImageModelUtil.modelCheck(fileUrl, ImageModelEnum.getImageModelEnum(patrolTask.getImageModel()));
                                        taskDetailVehiclesChannel.setSysStatus(b ? 2 : 3);
                                        taskDetailVehiclesChannelService.updateById(taskDetailVehiclesChannel);
                                    }
                                }
                            }else{
                                taskDetailVehiclesChannel.setImageUrl(fileUrl);
                                taskDetailVehiclesChannel.setSysCreateTime(LocalDateTime.now());
                                taskDetailVehiclesChannel.setArtificialStatus(1);
                                //开始调模型接口得出结果
                                boolean b = ImageModelUtil.modelCheck(fileUrl, ImageModelEnum.getImageModelEnum(patrolTask.getImageModel()));
                                taskDetailVehiclesChannel.setSysStatus(b ? 2 : 3);
                                taskDetailVehiclesChannelService.updateById(taskDetailVehiclesChannel);
                            }
                        }
                    }
                }
                taskDetailVehicle.setEndExecutionTime(LocalDateTime.now());
                taskDetailVehicle.setStatus(3);
                taskDetailVehiclesService.updateById(taskDetailVehicle);
            }catch (Exception e){
                e.printStackTrace();
                //失败
                taskDetailVehicle.setEndExecutionTime(LocalDateTime.now());
                taskDetailVehicle.setStatus(5);
                taskDetailVehiclesService.updateById(taskDetailVehicle);
                errNum++;
            }
        }
        taskDetail.setStatus(0 == errNum ? 3 : 4);
        taskDetailService.updateById(taskDetail);
    }
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        now = now.plusDays(5);
        int value = now.getDayOfWeek().getValue();
        System.err.println(value);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/RelationServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.RelationMapper;
import com.stylefeng.guns.modular.system.model.Relation;
import com.stylefeng.guns.modular.system.service.IRelationService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 角色和菜单关联表 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
@Service
public class RelationServiceImpl extends ServiceImpl<RelationMapper, Relation> implements IRelationService {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/RoleServiceImpl.java
New file
@@ -0,0 +1,73 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.node.ZTreeNode;
import com.stylefeng.guns.core.util.Convert;
import com.stylefeng.guns.modular.system.dao.RelationMapper;
import com.stylefeng.guns.modular.system.dao.RoleMapper;
import com.stylefeng.guns.modular.system.model.Relation;
import com.stylefeng.guns.modular.system.model.Role;
import com.stylefeng.guns.modular.system.service.IRoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RelationMapper relationMapper;
    @Override
    @Transactional(readOnly = false)
    public void setAuthority(Integer roleId, String ids) {
        // 删除该角色所有的权限
        this.roleMapper.deleteRolesById(roleId);
        // 添加新的权限
        for (Long id : Convert.toLongArray(true, Convert.toStrArray(",", ids))) {
            Relation relation = new Relation();
            relation.setRoleid(roleId);
            relation.setMenuid(id);
            this.relationMapper.insert(relation);
        }
    }
    @Override
    @Transactional(readOnly = false)
    public void delRoleById(Integer roleId) {
        //删除角色
        this.roleMapper.deleteById(roleId);
        // 删除该角色所有的权限
        this.roleMapper.deleteRolesById(roleId);
    }
    @Override
    public List<Map<String, Object>> selectRoles(String condition) {
        return this.baseMapper.selectRoles(condition);
    }
    @Override
    public int deleteRolesById(Integer roleId) {
        return this.baseMapper.deleteRolesById(roleId);
    }
    @Override
    public List<ZTreeNode> roleTreeList() {
        return this.baseMapper.roleTreeList();
    }
    @Override
    public List<ZTreeNode> roleTreeListByRoleId(String[] roleId) {
        return this.baseMapper.roleTreeListByRoleId(roleId);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailServiceImpl.java
New file
@@ -0,0 +1,475 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.dao.TaskDetailMapper;
import com.stylefeng.guns.modular.system.model.PatrolTask;
import com.stylefeng.guns.modular.system.model.TaskDetail;
import com.stylefeng.guns.modular.system.model.TaskDetailVehicles;
import com.stylefeng.guns.modular.system.model.TaskDetailVehiclesChannel;
import com.stylefeng.guns.modular.system.model.enums.VideoChannelEnum;
import com.stylefeng.guns.modular.system.model.vo.*;
import com.stylefeng.guns.modular.system.service.*;
import com.stylefeng.guns.modular.system.util.ExcelUtil;
import com.stylefeng.guns.modular.system.util.ResultUtil;
import com.stylefeng.guns.modular.system.util.quartz.QuartzUtil;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;
import org.quartz.JobKey;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:23
 */
@Service
public class TaskDetailServiceImpl extends ServiceImpl<TaskDetailMapper, TaskDetail> implements ITaskDetailService {
    @Autowired
    private QuartzUtil quartzUtil;
    @Autowired
    private IPatrolTaskService patrolTaskService;
    @Autowired
    private ITaskDetailVehiclesService taskDetailVehiclesService;
    @Autowired
    private ITaskDetailVehiclesChannelService taskDetailVehiclesChannelService;
    @Autowired
    private IUserService userService;
    /**
     * 获取巡查任务列表数据
     * @param vo
     * @return
     */
    @Override
    public List<TaskDetailList> getTaskDetailList(Page<TaskDetailList> pageInfo, TaskDetailListVo vo) {
        return this.baseMapper.getTaskDetailList(pageInfo, vo);
    }
    /**
     * 删除任务
     * @param ids
     */
    @Override
    public void delTaskDetail(List<Integer> ids) {
        this.baseMapper.deleteBatchIds(ids);
        List<TaskDetail> taskDetails = this.selectBatchIds(ids);
        for (TaskDetail taskDetail : taskDetails) {
            JobKey jobKey = new JobKey(taskDetail.getId().toString());
            quartzUtil.deleteQuartzTask(jobKey);
        }
    }
    /**
     * 获取任务记录列表
     * @param pageInfo
     * @param vo
     * @return
     */
    @Override
    public List<TaskRecordList> getTaskRecordList(Page<TaskRecordList> pageInfo, TaskRecordListVo vo) {
        return this.baseMapper.getTaskRecordList(pageInfo, vo);
    }
    /**
     * 获取任务记录详情
     * @param id
     * @return
     */
    @Override
    public TaskRecordInfo getTaskRecordInfo(Integer id) {
        TaskDetail taskDetail = this.selectById(id);
        TaskRecordInfo info = new TaskRecordInfo();
        info.setId(id);
        List<TaskDetailVehicles> taskDetailVehiclesList = taskDetailVehiclesService.selectList(new EntityWrapper<TaskDetailVehicles>().eq("task_detail_id", id));
        info.setVehicleNum(taskDetailVehiclesList.size());
        long unexecutedQuantity = taskDetailVehiclesList.stream().filter(s -> s.getStatus() == 1).count();
        info.setUnexecutedQuantity(unexecutedQuantity);
        PatrolTask patrolTask = patrolTaskService.selectById(taskDetail.getPatrolTaskId());
        info.setType(patrolTask.getType());
        info.setName(patrolTask.getName());
        info.setStatus(taskDetail.getStatus());
        info.setExecutionTime(taskDetail.getExecutionTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        long offlineNum = taskDetailVehiclesList.stream().filter(s -> s.getStatus() == 3).count();
        info.setOfflineNum(offlineNum);
        long normalNum = taskDetailVehiclesList.stream().filter(s -> s.getStatus() == 2).count();
        info.setNormalNum(normalNum);
        long abnormalNum = taskDetailVehiclesList.stream().filter(s -> s.getStatus() == 4).count();
        info.setAbnormalNum(abnormalNum);
        return info;
    }
    /**
     * 获取任务记录中的车船数据
     * @param vo
     * @return
     */
    @Override
    public PictureDetailsVehicle getPictureDetailsVehicle(PictureDetailsVo vo) {
        PictureDetailsVehicle info = new PictureDetailsVehicle();
        Wrapper<TaskDetailVehicles> wrapper = new EntityWrapper<TaskDetailVehicles>().eq("task_detail_id", vo.getId());
        if(ToolUtil.isNotEmpty(vo.getVehicle())){
            JSONArray jsonArray = JSON.parseArray(vo.getVehicle());
            List<String> vehicleIdList = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                Integer vehicleId = jsonArray.getJSONObject(i).getInteger("vehicleId");
                Integer vehicleType = jsonArray.getJSONObject(i).getInteger("vehicleType");
                vehicleIdList.add(vehicleId + "_" + vehicleType);
            }
            wrapper.in("vehicleIdUnique", vehicleIdList);
        }
        if(null != vo.getStatus()){
            wrapper.eq("status", vo.getStatus());
        }
        if(null != vo.getSysStatus()){
            List<TaskDetailVehiclesChannel> sys_status = taskDetailVehiclesChannelService.selectList(new EntityWrapper<TaskDetailVehiclesChannel>().eq("sys_status", vo.getSysStatus()));
            List<Integer> collect = sys_status.stream().map(TaskDetailVehiclesChannel::getTaskDetailVehiclesId).collect(Collectors.toList());
            if(collect.size() > 0){
                wrapper.in("id", collect);
            }
        }
        if(null != vo.getArtificialStatus()){
            List<TaskDetailVehiclesChannel> sys_status = taskDetailVehiclesChannelService.selectList(new EntityWrapper<TaskDetailVehiclesChannel>().eq("artificial_status", vo.getArtificialStatus()));
            List<Integer> collect = sys_status.stream().map(TaskDetailVehiclesChannel::getTaskDetailVehiclesId).collect(Collectors.toList());
            if(collect.size() > 0){
                wrapper.in("id", collect);
            }
        }
        List<TaskDetailVehicles> taskDetailVehiclesList = taskDetailVehiclesService.selectList(wrapper);
        List<TaskDetailVehicles> vehiclesList = taskDetailVehiclesList.stream().filter(s -> s.getVehicleType() == 1).collect(Collectors.toList());
        List<VehicleVo> vehicle = new ArrayList<>();
        for (TaskDetailVehicles taskDetailVehicles : vehiclesList) {
            VehicleVo vehicleVo = new VehicleVo();
            BeanUtils.copyProperties(taskDetailVehicles, vehicleVo);
            vehicle.add(vehicleVo);
        }
        info.setVehicle(vehicle);
        List<TaskDetailVehicles> shipList = taskDetailVehiclesList.stream().filter(s -> s.getVehicleType() == 2).collect(Collectors.toList());
        List<VehicleVo> ship = new ArrayList<>();
        for (TaskDetailVehicles taskDetailVehicles : shipList) {
            VehicleVo vehicleVo = new VehicleVo();
            BeanUtils.copyProperties(taskDetailVehicles, vehicleVo);
            ship.add(vehicleVo);
        }
        info.setShip(ship);
        return info;
    }
    /**
     * 获取任务记录详情中的通道数据
     * @param vo
     * @return
     */
    @Override
    public List<PictureDetails> getPictureDetails(Page<PictureDetails> pageInfo, PictureDetailsVo vo) {
        Wrapper<TaskDetailVehicles> wrapper = new EntityWrapper<TaskDetailVehicles>().eq("task_detail_id", vo.getId());
        if(ToolUtil.isNotEmpty(vo.getVehicle())){
            JSONArray jsonArray = JSON.parseArray(vo.getVehicle());
            List<String> vehicleIdList = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                Integer vehicleId = jsonArray.getJSONObject(i).getInteger("vehicleId");
                Integer vehicleType = jsonArray.getJSONObject(i).getInteger("vehicleType");
                vehicleIdList.add(vehicleId + "_" + vehicleType);
            }
            wrapper.in("vehicleIdUnique", vehicleIdList);
        }
        if(null != vo.getStatus()){
            wrapper.eq("status", vo.getStatus());
        }
        List<TaskDetailVehicles> taskDetailVehiclesList = taskDetailVehiclesService.selectList(wrapper);
        List<Integer> collect = taskDetailVehiclesList.stream().map(TaskDetailVehicles::getId).collect(Collectors.toList());
        List<PictureDetails> pictureDetails = taskDetailVehiclesChannelService.getPictureDetails(pageInfo, collect, vo.getSysStatus(), vo.getArtificialStatus());
        for (PictureDetails pictureDetail : pictureDetails) {
            String videoChannel = pictureDetail.getVideoChannel();
            String name = VideoChannelEnum.getName(Integer.valueOf(videoChannel));
            pictureDetail.setVideoChannel(name);
        }
        return pictureDetails;
    }
    /**
     * 人工审核
     * @param vo
     * @return
     */
    @Override
    public ResultUtil manualAudit(ManualAuditVo vo) {
        List<TaskDetailVehiclesChannel> taskDetailVehiclesChannels = taskDetailVehiclesChannelService.selectBatchIds(vo.getId());
        for (TaskDetailVehiclesChannel taskDetailVehiclesChannel : taskDetailVehiclesChannels) {
            if(1 == taskDetailVehiclesChannel.getArtificialStatus()){
                return ResultUtil.error("不能重复审核");
            }
            taskDetailVehiclesChannel.setArtificialStatus(vo.getStatus());
            taskDetailVehiclesChannel.setRemark(vo.getRemark());
            taskDetailVehiclesChannelService.updateById(taskDetailVehiclesChannel);
        }
        return ResultUtil.success();
    }
    /**
     * 下载任务记录数据
     * @param ids
     * @param code
     * @param status
     * @param response
     */
    @Override
    public void downloadTaskRecord(List<String> ids, String code, Integer status, HttpServletResponse response) {
        List<Map<String, Object>> mapList = this.baseMapper.getDownloadTaskRecord(ids, code, status);
        try {
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
            HSSFSheet hssfSheet = hssfWorkbook.createSheet();
            hssfSheet.setDefaultColumnWidth(20);
            hssfSheet.setDefaultRowHeight((short) 800);
            //设置单元格合并
            for (int i = 0; i < 10; i++) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 1, i, i);
                hssfSheet.addMergedRegion(cellRangeAddress);
            }
            CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 10, 16);
            hssfSheet.addMergedRegion(cellRangeAddress);
            // 创建单元格样式
            HSSFCellStyle style = hssfWorkbook.createCellStyle();
            style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
            style.setAlignment(HorizontalAlignment.CENTER); // 水平居中
            HSSFFont font = hssfWorkbook.createFont();
            font.setBold(true);
            style.setFont(font);
            HSSFCellStyle style1 = hssfWorkbook.createCellStyle();
            style1.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
            style1.setAlignment(HorizontalAlignment.CENTER); // 水平居中
            HSSFRow hssfRow = hssfSheet.createRow(0);//设置第一行数据(标题)
            List<String> titles = Arrays.asList("序号", "任务名称", "任务类型", "执行时间", "执行状态", "车牌号", "运输公司", "年审有效期", "巡检状态", "车辆轨迹图片", "货箱通道");
            for (int l = 0; l < titles.size(); l++) {
                HSSFCell hssfCell = hssfRow.createCell(l);
                hssfCell.setCellType(CellType.STRING);//设置表格类型
                hssfCell.setCellStyle(style);
                hssfCell.setCellValue(titles.get(l));
            }
            hssfRow = hssfSheet.createRow(1);//设置第一行数据(标题)
            titles = Arrays.asList("图片", "系统审核", "系统审核时间", "人工审核", "审核意见", "审核人", "审核时间");
            for (int l = 0; l < titles.size(); l++) {
                HSSFCell hssfCell = hssfRow.createCell(l + 10);
                hssfCell.setCellType(CellType.STRING);//设置表格类型
                hssfCell.setCellStyle(style);
                hssfCell.setCellValue(titles.get(l));
            }
            HSSFPatriarch patriarch = hssfSheet.createDrawingPatriarch();
            for (int i = 0; i < mapList.size(); i++) {
                hssfRow = hssfSheet.createRow(i + 2);
                Map<String, Object> map = mapList.get(i);
                //序号
                HSSFCell hssfCell = hssfRow.createCell(0);
                hssfCell.setCellType(CellType.STRING);//设置表格类型
                hssfCell.setCellStyle(style1);
                hssfCell.setCellValue(i + 1);
                //任务名称
                HSSFCell hssfCell1 = hssfRow.createCell(1);
                hssfCell1.setCellType(CellType.STRING);//设置表格类型
                hssfCell1.setCellStyle(style1);
                hssfCell1.setCellValue("");
                if(null != map.get("name")){
                    hssfCell1.setCellValue(map.get("name").toString());
                }
                //任务类型
                HSSFCell hssfCell2 = hssfRow.createCell(2);
                hssfCell2.setCellType(CellType.STRING);//设置表格类型
                hssfCell2.setCellStyle(style1);
                hssfCell2.setCellValue("");
                if(null != map.get("taskType")){
                    hssfCell2.setCellValue(map.get("taskType").toString());
                }
                //执行时间
                HSSFCell hssfCell3 = hssfRow.createCell(3);
                hssfCell3.setCellType(CellType.STRING);//设置表格类型
                hssfCell3.setCellStyle(style1);
                hssfCell3.setCellValue("");
                if(null != map.get("executionTime")){
                    hssfCell3.setCellValue(map.get("executionTime").toString());
                }
                //执行状态
                HSSFCell hssfCell4 = hssfRow.createCell(4);
                hssfCell4.setCellType(CellType.STRING);//设置表格类型
                hssfCell4.setCellStyle(style1);
                hssfCell4.setCellValue("");
                if(null != map.get("status")){
                    Integer status1 = Integer.valueOf(map.get("status").toString());
                    //执行状态(1=待执行,2=进行中,3=成功,4=失败)
                    hssfCell4.setCellValue(1 == status1 ? "待执行" : 2 == status1 ? "进行中" : 3 == status1 ? "成功" : "失败");
                }
                //车牌号
                HSSFCell hssfCell5 = hssfRow.createCell(5);
                hssfCell5.setCellType(CellType.STRING);//设置表格类型
                hssfCell5.setCellStyle(style1);
                hssfCell5.setCellValue("");
                if(null != map.get("vehicleNum")){
                    hssfCell5.setCellValue(map.get("vehicleNum").toString());
                }
                //运输公司
                HSSFCell hssfCell6 = hssfRow.createCell(6);
                hssfCell6.setCellType(CellType.STRING);//设置表格类型
                hssfCell6.setCellStyle(style1);
                hssfCell6.setCellValue("");
                if(null != map.get("companyName")){
                    hssfCell6.setCellValue(map.get("companyName").toString());
                }
                //年审有效期
                HSSFCell hssfCell7 = hssfRow.createCell(7);
                hssfCell7.setCellType(CellType.STRING);//设置表格类型
                hssfCell7.setCellStyle(style1);
                hssfCell7.setCellValue("");
                if(null != map.get("inspectPeriodEnd")){
                    hssfCell7.setCellValue(map.get("inspectPeriodEnd").toString());
                }
                //巡检状态
                HSSFCell hssfCell8 = hssfRow.createCell(8);
                hssfCell8.setCellType(CellType.STRING);//设置表格类型
                hssfCell8.setCellStyle(style1);
                hssfCell8.setCellValue("");
                if(null != map.get("vehiclesStatus")){
                    //审核状态(1=未执行,2=正常,3=异常)
                    Integer vehiclesStatus = Integer.valueOf(map.get("vehiclesStatus").toString());
                    hssfCell8.setCellValue(1 == vehiclesStatus ? "未执行" : 2 == vehiclesStatus ? "正常" : "异常");
                }
                //车辆轨迹图片
                HSSFCell hssfCell9 = hssfRow.createCell(9);
                hssfCell9.setCellType(CellType.STRING);//设置表格类型
                hssfCell9.setCellStyle(style1);
                hssfCell9.setCellValue("");
                //图片
                if(null != map.get("imageUrl")){
                    try {
                        URL url = new URL(map.get("imageUrl").toString());
                        URLConnection urlConnection = url.openConnection();
                        urlConnection.connect();
                        InputStream inputStream = urlConnection.getInputStream();
                        byte[] bytes = IOUtils.toByteArray(inputStream);
                        int pictureIdx = hssfWorkbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
                        inputStream.close();
                        HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 10, i + 2, (short) 11, i + 3);
                        //在Excel中添加图片
                        HSSFPicture picture = patriarch.createPicture(anchor, pictureIdx);
                        //设置图片尺寸
                        //picture.resize(0.5, 0.18);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }else{
                    HSSFCell hssfCell10 = hssfRow.createCell(10);
                    hssfCell10.setCellType(CellType.STRING);//设置表格类型
                    hssfCell10.setCellStyle(style1);
                    hssfCell10.setCellValue("");
                }
                //系统审核
                HSSFCell hssfCell11 = hssfRow.createCell(11);
                hssfCell11.setCellType(CellType.STRING);//设置表格类型
                hssfCell11.setCellStyle(style1);
                hssfCell11.setCellValue("");
                if(null != map.get("sysStatus")){
                    //系统审核状态(1=未执行,2=正常,3=异常)
                    Integer sysStatus = Integer.valueOf(map.get("sysStatus").toString());
                    hssfCell11.setCellValue(1 == sysStatus ? "未执行" : 2 == sysStatus ? "正常" : "异常");
                }
                //系统审核时间
                HSSFCell hssfCell12 = hssfRow.createCell(12);
                hssfCell12.setCellType(CellType.STRING);//设置表格类型
                hssfCell12.setCellStyle(style1);
                hssfCell12.setCellValue("");
                if(null != map.get("sysCreateTime")){
                    hssfCell12.setCellValue(map.get("sysCreateTime").toString());
                }
                //人工审核
                HSSFCell hssfCell13 = hssfRow.createCell(13);
                hssfCell13.setCellType(CellType.STRING);//设置表格类型
                hssfCell13.setCellStyle(style1);
                hssfCell13.setCellValue("");
                if(null != map.get("artificialStatus")){
                    //人工审核状态(1=未执行,2=正常,3=异常)
                    Integer artificialStatus = Integer.valueOf(map.get("artificialStatus").toString());
                    hssfCell13.setCellValue(1 == artificialStatus ? "未执行" : 2 == artificialStatus ? "正常" : "异常");
                }
                //审核意见
                HSSFCell hssfCell14 = hssfRow.createCell(14);
                hssfCell14.setCellType(CellType.STRING);//设置表格类型
                hssfCell14.setCellStyle(style1);
                hssfCell14.setCellValue("");
                if(null != map.get("remark")){
                    hssfCell14.setCellValue(map.get("remark").toString());
                }
                //审核人
                HSSFCell hssfCell15 = hssfRow.createCell(15);
                hssfCell15.setCellType(CellType.STRING);//设置表格类型
                hssfCell15.setCellStyle(style1);
                hssfCell15.setCellValue("");
                if(null != map.get("artificialUser")){
                    hssfCell15.setCellValue(map.get("artificialUser").toString());
                }
                //审核时间
                HSSFCell hssfCell16 = hssfRow.createCell(16);
                hssfCell16.setCellType(CellType.STRING);//设置表格类型
                hssfCell16.setCellStyle(style1);
                hssfCell16.setCellValue("");
                if(null != map.get("artificialCreateTime")){
                    hssfCell16.setCellValue(map.get("artificialCreateTime").toString());
                }
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("任务记录(" + sdf.format(new Date()) + ").xls", "utf-8"));
            response.setContentType("application/vnd.ms-excel");
            ServletOutputStream out = response.getOutputStream();
            hssfWorkbook.write(out);
            out.flush();
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailVehiclesChannelServiceImpl.java
New file
@@ -0,0 +1,33 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.TaskDetailVehiclesChannelMapper;
import com.stylefeng.guns.modular.system.model.TaskDetailVehiclesChannel;
import com.stylefeng.guns.modular.system.model.vo.PictureDetails;
import com.stylefeng.guns.modular.system.service.ITaskDetailVehiclesChannelService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:35
 */
@Service
public class TaskDetailVehiclesChannelServiceImpl extends ServiceImpl<TaskDetailVehiclesChannelMapper, TaskDetailVehiclesChannel> implements ITaskDetailVehiclesChannelService {
    /**
     * 根据任务车船关系数据id获取通道数据
     * @param pageInfo
     * @param taskDetailVehiclesIdList
     * @param sysStatus
     * @param artificialStatus
     * @return
     */
    @Override
    public List<PictureDetails> getPictureDetails(Page<PictureDetails> pageInfo, List<Integer> taskDetailVehiclesIdList, Integer sysStatus, Integer artificialStatus) {
        return this.baseMapper.getPictureDetails(pageInfo, taskDetailVehiclesIdList, sysStatus, artificialStatus);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailVehiclesServiceImpl.java
New file
@@ -0,0 +1,15 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.system.dao.TaskDetailVehiclesMapper;
import com.stylefeng.guns.modular.system.model.TaskDetailVehicles;
import com.stylefeng.guns.modular.system.service.ITaskDetailVehiclesService;
import org.springframework.stereotype.Service;
/**
 * @author zhibing.pu
 * @Date 2024/12/17 20:29
 */
@Service
public class TaskDetailVehiclesServiceImpl extends ServiceImpl<TaskDetailVehiclesMapper, TaskDetailVehicles> implements ITaskDetailVehiclesService {
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/UserServiceImpl.java
New file
@@ -0,0 +1,48 @@
package com.stylefeng.guns.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.datascope.DataScope;
import com.stylefeng.guns.modular.system.dao.UserMapper;
import com.stylefeng.guns.modular.system.model.User;
import com.stylefeng.guns.modular.system.service.IUserService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 管理员表 服务实现类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Override
    public int setStatus(Integer userId, int status) {
        return this.baseMapper.setStatus(userId, status);
    }
    @Override
    public int changePwd(Integer userId, String pwd) {
        return this.baseMapper.changePwd(userId, pwd);
    }
    @Override
    public List<Map<String, Object>> selectUsers(DataScope dataScope, String name, String beginTime, String endTime, Integer deptid) {
        return this.baseMapper.selectUsers(dataScope, name, beginTime, endTime, deptid);
    }
    @Override
    public int setRoles(Integer userId, String roleIds) {
        return this.baseMapper.setRoles(userId, roleIds);
    }
    @Override
    public User getByAccount(String account) {
        return this.baseMapper.getByAccount(account);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/ManagerUser.java
New file
@@ -0,0 +1,97 @@
package com.stylefeng.guns.modular.system.transfer;
import java.util.Date;
/**
 * 管理员的信息封装
 *
 * @author fengshuonan
 * @Date 2017年1月11日 下午7:46:53
 */
public class ManagerUser {
    private String userId;
    /* 用户账号 */
    private String userNo;
    /* 用户姓名 */
    private String userName;
    private String userPhone;
    //1:超级管理员  2:管理员
    private String userRole;
    /* 1:登录状态 2:退出状态 3:停用状态 */
    private Integer userStatus;
    private Date createTime;
    private Date loginTime;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getUserNo() {
        return userNo;
    }
    public void setUserNo(String userNo) {
        this.userNo = userNo;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserPhone() {
        return userPhone;
    }
    public void setUserPhone(String userPhone) {
        this.userPhone = userPhone;
    }
    public String getUserRole() {
        return userRole;
    }
    public void setUserRole(String userRole) {
        this.userRole = userRole;
    }
    public Integer getUserStatus() {
        return userStatus;
    }
    public void setUserStatus(Integer userStatus) {
        this.userStatus = userStatus;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public Date getLoginTime() {
        return loginTime;
    }
    public void setLoginTime(Date loginTime) {
        this.loginTime = loginTime;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/ReqAddManager.java
New file
@@ -0,0 +1,76 @@
package com.stylefeng.guns.modular.system.transfer;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
/**
 * 添加管理员的请求bean
 *
 * @author fengshuonan
 * @Date 2017年1月12日 下午6:46:24
 */
public class ReqAddManager {
    // 用户姓名
    @NotNull
    private String userName;
    // 用户账号
    @NotNull
    private String userNo;
    // 手机号
    @NotNull
    @Length(min = 11, max = 11)
    private String userPhone;
    // 1:超级管理员 2:管理员
    @NotNull
    private String userRole;
    // 密码
    @NotNull
    private String userPassword;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserNo() {
        return userNo;
    }
    public void setUserNo(String userNo) {
        this.userNo = userNo;
    }
    public String getUserPhone() {
        return userPhone;
    }
    public void setUserPhone(String userPhone) {
        this.userPhone = userPhone;
    }
    public String getUserRole() {
        return userRole;
    }
    public void setUserRole(String userRole) {
        this.userRole = userRole;
    }
    public String getUserPassword() {
        return userPassword;
    }
    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/ReqEditManager.java
New file
@@ -0,0 +1,60 @@
package com.stylefeng.guns.modular.system.transfer;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
/**
 * 编辑管理员的请求
 *
 * @author fengshuonan
 * @Date 2017年1月15日 下午10:29:16
 */
public class ReqEditManager {
    @NotNull
    private String userId;
    /* 用户姓名 */
    @NotNull
    private String userName;
    private String userPassword;
    @NotNull
    @Length(min = 11, max = 11)
    private String userPhone;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserPassword() {
        return userPassword;
    }
    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }
    public String getUserPhone() {
        return userPhone;
    }
    public void setUserPhone(String userPhone) {
        this.userPhone = userPhone;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/transfer/UserDto.java
New file
@@ -0,0 +1,153 @@
package com.stylefeng.guns.modular.system.transfer;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
 * 用户传输bean
 *
 * @author stylefeng
 * @Date 2017/5/5 22:40
 */
public class UserDto{
    private Integer id;
    private String account;
    private String password;
    private String salt;
    private String name;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    private Integer sex;
    private String email;
    private String phone;
    private String roleid;
    private Integer deptid;
    private Integer status;
    private Date createtime;
    private Integer version;
    private String avatar;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getSalt() {
        return salt;
    }
    public void setSalt(String salt) {
        this.salt = salt;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public Integer getSex() {
        return sex;
    }
    public void setSex(Integer sex) {
        this.sex = sex;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getRoleid() {
        return roleid;
    }
    public void setRoleid(String roleid) {
        this.roleid = roleid;
    }
    public Integer getDeptid() {
        return deptid;
    }
    public void setDeptid(Integer deptid) {
        this.deptid = deptid;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    public String getAvatar() {
        return avatar;
    }
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/DateUtil.java
New file
@@ -0,0 +1,298 @@
package com.stylefeng.guns.modular.system.util;
import com.stylefeng.guns.core.util.ToolUtil;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
 * 日期处理工具类
 */
@Component
public class DateUtil {
    /**
     * 获取给定日期天的开始时间点或结束时间点
     * @param time  日期
     * @param type  时间点类型start一天的开始时间点,end一天的结束时间点
     * @return
     */
    public Date getStartOrEndDate(Date time, String type){
        if(ToolUtil.isEmpty(time) || ToolUtil.isEmpty(type)){
            return null;
        }
        int hourOfDay = "start".equals(type) ? 0 : 23;
        int minute = "start".equals(type) ? 0 : 59;
        int second = "start".equals(type) ? 0 : 59;
        int millisecond = "start".equals(type) ? 0 : 999;
        Calendar s = Calendar.getInstance();
        s.setTime(time);
        s.set(s.get(Calendar.YEAR), s.get(Calendar.MONTH), s.get(Calendar.DAY_OF_MONTH), hourOfDay, minute, second);
        s.set(Calendar.MILLISECOND, millisecond);
        return s.getTime();
    }
    /**
     * 获取给定日期天的起始时间和结束时间
     * @param time
     * @return
     */
    public Map<String, Date> getStartAndEndDate(Date time){
        if(ToolUtil.isEmpty(time)){
            return null;
        }
        Map<String, Date> map = new HashMap<>();
        map.put("startTime", getStartOrEndDate(time, "start"));
        map.put("endTime", getStartOrEndDate(time, "end"));
        return map;
    }
    /**
     * 获取格式化的字符串日期返回日期天的起始时间和结束时间
     * @param time  yyyy-MM-dd DD:mm:ss/yyyy-MM-dd
     * @return
     */
    public Map<String, Date> getStartAndEndDate(String time){
        if(ToolUtil.isEmpty(time)){
            return null;
        }
        int index = time.indexOf(" ");
        String pattern = "yyyy-MM-dd DD:mm:ss";
        if(index == -1){
            pattern = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        Date date = null;
        try {
            date = sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return getStartAndEndDate(date);
    }
    /**
     * 获取格式化的字符串区间日期返回区间日期天的起始时间和结束时间
     * @param time      yyyy-MM-dd DD:mm:ss - yyyy-MM-dd DD:mm:ss/yyyy-MM-dd - yyyy-MM-dd
     * @param split     区间时间的分隔符
     * @return
     */
    public List<Date> getStartAndEndDate(String time, String split){
        if(ToolUtil.isEmpty(time) || ToolUtil.isEmpty(split)){
            return null;
        }
        List<Date> list = new ArrayList<>();
        String[] split1 = time.split(split);
        int index = split1[0].indexOf(" ");
        String pattern = "yyyy-MM-dd DD:mm:ss";
        if(index == -1){
            pattern = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        Date date1 = null;
        Date date2 = null;
        try {
            date1 = sdf.parse(split1[0]);
            date2 = sdf.parse(split1[1]);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        list.add(getStartOrEndDate(date1, "start"));
        list.add(getStartOrEndDate(date2, "end"));
        return list;
    }
    /**
     * 获取月初和月末日期
     * @param date
     * @return
     */
    public Map<String, Date> getMonthStartAndEnd(Date date){
        Calendar s = Calendar.getInstance();
        s.setTime(date);
        s.set(Calendar.DAY_OF_MONTH, 1);
        Calendar e = Calendar.getInstance();
        e.setTime(date);
        e.set(Calendar.DAY_OF_MONTH, e.getActualMaximum(Calendar.DAY_OF_MONTH));
        Date start = this.getStartOrEndDate(s.getTime(), "start");
        Date end = this.getStartOrEndDate(e.getTime(), "end");
        Map<String, Date> map = new HashMap<>();
        map.put("startTime", start);
        map.put("endTime", end);
        return map;
    }
    /**
     * 多语言时间日期格式转换
     * @param language  语言编号
     * @param datetime      标准格式化时间 yyyy-MM-dd
     * @return
     */
    public static String conversionFormat(Integer language, String datetime){
        String time = "";
        String date = datetime;
        int index = datetime.indexOf(" ");
        if(index != -1){
            time = datetime.substring(datetime.indexOf(" ") + 1);
            date = datetime.substring(0, datetime.indexOf(" "));
        }
        String[] split = date.split("-");
        switch (language){
            case 2:
                split[1] = englishMonth(Integer.valueOf(split[1]));
                datetime = split[1] + " " + split[2] + ", " + split[0];
                if(index != -1){
                    datetime += " " + time;
                }
                break;
            case 3:
                split[1] = frenchMonth(Integer.valueOf(split[1]));
                datetime = split[2] + " " + split[1] + " " + split[0];
                if(index != -1){
                    datetime += " " + time;
                }
                break;
        }
        return datetime;
    }
    public static String conversionFormat1(Integer language, String datetime){
        String time = "";
        String date = datetime;
        int index = datetime.indexOf(" ");
        if(index != -1){
            time = datetime.substring(datetime.indexOf(" ") + 1);
            date = datetime.substring(0, datetime.indexOf(" "));
        }
        String[] split = date.split("-");
        //'%m-%d %H:%i'
        String m = "";
        switch (language){
            case 2:
                m = englishMonth(Integer.valueOf(split[0]));
                datetime = m + " " + split[1];
                if(index != -1){
                    datetime += " " + time;
                }
                break;
            case 3:
                m = frenchMonth(Integer.valueOf(split[0]));
                datetime = split[1] + " " + m;
                if(index != -1){
                    datetime += " " + time;
                }
                break;
        }
        return datetime;
    }
    public static String frenchMonth(Integer month){
        String m = "";
        switch (month){
            case 1:
                m = "Janvier";
                break;
            case 2:
                m = "Février";
                break;
            case 3:
                m = "Mars";
                break;
            case 4:
                m = "Avril";
                break;
            case 5:
                m = "Mai";
                break;
            case 6:
                m = "Juin";
                break;
            case 7:
                m = "Juillet";
                break;
            case 8:
                m = "Août";
                break;
            case 9:
                m = "Septembre";
                break;
            case 10:
                m = "Octobre";
                break;
            case 11:
                m = "Novembre";
                break;
            case 12:
                m = "Décembre";
                break;
            default:
                m = "";
                break;
        }
        return m;
    }
    public static String englishMonth(Integer month){
        String m = "";
        switch (month){
            case 1:
                m = "January";
                break;
            case 2:
                m = "February";
                break;
            case 3:
                m = "March";
                break;
            case 4:
                m = "April";
                break;
            case 5:
                m = "May";
                break;
            case 6:
                m = "June";
                break;
            case 7:
                m = "July";
                break;
            case 8:
                m = "August";
                break;
            case 9:
                m = "September";
                break;
            case 10:
                m = "October";
                break;
            case 11:
                m = "November";
                break;
            case 12:
                m = "December";
                break;
            default:
                m = "";
                break;
        }
        return m;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/ExcelUtil.java
New file
@@ -0,0 +1,206 @@
package com.stylefeng.guns.modular.system.util;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 定义Excel工具类
 */
@Component
public class ExcelUtil {
    public List<List<List<String>>> upload(MultipartFile file){
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取文件名
        String fileName=file.getOriginalFilename();
        List<List<List<String>>> list = null;
        if(validateExcel(fileName)) {
            // 根据版本选择创建Workbook的方式
            Workbook wb = null;
            // 根据文件名判断文件是2003版本还是2007版本
            if (isExcel2007(fileName)) {
                try {
                    wb = new XSSFWorkbook(inputStream);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else {
                try {
                    wb = new HSSFWorkbook(inputStream);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            int num = wb.getNumberOfSheets();//获取页数
            list = new ArrayList<>();
            for (int i = 0; i < num; i++) {
                List<List<String>> sheetList = new ArrayList<>();
                //获取每一页对象
                Sheet sheet = wb.getSheetAt(i);
                // 得到Excel的行数
                int totalRows = sheet.getPhysicalNumberOfRows();
                for (int j = 0; j < totalRows; j++) {
                    if (j == 0) {
                        continue;// 标题行
                    }
                    Row row = sheet.getRow(j);// 获取索引为i的行数据
                    if(null == row){
                        continue;
                    }
                    int index = sheet.getRow(0).getPhysicalNumberOfCells();//获取标题的列数用于遍历
                    List<String> strings = new ArrayList<>();
                    int in = 0;//用于遍历单元格判断该行是否全为空值
                    for (int k = 0; k < index; k++) {//遍历获取每个单元格的数据
                        String str = null;
                        Cell cell = row.getCell(k);
                        if(cell == null) {
                            str = "";
                            in++;
                        }else {
                            switch (cell.getCellType()) {//判断数据类型取值
                                case NUMERIC :
                                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                                        Date theDate = cell.getDateCellValue();
                                        str = String.valueOf(theDate.getTime());
                                    }else{
                                        String string = String.valueOf(cell.getNumericCellValue());
                                        str = string.substring(0, string.indexOf("."));
                                    }
                                    break;
                                case STRING :
                                    str = cell.getStringCellValue();
                                    if(str == null) {
                                        str = "";
                                        in++;
                                    }
                                    break;
                                case _NONE :
                                    System.err.println("_NONE");
                                    break;
                                case FORMULA :
                                    System.err.println("FORMULA");
                                    break;
                                case BLANK :
                                    str = cell.getStringCellValue();
                                    if("".equals(str)) {
                                        str = "";
                                        in++;
                                    }
                                    break;
                                case BOOLEAN :
                                    System.err.println("BOOLEAN");
                                    break;
                                case ERROR :
                                    System.err.println("ERROR");
                                    break;
                                default:
                                    break;
                            }
                        }
                        strings.add(String.valueOf(str).trim());
                    }
                    if(in != index) {//判断如果每个单元格都为null则不需要添加到集合中
                        sheetList.add(strings);
                    }
                }
                list.add(sheetList);
            }
        }
        return list;
    }
    // @描述:是否是2003的excel,返回true是2003
    public static boolean isExcel2003(String filePath)  {
        return filePath.matches("^.+\\.(?i)(xls)$");
    }
    //@描述:是否是2007的excel,返回true是2007
    public static boolean isExcel2007(String filePath)  {
        return filePath.matches("^.+\\.(?i)(xlsx)$");
    }
    /**
     * 验证EXCEL文件
     * @param filePath
     * @return
     */
    public static boolean validateExcel(String filePath){
        if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))){
            return false;
        }
        return true;
    }
    /**
     * 将数据写入Excel中
     * @param titles    标题
     * @param datas     数据
     * @return
     */
    public HSSFWorkbook writeDataToExcel(List<List<String>> titles, List<List<List<String>>> datas) {
        HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
        for(int i = 0; i < titles.size(); i++){
            HSSFSheet hssfSheet = hssfWorkbook.createSheet();
            hssfSheet.setColumnWidth(0, 6 * 256);
            hssfSheet.setDefaultRowHeightInPoints(20f);
            HSSFRow hssfRow = hssfSheet.createRow(0);//设置第一行数据(标题)
            HSSFCellStyle style = hssfWorkbook.createCellStyle();
            HSSFFont font = hssfWorkbook.createFont();
            font.setBold(true);
            style.setFont(font);
            style.setAlignment(HorizontalAlignment.CENTER);
            for (int l = 0; l < titles.get(i).size(); l++) {
                HSSFCell hssfCell = hssfRow.createCell(l);
                hssfCell.setCellType(CellType.STRING);//设置表格类型
                hssfCell.setCellValue(titles.get(i).get(l));
                hssfCell.setCellStyle(style);
                if(l > 0) {
                    hssfSheet.setColumnWidth(l , 20 * 256);
                }
            }
            //将数据添加到表格中
            List<String> data = null;
            for (int l = 0; l < datas.get(i).size(); l++) {
                hssfRow = hssfSheet.createRow(l + 1);
                data = datas.get(i).get(l);
                for (int j = 0; j < data.size(); j++) {
                    HSSFCell hssfCell = hssfRow.createCell(j);
                    hssfCell.setCellType(CellType.STRING);//设置表格类型
                    hssfCell.setCellValue(data.get(j));
                }
            }
        }
        return hssfWorkbook;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/MD5AndKL.java
New file
@@ -0,0 +1,123 @@
package com.stylefeng.guns.modular.system.util;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.core.shiro.ShiroKit;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
public class MD5AndKL {
    /**
     * MD5加码。32位
     *
     * @param inStr
     * @return
     */
    public static String MD5(String inStr) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }
        byte[] md5Bytes = md5.digest(inStr.getBytes());
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }
    /**
     * 可逆的加密算法
     *
     * @param inStr
     * @return
     */
    public static String KL(String inStr) {
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String s = new String(a);
        return s;
    }
    /**
     * 加密后解密
     *
     * @param inStr
     * @return
     */
    public static String JM(String inStr) {
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String k = new String(a);
        return k;
    }
    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));
        return resultSb.toString();
    }
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }
    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)){
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return resultString;
    }
    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    public static void main(String args[]) {
        System.out.println("MD5后再加密:" + KL(MD5("123456")));
        System.out.println(MD5("123456"));
        // System.out.println("加密:" + KL(MD5("123456")));
        // s = KL(s);
        // System.out.println("解密:" + KL("81dc9bdb52d04dc20036dbd8313ed055"));
        // System.out.println("解密:" + JM(KL(s)));
        // System.out.println("解密为MD5后的:" + KL(KL(MD5(s))));
        // System.out.println(JM("5d62957bb57d3e49dcf48a0df064be4c"));
        // System.out.println(MD5AndKL.KL(MD5AndKL.MD5("admin"+"87654321")));
        System.out.println(ShiroKit.md5("111111", "SA;d5#"));
        Map<String, String> map = new HashMap<>();
        map.put("orderString","alipay_sdk=alipay-sdk-java-4.8.10.ALL&app_id=2019080866147541&biz_content=%7B%22body%22%3A%22%E6%94%B9%E6%B4%BE%E8%AE%A2%E5%8D%95%22%2C%22out_trade_no%22%3A%227_1%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22subject%22%3A%22%E6%94%B9%E6%B4%BE%E8%AE%A2%E5%8D%95%22%2C%22timeout_express%22%3A%2230m%22%2C%22total_amount%22%3A%220.01%22%7D&charset=UTF-8&format=json&method=alipay.trade.app.pay&notify_url=http%3A%2F%2F47.107.98.201%3A8007%2Fbase%2FaliReassign&sign=GSn1vEUQuUmmsyLMkx78IIdOB2VK08eE%2FB%2FrdZNt6FzWP%2FCf22tlYKVoaJTsPh4rp3A2tKQ9o9KZNIt3MB2IEL9wp6n63theHzTUcGTr4YFzgtvOUtxGEX2%2F195%2Fwo1rrhHy9NbW0WQCEnS87VLSzQYGPS%2FXrxbqfNgtEAkI%2FtKKiBs%2B7RsFLbfZLkh5jPUblRXQ94unfbxaIC2tp60JgLEq1l6XUCPjQ0MPJqPx8SBpeUB%2BoDDc38s%2FxdmqcnmEhwVyI5WbNh7zPYLutbojQQdzEBINPyYLFLWCn8w1G6HCnu1j%2F20eRLyB8Etdr%2FWAZ%2FUGywsYRPFHfGi9TqG6QA%3D%3D&sign_type=RSA2&timestamp=2020-12-25+21%3A16%3A32&version=1.0");
        System.out.println(map);//就是orderString 可以直接给客户端请求,无需再做处理。
        ResultUtil resultUtil = ResultUtil.success(map);
        System.out.println(resultUtil.getCode()==200);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/ResultUtil.java
New file
@@ -0,0 +1,188 @@
package com.stylefeng.guns.modular.system.util;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
 * 定义统一返回对象
 */
@ApiModel(value = "统一返回结果集")
public class ResultUtil<T> {
    public static final Integer SUCCESS = 200;
    public static final Integer PARAM_ERROR = 300;
    public static final Integer RUNTIME_ERROR = 400;
    public static final Integer ERROR = 500;
    public static final Integer TOKEN_ERROR = 600;
    public static final Integer SIGN_ERROR = 700;
    public static final String Token = "TOKEN_INVALID";
    public static final String SIGN = "SIGN_INVALID";
    @ApiModelProperty(name = "code", value = "业务状态码 200:成功,300:参数错误,400:运行异常,500:其他异常, 600:token无效,需重新登录,700:签名无效")
    private Integer code;//备用状态码
    @ApiModelProperty(name = "msg", value = "返回结果说明")
    private String msg;//返回说明
    @ApiModelProperty(name = "data", value = "返回结果值")
    private T data;//返回数据
    public String getMsg() {
        return msg;
    }
    public T getData() {
        return data;
    }
    public Integer getCode() {
        return code;
    }
    private ResultUtil(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private ResultUtil(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static <T> ResultUtil<T> getResult(Integer code, String msg){
        return new ResultUtil<>(code, msg);
    }
    public static <T> ResultUtil<T> getResult(Integer code, String msg, T data){
        return new ResultUtil<>(code, msg, data);
    }
    /**
     * 错误信息
     * @return
     */
    public static ResultUtil error(String mag){
        return ResultUtil.getResult(ResultUtil.ERROR, mag, new JSONObject());
    }
    /**
     * 错误信息
     * @return
     */
    public static <T> ResultUtil<T> error(String mag, T obj){
        return ResultUtil.getResult(ResultUtil.ERROR, mag, obj);
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, ResultUtil.Token, new JSONObject());
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(String msg){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, msg, new JSONObject());
    }
    /**
     * 参数异常
     * @return
     */
    public static ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "PARAM_ERROR", new JSONObject());
    }
    /**
     * 参数异常
     * @return
     */
    public static <T> ResultUtil<T> paranErr(T data){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "SYSTEM_RUN_ERROR", data);
    }
    /**
     * 运行异常
     * @return
     */
    public static ResultUtil runErr(){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, "SYSTEM_RUN_ERROR", new JSONObject());
    }
    /**
     * 运行异常
     * @return
     */
    public static <T> ResultUtil<T> runErr(T data){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, "SYSTEM_RUN_ERROR", data);
    }
    /**
     * 运行异常
     * @return
     */
    public static <T> ResultUtil<T> runErr(T data, String msg){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, msg, data);
    }
    /**
     * 返回成功
     * @param
     * @return
     */
    public static ResultUtil success(){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "SUCCESS", new JSONObject());
    }
    /**
     * 返回成功
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "SUCCESS", data);
    }
    /**
     * 返回成功
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(String msg, T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, msg, data);
    }
    /**
     * 签名无效
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> sign(){
        return ResultUtil.getResult(ResultUtil.SIGN_ERROR, SIGN);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/SpringUtils.java
New file
@@ -0,0 +1,173 @@
package com.stylefeng.guns.modular.system.util;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
 * spring工具类 方便在非spring管理环境中获取bean
 *
 * @author ruoyi
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
    /** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;
    private static ApplicationContext applicationContext;
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        SpringUtils.beanFactory = beanFactory;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        SpringUtils.applicationContext = applicationContext;
    }
    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }
    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }
    /**
     * 在系统上下文中获取注入IOC的对象
     * @param clz
     * @return
     * @param <T>
     * @throws BeansException
     */
    public static <T> T getApplicationContextBean(Class<T> clz) throws BeansException
    {
        return applicationContext.getBean(clz);
    }
    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }
    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }
    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }
    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }
    /**
     * 获取aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker)
    {
        return (T) AopContext.currentProxy();
    }
    /**
     * 获取当前的环境配置,无配置返回null
     *
     * @return 当前的环境配置
     */
    public static String[] getActiveProfiles()
    {
        return applicationContext.getEnvironment().getActiveProfiles();
    }
    /**
     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
     *
     * @return 当前的环境配置
     */
    public static String getActiveProfile()
    {
        final String[] activeProfiles = getActiveProfiles();
        return null != activeProfiles && activeProfiles.length > 0 ? activeProfiles[0] : null;
    }
    /**
     * 获取配置文件中的值
     *
     * @param key 配置文件的key
     * @return 当前的配置文件的值
     *
     */
    public static String getRequiredProperty(String key)
    {
        return applicationContext.getEnvironment().getRequiredProperty(key);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/SystemException.java
New file
@@ -0,0 +1,18 @@
package com.stylefeng.guns.modular.system.util;
public class SystemException extends Exception {
    private String msg;
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public SystemException(String msg){
        super(msg);
        this.setMsg(msg);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/UUIDUtil.java
New file
@@ -0,0 +1,78 @@
package com.stylefeng.guns.modular.system.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
 * 定义生成随机码的工具类
 */
public class UUIDUtil {
    private int i = 1;
    /**
     * 定义生成原生的UUID随机码
     * @return
     */
    public static String getNativeUUID(){
        return UUID.randomUUID().toString();
    }
    /**
     * 生成32位随机码
     * @return
     */
    public static String getRandomCode(){
        return UUIDUtil.getNativeUUID().replaceAll("-", "");
    }
    /**
     * 获取给定长度的随机码
     * @param num
     * @return
     * @throws Exception
     */
    public static String getRandomCode(Integer num) throws Exception{
        String str = null;
        if(0 < num){
            if(num % 32 > 0){
                Integer s = num / 32;
                Integer l = num % 32;
                StringBuffer sb = new StringBuffer();
                for(int i = 0; i < s; i++){
                    sb.append(UUIDUtil.getRandomCode());
                }
                sb.append(UUIDUtil.getRandomCode().substring(0, l));
                str = sb.toString();
            }else if(num % 32 == 0){
                Integer s = num / 32;
                StringBuffer sb = new StringBuffer();
                for(int i = 0; i < s; i++){
                    sb.append(UUIDUtil.getRandomCode());
                }
                str = sb.toString();
            }else{
                str = UUIDUtil.getRandomCode().substring(0, num);
            }
        }else{
            throw new Exception("参数只能大于0");
        }
        return str;
    }
    /**
     * 获取根据当前时间的字符串数据
     * @return
     */
    public synchronized static String getTimeStr(){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmssS");
        return simpleDateFormat.format(new Date());
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/imageModel/ImageModelUtil.java
New file
@@ -0,0 +1,204 @@
package com.stylefeng.guns.modular.system.util.imageModel;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.modular.system.model.enums.ImageModelEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/12/20 15:48
 */
@Slf4j
public class ImageModelUtil {
    /**
     * 本地存储图片地址
     */
    @Value("${filePath}")
    private static String filePath;
    /**
     * 顶盖密闭模型
     * @param url  图片网络地址
     */
    private static List<String> closedTopModel(String url){
        try {
            URLConnection urlConnection = new URL(url).openConnection();
            urlConnection.connect();
            InputStream inputStream = urlConnection.getInputStream();
            File file = FileUtil.writeFromStream(inputStream, filePath);
            inputStream.close();
            return closedTopModel(file);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 顶盖密闭模型
     * @param file  图片文件
     */
    private static List<String> closedTopModel(File file){
        HttpRequest post = HttpUtil.createPost("http://120.232.235.142:5000/predict");
        post.form("file", file);
        HttpResponse execute = post.execute();
        int status = execute.getStatus();
        if(200 != status){
            log.error("顶盖密闭模型调用失败:" + execute.body());
            return null;
        }
        JSONObject result = JSON.parseObject(execute.body());
        JSONArray predicted_labels = result.getJSONArray("predicted_labels");
        List<String> list = new ArrayList<>();
        for (int i = 0; i < predicted_labels.size(); i++) {
            list.add(predicted_labels.getString(i));
        }
        return list;
    }
    /**
     * 摄像头故障模型
     * @param url 图片网络地址
     * @return
     */
    private static List<String> cameraFaultModel(String url){
        try {
            URLConnection urlConnection = new URL(url).openConnection();
            urlConnection.connect();
            InputStream inputStream = urlConnection.getInputStream();
            File file = FileUtil.writeFromStream(inputStream, filePath);
            inputStream.close();
            return cameraFaultModel(file);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 摄像头故障模型
     * @param file  图片文件
     * @return
     */
    private static List<String> cameraFaultModel(File file){
        HttpRequest post = HttpUtil.createPost("http://120.232.235.142:4000/predict");
        post.form("file", file);
        HttpResponse execute = post.execute();
        int status = execute.getStatus();
        if(200 != status){
            log.error("摄像头故障模型调用失败:" + execute.body());
            return null;
        }
        JSONObject result = JSON.parseObject(execute.body());
        String predicted_labels = result.getString("predicted_label");
        List<String> list = new ArrayList<>();
        list.add(predicted_labels);
        return list;
    }
    /**
     * 建筑垃圾装载模型
     * @param url 图片网络地址
     * @return
     */
    private static List<String> constructionWasteLoadModel(String url){
        try {
            URLConnection urlConnection = new URL(url).openConnection();
            urlConnection.connect();
            InputStream inputStream = urlConnection.getInputStream();
            File file = FileUtil.writeFromStream(inputStream, filePath);
            inputStream.close();
            return constructionWasteLoadModel(file);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 建筑垃圾装载模型
     * @param file  图片文件
     * @return
     */
    private static List<String> constructionWasteLoadModel(File file){
        HttpRequest post = HttpUtil.createPost("http://120.232.235.142:");
        post.form("file", file);
        HttpResponse execute = post.execute();
        int status = execute.getStatus();
        if(200 != status){
            log.error("建筑垃圾装载模型调用失败:" + execute.body());
            return null;
        }
        JSONObject result = JSON.parseObject(execute.body());
        String predicted_labels = result.getString("predicted_label");
        List<String> list = new ArrayList<>();
        list.add(predicted_labels);
        return list;
    }
    /**
     * 1号模型四类标签分别是
     * Loaded Cargo - Unsealed装载-未关闭
     * Empty Container - Sealed 空载-关闭
     * Empty Container - Unsealed空载-未关闭
     * Loaded Cargo - Sealed-装载-关闭
     * 2号模型四类分别是:'blurred'(模糊), 'no_video'(无视频),'normalcy'(正常), 'splash_screen(花屏)'
     * @param url
     * @param modelEnum
     * @return
     */
    public static boolean modelCheck(String url, ImageModelEnum modelEnum){
        switch (modelEnum){
            case TOP_SEAL:
                List<String> list1 = closedTopModel(url);
                //其中包含装载未关闭,视为异常
                return !list1.contains("Loaded Cargo - Unsealed");
            case CAMERA_FAULT:
                List<String> list2 = cameraFaultModel(url);
                //其中包含正常,视为正常
                return list2.contains("normalcy");
            case CONSTRUCTION_WASTE_LOAD: // TODO 待完善
                List<String> list3 = constructionWasteLoadModel(url);
                //其中包含正常,视为正常
                return list3.contains("normalcy");
        }
        return false;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/quartz/QuartzUtil.java
New file
@@ -0,0 +1,248 @@
package com.stylefeng.guns.modular.system.util.quartz;
import com.stylefeng.guns.modular.system.util.quartz.model.QuartzEnum;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * quartz任务调度工具类
 * @author zhibing.pu
 * @Date 2024/3/20 11:12
 */
@Slf4j
@Component
public class QuartzUtil {
    @Autowired
    private Scheduler scheduler;
    /**
     * 添加普通定时任务
     * @param startTime 任务开始执行时间,为空则立即执行
     * @param intervalInMilliseconds 执行间隔毫秒数
     * @param repeatCount 重复执行次数,-1表示永远执行
     * @throws SchedulerException
     */
    public void addSimpleQuartzTask(Class<? extends Job> clazz, String job_name, String group_name, JobDataMap jobDataMap, Date startTime, long intervalInMilliseconds, int repeatCount) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job_name, group_name);
        if(scheduler.checkExists(jobKey)){
            log.error("[添加定时任务]已存在该作业,jobkey为:{}", jobKey);
            return;
        }
        // 构建 Job
        JobDetail job = JobBuilder.newJob(clazz)
                .setJobData(jobDataMap)
                .withIdentity(jobKey).build();
        // 构建 Trigger
        Trigger trigger = getSimpleTrigger(job_name, group_name, startTime, intervalInMilliseconds, repeatCount);
        // 启动调度器
        scheduler.scheduleJob(job, trigger);
        scheduler.start();
    }
    /**
     * 添加Cron表达式的定时任务
     * @param cron cron表达式
     * @throws SchedulerException
     */
    public void addCronQuartzTask(Class<? extends Job> clazz, String job_name, String group_name, JobDataMap jobDataMap, String cron) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(job_name, group_name);
        if(scheduler.checkExists(jobKey)){
            log.error("[添加定时任务]已存在该作业,jobkey为:{}", jobKey);
            return;
        }
        // 构建 Job
        JobDetail job = JobBuilder.newJob(clazz)
                .setJobData(jobDataMap)
                .withIdentity(jobKey).build();
        // 构建 Trigger
        Trigger trigger = getCronTrigger(job_name, group_name, cron);
        // 启动调度器
        scheduler.scheduleJob(job, trigger);
        scheduler.start();
    }
    /**
     * 删除任务
     * @param name 任务名称
     * @param group 任务分组
     * @return
     */
    public boolean deleteQuartzTask(String name, String group){
        JobKey jobKey = new JobKey(name, group);
        boolean b = false;
        try {
            b = scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
        return b;
    }
    /**
     * 删除任务
     * @param jobKey
     * @return
     */
    public boolean deleteQuartzTask(JobKey jobKey){
        boolean b = false;
        try {
            b = scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
        return b;
    }
    /**
     * 删除分组下的所有定时任务
     * @param group 分组名称
     * @return
     */
    public boolean deleteGroupQuartzTask(String group){
        try {
            GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(group);
            Set<JobKey> jobKeys = scheduler.getJobKeys(groupMatcher);
            boolean b = scheduler.deleteJobs(jobKeys.stream().collect(Collectors.toList()));
            if(!b){
                return false;
            }
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 清空所有定时任务
     * @return
     */
    public boolean deleteAllQuartzTask(){
        try {
            List<String> jobGroupNames = scheduler.getJobGroupNames();
            for (String jobGroupName : jobGroupNames) {
                GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(jobGroupName);
                Set<JobKey> jobKeys = scheduler.getJobKeys(groupMatcher);
                boolean b = scheduler.deleteJobs(jobKeys.stream().collect(Collectors.toList()));
                if(!b){
                    return false;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 构建任务描述JobDetail对象
     * @return
     */
    private JobDetail getJobDetail(Job job, String job_name, String group_name){
        if(null == job_name || "".equals(job_name)){
            job_name = QuartzEnum.JOB_NAME.getValue();
        }
        if(null == group_name || "".equals(group_name)){
            group_name = QuartzEnum.DEFAULT_GROUP.getValue();
        }
        return getJobDetail(job, job_name, group_name, null);
    }
    /**
     * 构建任务描述JobDetail对象
     * @param job 任务类
     * @param job_name 任务名称
     * @param group_name 任务分组名称
     * @param jobDataMap 自定义参数
     * @return
     */
    private JobDetail getJobDetail(Job job, String job_name, String group_name, JobDataMap jobDataMap){
        JobDetail jobDetail = JobBuilder.newJob(job.getClass())
                .withIdentity(job_name, group_name)
                .setJobData(jobDataMap)
                .build();
        return jobDetail;
    }
    /**
     * 构建Trigger执行器
     * @param startTime 任务开始执行时间,为空则立即执行
     * @param intervalInMilliseconds 执行间隔毫秒数
     * @param repeatCount 重读执行次数,-1表示永远执行
     * @return
     */
    private static Trigger getSimpleTrigger(String job_name, String group_name, Date startTime, long intervalInMilliseconds, int repeatCount){
        if(null == job_name || "".equals(job_name)){
            job_name = QuartzEnum.JOB_NAME.getValue();
        }
        if(null == group_name || "".equals(group_name)){
            group_name = QuartzEnum.DEFAULT_GROUP.getValue();
        }
        TriggerBuilder<Trigger> triggerTriggerBuilder = TriggerBuilder.newTrigger();
        if(null == startTime){
            triggerTriggerBuilder.startNow();
        }else{
            triggerTriggerBuilder.startAt(startTime);
        }
        SimpleTrigger trigger = triggerTriggerBuilder
                .withIdentity(job_name, group_name)
                .withSchedule(
                        SimpleScheduleBuilder
                                .simpleSchedule()
                                .withIntervalInMilliseconds(intervalInMilliseconds)
                                .withRepeatCount(repeatCount)
                ).build();
        return trigger;
    }
    /**
     * 构建cronExpression表达式执行器
     * @param cron cron表达式
     * @return
     */
    private static Trigger getCronTrigger(String job_name, String group_name, String cron) {
        if(null == job_name || "".equals(job_name)){
            job_name = QuartzEnum.JOB_NAME.getValue();
        }
        if(null == group_name || "".equals(group_name)){
            group_name = QuartzEnum.DEFAULT_GROUP.getValue();
        }
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .startNow()
                .withIdentity(job_name, group_name)
                .withSchedule(
                        CronScheduleBuilder.cronSchedule(cron)
                ).build();
        return trigger;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/quartz/jobs/PatrolTaskJob.java
New file
@@ -0,0 +1,49 @@
package com.stylefeng.guns.modular.system.util.quartz.jobs;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.service.IPatrolTaskService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * 订单司机超时提醒任务
 * @author zhibing.pu
 * @Date 2024/4/18 15:19
 */
@Slf4j
public class PatrolTaskJob implements Job {
    @Autowired
    private IPatrolTaskService patrolTaskService;
    /**
     * 执行的业务逻辑
     * @param jobExecutionContext 定时任务上下文对象
     */
    public void run(JobExecutionContext jobExecutionContext) {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        String name = jobDetail.getKey().getName();
        log.info("执行【{}】定时任务 JobDataMap:{}", name, JSON.toJSONString(jobDataMap));
        Integer id = jobDataMap.getIntValue("id");
        patrolTaskService.execute(id);
    }
    @Override
    public void execute(JobExecutionContext jobExecutionContext){
        run(jobExecutionContext);
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/quartz/model/QuartzEnum.java
New file
@@ -0,0 +1,46 @@
package com.stylefeng.guns.modular.system.util.quartz.model;
/**
 *
 * quartz枚举常量
 * @author zhibing.pu
 * @Date 2024/3/20 11:20
 */
public enum QuartzEnum {
    /**
     * 任务名称
     */
    JOB_NAME("quartz_job"),
    /**
     * 任务分组
     */
    DEFAULT_GROUP("quartz_group"),
    /**
     * quartz任务调度器启动成功
     */
    SCHEDULER_START_SUCCESS("Quartz Scheduler start success!"),
    /**
     * 任务添加到调度器成功
     */
    ADD_SIMPLE_TRIGGER_SUCCESS("add Quartz SimpleTrigger success!"),
    /**
     * 任务添加到调度器成功
     */
    ADD_CRON_TRIGGER_SUCCESS("add Quartz CronTrigger success!")
    ;
    QuartzEnum(String value) {
        this.value = value;
    }
    private String value;
    public String getValue() {
        return value;
    }
    private void setValue(String value) {
        this.value = value;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/VideoGateway.java
New file
@@ -0,0 +1,518 @@
package com.stylefeng.guns.modular.system.util.videoGateway;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.stylefeng.guns.modular.system.util.videoGateway.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 视频网关工具类型
 * @author zhibing.pu
 * @Date 2024/12/18 19:32
 */
@Slf4j
public class VideoGateway {
    private static AccountLogin accountLogin;
    /**
     * 获取 SessionId
     * @return
     */
    public static SessionId getSessionId(){
        HttpRequest get = HttpUtil.createGet("https://zhyn.cg.gz.gov.cn/api/cws-auth/v1/session-id/third-platform");
        get.header("operate-terminal", "4");
        log.info("请求参数:" + get);
        HttpResponse execute = get.execute();
        String body = execute.body();
        log.info("返回结果:" + body);
        JSONObject result = JSON.parseObject(body);
        Integer code = result.getInteger("code");
        if(-1 == code){
            log.error(result.getString("msg"));
            return null;
        }
        SessionId sessionId = result.getObject("data", SessionId.class);
        SM4 sm4 = SmUtil.sm4("EP77VsBj9yeOKpcO".getBytes());
        String decryptStr = sm4.decryptStr(sessionId.getPublicKey(), CharsetUtil.CHARSET_UTF_8);
        sessionId.setKey(decryptStr);
        return sessionId;
    }
    /**
     * 登录
     */
    public static void accountLogin(){
        SessionId sessionId = getSessionId();
        if(null == sessionId){
            throw new RuntimeException("获取sessionId失败");
        }
        HttpRequest post = HttpUtil.createPost("https://zhyn.cg.gz.gov.cn/api/cws-auth/v1/account-login/applet/third-platform");
        post.header("operate-terminal", "4");
        Map<String, Object> body = new HashMap<>();
        body.put("account", "UgRn8RGM1Z9k");
        SM4 sm4 = SmUtil.sm4(sessionId.getKey().getBytes());
        String encryptHex = sm4.encryptHex("Lti52D@#&J6q");
        body.put("pwd", encryptHex);
        body.put("sessionId", sessionId.getSessionId());
        log.info("请求参数:" + JSON.toJSONString(body) + "\npublicKey:" + sessionId.getPublicKey() + "\n加密key:" + sessionId.getKey());
        post.body(JSON.toJSONString(body));
        HttpResponse execute = post.execute();
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return;
        }
        accountLogin = result.getObject("data", AccountLogin.class);
    }
    /**
     * 获取车辆列表数据
     * @param vehicleNum    车牌号
     * @param companyId     公司id
     * @param companyName   公司名称
     * @return
     */
    public static List<Vehicle> getVehicleList(String vehicleNum, String companyId, String companyName, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest post = HttpUtil.createPost("https://zhyn.cg.gz.gov.cn/api/cws-user/biz-vehicle-infos/v1/smallDataList");
        post.header("operate-terminal", "4");
        post.header("token", accountLogin.getToken());
        Map<String, Object> body = new HashMap<>();
        if(StringUtils.isNotEmpty(vehicleNum)){
            body.put("vehicleNum", vehicleNum);
        }
        if(StringUtils.isNotEmpty(companyId)){
            body.put("companyId", companyId);
        }
        if(StringUtils.isNotEmpty(companyName)){
            body.put("companyName", companyName);
        }
        log.info("请求参数:" + JSON.toJSONString(body));
        post.body(JSON.toJSONString(body));
        HttpResponse execute = post.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            accountLogin = null;
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            return getVehicleList(vehicleNum, companyId, companyName, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        List<Vehicle> list = new ArrayList();
        JSONArray data = result.getJSONArray("data");
        for (int i = 0; i < data.size(); i++) {
            Vehicle object = data.getObject(i, Vehicle.class);
            list.add(object);
        }
        return list;
    }
    /**
     * 获取船舶列表
     * @param shipNum       船舶号
     * @param companyId     公司id
     * @param companyName   公司名称
     * @return
     */
    public static List<Ship> getShipList(String shipNum, String companyId, String companyName, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest post = HttpUtil.createPost("https://zhyn.cg.gz.gov.cn/api/cws-user/biz-ship-infos/v1/smallDataList");
        post.header("operate-terminal", "4");
        post.header("token", accountLogin.getToken());
        Map<String, Object> body = new HashMap<>();
        if(StringUtils.isNotEmpty(shipNum)){
            body.put("shipNum", shipNum);
        }
        if(StringUtils.isNotEmpty(companyId)){
            body.put("companyId", companyId);
        }
        if(StringUtils.isNotEmpty(companyName)){
            body.put("companyName", companyName);
        }
        log.info("请求参数:" + JSON.toJSONString(body));
        post.body(JSON.toJSONString(body));
        HttpResponse execute = post.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return getShipList(shipNum, companyId, companyName, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        List<Ship> list = new ArrayList();
        JSONArray data = result.getJSONArray("data");
        for (int i = 0; i < data.size(); i++) {
            Ship object = data.getObject(i, Ship.class);
            list.add(object);
        }
        return list;
    }
    /**
     * 2018年协议车辆在线状态接口
     * @return
     */
    public static List<VehicleOnline> queryRuntimeInfoByCache(int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest post = HttpUtil.createPost("https://zhyn.cg.gz.gov.cn/map/web/map/queryRuntimeInfoByCache");
        post.header("operate-terminal", "4");
        post.header("token", accountLogin.getToken());
        post.body("{}");
        HttpResponse execute = post.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return queryRuntimeInfoByCache(num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        List<VehicleOnline> list = new ArrayList();
        JSONArray data = result.getJSONArray("data");
        for (int i = 0; i < data.size(); i++) {
            VehicleOnline object = data.getObject(i, VehicleOnline.class);
            list.add(object);
        }
        return list;
    }
    /**
     * 2023年协议车辆在线状态接口
     * @return
     */
    public static List<VehicleOnline> locationRealTimeInfoCache(int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest get = HttpUtil.createGet("https://zhyn.cg.gz.gov.cn/jttweb/api/v1/location/locationRealTimeInfoCache");
        get.header("operate-terminal", "4");
        get.header("token", accountLogin.getToken());
        HttpResponse execute = get.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return locationRealTimeInfoCache(num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        List<VehicleOnline> list = new ArrayList();
        JSONArray data = result.getJSONArray("data");
        for (int i = 0; i < data.size(); i++) {
            VehicleOnline object = data.getObject(i, VehicleOnline.class);
            list.add(object);
        }
        return list;
    }
    /**
     * 2018年协议发送拍摄指令接口
     * @param terminalId    终点卡号
     * @param channelId     通道ID
     * @return
     */
    public static String cameraShot2018(String terminalId, Integer channelId, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest post = HttpUtil.createPost("https://zhyn.cg.gz.gov.cn/map/web/vehicleCtrl/" + terminalId + "/cameraShot");
        post.header("operate-terminal", "4");
        post.header("token", accountLogin.getToken());
        Map<String, Object> body = new HashMap<>();
        body.put("channelId", channelId);
        log.info("请求参数:" + JSON.toJSONString(body));
        post.body(JSON.toJSONString(body));
        HttpResponse execute = post.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return cameraShot2018(terminalId, channelId, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        //返回文件ID
        return result.getString("data");
    }
    /**
     * 2023年协议发送拍摄指令接口
     * @param vehicleId     车船 ID
     * @param vehicleType   车船类型:1 车辆 2 船舶
     * @param terminalId    终点卡号
     * @param channelId     通道ID
     * @return
     */
    public static String cameraShot2023(Integer vehicleId, Integer vehicleType, String terminalId, Integer channelId, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest get = HttpUtil.createGet("https://zhyn.cg.gz.gov.cn/api/cws-business/biz-device-send-records/v1/cameraShot?vehicleId=" + vehicleId + "&vehicleType=" + vehicleType + "&terminalId=" + terminalId + "&channelId=" + channelId);
        get.header("operate-terminal", "4");
        get.header("token", accountLogin.getToken());
        Map<String, Object> body = new HashMap<>();
        log.info("请求参数:" + get.getUrl());
        HttpResponse execute = get.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return cameraShot2023(vehicleId, vehicleType, terminalId, channelId, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        //返回文件ID
        return result.getString("data");
    }
    /**
     * 2018年协议车辆获取拍摄图片接口
     * @param terminalId    终端卡号
     * @param fileId        文件ID
     * @return
     */
    public static String getCameraShotByFileId2018(String terminalId, String fileId, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest get = HttpUtil.createGet("https://zhyn.cg.gz.gov.cn/map/web/vehicleCtrl/getCameraShotById?terminalId=" + terminalId + "&id=" + fileId);
        get.header("operate-terminal", "4");
        get.header("token", accountLogin.getToken());
        log.info("请求参数:" + get.getUrl());
        HttpResponse execute = get.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return getCameraShotByFileId2018(terminalId, fileId, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        //图片地址
        String data = result.getString("data");
        if(null == data){
            return null;
        }
        return "https://zhyn-pic.cg.gz.gov.cn" + data;
    }
    /**
     * 2023年协议车辆获取拍摄图片接口
     * @param fileId        文件ID
     * @return
     */
    public static String getCameraShotByFileId2023(String fileId, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest get = HttpUtil.createGet("https://zhyn.cg.gz.gov.cn/api/cws-business/biz-device-send-records/v1/getCameraShotById?id=" + fileId);
        get.header("operate-terminal", "4");
        get.header("token", accountLogin.getToken());
        log.info("请求参数:" + get.getUrl());
        HttpResponse execute = get.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return getCameraShotByFileId2023(fileId, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        //图片地址
        String data = result.getString("data");
        if(null == data){
            return null;
        }
        return "https://zhyn-pic.cg.gz.gov.cn" + data;
    }
    /**
     * 获取车辆轨迹接口
     * @param vehicleNum    车牌号
     * @param vehicleType   车船类型(1=车辆,2=船舶)
     * @param startTime     开始时间(yyyy-MM-dd HH:mm:ss)
     * @param endTime       结束时间(yyyy-MM-dd HH:mm:ss)
     * @return
     */
    public static List<TrackInfo> getTrackInfoByVehicleNum(String vehicleNum, String vehicleType, String startTime, String endTime, int num){
        if(null == accountLogin){
            accountLogin();
        }
        HttpRequest post = HttpUtil.createPost("https://zhyn.cg.gz.gov.cn/map/web/map/getTrackInfoByVehicleNum");
        post.header("operate-terminal", "4");
        post.header("token", accountLogin.getToken());
        Map<String, Object> body = new HashMap<>();
        body.put("vehicleNum", vehicleNum);
        body.put("vehicleType", vehicleType);
        body.put("startTime", startTime);
        body.put("endTime", endTime);
        log.info("请求参数:" + JSON.toJSONString(body));
        post.body(JSON.toJSONString(body));
        HttpResponse execute = post.execute();
        if(401 == execute.getStatus()){
            log.error("token失效,重新登录");
            if(num == 3){
                log.error("token失效,请联系管理员");
                return null;
            }
            num++;
            accountLogin = null;
            return getTrackInfoByVehicleNum(vehicleNum, vehicleType, startTime, endTime, num);
        }
        log.info("返回结果:" + execute.body());
        JSONObject result = JSON.parseObject(execute.body());
        Integer code = result.getInteger("code");
        if(0 != code){
            log.error(result.getString("msg"));
            return null;
        }
        List<TrackInfo> list = new ArrayList();
        JSONArray data = result.getJSONArray("data");
        for (int i = 0; i < data.size(); i++) {
            TrackInfo object = data.getObject(i, TrackInfo.class);
            list.add(object);
        }
        return list;
    }
    public static void main(String[] args) {
//        SM4 sm4 = SmUtil.sm4("EP77VsBj9yeOKpcO".getBytes());
//        String encryptHex = sm4.encryptHex(content);
//        String decryptStr = sm4.decryptStr("357b94ca60ce8140f3d22eceaaa5d71b0d25d6cd20c8218d9a3ddcd30881126d", CharsetUtil.CHARSET_UTF_8);
//        System.err.println(decryptStr);
        accountLogin();
        System.err.println(accountLogin);
//        getVehicleList(null, null, null);
//        getShipList(null, null, null);
//        queryRuntimeInfoByCache();
        locationRealTimeInfoCache(0);
    }
//    public static void main(String[] args) {
////        SM4 sm4 = SmUtil.sm4("EP77VsBj9yeOKpcO".getBytes());
////        String encryptHex = sm4.encryptHex(content);
////        String decryptStr = sm4.decryptStr("357b94ca60ce8140f3d22eceaaa5d71b0d25d6cd20c8218d9a3ddcd30881126d", CharsetUtil.CHARSET_UTF_8);
////        System.err.println(decryptStr);
//
//        accountLogin();
//        System.err.println(accountLogin);
////        Integer integer2018 = cameraShot2018("041023412161", 5);
////        System.err.println(integer2018);
////        String cameraShotByFileId2018 = getCameraShotByFileId2018("041023412161", integer2018.toString());
////        System.err.println(cameraShotByFileId2018);
//        Integer integer2023 = cameraShot2023(918, 1, "00000000041033990843", 6);
//        System.err.println(integer2023);
//        String cameraShotByFileId2023 = getCameraShotByFileId2023("00000000041033990843", integer2023.toString());
//        System.err.println(cameraShotByFileId2023);
//
//    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/AccountLogin.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.modular.system.util.videoGateway.model;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/18 19:46
 */
@Data
public class AccountLogin {
    /**
     * 用户 token
     */
    private String token;
    /**
     * 用户 refreshToken
     */
    private String refreshToken;
    /**
     * 用户账号 id
     */
    private Integer accountId;
    /**
     * 登录账号
     */
    private String account;
    /**
     * 所属单位
     */
    private String companyName;
    /**
     * 平台 code(后面的接口中需要传递
     * 该参数)
     */
    private String platformCode;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/SessionId.java
New file
@@ -0,0 +1,25 @@
package com.stylefeng.guns.modular.system.util.videoGateway.model;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/18 19:41
 */
@Data
public class SessionId {
    /**
     * 公钥(国密 SM4 加密算法加密后的,需要用
     * 给定的公钥解密),每次请求该接口返回的
     * publicKey 参数值都不一样
     */
    private String publicKey;
    /**
     * 登录接口中需要传递的参数
     */
    private String sessionId;
    /**
     * 加密key
     */
    private String key;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/Ship.java
New file
@@ -0,0 +1,49 @@
package com.stylefeng.guns.modular.system.util.videoGateway.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/19 11:06
 */
@Data
@ApiModel
public class Ship {
    /**
     * 记录id
     */
    @ApiModelProperty("记录id")
    private Integer Id;
    /**
     * 船舶号
     */
    @ApiModelProperty("船舶号")
    private String shipNum;
    /**
     * 船舶简称
     */
    @ApiModelProperty("船舶简称")
    private String shipAlias;
    /**
     * 公司 id
     */
    @ApiModelProperty("公司 id")
    private String companyId;
    /**
     * 公司名称
     */
    @ApiModelProperty("公司名称")
    private String companyName;
    /**
     * 年审开始时间,格式:yyyy-MM-dd
     */
    @ApiModelProperty("年审开始时间,格式:yyyy-MM-dd")
    private String inspectPeriodStart;
    /**
     * 年审结束时间,格式:yyyy-MM-dd
     */
    @ApiModelProperty("年审结束时间,格式:yyyy-MM-dd")
    private String inspectPeriodEnd;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/TrackInfo.java
New file
@@ -0,0 +1,44 @@
package com.stylefeng.guns.modular.system.util.videoGateway.model;
import lombok.Data;
/**
 * 车辆轨迹
 * @author zhibing.pu
 * @Date 2024/12/19 11:37
 */
@Data
public class TrackInfo {
    /**
     * 车牌号
     */
    private String vehicleNum;
    /**
     * 终端卡号
     */
    private String terminalId;
    /**
     * 设备时间
     */
    private String reportTime;
    /**
     * 经度
     */
    private String longitude;
    /**
     * 纬度
     */
    private String latitude;
    /**
     * 0 acc 关,1:acc 开
     */
    private Integer acc;
    /**
     * 方向
     */
    private Integer direction;
    /**
     * 海拔
     */
    private Integer altitude;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/Vehicle.java
New file
@@ -0,0 +1,42 @@
package com.stylefeng.guns.modular.system.util.videoGateway.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/12/19 11:01
 */
@Data
public class Vehicle {
    /**
     * 记录id
     */
    @ApiModelProperty("记录id")
    private Integer Id;
    /**
     * 车牌号
     */
    @ApiModelProperty("车牌号")
    private String vehicleNum;
    /**
     * 公司 id
     */
    @ApiModelProperty("公司 id")
    private String companyId;
    /**
     * 公司名称
     */
    @ApiModelProperty("公司名称")
    private String companyName;
    /**
     * 年审开始时间,格式:yyyy-MM-dd
     */
    @ApiModelProperty("年审开始时间,格式:yyyy-MM-dd")
    private String inspectPeriodStart;
    /**
     * 年审结束时间,格式:yyyy-MM-dd
     */
    @ApiModelProperty("年审结束时间,格式:yyyy-MM-dd")
    private String inspectPeriodEnd;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/videoGateway/model/VehicleOnline.java
New file
@@ -0,0 +1,56 @@
package com.stylefeng.guns.modular.system.util.videoGateway.model;
import lombok.Data;
/**
 * 车辆在线状态
 * @author zhibing.pu
 * @Date 2024/12/19 11:01
 */
@Data
public class VehicleOnline {
    /**
     * 车辆 Id
     */
    private Integer vehicleId;
    /**
     * 车牌号
     */
    private String vehicleNum;
    /**
     * 车船类型:1 车辆设备 2 船舶设备
     */
    private Integer vehicleType;
    /**
     * 协议类型:1、2018 协议 2、2023 标准
     */
    private String vehicleGpsProtocol;
    /**
     * 终端卡号
     */
    private String terminalId;
    /**
     * 设备时间
     */
    private String reportTime;
    /**
     * 公司 id
     */
    private String companyId;
    /**
     * 公司名称
     */
    private String companyName;
    /**
     * 经度
     */
    private String longitude;
    /**
     * 纬度
     */
    private String latitude;
    /**
     * 速度
     */
    private String speed;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/ActivityWarpper.java
New file
@@ -0,0 +1,38 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("活动")
public class ActivityWarpper {
    @ApiModelProperty("活动id")
    private Integer id;
    @ApiModelProperty("活动描述")
    private String content;
    @ApiModelProperty("完成情况")
    private String carryOut;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getCarryOut() {
        return carryOut;
    }
    public void setCarryOut(String carryOut) {
        this.carryOut = carryOut;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/BalanceUsageRecord.java
New file
@@ -0,0 +1,20 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/5/6 11:16
 */
@ApiModel
@Data
public class BalanceUsageRecord {
    @ApiModelProperty("总金额")
    private Double total;
    @ApiModelProperty("明细列表")
    private List<BalanceUsageRecordList> list;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/BalanceUsageRecordList.java
New file
@@ -0,0 +1,21 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2024/5/6 11:17
 */
@ApiModel
@Data
public class BalanceUsageRecordList {
    @ApiModelProperty("日期")
    private String time;
    @ApiModelProperty("金额")
    private Double money;
    @ApiModelProperty("用途")
    private String content;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/BaseWarpper.java
New file
@@ -0,0 +1,184 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * 公共封装类
 */
@ApiModel("公共对象")
public class BaseWarpper {
    @ApiModelProperty("主键id")
    private Integer id;
    @ApiModelProperty("名称")
    private String name;
    @ApiModelProperty("内容")
    private String content;
    @ApiModelProperty("数量")
    private Integer number;
    @ApiModelProperty("金额")
    private Double amount;
    @ApiModelProperty("时长(分钟)")
    private Integer minute;
    @ApiModelProperty("经度")
    private Double lon;
    @ApiModelProperty("纬度")
    private Double lat;
    @ApiModelProperty("日期")
    private String day;
    @ApiModelProperty("其他内容")
    private Object data;
    @ApiModelProperty("类型(1=活动收入,2=跑单收入,3=取消订单收入,4=改派订单收入,5=优惠券补贴,6=折扣不贴,7=红包补贴)")
    private Integer type;
    public BaseWarpper() {
        this.id = 0;
        this.name = "";
        this.content = "";
        this.number = 0;
        this.amount = 0D;
        this.minute = 0;
        this.lon = 0D;
        this.lat = 0D;
        this.day = "";
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Integer getNumber() {
        return number;
    }
    public void setNumber(Integer number) {
        this.number = number;
    }
    public Double getAmount() {
        return amount;
    }
    public void setAmount(Double amount) {
        this.amount = amount;
    }
    public Integer getMinute() {
        return minute;
    }
    public void setMinute(Integer minute) {
        this.minute = minute;
    }
    public Double getLon() {
        return lon;
    }
    public void setLon(Double lon) {
        this.lon = lon;
    }
    public Double getLat() {
        return lat;
    }
    public void setLat(Double lat) {
        this.lat = lat;
    }
    public String getDay() {
        return day;
    }
    public void setDay(String day) {
        this.day = day;
    }
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    @Override
    public String toString() {
        return "BaseWarpper{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", content='" + content + '\'' +
                ", number=" + number +
                ", amount=" + amount +
                ", minute=" + minute +
                ", lon=" + lon +
                ", lat=" + lat +
                ", day='" + day + '\'' +
                ", data=" + data +
                '}';
    }
    public static BaseWarpper getBaseWarpper(Map<String, Object> map){
        BaseWarpper baseWarpper = new BaseWarpper();
        if(null != map){
            baseWarpper.setId(null != map.get("id") ? Integer.valueOf(map.get("id").toString()) : 0);
            baseWarpper.setName(null != map.get("name") ? map.get("name").toString() : "");
            baseWarpper.setContent(null != map.get("content") ? map.get("content").toString() : "");
            baseWarpper.setNumber(null != map.get("number") ? Integer.valueOf(map.get("number").toString()) : 0);
            baseWarpper.setAmount(null != map.get("amount") ? Double.valueOf(map.get("amount").toString()) : 0);
            baseWarpper.setMinute(null != map.get("minute") ? Integer.valueOf(map.get("minute").toString()) : 0);
            baseWarpper.setLon(null != map.get("lon") ? Double.valueOf(map.get("lon").toString()) : 0.0);
            baseWarpper.setLat(null != map.get("lat") ? Double.valueOf(map.get("lat").toString()) : 0.0);
            baseWarpper.setDay(null != map.get("day") ? map.get("day").toString() : "");
            baseWarpper.setData(null != map.get("data") ? map.get("data") : new Object());
            baseWarpper.setType(null != map.get("type") ? Integer.valueOf(map.get("type").toString()) : 0);
        }
        return baseWarpper;
    }
    public static List<BaseWarpper> getBaseWarppers(List<Map<String, Object>> list){
        List<BaseWarpper> data = new ArrayList<>();
        if(null != list){
            for(Map<String, Object> map : list){
                data.add(BaseWarpper.getBaseWarpper(map));
            }
        }
        return data;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DeptWarpper.java
New file
@@ -0,0 +1,33 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import com.stylefeng.guns.core.util.ToolUtil;
import java.util.Map;
/**
 * 部门列表的包装
 *
 * @author fengshuonan
 * @date 2017年4月25日 18:10:31
 */
public class DeptWarpper extends BaseControllerWarpper {
    public DeptWarpper(Object list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        Integer pid = (Integer) map.get("pid");
        if (ToolUtil.isEmpty(pid) || pid.equals(0)) {
            map.put("pName", "--");
        } else {
            map.put("pName", ConstantFactory.me().getDeptName(pid));
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DictWarpper.java
New file
@@ -0,0 +1,36 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.modular.system.model.Dict;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import com.stylefeng.guns.core.util.ToolUtil;
import java.util.List;
import java.util.Map;
/**
 * 字典列表的包装
 *
 * @author fengshuonan
 * @date 2017年4月25日 18:10:31
 */
public class DictWarpper extends BaseControllerWarpper {
    public DictWarpper(Object list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        StringBuffer detail = new StringBuffer();
        Integer id = Integer.valueOf(map.get("id").toString());
        List<Dict> dicts = ConstantFactory.me().findInDict(id);
        if(dicts != null){
            for (Dict dict : dicts) {
                detail.append(dict.getCode() + ":" +dict.getName() + ",");
            }
            map.put("detail", ToolUtil.removeSuffix(detail.toString(),","));
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DriverInfoWarpper.java
New file
@@ -0,0 +1,506 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Map;
@ApiModel("个人中心详情")
public class DriverInfoWarpper {
    @ApiModelProperty("司机id(用于生成二维码)")
    private Integer id;
    @ApiModelProperty("头像")
    private String avatar;
    @ApiModelProperty("姓")
    private String lastName;
    @ApiModelProperty("名")
    private String firstName;
    @ApiModelProperty("手机号码运营商")
    private String phoneOperator;
    @ApiModelProperty("电话")
    private String phone;
    @ApiModelProperty("邮箱")
    private String email;
    @ApiModelProperty("性别")
    private Integer sex;
    @ApiModelProperty("车牌")
    private String licensePlate;
    @ApiModelProperty("车辆品牌")
    private String brand;
    @ApiModelProperty("车辆颜色")
    private String carColor;
    @ApiModelProperty("历史接单数")
    private Integer orderNum;
    @ApiModelProperty("评分")
    private Double score;
    @ApiModelProperty("账户余额")
    private Double balance;
    @ApiModelProperty("活动总收入")
    private Double activityMoney;
    @ApiModelProperty("剩余可提现活动收入")
    private Double laveActivityMoney;
    @ApiModelProperty("历史总收入")
    private Double businessMoney;
    @ApiModelProperty("剩余可提现收入")
    private Double laveBusinessMoney;
    @ApiModelProperty("剩余可提现收入-下周")
    private Double laveBusinessNextWeekMoney;
    @ApiModelProperty("出租车资格证号")
    private String taxiAptitudeCard;
    @ApiModelProperty("发证日期")
    private String networkCarlssueDate;
    @ApiModelProperty("公司")
    private String company;
    @ApiModelProperty("居住地(带分隔符)")
    private String driverContactAddress_;
    @ApiModelProperty("身份证号码")
    private String idCard;
    @ApiModelProperty("身份证正面照")
    private String idCardImgUrl1;
    @ApiModelProperty("身份证背面照")
    private String idCardImgUrl2;
    @ApiModelProperty("初次领取驾驶证日期")
    private String getDriverLicenseDate;
    @ApiModelProperty("服务模式(1=专车,2=出租车,3=城际,4=小件物流-同城,5=小件物流-跨城,6=包车)多个以逗号分隔")
    private String type;
    @ApiModelProperty("从业地(带分隔符)")
    private String placeOfPractice;
    @ApiModelProperty("从业地id")
    private String placeOfPracticeId;
    @ApiModelProperty("驾驶证照片")
    private String driveCardImgUrl;
    @ApiModelProperty("驾驶证照片")
    private String driveCardImgUrl2;
    @ApiModelProperty("网约车资格证照片")
    private String networkCarlssueImg;
    @ApiModelProperty("语言(1=简体中文,2=英语,3=法语)")
    private Integer language;
    @ApiModelProperty("审核状态(1=待审核,2=正常,3=冻结,4=拒绝)")
    private Integer authState;
    @ApiModelProperty("车辆品牌ID")
    private Integer carBrandId;
    @ApiModelProperty("车型id")
    private Integer carModelId;
    @ApiModelProperty("行驶证照片")
    private String drivingLicensePhoto;
    private Integer carId;
    @ApiModelProperty("小程序二维码路径")
    private String qrCode;
    @ApiModelProperty("二维码是否打开 true打开,false关闭")
    private Boolean qrCodeIsOpen;
    @ApiModelProperty("生日")
    private String birthday;
    @ApiModelProperty("居住地")
    private String driverAddress;
    @ApiModelProperty("google车辆id")
    private String vehicleId;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getAvatar() {
        return avatar;
    }
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getPhoneOperator() {
        return phoneOperator;
    }
    public void setPhoneOperator(String phoneOperator) {
        this.phoneOperator = phoneOperator;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Integer getSex() {
        return sex;
    }
    public void setSex(Integer sex) {
        this.sex = sex;
    }
    public String getLicensePlate() {
        return licensePlate;
    }
    public void setLicensePlate(String licensePlate) {
        this.licensePlate = licensePlate;
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public String getCarColor() {
        return carColor;
    }
    public void setCarColor(String carColor) {
        this.carColor = carColor;
    }
    public Integer getOrderNum() {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum) {
        this.orderNum = orderNum;
    }
    public Double getScore() {
        return score;
    }
    public void setScore(Double score) {
        this.score = score;
    }
    public Double getBalance() {
        return balance;
    }
    public void setBalance(Double balance) {
        this.balance = balance;
    }
    public Double getActivityMoney() {
        return activityMoney;
    }
    public void setActivityMoney(Double activityMoney) {
        this.activityMoney = activityMoney;
    }
    public Double getLaveActivityMoney() {
        return laveActivityMoney;
    }
    public void setLaveActivityMoney(Double laveActivityMoney) {
        this.laveActivityMoney = laveActivityMoney;
    }
    public Double getBusinessMoney() {
        return businessMoney;
    }
    public void setBusinessMoney(Double businessMoney) {
        this.businessMoney = businessMoney;
    }
    public Double getLaveBusinessMoney() {
        return laveBusinessMoney;
    }
    public void setLaveBusinessMoney(Double laveBusinessMoney) {
        this.laveBusinessMoney = laveBusinessMoney;
    }
    public Double getLaveBusinessNextWeekMoney() {
        return laveBusinessNextWeekMoney;
    }
    public void setLaveBusinessNextWeekMoney(Double laveBusinessNextWeekMoney) {
        this.laveBusinessNextWeekMoney = laveBusinessNextWeekMoney;
    }
    public String getTaxiAptitudeCard() {
        return taxiAptitudeCard;
    }
    public void setTaxiAptitudeCard(String taxiAptitudeCard) {
        this.taxiAptitudeCard = taxiAptitudeCard;
    }
    public String getNetworkCarlssueDate() {
        return networkCarlssueDate;
    }
    public void setNetworkCarlssueDate(String networkCarlssueDate) {
        this.networkCarlssueDate = networkCarlssueDate;
    }
    public String getCompany() {
        return company;
    }
    public void setCompany(String company) {
        this.company = company;
    }
    public String getDriverContactAddress_() {
        return driverContactAddress_;
    }
    public void setDriverContactAddress_(String driverContactAddress_) {
        this.driverContactAddress_ = driverContactAddress_;
    }
    public String getIdCard() {
        return idCard;
    }
    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }
    public String getIdCardImgUrl1() {
        return idCardImgUrl1;
    }
    public void setIdCardImgUrl1(String idCardImgUrl1) {
        this.idCardImgUrl1 = idCardImgUrl1;
    }
    public String getIdCardImgUrl2() {
        return idCardImgUrl2;
    }
    public void setIdCardImgUrl2(String idCardImgUrl2) {
        this.idCardImgUrl2 = idCardImgUrl2;
    }
    public String getGetDriverLicenseDate() {
        return getDriverLicenseDate;
    }
    public void setGetDriverLicenseDate(String getDriverLicenseDate) {
        this.getDriverLicenseDate = getDriverLicenseDate;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getPlaceOfPractice() {
        return placeOfPractice;
    }
    public void setPlaceOfPractice(String placeOfPractice) {
        this.placeOfPractice = placeOfPractice;
    }
    public String getPlaceOfPracticeId() {
        return placeOfPracticeId;
    }
    public void setPlaceOfPracticeId(String placeOfPracticeId) {
        this.placeOfPracticeId = placeOfPracticeId;
    }
    public String getDriveCardImgUrl() {
        return driveCardImgUrl;
    }
    public void setDriveCardImgUrl(String driveCardImgUrl) {
        this.driveCardImgUrl = driveCardImgUrl;
    }
    public String getDriveCardImgUrl2() {
        return driveCardImgUrl2;
    }
    public void setDriveCardImgUrl2(String driveCardImgUrl2) {
        this.driveCardImgUrl2 = driveCardImgUrl2;
    }
    public String getNetworkCarlssueImg() {
        return networkCarlssueImg;
    }
    public void setNetworkCarlssueImg(String networkCarlssueImg) {
        this.networkCarlssueImg = networkCarlssueImg;
    }
    public Integer getLanguage() {
        return language;
    }
    public void setLanguage(Integer language) {
        this.language = language;
    }
    public Integer getAuthState() {
        return authState;
    }
    public void setAuthState(Integer authState) {
        this.authState = authState;
    }
    public Integer getCarBrandId() {
        return carBrandId;
    }
    public void setCarBrandId(Integer carBrandId) {
        this.carBrandId = carBrandId;
    }
    public Integer getCarModelId() {
        return carModelId;
    }
    public void setCarModelId(Integer carModelId) {
        this.carModelId = carModelId;
    }
    public String getDrivingLicensePhoto() {
        return drivingLicensePhoto;
    }
    public void setDrivingLicensePhoto(String drivingLicensePhoto) {
        this.drivingLicensePhoto = drivingLicensePhoto;
    }
    public Integer getCarId() {
        return carId;
    }
    public void setCarId(Integer carId) {
        this.carId = carId;
    }
    public String getQrCode() {
        return qrCode;
    }
    public void setQrCode(String qrCode) {
        this.qrCode = qrCode;
    }
    public Boolean getQrCodeIsOpen() {
        return qrCodeIsOpen;
    }
    public void setQrCodeIsOpen(Boolean qrCodeIsOpen) {
        this.qrCodeIsOpen = qrCodeIsOpen;
    }
    public String getBirthday() {
        return birthday;
    }
    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }
    public String getDriverAddress() {
        return driverAddress;
    }
    public void setDriverAddress(String driverAddress) {
        this.driverAddress = driverAddress;
    }
    public static DriverInfoWarpper getDriverInfoWarpper(Map<String, Object> map){
        DriverInfoWarpper driverInfoWarpper = new DriverInfoWarpper();
        if(null != map){
            driverInfoWarpper.setAuthState(null != map.get("authState") ? Integer.valueOf(String.valueOf(map.get("authState"))) : 1);
            driverInfoWarpper.setCarId(null != map.get("carId") ? Integer.valueOf(String.valueOf(map.get("carId"))) : 1);
            driverInfoWarpper.setCarModelId(null != map.get("carModelId") ? Integer.valueOf(String.valueOf(map.get("carModelId"))) : 0);
            driverInfoWarpper.setCarBrandId(null != map.get("carBrandId") ? Integer.valueOf(String.valueOf(map.get("carBrandId"))) : 0);
            driverInfoWarpper.setDrivingLicensePhoto(null != map.get("drivingLicensePhoto") ? String.valueOf(map.get("drivingLicensePhoto")) : "");
            driverInfoWarpper.setId(null != map.get("id") ? Integer.valueOf(String.valueOf(map.get("id"))) : 0);
            driverInfoWarpper.setAvatar(null != map.get("avatar") ? String.valueOf(map.get("avatar")) : "");
            driverInfoWarpper.setQrCode(null != map.get("qrCode") ? String.valueOf(map.get("qrCode")) : "");
            driverInfoWarpper.setQrCodeIsOpen(null != map.get("qrCodeIsOpen") ? Boolean.valueOf(map.get("qrCodeIsOpen").toString()) : false);
            driverInfoWarpper.setLastName(null != map.get("lastName") ? String.valueOf(map.get("lastName")) : "");
            driverInfoWarpper.setFirstName(null != map.get("firstName") ? String.valueOf(map.get("firstName")) : "");
            driverInfoWarpper.setPhoneOperator(null != map.get("phoneOperator") ? String.valueOf(map.get("phoneOperator")) : "");
            driverInfoWarpper.setPhone(null != map.get("phone") ? String.valueOf(map.get("phone")) : "");
            driverInfoWarpper.setEmail(null != map.get("email") ? String.valueOf(map.get("email")) : "");
            driverInfoWarpper.setSex(null != map.get("sex") ? Integer.valueOf(String.valueOf(map.get("sex"))) : 0);
            driverInfoWarpper.setLicensePlate(null != map.get("licensePlate") ? String.valueOf(map.get("licensePlate")) : "");
            driverInfoWarpper.setBrand(null != map.get("brand") ? String.valueOf(map.get("brand")) : "");
            driverInfoWarpper.setCarColor(null != map.get("carColor") ? String.valueOf(map.get("carColor")) : "");
            driverInfoWarpper.setOrderNum(null != map.get("orderNum") ? Integer.valueOf(String.valueOf(map.get("orderNum"))) : 0);
            driverInfoWarpper.setScore(null != map.get("score") ? Double.valueOf(String.valueOf(map.get("score"))) : 0);
            driverInfoWarpper.setBalance(null != map.get("balance") ? Double.valueOf(String.valueOf(map.get("balance"))) : 0);
            driverInfoWarpper.setActivityMoney(null != map.get("activityMoney") ? Double.valueOf(String.valueOf(map.get("activityMoney"))) : 0);
            driverInfoWarpper.setBusinessMoney(null != map.get("businessMoney") ? Double.valueOf(String.valueOf(map.get("businessMoney"))) : 0);
            driverInfoWarpper.setTaxiAptitudeCard(null != map.get("taxiAptitudeCard") ? String.valueOf(map.get("taxiAptitudeCard")) : "");
            driverInfoWarpper.setNetworkCarlssueDate(null != map.get("networkCarlssueDate") ? String.valueOf(map.get("networkCarlssueDate")) : "");
            driverInfoWarpper.setCompany(null != map.get("company") ? String.valueOf(map.get("company")) : "");
            driverInfoWarpper.setDriverContactAddress_(null != map.get("driverContactAddress_") ? String.valueOf(map.get("driverContactAddress_")) : "");
            driverInfoWarpper.setIdCard(null != map.get("idCard") ? String.valueOf(map.get("idCard")) : "");
            driverInfoWarpper.setIdCardImgUrl1(null != map.get("idCardImgUrl1") ? String.valueOf(map.get("idCardImgUrl1")) : "");
            driverInfoWarpper.setIdCardImgUrl2(null != map.get("idCardImgUrl2") ? String.valueOf(map.get("idCardImgUrl2")) : "");
            driverInfoWarpper.setGetDriverLicenseDate(null != map.get("getDriverLicenseDate") ? String.valueOf(map.get("getDriverLicenseDate")) : "");
            driverInfoWarpper.setType(null != map.get("type") ? String.valueOf(map.get("type")) : "");
            driverInfoWarpper.setPlaceOfPractice(null != map.get("placeOfPractice") ? String.valueOf(map.get("placeOfPractice")) : "");
            driverInfoWarpper.setDriveCardImgUrl(null != map.get("driveCardImgUrl") ? String.valueOf(map.get("driveCardImgUrl")) : "");
            driverInfoWarpper.setDriveCardImgUrl2(null != map.get("driveCardImgUrl2") ? String.valueOf(map.get("driveCardImgUrl2")) : "");
            driverInfoWarpper.setNetworkCarlssueImg(null != map.get("networkCarlssueImg") ? String.valueOf(map.get("networkCarlssueImg")) : "");
            driverInfoWarpper.setPlaceOfPracticeId(null != map.get("placeOfPracticeId") ? String.valueOf(map.get("placeOfPracticeId")) : "");
            driverInfoWarpper.setLaveActivityMoney(null != map.get("laveActivityMoney") ? Double.valueOf(String.valueOf(map.get("laveActivityMoney"))) : 0);
            driverInfoWarpper.setLaveBusinessMoney(null != map.get("laveBusinessMoney") ? Double.valueOf(String.valueOf(map.get("laveBusinessMoney"))) : 0);
            driverInfoWarpper.setLanguage(null != map.get("language") ? Integer.valueOf(String.valueOf(map.get("language"))) : 2);
            driverInfoWarpper.setBirthday(null != map.get("birthday") ? String.valueOf(map.get("birthday")) : "");
            driverInfoWarpper.setDriverAddress(null != map.get("driverAddress") ? String.valueOf(map.get("driverAddress")) : "");
            driverInfoWarpper.setVehicleId(null != map.get("vehicleId") ? String.valueOf(map.get("vehicleId")) : "");
        }
        return driverInfoWarpper;
    }
    public String getVehicleId() {
        return vehicleId;
    }
    public void setVehicleId(String vehicleId) {
        this.vehicleId = vehicleId;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/DriverInviteInfoWarpper.java
New file
@@ -0,0 +1,112 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * 司机邀请列表封装类
 * @author yxh
 * @date 2021年03月27日 10:40
 */
@ApiModel("司机邀请信息")
public class DriverInviteInfoWarpper {
    @ApiModelProperty("id")
    private Integer id;
    @ApiModelProperty("手机号")
    private String phone;
    @ApiModelProperty("昵称/姓名")
    private String name;
    @ApiModelProperty("头像")
    private String avatar;
    @ApiModelProperty("插入时间")
    private String insertTime;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAvatar() {
        return avatar;
    }
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
    public String getInsertTime() {
        return insertTime;
    }
    public void setInsertTime(String insertTime) {
        this.insertTime = insertTime;
    }
    @Override
    public String toString() {
        return "DriverInviteInfoWarpper{" +
                "id=" + id +
                ", phone='" + phone + '\'' +
                ", name='" + name + '\'' +
                ", avatar='" + avatar + '\'' +
                ", insertTime='" + insertTime + '\'' +
                '}';
    }
    public static List<DriverInviteInfoWarpper> getDriverInviteInfoWarpper(List<Map<String, Object>> maps){
        List<DriverInviteInfoWarpper> list = new ArrayList<>();
        if(null != maps){
            for (Map<String, Object> map : maps) {
                DriverInviteInfoWarpper driverInviteInfoWarpper=new DriverInviteInfoWarpper();
                if(null != map){
                    driverInviteInfoWarpper.setId(null != map.get("id") ? Integer.valueOf(String.valueOf(map.get("id"))):0);
                    driverInviteInfoWarpper.setName(null!=map.get("name")? String.valueOf(map.get("name")) : "");
                    if(null!=map.get("phone")){
                        String phone=String.valueOf(map.get("phone"));
                        if (phone.length()<=4){
                            driverInviteInfoWarpper.setPhone(phone);
                        }else{
                            String start = phone.substring(0,3);
                            String end = phone.substring(phone.length()-4,phone.length());
                            StringBuilder sb=new StringBuilder();
                            sb.append(start).append("****").append(end);
                            driverInviteInfoWarpper.setPhone(sb.toString());
                        }
                    }else{
                        driverInviteInfoWarpper.setPhone("");
                    }
                    driverInviteInfoWarpper.setInsertTime(null != map.get("insertTime") ? String.valueOf(map.get("insertTime")) : "");
                    driverInviteInfoWarpper.setAvatar(null!=map.get("avatar")? String.valueOf(map.get("avatar")) : "");
                    list.add(driverInviteInfoWarpper);
                }
            }
        }
        return list;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/EmailWarpper.java
New file
@@ -0,0 +1,41 @@
package com.stylefeng.guns.modular.system.warpper;
import lombok.Data;
/**
 * <p>
 *
 * </p>
 *
 * @author administrator
 * @since 2023-09-01
 */
@Data
public class EmailWarpper {
    private static final long serialVersionUID=1L;
    private Integer id;
    /**
     * 用户id
     */
    private Integer userId;
    /**
     * 1用户2司机
     */
    private Integer type;
    /**
     * html 链接
     */
    private String link;
    private Integer orderId;
    private String createTime;
    private String week;
    private String amOrPm;
    private String name;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/HomeWarpper.java
New file
@@ -0,0 +1,115 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Map;
@ApiModel("首页统计")
public class HomeWarpper {
    @ApiModelProperty("车牌号")
    private String licensePlate;
    @ApiModelProperty("车辆品牌")
    private String brand;
    @ApiModelProperty("今日接单")
    private Integer dayNum;
    @ApiModelProperty("月接单")
    private Integer mouthNum;
    @ApiModelProperty("评分")
    private Double score;
    @ApiModelProperty("活动数")
    private Integer activity;
    @ApiModelProperty("上下班状态(1=上班,2=下班)")
    private Integer work;
    public String getLicensePlate() {
        return licensePlate;
    }
    public void setLicensePlate(String licensePlate) {
        this.licensePlate = licensePlate;
    }
    public String getBand() {
        return brand;
    }
    public void setBand(String brand) {
        this.brand = brand;
    }
    public Integer getDayNum() {
        return dayNum;
    }
    public void setDayNum(Integer dayNum) {
        this.dayNum = dayNum;
    }
    public Integer getMouthNum() {
        return mouthNum;
    }
    public void setMouthNum(Integer mouthNum) {
        this.mouthNum = mouthNum;
    }
    public Double getScore() {
        return score;
    }
    public void setScore(Double score) {
        this.score = score;
    }
    public Integer getActivity() {
        return activity;
    }
    public void setActivity(Integer activity) {
        this.activity = activity;
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public Integer getWork() {
        return work;
    }
    public void setWork(Integer work) {
        this.work = work;
    }
    @Override
    public String toString() {
        return "HomeWarpper{" +
                "licensePlate='" + licensePlate + '\'' +
                ", brand='" + brand + '\'' +
                ", dayNum=" + dayNum +
                ", mouthNum=" + mouthNum +
                ", score=" + score +
                ", activity=" + activity +
                ", work=" + work +
                '}';
    }
    public static HomeWarpper getHomeWarpper(Map<String, Object> map){
        HomeWarpper homeWarpper = new HomeWarpper();
        if(null != map){
            homeWarpper.setLicensePlate(null != map.get("licensePlate") ? String.valueOf(map.get("licensePlate")) : "");
            homeWarpper.setBand(null != map.get("brand") ? String.valueOf(map.get("brand")) : "");
            homeWarpper.setDayNum(null != map.get("dayNum") ? Integer.valueOf(String.valueOf(map.get("dayNum"))) : 0);
            homeWarpper.setMouthNum(null != map.get("mouthNum") ? Integer.valueOf(String.valueOf(map.get("mouthNum"))) : 0);
            homeWarpper.setScore(null != map.get("score") ? Double.valueOf(String.valueOf(map.get("score"))) : 0);
            homeWarpper.setActivity(null != map.get("activity") ? Integer.valueOf(String.valueOf(map.get("activity"))) : 0);
            homeWarpper.setWork(null != map.get("work") ? Integer.valueOf(String.valueOf(map.get("work"))) : 0);
        }
        return homeWarpper;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/LogWarpper.java
New file
@@ -0,0 +1,44 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import com.stylefeng.guns.core.util.Contrast;
import com.stylefeng.guns.core.util.ToolUtil;
import java.util.Map;
/**
 * 日志列表的包装类
 *
 * @author fengshuonan
 * @date 2017年4月5日22:56:24
 */
public class LogWarpper extends BaseControllerWarpper {
    public LogWarpper(Object list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        String message = (String) map.get("message");
        Integer userid = (Integer) map.get("userid");
        map.put("userName", ConstantFactory.me().getUserNameById(userid));
        //如果信息过长,则只截取前100位字符串
        if (ToolUtil.isNotEmpty(message) && message.length() >= 100) {
            String subMessage = message.substring(0, 100) + "...";
            map.put("message", subMessage);
        }
        //如果信息中包含分割符号;;;   则分割字符串返给前台
        if (ToolUtil.isNotEmpty(message) && message.indexOf(Contrast.separator) != -1) {
            String[] msgs = message.split(Contrast.separator);
            map.put("regularMessage",msgs);
        }else{
            map.put("regularMessage",message);
        }
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/LoginWarpper.java
New file
@@ -0,0 +1,92 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("登录")
public class LoginWarpper {
    @ApiModelProperty("用户id")
    private Integer id;
    @ApiModelProperty("token")
    private String token;
    @ApiModelProperty("appid")
    private String appid;
    @ApiModelProperty("高德猎鹰服务id")
    private String serverId;
    @ApiModelProperty("高德猎鹰终端id")
    private String terminalId;
    @ApiModelProperty("跳转页面 100000=跳转至【完善个人资料】 200000=跳转至【完善车辆信息】")
    private String jumpCode;
    @ApiModelProperty("google车辆id")
    private String vehicleId;
    private String audioUrl;
    public String getJumpCode() {
        return jumpCode;
    }
    public void setJumpCode(String jumpCode) {
        this.jumpCode = jumpCode;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }
    public String getAppid() {
        return appid;
    }
    public void setAppid(String appid) {
        this.appid = appid;
    }
    public String getServerId() {
        return serverId;
    }
    public void setServerId(String serverId) {
        this.serverId = serverId;
    }
    public String getTerminalId() {
        return terminalId;
    }
    public void setTerminalId(String terminalId) {
        this.terminalId = terminalId;
    }
    public String getVehicleId() {
        return vehicleId;
    }
    public void setVehicleId(String vehicleId) {
        this.vehicleId = vehicleId;
    }
    public String getAudioUrl() {
        return audioUrl;
    }
    public void setAudioUrl(String audioUrl) {
        this.audioUrl = audioUrl;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/MenuWarpper.java
New file
@@ -0,0 +1,28 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.constant.IsMenu;
import java.util.List;
import java.util.Map;
/**
 * 菜单列表的包装类
 *
 * @author fengshuonan
 * @date 2017年2月19日15:07:29
 */
public class MenuWarpper extends BaseControllerWarpper {
    public MenuWarpper(List<Map<String, Object>> list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        map.put("statusName", ConstantFactory.me().getMenuStatusName((Integer) map.get("status")));
        map.put("isMenuName", IsMenu.valueOf((Integer) map.get("ismenu")));
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/MoneyInfoWarpper.java
New file
@@ -0,0 +1,79 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
 * 费用明细
 */
@Data
@ApiModel("费用明细")
public class MoneyInfoWarpper {
    @ApiModelProperty("订单总金额")
    private Double orderMoney;
    @ApiModelProperty("起步里程")
    private Double startMileage;
    @ApiModelProperty("起步价")
    private Double startMoney;
    @ApiModelProperty("里程费")
    private Double mileageMoney;
    @ApiModelProperty("里程数")
    private Double mileage;
    @ApiModelProperty("时长费")
    private Double durationMoney;
    @ApiModelProperty("时长")
    private Double duration;
    @ApiModelProperty("等待费")
    private Double waitMoney;
    @ApiModelProperty("等待时长")
    private Double wait;
    @ApiModelProperty("远途费")
    private Double longDistanceMoney;
    @ApiModelProperty("远途里程")
    private Double longDistance;
    @ApiModelProperty("停车费")
    private Double parkMoney;
    @ApiModelProperty("过路费")
    private Double roadTollMoney;
    @ApiModelProperty("红包抵扣金额")
    private Double redPacketMoney;
    @ApiModelProperty("优惠券抵扣金额")
    private Double couponMoney;
    @ApiModelProperty("折扣抵扣金额")
    private Double discountMoney;
    @ApiModelProperty("折扣")
    private Double discount;
    @ApiModelProperty("补差价")
    private Double priceDifference;
    @ApiModelProperty("争议订单(0=否,1=是)")
    private Integer isDispute;
    public static MoneyInfoWarpper getMoneyInfoWarpper(Map<String, Object> map){
        MoneyInfoWarpper moneyInfoWarpper = new MoneyInfoWarpper();
        if(null != map){
            moneyInfoWarpper.setOrderMoney(null != map.get("orderMoney") ? Double.valueOf(map.get("orderMoney").toString()) : 0D);
            moneyInfoWarpper.setStartMileage(null != map.get("startMileage") ? Double.valueOf(map.get("startMileage").toString()) : 0D);
            moneyInfoWarpper.setStartMoney(null != map.get("startMoney") ? Double.valueOf(map.get("startMoney").toString()) : 0D);
            moneyInfoWarpper.setMileage(null != map.get("mileageKilometers") ? Double.valueOf(map.get("mileageKilometers").toString()) : 0D);
            moneyInfoWarpper.setMileageMoney(null != map.get("mileageMoney") ? Double.valueOf(map.get("mileageMoney").toString()) : 0D);
            moneyInfoWarpper.setDuration(null != map.get("duration") ? Double.valueOf(map.get("duration").toString()) : 0D);
            moneyInfoWarpper.setDurationMoney(null != map.get("durationMoney") ? Double.valueOf(map.get("durationMoney").toString()) : 0D);
            moneyInfoWarpper.setWait(null != map.get("wait") ? Double.valueOf(map.get("wait").toString()) : 0D);
            moneyInfoWarpper.setWaitMoney(null != map.get("waitMoney") ? Double.valueOf(map.get("waitMoney").toString()) : 0D);
            moneyInfoWarpper.setLongDistance(null != map.get("longDistance") ? Double.valueOf(map.get("longDistance").toString()) : 0D);
            moneyInfoWarpper.setLongDistanceMoney(null != map.get("longDistanceMoney") ? Double.valueOf(map.get("longDistanceMoney").toString()) : 0D);
            moneyInfoWarpper.setParkMoney(null != map.get("parkMoney") ? Double.valueOf(map.get("parkMoney").toString()) : 0D);
            moneyInfoWarpper.setRoadTollMoney(null != map.get("roadTollMoney") ? Double.valueOf(map.get("roadTollMoney").toString()) : 0D);
            moneyInfoWarpper.setRedPacketMoney(null != map.get("redPacketMoney") ? Double.valueOf(map.get("redPacketMoney").toString()) : 0D);
            moneyInfoWarpper.setCouponMoney(null != map.get("couponMoney") ? Double.valueOf(map.get("couponMoney").toString()) : 0D);
            moneyInfoWarpper.setDiscountMoney(null != map.get("discountMoney") ? Double.valueOf(map.get("discountMoney").toString()) : 0D);
            moneyInfoWarpper.setDiscount(null != map.get("discount") ? Double.valueOf(map.get("discount").toString()) : 0D);
            moneyInfoWarpper.setPriceDifference(null != map.get("priceDifference") ? Double.valueOf(map.get("priceDifference").toString()) : 0D);
            moneyInfoWarpper.setIsDispute(null != map.get("isDispute") ? Integer.valueOf(map.get("isDispute").toString()) : 0);
        }
        return moneyInfoWarpper;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/NoticeWrapper.java
New file
@@ -0,0 +1,26 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import java.util.Map;
/**
 * 部门列表的包装
 *
 * @author fengshuonan
 * @date 2017年4月25日 18:10:31
 */
public class NoticeWrapper extends BaseControllerWarpper {
    public NoticeWrapper(Object list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        Integer creater = (Integer) map.get("creater");
        map.put("createrName", ConstantFactory.me().getUserNameById(creater));
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderEvaluateWarpper.java
New file
@@ -0,0 +1,45 @@
package com.stylefeng.guns.modular.system.warpper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ApiModel("评价列表")
public class OrderEvaluateWarpper {
    @ApiModelProperty("总评分")
    private Double sumScore;
    @ApiModelProperty("历史评价列表")
    private List<JSONObject> list;
    public Double getSumScore() {
        return sumScore;
    }
    public void setSumScore(Double sumScore) {
        this.sumScore = sumScore;
    }
    public List<JSONObject> getList() {
        return list;
    }
    public void setList(List<JSONObject> list) {
        this.list = list;
    }
    public static OrderEvaluateWarpper getOrderEvaluateWarpper(Map<String, Object> map){
        OrderEvaluateWarpper orderEvaluateWarpper = new OrderEvaluateWarpper();
        if(null != map){
            orderEvaluateWarpper.setSumScore(null != map.get("sumScore") ? Double.valueOf(String.valueOf(map.get("sumScore"))) : 0);
            List<JSONObject> list = JSONArray.parseArray(JSON.toJSONString(map.get("list")), JSONObject.class);
            orderEvaluateWarpper.setList(null != map.get("list") ? list : new ArrayList<>());
        }
        return orderEvaluateWarpper;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderInfoWarpper.java
New file
@@ -0,0 +1,598 @@
package com.stylefeng.guns.modular.system.warpper;
import com.baomidou.mybatisplus.annotations.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
@ApiModel("订单详情22")
@Data
public class OrderInfoWarpper {
    @ApiModelProperty("订单id")
    private Integer orderId;
    @ApiModelProperty("状态(1=待接单,2=待出发,3=待到达预约地点,4=待乘客上车,5=服务中,6=完成服务,7=待支付,8=待评价,9=已完成,10=已取消,11=改派中,12=取消待支付,13=补差价)")
    private Integer orderState;
    @ApiModelProperty("订单名称")
    private String orderName;
    @ApiModelProperty("出行时间")
    private String travelTime;
    @ApiModelProperty("出行时间")
    private String travelTime_;
    @ApiModelProperty("到达预约点时间")
    private String arriveTime;
    @ApiModelProperty("起点")
    private String startAddress;
    @ApiModelProperty("终点")
    private String endAddress;
    @ApiModelProperty("红包")
    private Double tipMoney;
    @ApiModelProperty("司机当前位置到起点距离(公里)")
    private Double startDistance;
    @ApiModelProperty("全程公里数")
    private Double totalDistance;
    @ApiModelProperty("起点经度")
    private String startLon;
    @ApiModelProperty("起点纬度")
    private String startLat;
    @ApiModelProperty("终点经度")
    private String endLon;
    @ApiModelProperty("终点纬度")
    private String endLat;
    @ApiModelProperty("乘客昵称")
    private String nickName;
    @ApiModelProperty("乘客电话")
    private String phone;
    @ApiModelProperty("乘客历史乘车次数")
    private Integer historyNum;
    @ApiModelProperty("订单总金额")
    private Double orderMoney;
    @ApiModelProperty(value = "支付方式(1=OK平台支付(线上支付),2=其他方式支付(线下支付))", example = "1")
    private Integer payManner;
    @ApiModelProperty("小件物流差价")
    private Double priceDifference;
    @ApiModelProperty("支付金额")
    private Double payMoney;
    @ApiModelProperty("是否是改派单(1=否,2=是)")
    private Integer isReassign;
    @ApiModelProperty("高德猎鹰轨迹id(订单开始后需要上传坐标到指定轨迹中)")
    private String trackId;
    @ApiModelProperty("是否是预约单(1=否,2=是)")
    private Integer reservation;
    @ApiModelProperty("订单类型(乘客下单,调度下单,改派,预约)")
    private String type;
    @ApiModelProperty("报警电话")
    private String emergencyCall;
    @ApiModelProperty("取消原因")
    private String cancelReason;
    @ApiModelProperty("取消备注")
    private String cancelRemark;
    @ApiModelProperty("取消支付金额")
    private Double cancelPayMoney;
    @ApiModelProperty("取消方")
    private String cancelUser;
    @ApiModelProperty("能否改派(1=否,2=是)")
    private Integer reassign;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("乘车人数")
    private Integer peopleNumber;
    @ApiModelProperty("座位号")
    private String seatNumber;
    @ApiModelProperty("货物类型(1=普通货物,2=贵重货物)")
    private Integer cargoType;
    @ApiModelProperty("是否加急(1=否,2=是)")
    private Integer urgent;
    @ApiModelProperty("下单用户姓名")
    private String userName;
    @ApiModelProperty("下单用户电话")
    private String userPhone;
    @ApiModelProperty("司机支付状态【现金支付需要司机代支付】(1=待支付,2=已支付)")
    private Integer driverPay;
    @ApiModelProperty("轨迹")
    private String orderPositionList;
    private Integer startDuration;
    @ApiModelProperty("是否冻结(1=否,2=是)")
    private Integer isFrozen;
    @ApiModelProperty("超时取消时间")
    private Long timeOutCancel;
    @ApiModelProperty("超时语音文件地址")
    private String audioUrl;
    @ApiModelProperty("接单时间")
    private String snatchOrderTime;
    private String tripId;
    @ApiModelProperty("中途取消(0=否,1=是)")
    private Integer cancelMidway;
    @ApiModelProperty("争议订单(0=否,1=是)")
    private Integer isDispute;
    public Integer getStartDuration() {
        return startDuration;
    }
    public void setStartDuration(Integer startDuration) {
        this.startDuration = startDuration;
    }
    public String getOrderPositionList() {
        return orderPositionList;
    }
    public void setOrderPositionList(String orderPositionList) {
        this.orderPositionList = orderPositionList;
    }
    public Integer getOrderId() {
        return orderId;
    }
    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }
    public Integer getOrderState() {
        return orderState;
    }
    public void setOrderState(Integer orderState) {
        this.orderState = orderState;
    }
    public String getOrderName() {
        return orderName;
    }
    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }
    public String getTravelTime() {
        return travelTime;
    }
    public void setTravelTime(String travelTime) {
        this.travelTime = travelTime;
    }
    public String getStartAddress() {
        return startAddress;
    }
    public void setStartAddress(String startAddress) {
        this.startAddress = startAddress;
    }
    public String getEndAddress() {
        return endAddress;
    }
    public void setEndAddress(String endAddress) {
        this.endAddress = endAddress;
    }
    public Double getTipMoney() {
        return tipMoney;
    }
    public void setTipMoney(Double tipMoney) {
        this.tipMoney = tipMoney;
    }
    public Double getStartDistance() {
        return startDistance;
    }
    public void setStartDistance(Double startDistance) {
        this.startDistance = startDistance;
    }
    public Double getTotalDistance() {
        return totalDistance;
    }
    public void setTotalDistance(Double totalDistance) {
        this.totalDistance = totalDistance;
    }
    public String getStartLon() {
        return startLon;
    }
    public void setStartLon(String startLon) {
        this.startLon = startLon;
    }
    public String getStartLat() {
        return startLat;
    }
    public void setStartLat(String startLat) {
        this.startLat = startLat;
    }
    public String getEndLon() {
        return endLon;
    }
    public void setEndLon(String endLon) {
        this.endLon = endLon;
    }
    public String getEndLat() {
        return endLat;
    }
    public void setEndLat(String endLat) {
        this.endLat = endLat;
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public Integer getHistoryNum() {
        return historyNum;
    }
    public void setHistoryNum(Integer historyNum) {
        this.historyNum = historyNum;
    }
    public Double getOrderMoney() {
        return orderMoney;
    }
    public void setOrderMoney(Double orderMoney) {
        this.orderMoney = orderMoney;
    }
    public Integer getPayManner() {
        return payManner;
    }
    public void setPayManner(Integer payManner) {
        this.payManner = payManner;
    }
    public Double getPayMoney() {
        return payMoney;
    }
    public void setPayMoney(Double payMoney) {
        this.payMoney = payMoney;
    }
    public Integer getIsReassign() {
        return isReassign;
    }
    public void setIsReassign(Integer isReassign) {
        this.isReassign = isReassign;
    }
    public String getTrackId() {
        return trackId;
    }
    public void setTrackId(String trackId) {
        this.trackId = trackId;
    }
    public String getArriveTime() {
        return arriveTime;
    }
    public void setArriveTime(String arriveTime) {
        this.arriveTime = arriveTime;
    }
    public Integer getReservation() {
        return reservation;
    }
    public void setReservation(Integer reservation) {
        this.reservation = reservation;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getEmergencyCall() {
        return emergencyCall;
    }
    public void setEmergencyCall(String emergencyCall) {
        this.emergencyCall = emergencyCall;
    }
    public String getTravelTime_() {
        return travelTime_;
    }
    public void setTravelTime_(String travelTime_) {
        this.travelTime_ = travelTime_;
    }
    public String getCancelReason() {
        return cancelReason;
    }
    public void setCancelReason(String cancelReason) {
        this.cancelReason = cancelReason;
    }
    public String getCancelRemark() {
        return cancelRemark;
    }
    public void setCancelRemark(String cancelRemark) {
        this.cancelRemark = cancelRemark;
    }
    public Double getCancelPayMoney() {
        return cancelPayMoney;
    }
    public void setCancelPayMoney(Double cancelPayMoney) {
        this.cancelPayMoney = cancelPayMoney;
    }
    public String getCancelUser() {
        return cancelUser;
    }
    public void setCancelUser(String cancelUser) {
        this.cancelUser = cancelUser;
    }
    public Integer getReassign() {
        return reassign;
    }
    public void setReassign(Integer reassign) {
        this.reassign = reassign;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public Integer getPeopleNumber() {
        return peopleNumber;
    }
    public void setPeopleNumber(Integer peopleNumber) {
        this.peopleNumber = peopleNumber;
    }
    public String getSeatNumber() {
        return seatNumber;
    }
    public void setSeatNumber(String seatNumber) {
        this.seatNumber = seatNumber;
    }
    public Integer getCargoType() {
        return cargoType;
    }
    public void setCargoType(Integer cargoType) {
        this.cargoType = cargoType;
    }
    public Integer getUrgent() {
        return urgent;
    }
    public void setUrgent(Integer urgent) {
        this.urgent = urgent;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Integer getDriverPay() {
        return driverPay;
    }
    public void setDriverPay(Integer driverPay) {
        this.driverPay = driverPay;
    }
    public Integer getIsFrozen() {
        return isFrozen;
    }
    public void setIsFrozen(Integer isFrozen) {
        this.isFrozen = isFrozen;
    }
    public Long getTimeOutCancel() {
        return timeOutCancel;
    }
    public void setTimeOutCancel(Long timeOutCancel) {
        this.timeOutCancel = timeOutCancel;
    }
    public String getSnatchOrderTime() {
        return snatchOrderTime;
    }
    public void setSnatchOrderTime(String snatchOrderTime) {
        this.snatchOrderTime = snatchOrderTime;
    }
    public String getUserPhone() {
        return userPhone;
    }
    public void setUserPhone(String userPhone) {
        this.userPhone = userPhone;
    }
    public String getTripId() {
        return tripId;
    }
    public void setTripId(String tripId) {
        this.tripId = tripId;
    }
    public Integer getCancelMidway() {
        return cancelMidway;
    }
    public void setCancelMidway(Integer cancelMidway) {
        this.cancelMidway = cancelMidway;
    }
    public String getAudioUrl() {
        return audioUrl;
    }
    public void setAudioUrl(String audioUrl) {
        this.audioUrl = audioUrl;
    }
    public Double getPriceDifference() {
        return priceDifference;
    }
    public void setPriceDifference(Double priceDifference) {
        this.priceDifference = priceDifference;
    }
    public Integer getIsDispute() {
        return isDispute;
    }
    public void setIsDispute(Integer isDispute) {
        this.isDispute = isDispute;
    }
    @Override
    public String toString() {
        return "OrderInfoWarpper{" +
                "orderId=" + orderId +
                ", orderState=" + orderState +
                ", orderName='" + orderName + '\'' +
                ", travelTime='" + travelTime + '\'' +
                ", travelTime_='" + travelTime_ + '\'' +
                ", arriveTime='" + arriveTime + '\'' +
                ", startAddress='" + startAddress + '\'' +
                ", endAddress='" + endAddress + '\'' +
                ", tipMoney=" + tipMoney +
                ", startDistance=" + startDistance +
                ", totalDistance=" + totalDistance +
                ", startLon='" + startLon + '\'' +
                ", startLat='" + startLat + '\'' +
                ", endLon='" + endLon + '\'' +
                ", endLat='" + endLat + '\'' +
                ", nickName='" + nickName + '\'' +
                ", phone='" + phone + '\'' +
                ", historyNum=" + historyNum +
                ", orderMoney=" + orderMoney +
                ", payManner=" + payManner +
                ", payMoney=" + payMoney +
                ", isReassign=" + isReassign +
                ", trackId='" + trackId + '\'' +
                ", reservation=" + reservation +
                ", type='" + type + '\'' +
                ", emergencyCall='" + emergencyCall + '\'' +
                ", cancelReason='" + cancelReason + '\'' +
                ", cancelRemark='" + cancelRemark + '\'' +
                ", cancelPayMoney=" + cancelPayMoney +
                ", cancelUser='" + cancelUser + '\'' +
                ", reassign=" + reassign +
                ", remark='" + remark + '\'' +
                ", peopleNumber=" + peopleNumber +
                ", seatNumber='" + seatNumber + '\'' +
                ", cargoType=" + cargoType +
                ", urgent=" + urgent +
                '}';
    }
    public static OrderInfoWarpper getOrderInfoWarpper(Map<String, Object> map){
        OrderInfoWarpper orderInfoWarpper = new OrderInfoWarpper();
        if(null != map){
            orderInfoWarpper.setOrderId(null != map.get("orderId") ? Integer.valueOf(String.valueOf(map.get("orderId"))) : 0);
            orderInfoWarpper.setStartDuration(null != map.get("startDuration") ? Integer.valueOf(String.valueOf(map.get("startDuration"))) : 0);
            orderInfoWarpper.setOrderState(null != map.get("orderState") ? Integer.valueOf(String.valueOf(map.get("orderState"))) : 0);
            orderInfoWarpper.setOrderName(null != map.get("orderName") ? String.valueOf(map.get("orderName")) : "");
            orderInfoWarpper.setTravelTime(null != map.get("travelTime") ? String.valueOf(map.get("travelTime")) : "");
            orderInfoWarpper.setTravelTime_(null != map.get("travelTime_") ? String.valueOf(map.get("travelTime_")) : "");
            orderInfoWarpper.setArriveTime(null != map.get("arriveTime") ? String.valueOf(map.get("arriveTime")) : "");
            orderInfoWarpper.setStartAddress(null != map.get("startAddress") ? String.valueOf(map.get("startAddress")) : "");
            orderInfoWarpper.setEndAddress(null != map.get("endAddress") ? String.valueOf(map.get("endAddress")) : "");
            orderInfoWarpper.setTipMoney(null != map.get("tipMoney") ? Double.valueOf(String.valueOf(map.get("tipMoney"))) : 0);
            orderInfoWarpper.setStartDistance(null != map.get("startDistance") ? Double.valueOf(String.valueOf(map.get("startDistance"))) : 0);
            orderInfoWarpper.setTotalDistance(null != map.get("totalDistance") ? Double.valueOf(String.valueOf(map.get("totalDistance"))) : 0);
            orderInfoWarpper.setStartLon(null != map.get("startLon") ? String.valueOf(map.get("startLon")) : "");
            orderInfoWarpper.setStartLat(null != map.get("startLat") ? String.valueOf(map.get("startLat")) : "");
            orderInfoWarpper.setEndLon(null != map.get("endLon") ? String.valueOf(map.get("endLon")) : "");
            orderInfoWarpper.setEndLat(null != map.get("endLat") ? String.valueOf(map.get("endLat")) : "");
            orderInfoWarpper.setNickName(null != map.get("nickName") ? String.valueOf(map.get("nickName")) : "");
            orderInfoWarpper.setPhone(null != map.get("telX") ? String.valueOf(map.get("telX")) : (null != map.get("phone") ? String.valueOf(map.get("phone")) : ""));
            orderInfoWarpper.setHistoryNum(null != map.get("historyNum") ? Integer.valueOf(String.valueOf(map.get("historyNum"))) : 0);
            orderInfoWarpper.setOrderMoney(null != map.get("orderMoney") ? Double.valueOf(String.valueOf(map.get("orderMoney"))) : 0);
            orderInfoWarpper.setPayManner(null != map.get("payManner") ? Integer.valueOf(String.valueOf(map.get("payManner"))) : 0);
            orderInfoWarpper.setPayMoney(null != map.get("payMoney") ? Double.valueOf(String.valueOf(map.get("payMoney"))) : 0);
            orderInfoWarpper.setIsReassign(null != map.get("isReassign") ? Integer.valueOf(String.valueOf(map.get("isReassign"))) : 1);
            orderInfoWarpper.setTrackId(null != map.get("trackId") ? String.valueOf(map.get("trackId")) : "");
            orderInfoWarpper.setReservation(null != map.get("reservation") ? Integer.valueOf(String.valueOf(map.get("reservation"))) : 0);
            orderInfoWarpper.setType(null != map.get("type") ? String.valueOf(map.get("type")) : "");
            orderInfoWarpper.setEmergencyCall(null != map.get("emergencyCall") ? String.valueOf(map.get("emergencyCall")) : "");
            orderInfoWarpper.setCancelReason(null != map.get("cancelReason") ? String.valueOf(map.get("cancelReason")) : "");
            orderInfoWarpper.setCancelRemark(null != map.get("cancelRemark") ? String.valueOf(map.get("cancelRemark")) : "");
            orderInfoWarpper.setCancelPayMoney(null != map.get("cancelPayMoney") ? Double.valueOf(String.valueOf(map.get("cancelPayMoney"))) : 0);
            orderInfoWarpper.setCancelUser(null != map.get("cancelUser") ? String.valueOf(map.get("cancelUser")) : "");
            orderInfoWarpper.setReassign(null != map.get("reassign") ? Integer.valueOf(String.valueOf(map.get("reassign"))) : 1);
            orderInfoWarpper.setPeopleNumber(null != map.get("peopleNumber") ? Integer.valueOf(String.valueOf(map.get("peopleNumber"))) : 1);
            orderInfoWarpper.setRemark(null != map.get("remark") ? String.valueOf(map.get("remark")) : "");
            orderInfoWarpper.setSeatNumber(null != map.get("seatNumber") ? String.valueOf(map.get("seatNumber")) : "");
            orderInfoWarpper.setCargoType(null != map.get("cargoType") ? Integer.valueOf(map.get("cargoType").toString()) : 0);
            orderInfoWarpper.setUrgent(null != map.get("urgent") ? Integer.valueOf(map.get("urgent").toString()) : 0);
            orderInfoWarpper.setUserName(null != map.get("userName") ? String.valueOf(map.get("userName")) : "");
            orderInfoWarpper.setDriverPay(null != map.get("driverPay") ? Integer.valueOf(map.get("driverPay").toString()) : 0);
            orderInfoWarpper.setIsFrozen(null != map.get("isFrozen") ? Integer.valueOf(map.get("isFrozen").toString()) : 1);
            orderInfoWarpper.setTimeOutCancel(null != map.get("timeOutCancel") ? Long.valueOf(map.get("timeOutCancel").toString()) : 0);
            orderInfoWarpper.setSnatchOrderTime(null != map.get("snatchOrderTime") ? map.get("snatchOrderTime").toString() : "");
            orderInfoWarpper.setUserPhone(null != map.get("userPhone") ? map.get("userPhone").toString() : "");
            orderInfoWarpper.setTripId(null != map.get("tripId") ? map.get("tripId").toString() : "");
            orderInfoWarpper.setCancelMidway(null != map.get("cancelMidway") ? Integer.valueOf(map.get("cancelMidway").toString()) : 0);
            orderInfoWarpper.setAudioUrl(null != map.get("audioUrl") ? map.get("audioUrl").toString() : "");
            orderInfoWarpper.setPriceDifference(null != map.get("priceDifference") ? Double.valueOf(map.get("priceDifference").toString()) : 0);
            orderInfoWarpper.setIsDispute(null != map.get("isDispute") ? Integer.valueOf(map.get("isDispute").toString()) : 0);
        }
        return orderInfoWarpper;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderListWarpper.java
New file
@@ -0,0 +1,271 @@
package com.stylefeng.guns.modular.system.warpper;
import com.baomidou.mybatisplus.annotations.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ApiModel("订单列表")
public class OrderListWarpper implements Comparable {
    @ApiModelProperty("订单id")
    private Integer id;
    @ApiModelProperty("订单类型(1=专车,2=出租车,3=城际,4=小件物流-同城,5=小件物流-跨城,6=包车)")
    private Integer type;
    @ApiModelProperty("订单名称")
    private String name;
    @ApiModelProperty("订单时间")
    private String time;
    @ApiModelProperty("出发地")
    private String startAddress;
    @ApiModelProperty("目的地")
    private String endAddress;
    @ApiModelProperty("红包金额")
    private Double redMoney;
    @ApiModelProperty("订单金额")
    private Double orderMoney;
    @ApiModelProperty("状态(1=待接单,2=待出发,3=待到达预约地点,4=待乘客上车,5=服务中,6=完成服务,7=待支付,8=待评价,9=已完成,10=已取消,11=改派中,12=取消待支付,13=补差价)")
    private Integer state;
    @ApiModelProperty("人数")
    private Integer peopleNumber;
    @ApiModelProperty("下单用户")
    private String user;
    @ApiModelProperty("货物信息")
    private String cargoNumber;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("支付方式(1=OK平台支付(线上支付),2=其他方式支付(线下支付))")
    private Integer payManner;
    private Long travelTime;
    @ApiModelProperty("司机支付状态(现金支付司机代支付)1待支付 2已支付")
    private Integer driverPay;
    @ApiModelProperty("中途取消(0=否,1=是)")
    private Integer cancelMidway;
    @ApiModelProperty("结算状态(0=否,1=是)")
    private Integer settleAccounts;
    @ApiModelProperty("是否冻结(1=否,2=是)")
    private Integer isFrozen;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getTime() {
        return time;
    }
    public void setTime(String time) {
        this.time = time;
    }
    public String getStartAddress() {
        return startAddress;
    }
    public void setStartAddress(String startAddress) {
        this.startAddress = startAddress;
    }
    public String getEndAddress() {
        return endAddress;
    }
    public void setEndAddress(String endAddress) {
        this.endAddress = endAddress;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    public Double getRedMoney() {
        return redMoney;
    }
    public void setRedMoney(Double redMoney) {
        this.redMoney = redMoney;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public Double getOrderMoney() {
        return orderMoney;
    }
    public void setOrderMoney(Double orderMoney) {
        this.orderMoney = orderMoney;
    }
    public Integer getPeopleNumber() {
        return peopleNumber;
    }
    public void setPeopleNumber(Integer peopleNumber) {
        this.peopleNumber = peopleNumber;
    }
    public String getUser() {
        return user;
    }
    public void setUser(String user) {
        this.user = user;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public Integer getPayManner() {
        return payManner;
    }
    public void setPayManner(Integer payManner) {
        this.payManner = payManner;
    }
    public Long getTravelTime() {
        return travelTime;
    }
    public void setTravelTime(Long travelTime) {
        this.travelTime = travelTime;
    }
    public String getCargoNumber() {
        return cargoNumber;
    }
    public void setCargoNumber(String cargoNumber) {
        this.cargoNumber = cargoNumber;
    }
    public Integer getDriverPay() {
        return driverPay;
    }
    public void setDriverPay(Integer driverPay) {
        this.driverPay = driverPay;
    }
    public Integer getCancelMidway() {
        return cancelMidway;
    }
    public void setCancelMidway(Integer cancelMidway) {
        this.cancelMidway = cancelMidway;
    }
    public Integer getSettleAccounts() {
        return settleAccounts;
    }
    public void setSettleAccounts(Integer settleAccounts) {
        this.settleAccounts = settleAccounts;
    }
    public Integer getIsFrozen() {
        return isFrozen;
    }
    public void setIsFrozen(Integer isFrozen) {
        this.isFrozen = isFrozen;
    }
    @Override
    public String toString() {
        return "OrderListWarpper{" +
                "id=" + id +
                ", type=" + type +
                ", name='" + name + '\'' +
                ", time='" + time + '\'' +
                ", startAddress='" + startAddress + '\'' +
                ", endAddress='" + endAddress + '\'' +
                ", redMoney=" + redMoney +
                ", orderMoney=" + orderMoney +
                ", state=" + state +
                ", peopleNumber=" + peopleNumber +
                ", user='" + user + '\'' +
                ", remark='" + remark + '\'' +
                ", payManner=" + payManner +
                '}';
    }
    public static List<OrderListWarpper> getOrderListWarpper(List<Map<String, Object>> maps){
        List<OrderListWarpper> list = new ArrayList<>();
        if(null != maps){
            for(Map<String, Object> map : maps){
                OrderListWarpper orderListWarpper = new OrderListWarpper();
                orderListWarpper.setId(null != map.get("id") ? Integer.valueOf(String.valueOf(map.get("id"))) : 0);
                orderListWarpper.setName(null != map.get("name") ? String.valueOf(map.get("name")) : "");
                orderListWarpper.setTime(null != map.get("time") ? String.valueOf(map.get("time")) : "");
                orderListWarpper.setStartAddress(null != map.get("startAddress") ? String.valueOf(map.get("startAddress")) : "");
                orderListWarpper.setEndAddress(null != map.get("endAddress") ? String.valueOf(map.get("endAddress")) : "");
                orderListWarpper.setState(null != map.get("state") ? Integer.valueOf(String.valueOf(map.get("state"))) : 0);
                orderListWarpper.setRedMoney(null != map.get("redMoney") ? Double.valueOf(String.valueOf(map.get("redMoney"))) : 0);
                orderListWarpper.setOrderMoney(null != map.get("orderMoney") ? Double.valueOf(String.valueOf(map.get("orderMoney"))) : 0);
                orderListWarpper.setType(null != map.get("type") ? Integer.valueOf(String.valueOf(map.get("type"))) : 0);
                orderListWarpper.setPeopleNumber(null != map.get("peopleNumber") ? Integer.valueOf(String.valueOf(map.get("peopleNumber"))) : 0);
                orderListWarpper.setUser(null != map.get("user") ? String.valueOf(map.get("user")) : "");
                orderListWarpper.setCargoNumber(null != map.get("cargoNumber") ? String.valueOf(map.get("cargoNumber")) : "");
                orderListWarpper.setRemark(null != map.get("remark") ? String.valueOf(map.get("remark")) : "");
                orderListWarpper.setPayManner(null != map.get("payManner") ? Integer.valueOf(String.valueOf(map.get("payManner"))) : 0);
                orderListWarpper.setTravelTime(null != map.get("travelTime") ? Long.valueOf(String.valueOf(map.get("travelTime"))) : 0);
                orderListWarpper.setDriverPay(null != map.get("driverPay") ? Integer.valueOf(map.get("driverPay").toString()) : 1);
                orderListWarpper.setCancelMidway(null != map.get("cancelMidway") ? Integer.valueOf(map.get("cancelMidway").toString()) : 0);
                orderListWarpper.setSettleAccounts(null != map.get("settleAccounts") ? Integer.valueOf(map.get("settleAccounts").toString()) : 0);
                orderListWarpper.setIsFrozen(null != map.get("isFrozen") ? Integer.valueOf(map.get("isFrozen").toString()) : 0);
                list.add(orderListWarpper);
            }
        }
        Collections.sort(list);
        return list;
    }
    @Override
    public int compareTo(Object o) {
        if (o instanceof OrderListWarpper) {
            OrderListWarpper s = (OrderListWarpper) o;
            if(this.travelTime == null || s.travelTime == null){
                return -1;
            }
            if (this.travelTime > s.travelTime) {
                return -1;
            } else if (this.travelTime == s.travelTime) {
                return 0;
            } else {
                return 1;
            }
        }
        return 0;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrderStatusWarpper.java
New file
@@ -0,0 +1,38 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("订单状态")
public class OrderStatusWarpper {
    @ApiModelProperty("订单id")
    private Integer orderId;
    @ApiModelProperty("订单类型(1=专车,2=出租车,3=城际,4=小件物流-同城,5=小件物流-跨城,6=包车)")
    private Integer orderType;
    @ApiModelProperty("状态(1=待接单,2=待出发,3=待到达预约地点,4=待乘客上车,5=服务中,6=完成服务,7=待支付,8=待评价,9=已完成,10=已取消,11=改派中,12=取消待支付,13=补差价)")
    private Integer state;
    public Integer getOrderId() {
        return orderId;
    }
    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }
    public Integer getOrderType() {
        return orderType;
    }
    public void setOrderType(Integer orderType) {
        this.orderType = orderType;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/OrdersWarpper.java
New file
@@ -0,0 +1,38 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("可接单业务")
public class OrdersWarpper {
    @ApiModelProperty("类型")
    private Integer type;
    @ApiModelProperty("类型名称")
    private String name;
    @ApiModelProperty("是否已设置(1=否,2=是)")
    private Integer state;
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/QueryHistoricalSettlement.java
New file
@@ -0,0 +1,24 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2023/8/17 12:39
 */
@Data
@ApiModel
public class QueryHistoricalSettlement {
    @ApiModelProperty("结算日期")
    private String createTime;
    @ApiModelProperty("结算金额")
    private Double price;
    @ApiModelProperty("结算总金额")
    private Double totalPrice;
    @ApiModelProperty("结算周期(1=日结算,2=周结算,3=月结算)")
    private Integer type;
    @ApiModelProperty("支付方式")
    private String payType;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/QuerySettlementAmount.java
New file
@@ -0,0 +1,22 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2023/8/17 9:41
 */
@Data
@ApiModel
public class QuerySettlementAmount {
    @ApiModelProperty("标题类型(1=日结算,2=周结算,3=月结算)")
    private Integer type;
    @ApiModelProperty("总待支付金额")
    private Double amount;
    @ApiModelProperty("明细列表")
    private List<QuerySettlementAmountDetails> list;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/QuerySettlementAmountDetails.java
New file
@@ -0,0 +1,20 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @author zhibing.pu
 * @Date 2023/8/17 9:42
 */
@Data
@ApiModel
public class QuerySettlementAmountDetails {
    @ApiModelProperty("订单日期")
    private String orderTime;
    @ApiModelProperty("订单金额")
    private Double orderMoney;
    @ApiModelProperty("应付金额")
    private Double payMoney;
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/RegisteredWarpper.java
New file
@@ -0,0 +1,209 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
@ApiModel("司机注册信息")
public class RegisteredWarpper {
    @ApiModelProperty("电话")
    private String phone;
    @ApiModelProperty("密码")
    private String password;
    @ApiModelProperty("姓")
    private String lastName;
    @ApiModelProperty("名")
    private String firstName;
    @ApiModelProperty("生日")
    private Date birthday;
    @ApiModelProperty("性别(1=男,2=女)")
    private Integer sex;
    @ApiModelProperty("居住地")
    private String driverContactAddress;
    @ApiModelProperty("居住地(带分隔符)")
    private String driverContactAddress_;
    @ApiModelProperty("身份证号码")
    private String idCard;
    @ApiModelProperty("身份证正面照")
    private String idCardImgUrl1;
    @ApiModelProperty("身份证背面照")
    private String idCardImgUrl2;
    @ApiModelProperty("服务模式(1=专车,2=出租车,3=城际,4=小件物流-同城,5=小件物流-跨城,6=包车)多个以逗号分隔")
    private String type;
    @ApiModelProperty("邮件")
    private String email;
    @ApiModelProperty("从业地城市id")
    private Integer placeOfPracticeId;
    @ApiModelProperty("头像")
    private String headImgUrl;
    @ApiModelProperty("驾驶证照片正面")
    private String driveCardImgUrl;
    @ApiModelProperty("驾驶证照片背面")
    private String driveCardImgUrl2;
    @ApiModelProperty("驾驶证号")
    private String driveCard;
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getDriverContactAddress() {
        return driverContactAddress;
    }
    public void setDriverContactAddress(String driverContactAddress) {
        this.driverContactAddress = driverContactAddress;
    }
    public String getDriverContactAddress_() {
        return driverContactAddress_;
    }
    public void setDriverContactAddress_(String driverContactAddress_) {
        this.driverContactAddress_ = driverContactAddress_;
    }
    public Integer getSex() {
        return sex;
    }
    public void setSex(Integer sex) {
        this.sex = sex;
    }
    public String getIdCard() {
        return idCard;
    }
    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }
    public String getIdCardImgUrl1() {
        return idCardImgUrl1;
    }
    public void setIdCardImgUrl1(String idCardImgUrl1) {
        this.idCardImgUrl1 = idCardImgUrl1;
    }
    public String getIdCardImgUrl2() {
        return idCardImgUrl2;
    }
    public void setIdCardImgUrl2(String idCardImgUrl2) {
        this.idCardImgUrl2 = idCardImgUrl2;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Integer getPlaceOfPracticeId() {
        return placeOfPracticeId;
    }
    public void setPlaceOfPracticeId(Integer placeOfPracticeId) {
        this.placeOfPracticeId = placeOfPracticeId;
    }
    public String getHeadImgUrl() {
        return headImgUrl;
    }
    public void setHeadImgUrl(String headImgUrl) {
        this.headImgUrl = headImgUrl;
    }
    public String getDriveCardImgUrl() {
        return driveCardImgUrl;
    }
    public void setDriveCardImgUrl(String driveCardImgUrl) {
        this.driveCardImgUrl = driveCardImgUrl;
    }
    public String getDriveCardImgUrl2() {
        return driveCardImgUrl2;
    }
    public void setDriveCardImgUrl2(String driveCardImgUrl2) {
        this.driveCardImgUrl2 = driveCardImgUrl2;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getDriveCard() {
        return driveCard;
    }
    public void setDriveCard(String driveCard) {
        this.driveCard = driveCard;
    }
    @Override
    public String toString() {
        return "RegisteredWarpper{" +
                "phone='" + phone + '\'' +
                ", password='" + password + '\'' +
                ", driverContactAddress='" + driverContactAddress + '\'' +
                ", driverContactAddress_='" + driverContactAddress_ + '\'' +
                ", idCard='" + idCard + '\'' +
                ", idCardImgUrl1='" + idCardImgUrl1 + '\'' +
                ", idCardImgUrl2='" + idCardImgUrl2 + '\'' +
                ", type='" + type + '\'' +
                ", email='" + email + '\'' +
                ", placeOfPracticeId=" + placeOfPracticeId +
                ", headImgUrl='" + headImgUrl + '\'' +
                ", driveCardImgUrl2='" + driveCardImgUrl2 + '\'' +
                '}';
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/RoleWarpper.java
New file
@@ -0,0 +1,27 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import java.util.List;
import java.util.Map;
/**
 * 角色列表的包装类
 *
 * @author fengshuonan
 * @date 2017年2月19日10:59:02
 */
public class RoleWarpper extends BaseControllerWarpper {
    public RoleWarpper(List<Map<String, Object>> list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        map.put("pName", ConstantFactory.me().getSingleRoleName((Integer) map.get("pid")));
        map.put("deptName", ConstantFactory.me().getDeptName((Integer) map.get("deptid")));
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/SystemNoticeWarpper.java
New file
@@ -0,0 +1,113 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ApiModel("消息类表")
public class SystemNoticeWarpper {
    @ApiModelProperty("主键")
    private Integer id;
    @ApiModelProperty("类型(1=公告,2=系统消息)")
    private Integer type;
    @ApiModelProperty("标题")
    private String title;
    @ApiModelProperty("内容")
    private String content;
    @ApiModelProperty("图片")
    private String img;
    @ApiModelProperty("时间")
    private String time;
    @ApiModelProperty("阅读状态(1=未读,2=已读)")
    private Integer read;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public String getImg() {
        return img;
    }
    public void setImg(String img) {
        this.img = img;
    }
    public String getTime() {
        return time;
    }
    public void setTime(String time) {
        this.time = time;
    }
    public Integer getRead() {
        return read;
    }
    public void setRead(Integer read) {
        this.read = read;
    }
    @Override
    public String toString() {
        return "SystemNoticeWarpper{" +
                "id=" + id +
                ", type=" + type +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", img='" + img + '\'' +
                ", time='" + time + '\'' +
                '}';
    }
    public static List<SystemNoticeWarpper> getSystemNoticeWarpper(List<Map<String, Object>> maps){
        List<SystemNoticeWarpper> list = new ArrayList<>();
        if(null != maps){
            for(Map<String, Object> map : maps){
                SystemNoticeWarpper systemNoticeWarpper = new SystemNoticeWarpper();
                systemNoticeWarpper.setId(null != map.get("id") ? Integer.valueOf(String.valueOf(map.get("id"))) : 0);
                systemNoticeWarpper.setType(null != map.get("type") ? Integer.valueOf(String.valueOf(map.get("type"))) : 0);
                systemNoticeWarpper.setTitle(null != map.get("title") ? String.valueOf(map.get("title")) : "");
                systemNoticeWarpper.setContent(null != map.get("content") ? String.valueOf(map.get("content")) : "");
                systemNoticeWarpper.setImg(null != map.get("img") ? String.valueOf(map.get("img")) : "");
                systemNoticeWarpper.setTime(null != map.get("time") ? String.valueOf(map.get("time")) : "");
                systemNoticeWarpper.setRead(null != map.get("read") ? Integer.valueOf(String.valueOf(map.get("read"))) : 0);
                list.add(systemNoticeWarpper);
            }
        }
        return list;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/UserWarpper.java
New file
@@ -0,0 +1,29 @@
package com.stylefeng.guns.modular.system.warpper;
import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import java.util.List;
import java.util.Map;
/**
 * 用户管理的包装类
 *
 * @author fengshuonan
 * @date 2017年2月13日 下午10:47:03
 */
public class UserWarpper extends BaseControllerWarpper {
    public UserWarpper(List<Map<String, Object>> list) {
        super(list);
    }
    @Override
    public void warpTheMap(Map<String, Object> map) {
        map.put("sexName", ConstantFactory.me().getSexName((Integer) map.get("sex")));
        map.put("roleName", ConstantFactory.me().getRoleName((String) map.get("roleid")));
        map.put("deptName", ConstantFactory.me().getDeptName((Integer) map.get("deptid")));
        map.put("statusName", ConstantFactory.me().getStatusName((Integer) map.get("status")));
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/VersionWarpper.java
New file
@@ -0,0 +1,84 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Map;
@ApiModel("版本")
public class VersionWarpper {
    @ApiModelProperty("主键")
    private Integer id = 0;
    @ApiModelProperty("包地址")
    private String url;
    @ApiModelProperty("版本说明")
    private String content;
    @ApiModelProperty("是否强制更新(0=否,1=是)")
    private Integer mandatory = 0;
    @ApiModelProperty("版本号")
    private String version;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Integer getMandatory() {
        return mandatory;
    }
    public void setMandatory(Integer mandatory) {
        this.mandatory = mandatory;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    @Override
    public String toString() {
        return "VersionWarpper{" +
                "id=" + id +
                ", url='" + url + '\'' +
                ", content='" + content + '\'' +
                ", mandatory=" + mandatory +
                ", version='" + version + '\'' +
                '}';
    }
    public static VersionWarpper getVersionWarpper(Map<String, Object> map){
        VersionWarpper versionWarpper = new VersionWarpper();
        if(null != map){
            versionWarpper.setId(null != map.get("id") ? Integer.valueOf(String.valueOf(map.get("id"))) : 0);
            versionWarpper.setUrl(null != map.get("url") ? String.valueOf(map.get("url")) : "");
            versionWarpper.setContent(null != map.get("content") ? String.valueOf(map.get("content")) : "");
            versionWarpper.setMandatory(null != map.get("mandatory") ? Integer.valueOf(String.valueOf(map.get("mandatory"))) : 0);
            versionWarpper.setVersion(null != map.get("version") ? String.valueOf(map.get("version")) : "");
        }
        return versionWarpper;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/WithdrawalListWarpper.java
New file
@@ -0,0 +1,101 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ApiModel("提现历史记录")
public class WithdrawalListWarpper {
    @ApiModelProperty("主键")
    private Integer id;
    @ApiModelProperty("提现时间")
    private String insertTime;
    @ApiModelProperty("提现金额")
    private Double money;
    @ApiModelProperty("提现方式")
    private String name;
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty("提现状态(1=待处理,2=成功,3=失败)")
    private Integer state;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getInsertTime() {
        return insertTime;
    }
    public void setInsertTime(String insertTime) {
        this.insertTime = insertTime;
    }
    public Double getMoney() {
        return money;
    }
    public void setMoney(Double money) {
        this.money = money;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    @Override
    public String toString() {
        return "WithdrawalWarpper{" +
                "id=" + id +
                ", insertTime='" + insertTime + '\'' +
                ", money=" + money +
                ", name='" + name + '\'' +
                ", remark='" + remark + '\'' +
                ", state=" + state +
                '}';
    }
    public static List<WithdrawalListWarpper> getWithdrawalWarpper(List<Map<String, Object>> maps){
        List<WithdrawalListWarpper> list = new ArrayList<>();
        if(null != maps){
            for(Map<String, Object> map : maps){
                WithdrawalListWarpper withdrawalWarpper = new WithdrawalListWarpper();
                withdrawalWarpper.setId(null != map.get("id") ? Integer.valueOf(String.valueOf(map.get("id"))) : 0);
                withdrawalWarpper.setMoney(null != map.get("money") ? Double.valueOf(String.valueOf(map.get("money"))) : 0);
                withdrawalWarpper.setName(null != map.get("name") ? String.valueOf(map.get("name")) : "");
                withdrawalWarpper.setRemark(null != map.get("remark") ? String.valueOf(map.get("remark")) : "");
                withdrawalWarpper.setState(null != map.get("state") ? Integer.valueOf(String.valueOf(map.get("state"))) : 0);
                withdrawalWarpper.setInsertTime(null != map.get("insertTime") ? String.valueOf(map.get("insertTime")) : "");
                list.add(withdrawalWarpper);
            }
        }
        return list;
    }
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/warpper/WithdrawalWarpper.java
New file
@@ -0,0 +1,20 @@
package com.stylefeng.guns.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2024/5/6 11:09
 */
@ApiModel
@Data
public class WithdrawalWarpper {
    @ApiModelProperty("提现总金额")
    private Double total;
    @ApiModelProperty("明细列表")
    private List<WithdrawalListWarpper> list;
}
guns-admin/src/main/resources/META-INF/spring-devtools.properties
New file
@@ -0,0 +1 @@
restart.include.beetl=/beetl-2.8.5.jar
guns-admin/src/main/resources/application.yml
New file
@@ -0,0 +1,93 @@
server:
  port: 8080
guns:
  swagger-open: true              #是否开启swagger (true/false)
  kaptcha-open: false             #是否开启登录时验证码 (true/false)
  #  file-upload-path: d:/tmp       #文件上传目录(不配置的话为java.io.tmpdir目录)
  spring-session-open: false      #是否开启spring session,如果是多机环境需要开启(true/false)
  session-invalidate-time: 1800     #session失效时间(只在单机环境下生效,多机环境在SpringSessionConfig类中配置) 单位:秒
  session-validation-interval: 900  #多久检测一次失效的session(只在单机环境下生效) 单位:秒
spring:
  profiles:
    active: dev
  application:
    name: VehicleInspection
  mvc:
    static-path-pattern: /static/**
    view:
      prefix: /WEB-INF/view
  devtools:
    restart:
      enabled: false
      additional-paths: src/main/java
      exclude: static/**,WEB-INF/view/**
  servlet:
    multipart:
      max-request-size: 100MB
      max-file-size: 100MB
mybatis-plus:
  typeAliasesPackage: com.stylefeng.guns.modular
  configuration:
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
---
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/vehicle_inspection?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    db-name: guns #用来搜集数据库的所有表
    filters: wall,mergeStat
#多数据源情况的配置
guns:
  muti-datasource:
    open: false
    url: jdbc:mysql://127.0.0.1:3306/guns_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root
    dataSourceNames:
      - dataSourceGuns
      - dataSourceBiz
---
spring:
  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: embedded
    properties:
      org:
        quartz:
          scheduler:
            # 调度器实例名称
            instanceName: QuartzScheduler
            # 分布式节点ID自动生成
            instanceId: AUTO
          jobStore:
            class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            # 表前缀
            tablePrefix: qrtz_
            # 是否开启集群
            isClustered: false
            # 数据源别名(自定义)
            dataSource: vehicle_inspection
            # 分布式节点有效性检查时间间隔(毫秒)
            clusterCheckinInterval: 10000
            useProperties: false
          # 线程池配置
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
---
filePath: d:/file/
guns-admin/src/main/resources/ehcache.xml
New file
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="false" monitoring="autodetect"
         dynamicConfig="true" >
    <diskStore path="java.io.tmpdir/ehcache"/>
    <defaultCache
            maxElementsInMemory="50000"
            eternal="false"
            timeToIdleSeconds="3600"
            timeToLiveSeconds="3600"
            overflowToDisk="true"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
    />
    <!-- 全局变量:永不过期-->
    <cache name="CONSTANT"
           maxElementsInMemory="50000"
           eternal="true"
           clearOnFlush="false"
           overflowToDisk="true"
           diskSpoolBufferSizeMB="1024"
           maxElementsOnDisk="100000"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LFU"
           transactionalMode="off">
    </cache>
</ehcache>
    <!--
        maxElementsInMemory="10000"     //Cache中最多允许保存的数据对象的数量
        external="false"                 //缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期
        timeToLiveSeconds="3600"          //缓存的存活时间,从开始创建的时间算起
        timeToIdleSeconds="3600"          //多长时间不访问该缓存,那么ehcache 就会清除该缓存
        这两个参数很容易误解,看文档根本没用,我仔细分析了ehcache的代码。结论如下:
        1、timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;
        2、timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;
        3、如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;
        4、如果没设置timeToLiveSeconds,则该对象的超时时间=min(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;
        5、如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。
        overflowToDisk="true"            //内存不足时,是否启用磁盘缓存
        diskSpoolBufferSizeMB    //设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
        maxElementsOnDisk        //硬盘最大缓存个数
        diskPersistent            //是否缓存虚拟机重启期数据The default value is false
        diskExpiryThreadIntervalSeconds    //磁盘失效线程运行时间间隔,默认是120秒。
        memoryStoreEvictionPolicy="LRU" //当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
        clearOnFlush    //内存数量最大时是否清除
        maxEntriesLocalHeap="0"  //堆内存中最大缓存对象数,0没有限制
        maxEntriesLocalDisk="1000" //硬盘最大缓存个数。
    -->
guns-admin/src/main/resources/logback-spring.xml
New file
@@ -0,0 +1,227 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds">
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="/home/igotechgh/app/log/driver"/>
    <!--0. 日志格式和颜色渲染 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--1. 输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--2. 输出到文档-->
    <!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.2 level为 INFO 日志,时间滚动输出  -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/info.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.3 level为 WARN 日志,时间滚动输出  -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/warn.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/error.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
    <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/all.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
        <logger name="org.springframework.web" level="info"/>
        <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
    -->
    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
    <!-- 4  最终的策略:
                 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
    <springProfile name="dev">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="info"/>
        <logger name="business-log" level="warn"/>
    </springProfile>
    <springProfile name="fat">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="info"/>
        <logger name="business-log" level="warn"/>
    </springProfile>
    <springProfile name="produce">
        <root level="info">
            <!-- 生产环境最好不配置console写文件 -->
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="error"/>
        <logger name="business-log" level="warn"/>
    </springProfile>
</configuration>
guns-admin/src/main/webapp/WEB-INF/view/404.html
New file
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Guns - 404 页面</title>
    <link rel="shortcut icon" href="${ctxPath}/static/favicon.ico"> <link href="${ctxPath}/static/css/bootstrap.min.css?v=3.3.6" rel="stylesheet">
    <link href="${ctxPath}/static/css/font-awesome.css?v=4.4.0" rel="stylesheet">
    <link href="${ctxPath}/static/css/style.css?v=4.1.0" rel="stylesheet">
</head>
<body class="gray-bg">
    <div class="middle-box text-center">
        <h1>404</h1>
        <h3 class="font-bold">页面未找到!</h3>
        <div class="error-desc">
            抱歉,页面好像去火星了~
            <form class="form-inline m-t" role="form">
                <div class="form-group">
                    <input type="email" class="form-control" placeholder="请输入您需要查找的内容 …">
                </div>
                <button type="submit" class="btn btn-primary">搜索</button>
            </form>
        </div>
    </div>
    <!-- 全局js -->
    <script src="${ctxPath}/static/js/jquery.min.js?v=2.1.4"></script>
    <script src="${ctxPath}/static/js/bootstrap.min.js?v=3.3.6"></script>
</body>
</html>
guns-admin/src/main/webapp/WEB-INF/view/blackboard.html
New file
@@ -0,0 +1,14 @@
@layout("/common/_container.html"){
<div class="container-fluid" style="padding: 0 !important;">
    <div class="row">
        <div class="col-sm-12">
            @for(notice in noticeList){
                <div class="alert alert-success alert-dismissable">
                    <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
                    ${notice.content}
                </div>
            @}
        </div>
    </div>
</div>
@}
guns-admin/src/main/webapp/WEB-INF/view/code/code.html
New file
@@ -0,0 +1,101 @@
@layout("/common/_container.html"){
<div class="row" xmlns="">
    <div class="col-sm-12">
        <div class="ibox float-e-margins">
            <div class="ibox-title">
                <h5>代码生成</h5>
            </div>
            <div class="ibox-content">
                <div class="row row-lg">
                    <div class="col-sm-12">
                        <div class="form-horizontal" id="generate">
                            <div class="row">
                                <div class="col-sm-4">
                                    <#input id="projectPath" name="项目路径" value="${params.projectPath}"/>
                                </div>
                                <div class="col-sm-4">
                                    <#input id="projectPackage" name="项目的包" value="${params.projectPackage}"/>
                                </div>
                                <div class="col-sm-4">
                                    <#input id="corePackage" name="核心包" value="${params.corePackage}"/>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-sm-3">
                                    <#input id="author" name="作者" value="${params.author!}"/>
                                </div>
                                <div class="col-sm-3">
                                    <#input id="bizName" name="业务名称" />
                                </div>
                                <div class="col-sm-3">
                                    <#input id="moduleName" name="模块名称" value="${params.moduleName}"/>
                                </div>
                                <div class="col-sm-3">
                                    <#input id="parentMenuName" name="父级菜单名称" underline="false" value="${params.parentMenuName}"
                                            hidden="pid" readonly="readonly"
                                            clickFun="Code.showMenuSelectTree(); return false;"
                                            style="background-color: #ffffff !important;"
                                            selectFlag="true" selectId="pcodeTreeDiv" selectTreeId="pcodeTree" selectStyle=""/>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-sm-3">
                                    <#input id="tableName" name="表名称" disabled="disabled"/>
                                </div>
                                <div class="col-sm-3">
                                    <#input id="ignoreTabelPrefix" name="表前缀" value="${params.ignoreTabelPrefix}"/>
                                </div>
                                <div class="col-sm-3">
                                    <#input id="className" name="类名" disabled="disabled"/>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-sm-6">
                                    <button id="genBtn" type="button" class="btn btn-primary mr10"
                                            onclick="Code.generate()">
                                        <span style="padding: 5px 20px;">生成</span>
                                    </button>
                                </div>
                            </div>
                        </div>
                        <div style="padding-top: 10px; overflow: hidden"
                             class="container-fluid">
                            <div class="col-md-12">
                                <div class="row admin-form">
                                    <div class="col-md-3 col-md-offset-3">
                                        <h2>数据表</h2>
                                        <div class="list-group" id="tableList"
                                             data-bind="foreach: tables"
                                             style="height: 500px; overflow-y: scroll">
                                            @for(table in tables!){
                                                <a href="javascript:void(0)" class="list-group-item" tableName="${table.tableName}" onclick="Code.selectTable('${table.tableName}')">${table.tableName}-${table.tableComment}</a>
                                            @}
                                        </div>
                                    </div>
                                    <div class="col-md-3">
                                        <span><h2>模板</h2></span>
                                        <div class="list-group" id="templateList"
                                             style="height: 500px; overflow-y: scroll">
                                            @for(template in templates!){
                                                <a href="javascript:void(0)" class="list-group-item" key="${template.key}" onclick="Code.selectTemplate('${template.key}')">${template.desc}</a>
                                            @}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <ul class="nav nav-list">
                            <li class="divider"></li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/js/common/select-list-object.js"></script>
<script src="${ctxPath}/static/modular/code/gen.js"></script>
@}
guns-admin/src/main/webapp/WEB-INF/view/common/_container.html
New file
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="renderer" content="webkit"/><!-- 让360浏览器默认选择webkit内核 -->
    <!-- 全局css -->
    <link rel="shortcut icon" href="${ctxPath}/static/favicon.ico">
    <link href="${ctxPath}/static/css/bootstrap.min.css?v=3.3.6" rel="stylesheet">
    <link href="${ctxPath}/static/css/font-awesome.css?v=4.4.0" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/chosen/chosen.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/validate/bootstrapValidator.min.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/style.css?v=4.1.0" rel="stylesheet">
    <link href="${ctxPath}/static/css/_fstyle.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/iCheck/custom.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/webuploader/webuploader.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/ztree/zTreeStyle.css" rel="stylesheet">
    <link href="${ctxPath}/static/css/plugins/bootstrap-treetable/bootstrap-treetable.css" rel="stylesheet"/>
    <!-- <link href="${ctxPath}/static/css/plugins/ztree/demo.css" rel="stylesheet"> -->
    <!-- 全局js -->
    <script src="${ctxPath}/static/js/jquery.min.js?v=2.1.4"></script>
    <script src="${ctxPath}/static/js/bootstrap.min.js?v=3.3.6"></script>
    <script src="${ctxPath}/static/js/plugins/ztree/jquery.ztree.all.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/bootstrap-table/bootstrap-table.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/validate/bootstrapValidator.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/validate/zh_CN.js"></script>
    <script src="${ctxPath}/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/bootstrap-treetable/bootstrap-treetable.js"></script>
    <script src="${ctxPath}/static/js/plugins/layer/layer.js"></script>
    <script src="${ctxPath}/static/js/plugins/chosen/chosen.jquery.js"></script>
    <script src="${ctxPath}/static/js/plugins/iCheck/icheck.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/laydate/laydate.js"></script>
    <script src="${ctxPath}/static/js/plugins/webuploader/webuploader.min.js"></script>
    <script src="${ctxPath}/static/js/common/ajax-object.js"></script>
    <script src="${ctxPath}/static/js/common/bootstrap-table-object.js"></script>
    <script src="${ctxPath}/static/js/common/tree-table-object.js"></script>
    <script src="${ctxPath}/static/js/common/web-upload-object.js"></script>
    <script src="${ctxPath}/static/js/common/ztree-object.js"></script>
    <script src="${ctxPath}/static/js/common/Feng.js"></script>
    <style type="text/css">
        table{
            width:100px;
            table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用。 */
        }
        td{
            width:100%;
            word-break:keep-all;/* 不换行 */
            white-space:nowrap;/* 不换行 */
            overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */
            text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用*/
        }
    </style>
    <script type="text/javascript">
        Feng.addCtx("${ctxPath}");
        Feng.sessionTimeoutRegistry();
    </script>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
    ${layoutContent}
</div>
<script src="${ctxPath}/static/js/content.js?v=1.0.0"></script>
</body>
</html>
guns-admin/src/main/webapp/WEB-INF/view/common/_right.html
New file
@@ -0,0 +1,53 @@
<div id="page-wrapper" class="gray-bg dashbard-1">
            <div class="row border-bottom">
                <nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">
            <div class="navbar-header"><a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
                <form role="search" class="navbar-form-custom" method="post" action="search_results.html">
                    <div class="form-group">
                        <input type="text" placeholder="请输入您需要查找的内容 …" class="form-control" name="top-search" id="top-search">
                    </div>
                </form>
            </div>
            <ul class="nav navbar-top-links navbar-right">
                <li class="dropdown hidden-xs">
                    <a class="right-sidebar-toggle" aria-expanded="false">
                        <i class="fa fa-tasks"></i> 主题
                    </a>
                </li>
            </ul>
        </nav>
    </div>
    <div class="row content-tabs">
        <button class="roll-nav roll-left J_tabLeft"><i class="fa fa-backward"></i>
        </button>
        <nav class="page-tabs J_menuTabs">
            <div class="page-tabs-content">
                <a href="javascript:;" class="active J_menuTab" data-id="${ctxPath}/blackboard">首页</a>
            </div>
        </nav>
        <button class="roll-nav roll-right J_tabRight"><i class="fa fa-forward"></i>
        </button>
        <div class="btn-group roll-nav roll-right">
            <button class="dropdown J_tabClose" data-toggle="dropdown">关闭操作<span class="caret"></span>
            </button>
            <ul role="menu" class="dropdown-menu dropdown-menu-right">
                <li class="J_tabShowActive"><a>定位当前选项卡</a>
                </li>
                <li class="divider"></li>
                <li class="J_tabCloseAll"><a>关闭全部选项卡</a>
                </li>
                <li class="J_tabCloseOther"><a>关闭其他选项卡</a>
                </li>
            </ul>
        </div>
        <a href="logout" class="roll-nav roll-right J_tabExit"><i class="fa fa fa-sign-out"></i> 退出</a>
    </div>
    <div class="row J_mainContent" id="content-main">
        <iframe class="J_iframe" name="iframe0" width="100%" height="100%" src="${ctxPath}/blackboard" frameborder="0" data-id="${ctxPath}/blackboard" seamless></iframe>
    </div>
    <div class="footer">
        <div class="pull-right">&copy; 2016-2017 <a href="http://git.oschina.net/naan1993/guns" target="_blank">guns</a>
        </div>
    </div>
</div>
guns-admin/src/main/webapp/WEB-INF/view/common/_tab.html
New file
@@ -0,0 +1,74 @@
<nav class="navbar-default navbar-static-side" role="navigation">
    <div class="nav-close"><i class="fa fa-times-circle"></i>
    </div>
    <div class="sidebar-collapse">
        <ul class="nav" id="side-menu">
            <li class="nav-header">
                <div class="dropdown profile-element">
                    <span><img alt="image" class="img-circle"
                               @if(isEmpty(avatar)){
                                    src="${ctxPath}/static/img/girl.gif"
                               @}else{
                                    src="${ctxPath}/kaptcha/${avatar}"
                               @}
                               width="64px" height="64px"/></span>
                    <a data-toggle="dropdown" class="dropdown-toggle" href="#">
                        <span class="clear">
                       <span class="block m-t-xs"><strong class="font-bold">${shiro.getUser().name}</strong></span>
                        <span class="text-muted text-xs block">${shiro.getUser().roleNames[0]}<b class="caret"></b></span>
                        </span>
                    </a>
                    <ul class="dropdown-menu m-t-xs">
                        <li><a class="J_menuItem" href="${ctxPath}/mgr/user_info">个人资料</a></li>
                        <li><a class="J_menuItem" href="${ctxPath}/mgr/user_chpwd">修改密码</a></li>
                        <li class="divider"></li>
                        <li><a href="${ctxPath}/logout">安全退出</a>
                        </li>
                    </ul>
                </div>
                <div class="logo-element">GS
                </div>
            </li>
            @for(title in titles){
                @if(tool.isEmpty(title.children)){
                    <li>
                        <a class="J_menuItem" href="${ctxPath}${title.url}" name="tabMenuItem">
                            <i class="fa ${title.icon}"></i>
                            <span class="nav-label">${title.name}</span>
                        </a>
                    </li>
                @}else{
                    <li>
                        <a href="#">
                            <i class="fa ${title.icon}"></i>
                            <span class="nav-label">${title.name}</span>
                            <span class="fa arrow"></span>
                        </a>
                        <ul class="nav nav-second-level">
                            @for(subTitle in title.children){
                                @if(tool.isEmpty(subTitle.children)){
                                    <li>
                                        <a class="J_menuItem" href="${ctxPath}${subTitle.url}" name="tabMenuItem">${subTitle.name}</a>
                                    </li>
                                @}else{
                                    <li>
                                        <a href="#">${subTitle.name} <span class="fa arrow"></span></a>
                                        <ul class="nav nav-third-level">
                                            @for(thirdTitle in subTitle.children){
                                            <li>
                                                <a class="J_menuItem" href="${ctxPath}${thirdTitle.url}" name="tabMenuItem">${thirdTitle.name}</a>
                                            </li>
                                            @}
                                        </ul>
                                    </li>
                                @}
                            @}
                        </ul>
                    </li>
                @}
            @}
        </ul>
    </div>
</nav>
guns-admin/src/main/webapp/WEB-INF/view/common/_theme.html
New file
@@ -0,0 +1,84 @@
<div id="right-sidebar">
    <div class="sidebar-container">
        <ul class="nav nav-tabs navs-3">
            <li class="active"><a data-toggle="tab" href="#tab-1"> <i
                    class="fa fa-gear"></i> 主题
            </a></li>
        </ul>
        <div class="tab-content">
            <div id="tab-1" class="tab-pane active">
                <div class="sidebar-title">
                    <h3>
                        <i class="fa fa-comments-o"></i> 主题设置
                    </h3>
                    <small><i class="fa fa-tim"></i>
                        你可以从这里选择和预览主题的布局和样式,这些设置会被保存在本地,下次打开的时候会直接应用这些设置。</small>
                </div>
                <div class="skin-setttings">
                    <div class="title">主题设置</div>
                    <div class="setings-item">
                        <span>收起左侧菜单</span>
                        <div class="switch">
                            <div class="onoffswitch">
                                <input type="checkbox" name="collapsemenu"
                                    class="onoffswitch-checkbox" id="collapsemenu"> <label
                                    class="onoffswitch-label" for="collapsemenu"> <span
                                    class="onoffswitch-inner"></span> <span
                                    class="onoffswitch-switch"></span>
                                </label>
                            </div>
                        </div>
                    </div>
                    <div class="setings-item">
                        <span>固定顶部</span>
                        <div class="switch">
                            <div class="onoffswitch">
                                <input type="checkbox" name="fixednavbar"
                                    class="onoffswitch-checkbox" id="fixednavbar"> <label
                                    class="onoffswitch-label" for="fixednavbar"> <span
                                    class="onoffswitch-inner"></span> <span
                                    class="onoffswitch-switch"></span>
                                </label>
                            </div>
                        </div>
                    </div>
                    <div class="setings-item">
                        <span> 固定宽度 </span>
                        <div class="switch">
                            <div class="onoffswitch">
                                <input type="checkbox" name="boxedlayout"
                                    class="onoffswitch-checkbox" id="boxedlayout"> <label
                                    class="onoffswitch-label" for="boxedlayout"> <span
                                    class="onoffswitch-inner"></span> <span
                                    class="onoffswitch-switch"></span>
                                </label>
                            </div>
                        </div>
                    </div>
                    <div class="title">皮肤选择</div>
                    <div class="setings-item default-skin nb">
                        <span class="skin-name "> <a href="#" class="s-skin-0">
                                默认皮肤 </a>
                        </span>
                    </div>
                    <div class="setings-item blue-skin nb">
                        <span class="skin-name "> <a href="#" class="s-skin-1">
                                蓝色主题 </a>
                        </span>
                    </div>
                    <div class="setings-item yellow-skin nb">
                        <span class="skin-name "> <a href="#" class="s-skin-3">
                                黄色/紫色主题 </a>
                        </span>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
guns-admin/src/main/webapp/WEB-INF/view/common/tags/NameCon.tag
New file
@@ -0,0 +1,14 @@
@/*
    名称查询条件标签的参数说明:
    name : 查询条件的名称
    id : 查询内容的input框id
@*/
<div class="input-group">
    <div class="input-group-btn">
        <button data-toggle="dropdown" class="btn btn-white dropdown-toggle"
                type="button">${name}
        </button>
    </div>
    <input type="text" class="form-control" id="${id}" placeholder="${placeholder!}" />
</div>
guns-admin/src/main/webapp/WEB-INF/view/common/tags/SelectCon.tag
New file
@@ -0,0 +1,16 @@
@/*
    选择查询条件标签的参数说明:
    name : 查询条件的名称
    id : 查询内容的input框id
@*/
<div class="input-group">
    <div class="input-group-btn">
        <button data-toggle="dropdown" class="btn btn-white dropdown-toggle" type="button">
            ${name}
        </button>
    </div>
    <select class="form-control" id="${id}">
        ${tagBody!}
    </select>
</div>
guns-admin/src/main/webapp/WEB-INF/view/common/tags/TimeCon.tag
New file
@@ -0,0 +1,15 @@
@/*
    时间查询条件标签的参数说明:
    name : 查询条件的名称
    id : 查询内容的input框id
    isTime : 日期是否带有小时和分钟(true/false)
@*/
<div class="input-group">
    <div class="input-group-btn">
        <button data-toggle="dropdown" class="btn btn-white dropdown-toggle"
                type="button">${name}
        </button>
    </div>
    <input type="text" class="form-control layer-date" id="${id}"/>
</div>
guns-admin/src/main/webapp/WEB-INF/view/common/tags/avatar.tag
New file
@@ -0,0 +1,29 @@
@/*
    头像参数的说明:
    name : 名称
    id : 头像的id
@*/
<div class="form-group">
    <label class="col-sm-3 control-label head-scu-label">${name}</label>
    <div class="col-sm-4">
        <div id="${id}PreId">
            <div><img width="100px" height="100px"
                @if(isEmpty(avatarImg)){
                      src="${ctxPath}/static/img/girl.gif"></div>
                @}else{
                      src="${ctxPath}/kaptcha/${avatarImg}"></div>
                @}
        </div>
    </div>
    <div class="col-sm-2">
        <div class="head-scu-btn upload-btn" id="${id}BtnId">
            <i class="fa fa-upload"></i>&nbsp;上传
        </div>
    </div>
    <input type="hidden" id="${id}" value="${avatarImg!}"/>
</div>
@if(isNotEmpty(underline) && underline == 'true'){
    <div class="hr-line-dashed"></div>
@}
guns-admin/src/main/webapp/WEB-INF/view/common/tags/button.tag
New file
@@ -0,0 +1,26 @@
@/*
    按钮标签中各个参数的说明:
    btnType : 按钮的类型决定了颜色(default-灰色,primary-绿色,success-蓝色,info-淡蓝色,warning-黄色,danger-红色,white-白色)
    space : 按钮左侧是否有间隔(true/false)
    clickFun : 点击按钮所执行的方法
    icon : 按钮上的图标的样式
    name : 按钮名称
@*/
@var spaceCss = "";
@var btnType = "";
@if(isEmpty(space) || space == "false"){
@   spaceCss = "";
@}else{
@   spaceCss = "button-margin";
@}
@if(isEmpty(btnCss)){
@   btnType = "primary";
@}else{
@   btnType = btnCss;
@}
<button type="button" class="btn btn-${btnType} ${spaceCss}" onclick="${clickFun!}" id="${id!}">
    <i class="fa ${icon}"></i>&nbsp;${name}
</button>
guns-admin/src/main/webapp/WEB-INF/view/common/tags/input.tag
New file
@@ -0,0 +1,51 @@
@/*
    表单中input框标签中各个参数的说明:
    hidden : input hidden框的id
    id : input框id
    name : input框名称
    readonly : readonly属性
    clickFun : 点击事件的方法名
    style : 附加的css属性
@*/
<div class="form-group">
    <label class="col-sm-3 control-label">${name}</label>
    <div class="col-sm-9">
        <input class="form-control" id="${id}" name="${id}"
               @if(isNotEmpty(value)){
                    value="${tool.dateType(value)}"
               @}
               @if(isNotEmpty(type)){
                    type="${type}"
               @}else{
                    type="text"
               @}
               @if(isNotEmpty(readonly)){
                    readonly="${readonly}"
               @}
               @if(isNotEmpty(clickFun)){
                    onclick="${clickFun}"
               @}
               @if(isNotEmpty(style)){
                    style="${style}"
               @}
               @if(isNotEmpty(disabled)){
                    disabled="${disabled}"
               @}
        >
        @if(isNotEmpty(hidden)){
            <input class="form-control" type="hidden" id="${hidden}" value="${hiddenValue!}">
        @}
        @if(isNotEmpty(selectFlag)){
            <div id="${selectId}" style="display: none; position: absolute; z-index: 200;">
                <ul id="${selectTreeId}" class="ztree tree-box" style="${selectStyle!}"></ul>
            </div>
        @}
    </div>
</div>
@if(isNotEmpty(underline) && underline == 'true'){
    <div class="hr-line-dashed"></div>
@}
guns-admin/src/main/webapp/WEB-INF/view/common/tags/select.tag
New file
@@ -0,0 +1,22 @@
@/*
    select标签中各个参数的说明:
    name : select的名称
    id : select的id
    underline : 是否带分割线
@*/
<div class="form-group">
    <label class="col-sm-3 control-label">${name}</label>
    <div class="col-sm-9">
        <select class="form-control" id="${id}" name="${id}">
            ${tagBody!}
        </select>
        @if(isNotEmpty(hidden)){
            <input class="form-control" type="hidden" id="${hidden}" value="${hiddenValue!}">
        @}
    </div>
</div>
@if(isNotEmpty(underline) && underline == 'true'){
    <div class="hr-line-dashed"></div>
@}
guns-admin/src/main/webapp/WEB-INF/view/common/tags/table.tag
New file
@@ -0,0 +1,12 @@
@/*
    表格标签的参数说明:
    id : table表格的id
@*/
<table id="${id}" data-mobile-responsive="true" data-click-to-select="true">
    <thead>
        <tr>
            <th data-field="selectItem" data-checkbox="true"></th>
        </tr>
    </thead>
</table>
guns-admin/src/main/webapp/WEB-INF/view/common/tags/tag_tips
New file
@@ -0,0 +1,22 @@
1 dictSelector(字典选择器)
    此标签是为了方便在前台form表单中使用系统中维护的字典而开发的,具体说明如下:
1.1 标签样例
    <#dictSelector id="sex" name ="sex" code="sys_sex" readonly="readonly" label="性别"  underline="true"  value="${user.sex}" />
1.2 属性说明
    id: (非必须) 控件的id
    name: (非必须) 控件的name
    code:(必须) 字典类型编码,根据code的值去后台查询该类型的字典。
    type:(非必须) 控件类型,可选项为[select,radio,checkbox],标签会根据填写的类型,生成不同的控件。
    searchnum:(非必须)下拉框达到多少个,开启搜索框,默认10个,type为select起效。
    label:(非必须) 字典属性名称
    width:(非必须) 控件的宽度单位为px,type为select起效。
    value: (非必须) 控件默认值,多选时值要用,分隔。
    placeholder:(非必须) 控件提示信息,type为select起效。
    multiple:(非必须) 是否开启多选,可选值[true,false],默认为false,type为select起效。
    underline:(非必须) 是否显示分割线,可选值[true,false],默认为false。
    onchange:(非必须) onchange事件方法名称,会传入更改后的值作为参数,例:onchange="myOnChange" function myOnChange(newVal){}。
    readonly:(非必须)只读控件,可选值[true,false],默认false
    disabled:(非必须) 禁用控件,可选值[true,false],默认false
guns-admin/src/main/webapp/WEB-INF/view/index.html
New file
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="renderer" content="webkit">
    <title>Guns - 主页</title>
    <link rel="shortcut icon" href="${ctxPath}/static/favicon.ico">
    <link href="${ctxPath}/static/css/bootstrap.min.css?v=3.3.6" rel="stylesheet">
    <link href="${ctxPath}/static/css/font-awesome.min.css?v=4.4.0" rel="stylesheet">
    <link href="${ctxPath}/static/css/style.css?v=4.1.0" rel="stylesheet">
</head>
<body class="fixed-sidebar full-height-layout gray-bg" style="overflow:hidden">
    <div id="wrapper">
        <!--左侧导航开始-->
            @include("/common/_tab.html"){}
        <!--左侧导航结束-->
        <!--右侧部分开始-->
            @include("/common/_right.html"){}
        <!--右侧部分结束-->
        <!--右侧边栏开始-->
            @include("/common/_theme.html"){}
        <!--右侧边栏结束-->
    </div>
    <!-- 全局js -->
    <script src="${ctxPath}/static/js/jquery.min.js?v=2.1.4"></script>
    <script src="${ctxPath}/static/js/bootstrap.min.js?v=3.3.6"></script>
    <script src="${ctxPath}/static/js/plugins/metisMenu/jquery.metisMenu.js"></script>
    <script src="${ctxPath}/static/js/plugins/slimscroll/jquery.slimscroll.min.js"></script>
    <script src="${ctxPath}/static/js/plugins/layer/layer.js"></script>
    <!-- 自定义js -->
    <script src="${ctxPath}/static/js/hplus.js?v=4.1.0"></script>
    <script type="text/javascript" src="${ctxPath}/static/js/contabs.js"></script>
    <!-- 第三方插件 -->
    <script src="${ctxPath}/static/js/plugins/pace/pace.min.js"></script>
</body>
</html>
Diff truncated after the above file
guns-admin/src/main/webapp/WEB-INF/view/login.html guns-admin/src/main/webapp/WEB-INF/view/system/code/code.html guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept.html guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_add.html guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_edit.html guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict.html guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_add.html guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_edit.html guns-admin/src/main/webapp/WEB-INF/view/system/log/log.html guns-admin/src/main/webapp/WEB-INF/view/system/log/login_log.html guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu.html guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_add.html guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_edit.html guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice.html guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_add.html guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_edit.html guns-admin/src/main/webapp/WEB-INF/view/system/role/role.html guns-admin/src/main/webapp/WEB-INF/view/system/role/role_add.html guns-admin/src/main/webapp/WEB-INF/view/system/role/role_assign.html guns-admin/src/main/webapp/WEB-INF/view/system/role/role_edit.html guns-admin/src/main/webapp/WEB-INF/view/system/user/user.html guns-admin/src/main/webapp/WEB-INF/view/system/user/user_add.html guns-admin/src/main/webapp/WEB-INF/view/system/user/user_chpwd.html guns-admin/src/main/webapp/WEB-INF/view/system/user/user_edit.html guns-admin/src/main/webapp/WEB-INF/view/system/user/user_roleassign.html guns-admin/src/main/webapp/WEB-INF/view/system/user/user_view.html guns-admin/src/main/webapp/static/css/_fstyle.css guns-admin/src/main/webapp/static/css/bootstrap-rtl.css guns-admin/src/main/webapp/static/css/bootstrap.min.css guns-admin/src/main/webapp/static/css/font-awesome.css guns-admin/src/main/webapp/static/css/font-awesome.min.css guns-admin/src/main/webapp/static/css/login.css guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-1.png guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-3.png guns-admin/src/main/webapp/static/css/patterns/header-profile.png guns-admin/src/main/webapp/static/css/patterns/shattered.png guns-admin/src/main/webapp/static/css/plugins/bootstrap-table/bootstrap-table.min.css guns-admin/src/main/webapp/static/css/plugins/bootstrap-treetable/bootstrap-treetable.css guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite.png guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite@2x.png guns-admin/src/main/webapp/static/css/plugins/chosen/chosen.css guns-admin/src/main/webapp/static/css/plugins/iCheck/custom.css guns-admin/src/main/webapp/static/css/plugins/iCheck/green.png guns-admin/src/main/webapp/static/css/plugins/iCheck/green@2x.png guns-admin/src/main/webapp/static/css/plugins/images/sprite-skin-flat.png guns-admin/src/main/webapp/static/css/plugins/validate/bootstrapValidator.min.css guns-admin/src/main/webapp/static/css/plugins/webuploader/webuploader.css guns-admin/src/main/webapp/static/css/plugins/ztree/demo.css guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_close.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_open.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/2.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/3.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/4.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/5.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/6.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/7.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/8.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/9.png guns-admin/src/main/webapp/static/css/plugins/ztree/img/line_conn.gif guns-admin/src/main/webapp/static/css/plugins/ztree/img/loading.gif guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.gif guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.png guns-admin/src/main/webapp/static/css/plugins/ztree/zTreeStyle.css guns-admin/src/main/webapp/static/css/style.css guns-admin/src/main/webapp/static/favicon.ico guns-admin/src/main/webapp/static/fonts/FontAwesome.otf guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.eot guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.svg guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.ttf guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff2 guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.eot guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.svg guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.ttf guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff2 guns-admin/src/main/webapp/static/img/bg.png guns-admin/src/main/webapp/static/img/boy.gif guns-admin/src/main/webapp/static/img/girl.gif guns-admin/src/main/webapp/static/img/icons.png guns-admin/src/main/webapp/static/img/loading-upload.gif guns-admin/src/main/webapp/static/img/locked.png guns-admin/src/main/webapp/static/img/user.png guns-admin/src/main/webapp/static/js/bootstrap.min.js guns-admin/src/main/webapp/static/js/common/DateUtils.js guns-admin/src/main/webapp/static/js/common/Feng.js guns-admin/src/main/webapp/static/js/common/ajax-object.js guns-admin/src/main/webapp/static/js/common/bootstrap-table-object.js guns-admin/src/main/webapp/static/js/common/select-list-object.js guns-admin/src/main/webapp/static/js/common/tree-table-object.js guns-admin/src/main/webapp/static/js/common/web-upload-object.js guns-admin/src/main/webapp/static/js/common/ztree-object.js guns-admin/src/main/webapp/static/js/contabs.js guns-admin/src/main/webapp/static/js/content.js guns-admin/src/main/webapp/static/js/hplus.js guns-admin/src/main/webapp/static/js/jquery.min.js guns-admin/src/main/webapp/static/js/jquery.min.map guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table.min.js guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js guns-admin/src/main/webapp/static/js/plugins/bootstrap-treetable/bootstrap-treetable.js guns-admin/src/main/webapp/static/js/plugins/chosen/chosen.jquery.js guns-admin/src/main/webapp/static/js/plugins/iCheck/icheck.min.js guns-admin/src/main/webapp/static/js/plugins/laydate/laydate.js guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.eot guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.svg guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.ttf guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.woff guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/laydate.css guns-admin/src/main/webapp/static/js/plugins/layer/layer.js guns-admin/src/main/webapp/static/js/plugins/layer/mobile/layer.js guns-admin/src/main/webapp/static/js/plugins/layer/mobile/need/layer.css guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon-ext.png guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon.png guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/layer.css guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-0.gif guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-1.gif guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-2.gif guns-admin/src/main/webapp/static/js/plugins/metisMenu/jquery.metisMenu.js guns-admin/src/main/webapp/static/js/plugins/pace/pace.min.js guns-admin/src/main/webapp/static/js/plugins/slimscroll/jquery.slimscroll.min.js guns-admin/src/main/webapp/static/js/plugins/validate/additional-methods.min.js guns-admin/src/main/webapp/static/js/plugins/validate/bootstrapValidator.min.js guns-admin/src/main/webapp/static/js/plugins/validate/zh_CN.js guns-admin/src/main/webapp/static/js/plugins/wangEditor/wangEditor.js guns-admin/src/main/webapp/static/js/plugins/webuploader/Uploader.swf guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.css guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.min.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.fis.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.min.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.min.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.min.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.min.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.min.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.js guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.min.js guns-admin/src/main/webapp/static/js/plugins/ztree/jquery.ztree.all.min.js guns-admin/src/main/webapp/static/modular/code/gen.js guns-admin/src/main/webapp/static/modular/flowable/expense/expense.js guns-admin/src/main/webapp/static/modular/flowable/expense/expense_info.js guns-admin/src/main/webapp/static/modular/flowable/process/process.js guns-admin/src/main/webapp/static/modular/flowable/process/process_info.js guns-admin/src/main/webapp/static/modular/system/code/code.js guns-admin/src/main/webapp/static/modular/system/dept/dept.js guns-admin/src/main/webapp/static/modular/system/dept/dept_info.js guns-admin/src/main/webapp/static/modular/system/dict/dict.js guns-admin/src/main/webapp/static/modular/system/dict/dict_info.js guns-admin/src/main/webapp/static/modular/system/log/log.js guns-admin/src/main/webapp/static/modular/system/log/login_log.js guns-admin/src/main/webapp/static/modular/system/menu/menu.js guns-admin/src/main/webapp/static/modular/system/menu/menu_info.js guns-admin/src/main/webapp/static/modular/system/notice/notice.js guns-admin/src/main/webapp/static/modular/system/notice/notice_info.js guns-admin/src/main/webapp/static/modular/system/role/role.js guns-admin/src/main/webapp/static/modular/system/role/role_info.js guns-admin/src/main/webapp/static/modular/system/user/user.js guns-admin/src/main/webapp/static/modular/system/user/user_info.js guns-admin/src/test/java/com/stylefeng/guns/GunsApplicationTest.java guns-core/pom.xml guns-core/src/main/java/com/stylefeng/guns/core/CoreFlag.java guns-core/src/main/java/com/stylefeng/guns/core/aop/BaseControllerExceptionHandler.java guns-core/src/main/java/com/stylefeng/guns/core/base/controller/BaseController.java guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GlobalController.java guns-core/src/main/java/com/stylefeng/guns/core/base/controller/GunsErrorView.java guns-core/src/main/java/com/stylefeng/guns/core/base/tips/ErrorTip.java guns-core/src/main/java/com/stylefeng/guns/core/base/tips/SuccessTip.java guns-core/src/main/java/com/stylefeng/guns/core/base/tips/Tip.java guns-core/src/main/java/com/stylefeng/guns/core/base/warpper/BaseControllerWarpper.java guns-core/src/main/java/com/stylefeng/guns/core/cache/BaseCacheFactory.java guns-core/src/main/java/com/stylefeng/guns/core/cache/CacheKit.java guns-core/src/main/java/com/stylefeng/guns/core/cache/EhcacheFactory.java guns-core/src/main/java/com/stylefeng/guns/core/cache/ICache.java guns-core/src/main/java/com/stylefeng/guns/core/cache/ILoader.java guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultFastjsonConfig.java guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultMultiConfig.java guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultProperties.java guns-core/src/main/java/com/stylefeng/guns/core/config/DefaultWebConfig.java guns-core/src/main/java/com/stylefeng/guns/core/config/properties/DruidProperties.java guns-core/src/main/java/com/stylefeng/guns/core/config/properties/MutiDataSourceProperties.java guns-core/src/main/java/com/stylefeng/guns/core/constant/IsMenu.java guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScope.java guns-core/src/main/java/com/stylefeng/guns/core/datascope/DataScopeInterceptor.java guns-core/src/main/java/com/stylefeng/guns/core/db/Db.java guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsException.java guns-core/src/main/java/com/stylefeng/guns/core/exception/GunsExceptionEnum.java guns-core/src/main/java/com/stylefeng/guns/core/exception/ServiceExceptionEnum.java guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DataSourceContextHolder.java guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/DynamicDataSource.java guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/annotion/DataSource.java guns-core/src/main/java/com/stylefeng/guns/core/mutidatasource/aop/MultiSourceExAop.java guns-core/src/main/java/com/stylefeng/guns/core/node/MenuNode.java guns-core/src/main/java/com/stylefeng/guns/core/node/ZTreeNode.java guns-core/src/main/java/com/stylefeng/guns/core/page/PageBT.java guns-core/src/main/java/com/stylefeng/guns/core/page/PageInfoBT.java guns-core/src/main/java/com/stylefeng/guns/core/qr/ImgQrTool.java guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageConfig.java guns-core/src/main/java/com/stylefeng/guns/core/qr/MatrixToImageWriter.java guns-core/src/main/java/com/stylefeng/guns/core/qr/QrImage.java guns-core/src/main/java/com/stylefeng/guns/core/support/BasicType.java guns-core/src/main/java/com/stylefeng/guns/core/support/BeanKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/ClassKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/CollectionKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/DateTime.java guns-core/src/main/java/com/stylefeng/guns/core/support/DateTimeKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/HexKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/HttpKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/ObjectKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/PageKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/StrKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/WafKit.java guns-core/src/main/java/com/stylefeng/guns/core/support/WafRequestWrapper.java guns-core/src/main/java/com/stylefeng/guns/core/support/exception/ToolBoxException.java guns-core/src/main/java/com/stylefeng/guns/core/util/Convert.java guns-core/src/main/java/com/stylefeng/guns/core/util/DateUtil.java guns-core/src/main/java/com/stylefeng/guns/core/util/FileUtil.java guns-core/src/main/java/com/stylefeng/guns/core/util/HttpSessionHolder.java guns-core/src/main/java/com/stylefeng/guns/core/util/IdGenerator.java guns-core/src/main/java/com/stylefeng/guns/core/util/MD5Util.java guns-core/src/main/java/com/stylefeng/guns/core/util/NumUtil.java guns-core/src/main/java/com/stylefeng/guns/core/util/PingYinUtil.java guns-core/src/main/java/com/stylefeng/guns/core/util/RenderUtil.java guns-core/src/main/java/com/stylefeng/guns/core/util/ResKit.java guns-core/src/main/java/com/stylefeng/guns/core/util/SimpleContrast.java guns-core/src/main/java/com/stylefeng/guns/core/util/SpringContextHolder.java guns-core/src/main/java/com/stylefeng/guns/core/util/SqlUtil.java guns-core/src/main/java/com/stylefeng/guns/core/util/ToolUtil.java guns-core/src/main/java/com/stylefeng/guns/core/xss/XssFilter.java guns-core/src/main/java/com/stylefeng/guns/core/xss/XssHttpServletRequestWrapper.java guns-core/src/main/resources/META-INF/spring.factories guns-core/src/main/resources/default-config.properties guns-generator/pom.xml guns-generator/src/main/java/com/stylefeng/guns/generator/action/GunsCodeGenerator.java guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/AbstractGeneratorConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/GunsGeneratorConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/action/config/WebGeneratorConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/action/model/GenQo.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/SimpleTemplateEngine.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/AbstractTemplateEngine.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/base/GunsTemplateEngine.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ContextConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ControllerConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/DaoConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/Menu.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/PageConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/ServiceConfig.java guns-generator/src/main/java/com/stylefeng/guns/generator/engine/config/SqlConfig.java guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl pom.xml vehicle_inspection.sql