puzhibing
2023-02-03 c880542ad099668bea6248fbe29d994953d1495d
提交基础框架及司机端部分接口
472个文件已添加
106535 ■■■■■ 已修改文件
driver/README.md 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/pom.xml 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/GunsApplication.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/GunsServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/EhCacheConfig.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/RedisConfig.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/SpringSessionConfig.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/SwaggerConfig.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/datasource/MultiDataSourceConfig.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/datasource/SingleDataSourceConfig.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/properties/BeetlProperties.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/properties/GunsProperties.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/web/BeetlConfig.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/web/ShiroConfig.java 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/web/WebConfig.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/aop/GlobalExceptionHandler.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/aop/LogAop.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/aop/PermissionAop.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/beetl/BeetlConfiguration.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/beetl/ShiroExt.java 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/annotion/BussinessLog.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/annotion/Permission.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/Const.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/DatasourceEnum.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/JwtConstants.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/cache/Cache.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/cache/CacheKey.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/DeleteDict.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/DeptDict.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/DictMap.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/LogDict.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/MenuDict.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/NoticeMap.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/RoleDict.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/UserDict.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/base/AbstractDictMap.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/base/SystemDict.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/factory/DictFieldWarpperFactory.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/ConstantFactory.java 333 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/IConstantFactory.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/MutiStrFactory.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/PageFactory.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/BizLogType.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/ExpenseState.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/LogSucceed.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/LogType.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/ManagerStatus.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/MenuOpenStatus.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/MenuStatus.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/Order.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/exception/BizExceptionEnum.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/exception/InvalidKaptchaException.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/intercept/GunsUserFilter.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/intercept/RestApiInteceptor.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/intercept/SessionHolderInterceptor.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/listener/ConfigListener.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/LogManager.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/LogObjectHolder.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/factory/LogFactory.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/factory/LogTaskFactory.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/ShiroDbRealm.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/ShiroKit.java 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/ShiroUser.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/check/ICheck.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/check/PermissionCheckFactory.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/check/PermissionCheckManager.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/factory/IShiro.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/factory/ShiroFactroy.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/tag/DictSelectorTag.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/ApiMenuFilter.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/Contrast.java 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/GetMobile.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/HttpUtils.java 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/JwtTokenUtil.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/KaptchaUtil.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/code/controller/CodeController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/code/factory/DefaultTemplateFactory.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/code/service/TableService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/api/DriverController.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/api/ImgController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/AuthIntercepter.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/AuthService.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/AuthenticationKit.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/Configuration.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/HMACSHA1.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/HashKit.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/UrlEncoderUtils.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/BlackboardController.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/DeptController.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/DictController.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/KaptchaController.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/LogController.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/LoginController.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/LoginLogController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/MenuController.java 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/NoticeController.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/RoleController.java 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/UserMgrController.java 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/BranchOfficeMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/DeptMapper.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/DictMapper.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/ExpenseMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/ImgMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/LoginLogMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/MenuMapper.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/NoticeMapper.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/OperationLogMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/RelationMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/RoleMapper.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/UserMapper.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/BranchOfficeMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/DeptMapper.xml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/DictMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/ExpenseMapper.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/ImgMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/LoginLogMapper.xml 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/MenuMapper.xml 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/NoticeMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/OperationLogMapper.xml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/RelationMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/RoleMapper.xml 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/UserMapper.xml 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/factory/UserFactory.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/BranchOffice.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Dept.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Dict.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Expense.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Img.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/LoginLog.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Menu.java 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Notice.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/OperationLog.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Region.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Relation.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Role.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/User.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IBranchOfficeService.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDeptService.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDictService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IImgService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/ILoginLogService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IMenuService.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/INoticeService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IOperationLogService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IRelationService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IRoleService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IUserService.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/BranchOfficeServiceImpl.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DeptServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DictServiceImpl.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/ImgServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/LoginLogServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/MenuServiceImpl.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/NoticeServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/OperationLogServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/RelationServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/RoleServiceImpl.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/UserServiceImpl.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/ManagerUser.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/ReqAddManager.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/ReqEditManager.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/UserDto.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ALiApiUtil.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ALiSendSms.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ApplicationRunnerUtil.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ChinaMobileUtil.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/DateUtil.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/GDFalconUtil.java 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/GeodesyUtil.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/HttpClientUtil.java 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/JuHeUtil.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MD5AndKL.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MinistryOfTransport.java 1062 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/PayMoneyUtil.java 809 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/RedisUtil.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ResultUtil.java 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/SystemException.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/TaskUtil.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/UUIDUtil.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/WeChatUtil.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/BaseWarpper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/DeptWarpper.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/DictWarpper.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/LogWarpper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/MenuWarpper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/NoticeWrapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/OpenCityWarpper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/ResponseWarpper.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/RoleWarpper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/UserWarpper.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/META-INF/spring-devtools.properties 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/application.yml 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/ehcache.xml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/logback-spring.xml 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/redis.properties 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/404.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/blackboard.html 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/code/code.html 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/_container.html 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/_right.html 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/_tab.html 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/_theme.html 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/NameCon.tag 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/SelectCon.tag 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/TimeCon.tag 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/avatar.tag 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/button.tag 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/input.tag 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/select.tag 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/table.tag 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/common/tags/tag_tips 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/index.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/login.html 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/code/code.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept.html 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_add.html 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_edit.html 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict.html 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_add.html 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_edit.html 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/log/log.html 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/log/login_log.html 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_add.html 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_edit.html 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice.html 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_add.html 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_edit.html 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role.html 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role_add.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role_assign.html 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role_edit.html 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user.html 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_add.html 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_chpwd.html 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_edit.html 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_roleassign.html 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_view.html 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/_fstyle.css 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/bootstrap-rtl.css 1468 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/bootstrap.min.css 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/font-awesome.css 2026 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/font-awesome.min.css 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/login.css 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-1.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-3.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/patterns/header-profile.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/patterns/shattered.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/bootstrap-table/bootstrap-table.min.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/bootstrap-treetable/bootstrap-treetable.css 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/chosen/chosen.css 423 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/iCheck/custom.css 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/iCheck/green.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/iCheck/green@2x.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/images/sprite-skin-flat.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/validate/bootstrapValidator.min.css 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/webuploader/webuploader.css 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/demo.css 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_close.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_open.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/2.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/3.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/4.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/5.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/6.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/7.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/8.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/9.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/line_conn.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/loading.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/plugins/ztree/zTreeStyle.css 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/css/style.css 7897 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/FontAwesome.otf 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.eot 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.svg 640 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.ttf 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff2 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.eot 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.svg 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.ttf 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff2 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/bg.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/boy.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/girl.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/icons.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/loading-upload.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/locked.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/img/user.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/bootstrap.min.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/DateUtils.js 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/Feng.js 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/ajax-object.js 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/bootstrap-table-object.js 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/select-list-object.js 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/tree-table-object.js 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/web-upload-object.js 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/common/ztree-object.js 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/contabs.js 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/content.js 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/hplus.js 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/jquery.min.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/jquery.min.map 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table.min.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-treetable/bootstrap-treetable.js 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/chosen/chosen.jquery.js 1211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/iCheck/icheck.min.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/laydate/laydate.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.eot 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.svg 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.ttf 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.woff 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/laydate.css 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/layer.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/mobile/layer.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/mobile/need/layer.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon-ext.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon.png 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/layer.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-0.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-1.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-2.gif 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/metisMenu/jquery.metisMenu.js 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/pace/pace.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/slimscroll/jquery.slimscroll.min.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/validate/additional-methods.min.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/validate/bootstrapValidator.min.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/validate/zh_CN.js 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/wangEditor/wangEditor.js 3967 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/Uploader.swf 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.css 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.js 6502 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.fis.js 8083 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.js 4622 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.js 6030 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.js 8106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.min.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.js 5026 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.js 8012 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.min.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.js 4993 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.min.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/js/plugins/ztree/jquery.ztree.all.min.js 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/code/gen.js 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/flowable/expense/expense.js 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/flowable/expense/expense_info.js 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/flowable/process/process.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/flowable/process/process_info.js 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/code/code.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/dept/dept.js 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/dept/dept_info.js 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/dict/dict.js 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/dict/dict_info.js 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/log/log.js 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/log/login_log.js 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/menu/menu.js 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/menu/menu_info.js 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/notice/notice.js 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/notice/notice_info.js 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/role/role.js 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/role/role_info.js 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/user/user.js 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/webapp/static/modular/system/user/user_info.js 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/pom.xml 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/CoreFlag.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/aop/BaseControllerExceptionHandler.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/controller/BaseController.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/controller/GlobalController.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/controller/GunsErrorView.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/tips/ErrorTip.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/tips/SuccessTip.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/tips/Tip.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/warpper/BaseControllerWarpper.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/BaseCacheFactory.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/CacheKit.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/EhcacheFactory.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/ICache.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/ILoader.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultFastjsonConfig.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultMultiConfig.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultProperties.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultWebConfig.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/properties/DruidProperties.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/properties/MutiDataSourceProperties.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/constant/IsMenu.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/datascope/DataScope.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/datascope/DataScopeInterceptor.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/db/Db.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/exception/GunsException.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/exception/GunsExceptionEnum.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/exception/ServiceExceptionEnum.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/DataSourceContextHolder.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/DynamicDataSource.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/annotion/DataSource.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/aop/MultiSourceExAop.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/node/MenuNode.java 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/node/ZTreeNode.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/page/PageBT.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/page/PageInfoBT.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/ImgQrTool.java 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/MatrixToImageConfig.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/MatrixToImageWriter.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/QrImage.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/BasicType.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/BeanKit.java 508 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/ClassKit.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/CollectionKit.java 801 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/DateTime.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/DateTimeKit.java 665 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/HexKit.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/HttpKit.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/ObjectKit.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/PageKit.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/StrKit.java 1370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/WafKit.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/WafRequestWrapper.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/exception/ToolBoxException.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/Convert.java 1060 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/DateUtil.java 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/FileUtil.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/HttpSessionHolder.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/IdGenerator.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/MD5Util.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/NumUtil.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/PingYinUtil.java 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/RenderUtil.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/ResKit.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/SimpleContrast.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/SpringContextHolder.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/SqlUtil.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/ToolUtil.java 582 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/xss/XssFilter.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/java/com/supersavedriving/driver/core/xss/XssHttpServletRequestWrapper.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/resources/META-INF/spring.factories 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-core/src/main/resources/default-config.properties 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/pom.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/GunsCodeGenerator.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/config/AbstractGeneratorConfig.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/config/GunsGeneratorConfig.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/config/WebGeneratorConfig.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/model/GenQo.java 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/SimpleTemplateEngine.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/base/AbstractTemplateEngine.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/base/GunsTemplateEngine.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/ContextConfig.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/ControllerConfig.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/DaoConfig.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/Menu.java 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/PageConfig.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/ServiceConfig.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/SqlConfig.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/pom.xml 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/README.md
New file
@@ -0,0 +1,186 @@
# Guns V4.1
## 介绍
Guns基于SpringBoot,致力于做更简洁的后台管理系统,完美整合springmvc + shiro + mybatis-plus + beetl!Guns项目代码简洁,注释丰富,上手容易,同时Guns包含许多基础模块(用户管理,角色管理,部门管理,字典管理等10个模块),可以直接作为一个后台管理系统的脚手架! 2018目标 `更简洁`,`更规范`!
Guns v3.0新增rest api服务,提供对接服务端接口的支持,并利用jwt token鉴权机制给予客户端的访问权限,传输数据进行md5签名保证传输过程数据的安全性!
### Guns v4.1更新内容
> * guns-admin提供rest api服务,并以jwt方式鉴权,所有以`/gunsApi`开头的接口走这种鉴权方式,其他接口仍为shiro鉴权
### Guns v4.0更新内容
> * spring boot升级到2.0版本!
> * 简化前端所有的html,js,css等资源文件,由11.8MB缩减为4.8MB!
> * 新增手动增加标签页的方法,Feng.newCrontab(href,menuName);
> * laydate时间插件和layer弹出层插件更新为官网最新,可以看着layui官网的文档直接开发啦!
> * 去掉animate动画效果,加快页面响应速度!
> * 修复登陆后重启应用造成404的bug!
> * 增强core模块的功能,拿来即用开发新的模块的后端管理系统!
> * 升级各个依赖包的版本!
> * 简化applicatioin.yml的配置,一些固定不变的配置写在core模块的default-config.properties!
> * 简化多数据源配置,简化mybatis-plus的配置!
> * 优化日志记录格式和策略,详情见logback-spring.xml!
此外,**更新Guns文档到《Guns技术文档 v2.0》**
## 最新Guns技术文档
Guns框架有作者在业余时间整理的技术文档,详情点击[查看详情](https://gitee.com/naan1993/guns/wikis/pages?title=Guns%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3&parent=)
## 最新Guns视频教程
Guns框架有作者在业余时间录制的视频教程,详情点击[教程介绍](https://gitee.com/naan1993/guns/wikis/pages?title=Guns%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B&parent=)
## 技术讨论 & [wiki地址](https://gitee.com/naan1993/guns/wikis/Home)
如果对项目有任何疑问或者建议,欢迎加入Guns技术交流1群:254550081,Guns技术交流2群:684163663,Guns技术交流3群:207434260(加之前先看下文档guns-admin/doc/Guns技术文档 v1.0.pdf)
## 管理系统功能
1.用户管理 2.角色管理 3.部门管理 4.菜单管理 5.字典管理 6.业务日志 7.登录日志 8.监控管理 9.通知管理 10.代码生成
## 项目特点
1. 基于SpringBoot,简化了大量项目配置和maven依赖,让您更专注于业务开发,独特的分包方式,代码多而不乱。
2. 完善的日志记录体系,可记录登录日志,业务操作日志(可记录操作前和操作后的数据),异常日志到数据库,通过@BussinessLog注解和LogObjectHolder.me().set()方法,业务操作日志可具体记录哪个用户,执行了哪些业务,修改了哪些数据,并且日志记录为异步执行,详情请见@BussinessLog注解和LogObjectHolder,LogManager,LogAop类。
3. 利用beetl模板引擎对前台页面进行封装和拆分,使臃肿的html代码变得简洁,更加易维护。
4. 对常用js插件进行二次封装,使js代码变得简洁,更加易维护,具体请见webapp/static/js/common文件夹内js代码。
5. 利用ehcache框架对经常调用的查询进行缓存,提升运行速度,具体请见ConstantFactory类中@Cacheable标记的方法。
6. controller层采用map + warpper方式的返回结果,返回给前端更为灵活的数据,具体参见com.supersavedriving.driver.modular.system.warpper包中具体类。
7. 防止XSS攻击,通过XssFilter类对所有的输入的非法字符串进行过滤以及替换。
8. 简单可用的代码生成体系,通过SimpleTemplateEngine可生成带有主页跳转和增删改查的通用控制器、html页面以及相关的js,还可以生成Service和Dao,并且这些生成项都为可选的,通过ContextConfig下的一些列xxxSwitch开关,可灵活控制生成模板代码,让您把时间放在真正的业务上。
9. 控制器层统一的异常拦截机制,利用@ControllerAdvice统一对异常拦截,具体见com.supersavedriving.driver.core.aop.GlobalExceptionHandler类。
10. 页面统一的js key-value单例模式写法,每个页面生成一个唯一的全局变量,提高js的利用效率,并且有效防止多个人员开发引起的函数名/类名冲突,并且可以更好地去维护代码。
## 基于javabean方式的spring配置
Guns以简洁为核心,抛弃了传统的易错,臃肿xml配置,采用javabean的方式配置spring,简化了项目的配置,如下示例为配置mybatis-plus和数据源:
```
@Configuration
@MapperScan(basePackages = {"com.supersavedriving.driver.modular.*.dao", "com.supersavedriving.driver.common.persistence.dao"})
public class MybatisPlusConfig {
    @Autowired
    DruidProperties druidProperties;
    /**
     * mybatis-plus分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setDialectType(DBType.MYSQL.getDb());
        return paginationInterceptor;
    }
}
```
## 业务日志记录
日志记录采用aop(LogAop类)方式对所有包含@BussinessLog注解的方法进行aop切入,会记录下当前用户执行了哪些操作(即@BussinessLog value属性的内容),如果涉及到数据修改,会取当前http请求的所有requestParameters与LogObjectHolder类中缓存的Object对象的所有字段作比较(所以在编辑之前的获取详情接口中需要缓存被修改对象之前的字段信息),日志内容会异步存入数据库中(通过ScheduledThreadPoolExecutor类)。
## beetl对前台页面的拆分与包装
例如,把主页拆分成三部分,每个部分单独一个页面,更加便于维护
```
<!--左侧导航开始-->
    @include("/common/_tab.html"){}
<!--左侧导航结束-->
<!--右侧部分开始-->
    @include("/common/_right.html"){}
<!--右侧部分结束-->
<!--右侧边栏开始-->
    @include("/common/_theme.html"){}
<!--右侧边栏结束-->
```
以及对重复的html进行包装,使前端页面更加专注于业务实现,例如,把所有页面引用包进行提取
```
<!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">
<!-- 全局js -->
<script src="${ctxPath}/static/js/jquery.min.js?v=2.1.4"></script>
<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>
```
开发页面时,只需编写如下代码即可
```
@layout("/common/_container.html"){
<div class="row">
    <div class="col-sm-12">
        <div class="ibox float-e-margins">
            <div class="ibox-title">
                <h5>部门管理</h5>
            </div>
            <div class="ibox-content">
               //自定义内容
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/dept/dept.js"></script>
@}
```
以上beetl的用法请参考beetl说明文档。
## 对js常用代码的封装
在webapp/static/js/common目录中,有对常用js代码的封装,例如Feng.js,其中Feng.info(),Feng.success(),Feng.error()三个方法,分别封装了普通提示,成功提示,错误提示的代码,简化了layer提示层插件的使用。
## 极简的图片上传方法
guns对web-upload进行二次封装,让图片的上传功能呢只用2行代码即可实现,如下
```
var avatarUp = new $WebUpload("avatar");
avatarUp.init();
```
具体实现请参考static/js/common/web-upload-object.js
## 独创controller层,map+warpper返回方式
map+warpper方式即为把controller层的返回结果使用BeanKit工具类把原有bean转化为Map的的形式(或者原有bean直接是map的形式),再用单独写的一个包装类再包装一次这个map,使里面的参数更加具体,更加有含义,下面举一个例子,例如,在返回给前台一个性别时,数据库查出来1是男2是女,假如直接返回给前台,那么前台显示的时候还需要增加一次判断,并且前后端分离开发时又增加了一次交流和文档的成本,但是采用warpper包装的形式,可以直接把返回结果包装一下,例如动态增加一个字段sexName直接返回给前台性别的中文名称即可。
## 独创mybatis数据范围拦截器,实现对数据权限的过滤
Guns的数据范围控制是指,对拥有相同角色的用户,根据部门的不同进行相应的数据筛选,如果部门不相同,那么有可能展示出的具体数据是不一致的.所以说Guns对数据范围控制是以部门id为单位来标识的,如何增加数据范围拦截呢?只需在相关的mapper接口的参数中增加一个DataScope对象即可,DataScope中有两个字段,scopeName用来标识sql语句中部门id的字段名称,例如deptiid或者id,另一个字段deptIds就是具体需要过滤的部门id的集合.拦截器原理如下:拦截mapper中包含DataScope对象的方法,获取其原始sql,并做一个包装限制部门id在deptIds范围内的数据进行展示.
## swagger api管理使用说明
swagger会管理所有包含@ApiOperation注解的控制器方法,同时,可利用@ApiImplicitParams注解标记接口中的参数,具体用法请参考CodeController类中的用法。
```
 @ApiOperation("生成代码")
 @ApiImplicitParams({
         @ApiImplicitParam(name = "moduleName", value = "模块名称", required = true, dataType = "String"),
         @ApiImplicitParam(name = "bizChName", value = "业务名称", required = true, dataType = "String"),
         @ApiImplicitParam(name = "bizEnName", value = "业务英文名称", required = true, dataType = "String"),
         @ApiImplicitParam(name = "path", value = "项目生成类路径", required = true, dataType = "String")
 })
 @RequestMapping(value = "/generate", method = RequestMethod.POST)
```
## jwt token鉴权机制
jwt token鉴权机制是指若需要请求服务器接口,必须通过AuthController获取一个请求令牌(jwt token),持有jwt token的用户才可以访问服务器的其他资源,如果没有此令牌,则访问接口会直接忽略,请求获取jwt token时,需要携带credenceName和credenceCode(可以是账号密码,可以是手机号验证码等等),校验credenceName和credenceCode成功后,会颁发给客户端一个jwt token还有一个随机字符串,用于传输过程中对数据进行签名用,签名机制请见下面介绍.基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息.这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利.
## 签名机制
签名机制是指客户端向服务端传输数据中,对传输数据进行md5加密,并且加密过程中利用Auth接口返回的随机字符串进行混淆加密,并把md5值同时附带给服务端,服务端通获取数据之后对数据再进行一次md5加密,若加密结果和客户端传来的数据一致,则认定客户端请求的数据是没有被篡改的,若不一致,则认为被加密的数据是被篡改的
## 效果图
![输入图片说明](https://git.oschina.net/uploads/images/2017/0604/194616_36ed7fd6_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0604/194623_a0761bc3_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0604/194630_640dfd35_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/104015_bdb14c74_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0516/000735_b83c5c46_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103734_bd3e8f6b_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0604/194539_f9bb482a_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103746_6b4129ed_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103755_7729b916_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103801_b8216865_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103807_20bfb868_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103814_67e078bb_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103822_58fd5d91_551203.png "在这里输入图片标题")
![输入图片说明](https://git.oschina.net/uploads/images/2017/0526/103827_d6218c74_551203.png "在这里输入图片标题")
## 曾获荣誉
![输入图片说明](https://gitee.com/uploads/images/2017/1015/151932_f1593f87_551203.jpeg "initpintu_副本_副本.jpg")
driver/guns-admin/pom.xml
New file
@@ -0,0 +1,246 @@
<?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>guns-admin</artifactId>
    <name>guns-admin</name>
    <description>guns 的spring boot版本</description>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--整合hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </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>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.11.3</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>
        <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ibeetl</groupId>
            <artifactId>beetl</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>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.8.10.ALL</version>
        </dependency>
        <!-- oos对象存储 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.8.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-core -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.4.3</version>
        </dependency>
        <!-- 计算两坐标间的直线距离 -->
        <dependency>
            <groupId>org.gavaghan</groupId>
            <artifactId>geodesy</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </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;-->
                    <!--<webResources>-->
                        <!--<resource>-->
                            <!--&lt;!&ndash;把本地lib里面的jar复制到lib&ndash;&gt;-->
                            <!--<directory>${project.basedir}/lib</directory>-->
                            <!--<targetPath>WEB-INF/lib/</targetPath>-->
                            <!--<includes>-->
                                <!--<include>**/*.jar</include>-->
                            <!--</includes>-->
                        <!--</resource>-->
                    <!--</webResources>-->
                <!--</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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/GunsApplication.java
New file
@@ -0,0 +1,83 @@
package com.supersavedriving.driver;
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.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
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
 */
@EnableEurekaClient//注册为服务提供者
@SpringBootApplication
@EnableScheduling//开启定时任务
@EnableTransactionManagement//启动事务功能
public class GunsApplication /*extends SpringBootServletInitializer*/ {
    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!");
    }
    /**
     * 向Spring容器中定义RestTemplate对象
     * @return
     */
    @Bean //SpringCloud内部服务质检使用服务名调用
    @LoadBalanced
    public RestTemplate internalRestTemplate() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());
        connectionManager.setDefaultMaxPerRoute(100);//最大并发连接
        connectionManager.setMaxTotal(200); // 总的最大连接数
        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
        httpRequestFactory.setConnectTimeout(30 * 3000);
        httpRequestFactory.setReadTimeout(30 * 3000);
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
    @Bean //通过ip地址调用
    public RestTemplate restTemplate() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());
        connectionManager.setDefaultMaxPerRoute(100);//最大并发连接
        connectionManager.setMaxTotal(200); // 总的最大连接数
        HttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        httpRequestFactory.setConnectionRequestTimeout(30 * 1000);
        httpRequestFactory.setConnectTimeout(30 * 3000);
        httpRequestFactory.setReadTimeout(30 * 3000);
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }
//    @Override
//    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
//        return builder.sources(GunsApplication.class);
//    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/GunsServletInitializer.java
New file
@@ -0,0 +1,18 @@
package com.supersavedriving.driver;
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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/EhCacheConfig.java
New file
@@ -0,0 +1,39 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/RedisConfig.java
New file
@@ -0,0 +1,46 @@
package com.supersavedriving.driver.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWaitMillis;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.block-when-exhausted}")
    private boolean  blockWhenExhausted;
    @Bean
    public JedisPool redisPoolFactory()  throws Exception{
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
        // 是否启用pool的jmx管理功能, 默认true
        jedisPoolConfig.setJmxEnabled(true);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
        return jedisPool;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/SpringSessionConfig.java
New file
@@ -0,0 +1,15 @@
package com.supersavedriving.driver.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 {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/SwaggerConfig.java
New file
@@ -0,0 +1,48 @@
package com.supersavedriving.driver.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.supersavedriving.driver.modular.system.controller"))    //这里采用包扫描的方式来确定要显示的接口
                .paths(PathSelectors.any())
                .build();
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("超省新代驾")
                .description("所有接口前需要加 /user 前缀,例如:/user/base/agreement/queryByType <br>" +
                        "所有以 /api/*** 路径的接口需要上传签名参数sign")
//                .termsOfServiceUrl("http://git.oschina.net/naan1993/guns")
                .contact("stylefeng")
                .version("1.0")
                .build();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/datasource/MultiDataSourceConfig.java
New file
@@ -0,0 +1,125 @@
package com.supersavedriving.driver.config.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.supersavedriving.driver.core.config.properties.DruidProperties;
import com.supersavedriving.driver.core.config.properties.MutiDataSourceProperties;
import com.supersavedriving.driver.core.datascope.DataScopeInterceptor;
import com.supersavedriving.driver.core.mutidatasource.DynamicDataSource;
import com.supersavedriving.driver.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.supersavedriving.driver.modular.*.dao","com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/datasource/SingleDataSourceConfig.java
New file
@@ -0,0 +1,61 @@
package com.supersavedriving.driver.config.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.supersavedriving.driver.core.config.properties.DruidProperties;
import com.supersavedriving.driver.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.supersavedriving.driver.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();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/properties/BeetlProperties.java
New file
@@ -0,0 +1,103 @@
package com.supersavedriving.driver.config.properties;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/properties/GunsProperties.java
New file
@@ -0,0 +1,105 @@
package com.supersavedriving.driver.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
import static com.supersavedriving.driver.core.util.ToolUtil.getTempPath;
import static com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/web/BeetlConfig.java
New file
@@ -0,0 +1,45 @@
package com.supersavedriving.driver.config.web;
import com.supersavedriving.driver.config.properties.BeetlProperties;
import com.supersavedriving.driver.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.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/web/ShiroConfig.java
New file
@@ -0,0 +1,216 @@
package com.supersavedriving.driver.config.web;
import com.supersavedriving.driver.config.properties.GunsProperties;
import com.supersavedriving.driver.core.intercept.GunsUserFilter;
import com.supersavedriving.driver.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");//api不走shiro验证
        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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/config/web/WebConfig.java
New file
@@ -0,0 +1,174 @@
package com.supersavedriving.driver.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.supersavedriving.driver.config.properties.GunsProperties;
import com.supersavedriving.driver.core.intercept.RestApiInteceptor;
import com.supersavedriving.driver.core.listener.ConfigListener;
import com.supersavedriving.driver.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.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/aop/GlobalExceptionHandler.java
New file
@@ -0,0 +1,123 @@
package com.supersavedriving.driver.core.aop;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.common.exception.InvalidKaptchaException;
import com.supersavedriving.driver.core.base.tips.ErrorTip;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogManager;
import com.supersavedriving.driver.core.log.factory.LogTaskFactory;
import com.supersavedriving.driver.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.supersavedriving.driver.core.support.HttpKit.getIp;
import static com.supersavedriving.driver.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());
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/aop/LogAop.java
New file
@@ -0,0 +1,105 @@
package com.supersavedriving.driver.core.aop;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.constant.dictmap.base.AbstractDictMap;
import com.supersavedriving.driver.core.log.LogManager;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.log.factory.LogTaskFactory;
import com.supersavedriving.driver.core.shiro.ShiroKit;
import com.supersavedriving.driver.core.shiro.ShiroUser;
import com.supersavedriving.driver.core.support.HttpKit;
import com.supersavedriving.driver.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.supersavedriving.driver.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));
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.aop;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.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.supersavedriving.driver.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();
            }
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/beetl/BeetlConfiguration.java
New file
@@ -0,0 +1,71 @@
package com.supersavedriving.driver.core.beetl;
import com.supersavedriving.driver.core.tag.DictSelectorTag;
import com.supersavedriving.driver.core.util.KaptchaUtil;
import com.supersavedriving.driver.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);
                }
            }
        });
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.beetl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.beetl.core.GroupTemplate;
import com.supersavedriving.driver.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());
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/annotion/BussinessLog.java
New file
@@ -0,0 +1,33 @@
package com.supersavedriving.driver.core.common.annotion;
import com.supersavedriving.driver.core.common.constant.dictmap.base.AbstractDictMap;
import com.supersavedriving.driver.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;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/annotion/Permission.java
New file
@@ -0,0 +1,22 @@
package com.supersavedriving.driver.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 {};
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/Const.java
New file
@@ -0,0 +1,36 @@
package com.supersavedriving.driver.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 = "接口文档";
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/DatasourceEnum.java
New file
@@ -0,0 +1,15 @@
package com.supersavedriving.driver.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";            //其他业务的数据源
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/JwtConstants.java
New file
@@ -0,0 +1,19 @@
package com.supersavedriving.driver.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";
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/cache/Cache.java
New file
@@ -0,0 +1,15 @@
package com.supersavedriving.driver.core.common.constant.cache;
/**
 * 所有缓存名称的集合
 *
 * @author fengshuonan
 * @date 2017-04-24 21:56
 */
public interface Cache {
    /**
     * 常量缓存
     */
    String CONSTANT = "CONSTANT";
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/cache/CacheKey.java
New file
@@ -0,0 +1,31 @@
package com.supersavedriving.driver.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_";
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/DeleteDict.java
New file
@@ -0,0 +1,31 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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");
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/DeptDict.java
New file
@@ -0,0 +1,28 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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");
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/DictMap.java
New file
@@ -0,0 +1,24 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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() {
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/LogDict.java
New file
@@ -0,0 +1,22 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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() {
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/MenuDict.java
New file
@@ -0,0 +1,34 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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() {
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/NoticeMap.java
New file
@@ -0,0 +1,22 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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() {
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/RoleDict.java
New file
@@ -0,0 +1,31 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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");
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/UserDict.java
New file
@@ -0,0 +1,36 @@
package com.supersavedriving.driver.core.common.constant.dictmap;
import com.supersavedriving.driver.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");
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/base/AbstractDictMap.java
New file
@@ -0,0 +1,53 @@
package com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/base/SystemDict.java
New file
@@ -0,0 +1,20 @@
package com.supersavedriving.driver.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() {
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/dictmap/factory/DictFieldWarpperFactory.java
New file
@@ -0,0 +1,33 @@
package com.supersavedriving.driver.core.common.constant.dictmap.factory;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.constant.factory.IConstantFactory;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.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);
            }
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/ConstantFactory.java
New file
@@ -0,0 +1,333 @@
package com.supersavedriving.driver.core.common.constant.factory;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.supersavedriving.driver.core.common.constant.cache.Cache;
import com.supersavedriving.driver.core.common.constant.cache.CacheKey;
import com.supersavedriving.driver.core.common.constant.state.ManagerStatus;
import com.supersavedriving.driver.core.common.constant.state.MenuStatus;
import com.supersavedriving.driver.modular.system.dao.*;
import com.supersavedriving.driver.modular.system.model.*;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.support.StrKit;
import com.supersavedriving.driver.core.util.Convert;
import com.supersavedriving.driver.core.util.SpringContextHolder;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/IConstantFactory.java
New file
@@ -0,0 +1,116 @@
package com.supersavedriving.driver.core.common.constant.factory;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/MutiStrFactory.java
New file
@@ -0,0 +1,96 @@
package com.supersavedriving.driver.core.common.constant.factory;
import com.supersavedriving.driver.core.support.StrKit;
import com.supersavedriving.driver.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;
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/factory/PageFactory.java
New file
@@ -0,0 +1,38 @@
package com.supersavedriving.driver.core.common.constant.factory;
import com.baomidou.mybatisplus.plugins.Page;
import com.supersavedriving.driver.core.common.constant.state.Order;
import com.supersavedriving.driver.core.support.HttpKit;
import com.supersavedriving.driver.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;
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/BizLogType.java
New file
@@ -0,0 +1,51 @@
package com.supersavedriving.driver.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;
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/ExpenseState.java
New file
@@ -0,0 +1,52 @@
package com.supersavedriving.driver.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 "";
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/LogSucceed.java
New file
@@ -0,0 +1,27 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/LogType.java
New file
@@ -0,0 +1,30 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/ManagerStatus.java
New file
@@ -0,0 +1,49 @@
package com.supersavedriving.driver.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 "";
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/MenuOpenStatus.java
New file
@@ -0,0 +1,50 @@
package com.supersavedriving.driver.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 "";
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/MenuStatus.java
New file
@@ -0,0 +1,50 @@
package com.supersavedriving.driver.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 "";
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/constant/state/Order.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/exception/BizExceptionEnum.java
New file
@@ -0,0 +1,100 @@
package com.supersavedriving.driver.core.common.exception;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/common/exception/InvalidKaptchaException.java
New file
@@ -0,0 +1,10 @@
package com.supersavedriving.driver.core.common.exception;
/**
 * 验证码错误异常
 *
 * @author fengshuonan
 * @date 2017-05-05 23:52
 */
public class InvalidKaptchaException extends RuntimeException {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.intercept;
import com.supersavedriving.driver.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;
                }
            }
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/intercept/RestApiInteceptor.java
New file
@@ -0,0 +1,62 @@
package com.supersavedriving.driver.core.intercept;
import com.supersavedriving.driver.core.base.tips.ErrorTip;
import com.supersavedriving.driver.core.common.constant.JwtConstants;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.util.JwtTokenUtil;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/intercept/SessionHolderInterceptor.java
New file
@@ -0,0 +1,34 @@
package com.supersavedriving.driver.core.intercept;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.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.supersavedriving.driver.*..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();
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.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());
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/LogManager.java
New file
@@ -0,0 +1,33 @@
package com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/LogObjectHolder.java
New file
@@ -0,0 +1,34 @@
package com.supersavedriving.driver.core.log;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/factory/LogFactory.java
New file
@@ -0,0 +1,47 @@
package com.supersavedriving.driver.core.log.factory;
import com.supersavedriving.driver.core.common.constant.state.LogSucceed;
import com.supersavedriving.driver.core.common.constant.state.LogType;
import com.supersavedriving.driver.modular.system.model.LoginLog;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/log/factory/LogTaskFactory.java
New file
@@ -0,0 +1,102 @@
package com.supersavedriving.driver.core.log.factory;
import com.supersavedriving.driver.core.common.constant.state.LogSucceed;
import com.supersavedriving.driver.core.common.constant.state.LogType;
import com.supersavedriving.driver.modular.system.dao.LoginLogMapper;
import com.supersavedriving.driver.modular.system.dao.OperationLogMapper;
import com.supersavedriving.driver.modular.system.model.LoginLog;
import com.supersavedriving.driver.modular.system.model.OperationLog;
import com.supersavedriving.driver.core.db.Db;
import com.supersavedriving.driver.core.log.LogManager;
import com.supersavedriving.driver.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);
                }
            }
        };
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/ShiroDbRealm.java
New file
@@ -0,0 +1,78 @@
package com.supersavedriving.driver.core.shiro;
import com.supersavedriving.driver.core.shiro.factory.IShiro;
import com.supersavedriving.driver.core.shiro.factory.ShiroFactroy;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.shiro;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/ShiroUser.java
New file
@@ -0,0 +1,81 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.shiro.check;
/**
 * 检查用接口
 */
public interface ICheck {
    /**
     * 检查当前登录用户是否拥有指定的角色访问当
     */
    boolean check(Object[] permissions);
    /**
     * 检查当前登录用户是否拥有当前请求的servlet的权限
     */
    boolean checkAll();
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.shiro.check;
import com.supersavedriving.driver.core.listener.ConfigListener;
import com.supersavedriving.driver.core.shiro.ShiroKit;
import com.supersavedriving.driver.core.shiro.ShiroUser;
import com.supersavedriving.driver.core.support.CollectionKit;
import com.supersavedriving.driver.core.support.HttpKit;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.core.shiro.check;
import com.supersavedriving.driver.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();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/factory/IShiro.java
New file
@@ -0,0 +1,50 @@
package com.supersavedriving.driver.core.shiro.factory;
import com.supersavedriving.driver.core.shiro.ShiroUser;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/shiro/factory/ShiroFactroy.java
New file
@@ -0,0 +1,98 @@
package com.supersavedriving.driver.core.shiro.factory;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.constant.state.ManagerStatus;
import com.supersavedriving.driver.core.shiro.ShiroUser;
import com.supersavedriving.driver.core.util.Convert;
import com.supersavedriving.driver.core.util.SpringContextHolder;
import com.supersavedriving.driver.modular.system.dao.MenuMapper;
import com.supersavedriving.driver.modular.system.dao.UserMapper;
import com.supersavedriving.driver.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.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class ShiroFactroy implements IShiro {
    @Resource
    private UserMapper userMapper;
    @Resource
    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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/tag/DictSelectorTag.java
New file
@@ -0,0 +1,201 @@
package com.supersavedriving.driver.core.tag;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Dict;
import com.supersavedriving.driver.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("输出字典标签错误");
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/ApiMenuFilter.java
New file
@@ -0,0 +1,36 @@
package com.supersavedriving.driver.core.util;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.config.properties.GunsProperties;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/Contrast.java
New file
@@ -0,0 +1,211 @@
package com.supersavedriving.driver.core.util;
import com.supersavedriving.driver.core.common.constant.dictmap.base.AbstractDictMap;
import com.supersavedriving.driver.core.common.constant.dictmap.factory.DictFieldWarpperFactory;
import com.supersavedriving.driver.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();
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/GetMobile.java
New file
@@ -0,0 +1,87 @@
package com.supersavedriving.driver.core.util;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class GetMobile {
    public static String getPhone(String accessToken,String androidOrIos){
        String host = "http://verifystar.market.alicloudapi.com";
        String path = "/api/v1/mobile/info";
        String method = "POST";
        String appcode = "b7d32437d08149099457dcb50fb57df2";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求,定义相对应的Content-Type
        headers.put("Content-Type", "application/json; charset=UTF-8");
        //需要给X-Ca-Nonce的值生成随机字符串,每次请求不能相同
        headers.put("X-Ca-Nonce", UUID.randomUUID().toString());
        Map<String, String> querys = new HashMap<String, String>();
        if(androidOrIos.equals("android")){
            querys.put("appkey", "5f02e3cc978eea07661bde20");
            querys.put("verifyId", "");
        }else{
            querys.put("appkey", "5ee43367978eea081640dca7");
            querys.put("verifyId", "");
        }
        /*;*/
        String bodys = "{\"token\":\""+accessToken+"\"}";
        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            return  EntityUtils.toString(response.getEntity());
            //获取response的body
            //System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
            return  null;
        }
       /* DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI4G9Zez9H4B36vakPXGy4", "BOVPUeZndKVbrPOq6Ef5j6oiydB3XZ");
        IAcsClient client = new DefaultAcsClient(profile);
        GetMobileRequest request = new GetMobileRequest();
        request.setRegionId("cn-hangzhou");
        request.setAccessToken(accessToken);
        try {
            GetMobileResponse response = client.getAcsResponse(request);
            才
        } catch (ServerException e) {
            e.printStackTrace();
            return  null;
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
            return  null;
        }*/
    }
    public static void main(String[] args) {
        //String response = GetMobile.getPhone("eyAgIm8iIDogImlPUyIsICAiayIgOiAiY2lNVmw2S0ZyM0xlWlJOQVNSNTdZXC9WV1FZS3BCZlVSR1pQa1I5OFJFWmVJWmF3OHJGM0NVSDZQZVwvNzRPVTBSalpoZE5QT002NHl3b05yZlJkWUlrUkxVY29hdm10Rkg1ODhrNjJmXC9vdTEzalN2ZDduZDlscXFLWm5Ca2hQZzBBa09yS2M1dlwvWWY0U05lUjd4RHh6MUJoOUVYbkxnbHFEclZqVW85TXQ5XC9ieXk2SmVNVVB3UzhqRHM2N3VwUEg0SWRTNElqUUxCUXVHb1FyM1ltb1lpUnQ2R29YWlJCRzhDbndUTVBrSHM4YXNMQzRGVUpmZHcxbFlzN0srNGlyTGJSdXVacTg1NW9NMEo5b05FOExmdDZGTFpmVWVQY0d0WlwvTnhIMnFXM1ZIU3NtUEgxdHlkTzdUeGRmVUM1cEo2SmhRclVvNEdIazBXVHF3RTlCYlFnPT0iLCAgImMiIDogIkVjS0dHSzB5TjA2Tm9vSjhYV1h1K3d6eGdodElDaGpqOUtHRlliSjl4ZjhQMUR6UERsYVdRcGcxMHg5SkdNV2hcL2wyVDd4bXNxSUZmWERDZlBjZ05NdFY2dVZueEU1aGFTUUdPbFowekp4Z2JPZ3ZrR2ZkbVJvOGZFSGhEQ0czM1RYNHR5ZHJXUGFuQTBBSmo3VjljaGN0d25UT0ZzSG82WlhLOWZsQUlSbHpmNE1yaGZsRkhtTVRoejQ1UG01cHhtSlh5N3EyVlZTK0tEbU9GU2lzNlwvMnByK24zQWttazYxZ0RVUUhYV2FoVFwvYzc0dzhrTDhWYlliM3dOc0VkVEh2ZDhzYjlPbFNpVHNJUHNFUVJ6Wm9JRFJUaE5pWVg1U3VwNklQXC9LTFlLOFdaSlJWamU2QUpLT2JOakEybTlleTM0Sys2MUhtQktPNmNwTlZ4TTJITlJERjRzcG9lWStYdnhTT1pVcExaSWxXd3NFdUtUeVVBSzJUMHpOUmZBQVhlOWR6alBcL2lHSFU3aitwUWlaaU1XbHg5WGtIREM3MjNkXC80b3d2dEluem9yVlBNNjJQTzJsWWttOEt4TVVTYlRRTnBVNGZzRzlXcHB0cFJRR0JFUTYyNmxlNFFZeWdaSWxjZXlcL1VJOWlLWDVWTzhCU01VUnNoZUdNU29HejF2dmw2QUVmdTdBNm0raUhUYkxOd01uQkM3VHZ4TlYxNmd4M2dWRGtha0ZGNEdZTjZsWm0zMkNnT2hVakhlODMrUXFHNXhNNkZxUlBnMWN0QzRRN05DZFpHNUN5UEZVd2dRcUx3MFFWaE9IRnNZTFwvU3p3T1JUMFFlb0h3T1piZ3FmNU96T0k1TFwvelRqNEFJV3ZqejlteWNJZVc3cXMzXC9IdnJXck5GM3lSZCtYTml5a2d6d1RDMnZjaXRrSkszSVBENjlEVVRVVzBCNllvdng2ako5QW5xZXdUc1J3Nlp4ZXcra0xpXC9HTlB0K0hHRGVjclVZcFpwOFQ5ckN6QkM0Z0ZEa0ZOQ0Z2UkJKSE5JVGkrRGNUeWhVZz09In0=","ios");
        JSONObject json = JSONObject.parseObject("{\"success\":true,\"data\":{\"mobile\":\"15608199082\",\"score\":null,\"activeScore\":null,\"aesEncryptKey\":null},\"code\":2001,\"message\":\"gain mobile&#39;s result success\",\"requestId\":\"21D1E797-2B22-4D0E-B31D-AC470F7E06E7\"}");
        String phone = json.getJSONObject("data").getString("mobile");
        //JSONObject json = JSONObject.parseObject(response);
        if(json.getInteger("code")!=2003){
            System.out.println("1111="+ phone);
        }
        System.out.println( phone);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/HttpUtils.java
New file
@@ -0,0 +1,312 @@
package com.supersavedriving.driver.core.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
public class HttpUtils {
    /**
     * get
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doGet(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        return httpClient.execute(request);
    }
    /**
     * post form
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param bodys
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      Map<String, String> bodys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }
        return httpClient.execute(request);
    }
    /**
     * Post String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }
        return httpClient.execute(request);
    }
    /**
     * Post stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }
        return httpClient.execute(request);
    }
    /**
     * Put String
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }
        return httpClient.execute(request);
    }
    /**
     * Put stream
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }
        return httpClient.execute(request);
    }
    /**
     * Delete
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doDelete(String host, String path, String method,
                                        Map<String, String> headers,
                                        Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        return httpClient.execute(request);
    }
    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }
        return sbUrl.toString();
    }
    private static HttpClient wrapClient(String host) {
        HttpClient httpClient = new DefaultHttpClient();
        if (host.startsWith("https://")) {
            sslClient(httpClient);
        }
        return httpClient;
    }
    private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                }
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/JwtTokenUtil.java
New file
@@ -0,0 +1,127 @@
package com.supersavedriving.driver.core.util;
import com.supersavedriving.driver.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<>();
        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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/core/util/KaptchaUtil.java
New file
@@ -0,0 +1,16 @@
package com.supersavedriving.driver.core.util;
import com.supersavedriving.driver.config.properties.GunsProperties;
/**
 * 验证码工具类
 */
public class KaptchaUtil {
    /**
     * 获取验证码开关
     */
    public static Boolean getKaptchaOnOff() {
        return SpringContextHolder.getBean(GunsProperties.class).getKaptchaOpen();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/code/controller/CodeController.java
New file
@@ -0,0 +1,61 @@
package com.supersavedriving.driver.modular.code.controller;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.config.properties.DruidProperties;
import com.supersavedriving.driver.generator.action.config.WebGeneratorConfig;
import com.supersavedriving.driver.generator.action.model.GenQo;
import com.supersavedriving.driver.modular.code.factory.DefaultTemplateFactory;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/code/factory/DefaultTemplateFactory.java
New file
@@ -0,0 +1,61 @@
package com.supersavedriving.driver.modular.code.factory;
import com.supersavedriving.driver.GunsApplication;
import com.supersavedriving.driver.core.CoreFlag;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/code/service/TableService.java
New file
@@ -0,0 +1,29 @@
package com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/api/DriverController.java
New file
@@ -0,0 +1,95 @@
package com.supersavedriving.driver.modular.system.api;
import com.alibaba.fastjson.JSON;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.service.IBranchOfficeService;
import com.supersavedriving.driver.modular.system.util.ResultUtil;
import com.supersavedriving.driver.modular.system.warpper.OpenCityWarpper;
import com.supersavedriving.driver.modular.system.warpper.ResponseWarpper;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 司机控制器
* @author pzb
* @Date 2023/2/3 14:10
*/
@RestController
@RequestMapping("")
public class DriverController {
    Logger logger = LoggerFactory.getLogger("ServiceLog");
    @Autowired
    private IBranchOfficeService branchOfficeService;
    @ResponseBody
    @PostMapping("/base/driver/queryCityList")
    @ApiOperation(value = "获取开通的省市数据", tags = {"司机端-登录注册"}, notes = "")
    @ApiImplicitParams({
    })
    public ResponseWarpper<List<OpenCityWarpper>> queryCityList(){
        ResponseWarpper responseWarpper = null;
        try {
            List<OpenCityWarpper> list = branchOfficeService.queryOpenCity();
            responseWarpper = ResponseWarpper.success(list);
        }catch (Exception e){
            e.printStackTrace();
            responseWarpper = new ResponseWarpper(500, e.getMessage());
        }
        logger.debug("" +
                "\n接口地址:/base/driver/queryCityList" +
                "\n接口名称:获取开通的省市数据" +
                "\n请求参数:" +
                "\n响应结果:{}"
                , JSON.toJSONString(responseWarpper));
        return responseWarpper;
    }
    @ResponseBody
    @PostMapping("/base/driver/queryOpenDistrict")
    @ApiOperation(value = "根据城市code获取开通区域", tags = {"司机端-登录注册"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "城市code", name = "cityCode", required = true, dataType = "string"),
    })
    public ResponseWarpper<List<OpenCityWarpper>> queryOpenDistrict(String cityCode){
        ResponseWarpper responseWarpper = null;
        if(ToolUtil.isEmpty(cityCode)){
            responseWarpper = ResponseWarpper.success(ResultUtil.paranErr());
        }
        if(ToolUtil.isNotEmpty(cityCode)){
            try {
                List<OpenCityWarpper> list = branchOfficeService.queryOpenDistrict(cityCode);
                responseWarpper = ResponseWarpper.success(list);
            }catch (Exception e){
                e.printStackTrace();
                responseWarpper = new ResponseWarpper(500, e.getMessage());
            }
        }
        logger.debug("" +
                        "\n接口地址:/base/driver/queryOpenDistrict" +
                        "\n接口名称:根据城市code获取开通区域" +
                        "\n请求参数:cityCode={}" +
                        "\n响应结果:{}"
                , cityCode, JSON.toJSONString(responseWarpper));
        return responseWarpper;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/api/ImgController.java
New file
@@ -0,0 +1,69 @@
package com.supersavedriving.driver.modular.system.api;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Img;
import com.supersavedriving.driver.modular.system.service.IImgService;
import com.supersavedriving.driver.modular.system.util.ResultUtil;
import com.supersavedriving.driver.modular.system.warpper.BaseWarpper;
import com.supersavedriving.driver.modular.system.warpper.ResponseWarpper;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("")
public class ImgController {
    Logger logger = LoggerFactory.getLogger("ServiceLog");
    @Autowired
    private IImgService imgService;
    @ResponseBody
    @PostMapping("/base/img/querySysImg")
    @ApiOperation(value = "获取系统图片", tags = {"司机端-公共接口"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "数据类型(1=启动页)", name = "type", required = true, dataType = "int"),
    })
    public ResponseWarpper<List<BaseWarpper>> querySysImg(@RequestParam("type") Integer type){
        ResponseWarpper responseWarpper = null;
        if(ToolUtil.isEmpty(type)){
            responseWarpper = ResponseWarpper.success(ResultUtil.paranErr());
        }
        if(ToolUtil.isNotEmpty(type)){
            try {
                List<Img> imgs = imgService.selectList(new EntityWrapper<Img>().eq("type", type));
                List<BaseWarpper> list = new ArrayList<>();
                for (Img img : imgs) {
                    BaseWarpper baseWarpper = new BaseWarpper();
                    baseWarpper.setId(img.getId());
                    baseWarpper.setPath(img.getImg());
                    list.add(baseWarpper);
                }
                responseWarpper = ResponseWarpper.success(list);
            }catch (Exception e){
                e.printStackTrace();
                responseWarpper = new ResponseWarpper(500, e.getMessage());
            }
        }
        logger.debug("" +
                "\n接口地址:/base/img/querySysImg" +
                "\n接口名称:获取系统图片" +
                "\n请求参数:type:{}" +
                "\n响应结果:{}"
                , type, JSON.toJSONString(responseWarpper));
        return responseWarpper;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/AuthIntercepter.java
New file
@@ -0,0 +1,37 @@
package com.supersavedriving.driver.modular.system.auth;
import com.alibaba.fastjson.JSON;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/AuthService.java
New file
@@ -0,0 +1,50 @@
package com.supersavedriving.driver.modular.system.auth;
import com.supersavedriving.driver.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();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/AuthenticationKit.java
New file
@@ -0,0 +1,232 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/Configuration.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.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/**");
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/HMACSHA1.java
New file
@@ -0,0 +1,63 @@
package com.supersavedriving.driver.modular.system.auth;
import org.apache.tomcat.util.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();
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/HashKit.java
New file
@@ -0,0 +1,109 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/auth/UrlEncoderUtils.java
New file
@@ -0,0 +1,44 @@
package com.supersavedriving.driver.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();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/BlackboardController.java
New file
@@ -0,0 +1,35 @@
package com.supersavedriving.driver.modular.system.controller;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.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";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/DeptController.java
New file
@@ -0,0 +1,164 @@
package com.supersavedriving.driver.modular.system.controller;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.dictmap.DeptDict;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Dept;
import com.supersavedriving.driver.modular.system.service.IDeptService;
import com.supersavedriving.driver.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 + "],");
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/DictController.java
New file
@@ -0,0 +1,142 @@
package com.supersavedriving.driver.modular.system.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.dictmap.DictMap;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Dict;
import com.supersavedriving.driver.modular.system.service.IDictService;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/KaptchaController.java
New file
@@ -0,0 +1,114 @@
package com.supersavedriving.driver.modular.system.controller;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.supersavedriving.driver.config.properties.GunsProperties;
import com.supersavedriving.driver.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;
/**
 * 验证码生成
 *
 * @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
        BufferedImage bi = producer.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();
            }
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/LogController.java
New file
@@ -0,0 +1,84 @@
package com.supersavedriving.driver.modular.system.controller;
import com.baomidou.mybatisplus.mapper.SqlRunner;
import com.baomidou.mybatisplus.plugins.Page;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.factory.PageFactory;
import com.supersavedriving.driver.core.common.constant.state.BizLogType;
import com.supersavedriving.driver.core.support.BeanKit;
import com.supersavedriving.driver.modular.system.model.OperationLog;
import com.supersavedriving.driver.modular.system.service.IOperationLogService;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/LoginController.java
New file
@@ -0,0 +1,134 @@
package com.supersavedriving.driver.modular.system.controller;
import com.google.code.kaptcha.Constants;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.common.exception.InvalidKaptchaException;
import com.supersavedriving.driver.core.log.LogManager;
import com.supersavedriving.driver.core.log.factory.LogTaskFactory;
import com.supersavedriving.driver.core.node.MenuNode;
import com.supersavedriving.driver.core.shiro.ShiroKit;
import com.supersavedriving.driver.core.shiro.ShiroUser;
import com.supersavedriving.driver.core.util.ApiMenuFilter;
import com.supersavedriving.driver.core.util.KaptchaUtil;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.User;
import com.supersavedriving.driver.modular.system.service.IMenuService;
import com.supersavedriving.driver.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.supersavedriving.driver.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";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/LoginLogController.java
New file
@@ -0,0 +1,69 @@
package com.supersavedriving.driver.modular.system.controller;
import com.baomidou.mybatisplus.mapper.SqlRunner;
import com.baomidou.mybatisplus.plugins.Page;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.factory.PageFactory;
import com.supersavedriving.driver.modular.system.model.LoginLog;
import com.supersavedriving.driver.modular.system.service.ILoginLogService;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/MenuController.java
New file
@@ -0,0 +1,244 @@
package com.supersavedriving.driver.modular.system.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.base.tips.Tip;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.dictmap.MenuDict;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.constant.state.MenuStatus;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.core.support.BeanKit;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Menu;
import com.supersavedriving.driver.modular.system.service.IMenuService;
import com.supersavedriving.driver.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() + "],");
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/NoticeController.java
New file
@@ -0,0 +1,138 @@
package com.supersavedriving.driver.modular.system.controller;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.constant.dictmap.NoticeMap;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.shiro.ShiroKit;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Notice;
import com.supersavedriving.driver.modular.system.service.INoticeService;
import com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/RoleController.java
New file
@@ -0,0 +1,230 @@
package com.supersavedriving.driver.modular.system.controller;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.base.tips.Tip;
import com.supersavedriving.driver.core.cache.CacheKit;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.cache.Cache;
import com.supersavedriving.driver.core.common.constant.dictmap.RoleDict;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.core.util.Convert;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.Role;
import com.supersavedriving.driver.modular.system.model.User;
import com.supersavedriving.driver.modular.system.service.IRoleService;
import com.supersavedriving.driver.modular.system.service.IUserService;
import com.supersavedriving.driver.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;
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/controller/UserMgrController.java
New file
@@ -0,0 +1,373 @@
package com.supersavedriving.driver.modular.system.controller;
import com.supersavedriving.driver.config.properties.GunsProperties;
import com.supersavedriving.driver.core.base.controller.BaseController;
import com.supersavedriving.driver.core.base.tips.Tip;
import com.supersavedriving.driver.core.common.annotion.BussinessLog;
import com.supersavedriving.driver.core.common.annotion.Permission;
import com.supersavedriving.driver.core.common.constant.Const;
import com.supersavedriving.driver.core.common.constant.dictmap.UserDict;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.common.constant.state.ManagerStatus;
import com.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.datascope.DataScope;
import com.supersavedriving.driver.core.db.Db;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.core.log.LogObjectHolder;
import com.supersavedriving.driver.core.shiro.ShiroKit;
import com.supersavedriving.driver.core.shiro.ShiroUser;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.dao.UserMapper;
import com.supersavedriving.driver.modular.system.factory.UserFactory;
import com.supersavedriving.driver.modular.system.model.User;
import com.supersavedriving.driver.modular.system.service.IUserService;
import com.supersavedriving.driver.modular.system.transfer.UserDto;
import com.supersavedriving.driver.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);
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/BranchOfficeMapper.java
New file
@@ -0,0 +1,7 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.modular.system.model.BranchOffice;
public interface BranchOfficeMapper extends BaseMapper<BranchOffice> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/DeptMapper.java
New file
@@ -0,0 +1,31 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/DictMapper.java
New file
@@ -0,0 +1,34 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/ExpenseMapper.java
New file
@@ -0,0 +1,16 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.modular.system.model.Expense;
/**
 * <p>
  * 报销表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-12-04
 */
public interface ExpenseMapper extends BaseMapper<Expense> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/ImgMapper.java
New file
@@ -0,0 +1,7 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.modular.system.model.Img;
public interface ImgMapper extends BaseMapper<Img> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/LoginLogMapper.java
New file
@@ -0,0 +1,27 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/MenuMapper.java
New file
@@ -0,0 +1,80 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.core.node.MenuNode;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/NoticeMapper.java
New file
@@ -0,0 +1,25 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/OperationLogMapper.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/RelationMapper.java
New file
@@ -0,0 +1,16 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.modular.system.model.Relation;
/**
 * <p>
  * 角色和菜单关联表 Mapper 接口
 * </p>
 *
 * @author stylefeng
 * @since 2017-07-11
 */
public interface RelationMapper extends BaseMapper<Relation> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/RoleMapper.java
New file
@@ -0,0 +1,53 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/UserMapper.java
New file
@@ -0,0 +1,45 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.core.datascope.DataScope;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/BranchOfficeMapper.xml
New file
@@ -0,0 +1,21 @@
<?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.supersavedriving.driver.modular.system.dao.BranchOfficeMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.modular.system.model.BranchOffice">
        <id column="id" property="id"/>
        <result column="agentId" property="agentId"/>
        <result column="principal" property="principal"/>
        <result column="principalPhone" property="principalPhone"/>
        <result column="email" property="email"/>
        <result column="provinceCode" property="provinceCode"/>
        <result column="provinceName" property="provinceName"/>
        <result column="cityCode" property="cityCode"/>
        <result column="cityName" property="cityName"/>
        <result column="districtCode" property="districtCode"/>
        <result column="districtName" property="districtName"/>
        <result column="status" property="status"/>
        <result column="createTime" property="createTime"/>
    </resultMap>
</mapper>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.DeptMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.DictMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/ExpenseMapper.xml
New file
@@ -0,0 +1,20 @@
<?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.supersavedriving.driver.modular.system.dao.ExpenseMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.modular.system.model.Expense">
        <id column="id" property="id" />
        <result column="money" property="money" />
        <result column="desc" property="desc" />
        <result column="createtime" property="createtime" />
        <result column="state" property="state" />
        <result column="userid" property="userid" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, money, desc, createtime, state, userid
    </sql>
</mapper>
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/ImgMapper.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.supersavedriving.driver.modular.system.dao.ImgMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.modular.system.model.Img">
        <id column="id" property="id" />
        <result column="type" property="type" />
        <result column="img" property="img" />
        <result column="createTime" property="createTime" />
    </resultMap>
</mapper>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.LoginLogMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.MenuMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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.supersavedriving.driver.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.supersavedriving.driver.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.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.NoticeMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.OperationLogMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.RelationMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.modular.system.model.Relation">
        <id column="id" property="id" />
        <result column="menuid" property="menuid" />
        <result column="roleid" property="roleid" />
    </resultMap>
</mapper>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.RoleMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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.supersavedriving.driver.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.supersavedriving.driver.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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/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.supersavedriving.driver.modular.system.dao.UserMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.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="name" property="name" />
        <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, name, birthday, sex, email, avatar,
        phone, roleid,
        deptid, status,
        createtime, version
    </sql>
    <sql id="Base_Column_List_With_Pwd">
        id, account, name, 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 name 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>
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/factory/UserFactory.java
New file
@@ -0,0 +1,54 @@
package com.supersavedriving.driver.modular.system.factory;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.model.User;
import com.supersavedriving.driver.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;
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/BranchOffice.java
New file
@@ -0,0 +1,85 @@
package com.supersavedriving.driver.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.util.Date;
/**
* 分公司实体
* @author pzb
* @Date 2023/2/3 14:13
*/
@Data
@TableName("t_branch_office")
public class BranchOffice {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    @TableField("id")
    private Integer id;
    /**
     * 代理商id
     */
    @TableField("agentId")
    private Integer agentId;
    /**
     * 负责人姓名
     */
    @TableField("principal")
    private String principal;
    /**
     * 负责人电话
     */
    @TableField("principalPhone")
    private String principalPhone;
    /**
     * 邮箱
     */
    @TableField("email")
    private String email;
    /**
     * 代理区域省编号
     */
    @TableField("provinceCode")
    private String provinceCode;
    /**
     * 代理区域省名称
     */
    @TableField("provinceName")
    private String provinceName;
    /**
     * 代理区域市编号
     */
    @TableField("cityCode")
    private String cityCode;
    /**
     * 代理区域市名称
     */
    @TableField("cityName")
    private String cityName;
    /**
     * 代理区域区编号
     */
    @TableField("districtCode")
    private String districtCode;
    /**
     * 代理区域区名称
     */
    @TableField("districtName")
    private String districtName;
    /**
     * 状态(1=正常,2=冻结,3=删除)
     */
    @TableField("status")
    private Integer status;
    /**
     * 添加时间
     */
    @TableField("createTime")
    private Date createTime;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Dept.java
New file
@@ -0,0 +1,140 @@
package com.supersavedriving.driver.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 +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Dict.java
New file
@@ -0,0 +1,116 @@
package com.supersavedriving.driver.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 + '\'' +
                '}';
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Expense.java
New file
@@ -0,0 +1,123 @@
package com.supersavedriving.driver.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.math.BigDecimal;
import java.util.Date;
/**
 * <p>
 * 报销表
 * </p>
 *
 * @author stylefeng
 * @since 2017-12-05
 */
@TableName("sys_expense")
public class Expense extends Model<Expense> {
    private static final long serialVersionUID = 1L;
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    /**
     * 报销金额
     */
    private BigDecimal money;
    /**
     * 描述
     */
    private String desc;
    private Date createtime;
    /**
     * 状态: 1.待提交  2:待审核   3.审核通过
     */
    private Integer state;
    /**
     * 用户id
     */
    private Integer userid;
    /**
     * 流程定义id
     */
    private String processId;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public BigDecimal getMoney() {
        return money;
    }
    public void setMoney(BigDecimal money) {
        this.money = money;
    }
    public String getDesc() {
        return desc;
    }
    public void setDesc(String desc) {
        this.desc = desc;
    }
    public Date getCreatetime() {
        return createtime;
    }
    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
    public Integer getState() {
        return state;
    }
    public void setState(Integer state) {
        this.state = state;
    }
    public Integer getUserid() {
        return userid;
    }
    public void setUserid(Integer userid) {
        this.userid = userid;
    }
    public String getProcessId() {
        return processId;
    }
    public void setProcessId(String processId) {
        this.processId = processId;
    }
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
    @Override
    public String toString() {
        return "Expense{" +
            "id=" + id +
            ", money=" + money +
            ", desc=" + desc +
            ", createtime=" + createtime +
            ", state=" + state +
            ", userid=" + userid +
            ", processId=" + processId +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Img.java
New file
@@ -0,0 +1,40 @@
package com.supersavedriving.driver.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.util.Date;
/**
* 系统图片
* @author pzb
* @Date 2023/2/3 10:36
*/
@Data
@TableName("t_img")
public class Img {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    @TableField("id")
    private Integer id;
    /**
     * 数据类型(1=启动页)
     */
    @TableField("type")
    private Integer type;
    /**
     * 图片地址
     */
    @TableField("img")
    private String img;
    /**
     * 添加时间
     */
    @TableField("createTime")
    private Date createTime;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/LoginLog.java
New file
@@ -0,0 +1,128 @@
package com.supersavedriving.driver.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 +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Menu.java
New file
@@ -0,0 +1,208 @@
package com.supersavedriving.driver.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 +
                "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Notice.java
New file
@@ -0,0 +1,115 @@
package com.supersavedriving.driver.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 +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/OperationLog.java
New file
@@ -0,0 +1,154 @@
package com.supersavedriving.driver.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 +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Region.java
New file
@@ -0,0 +1,104 @@
package com.supersavedriving.driver.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;
/**
 * 省市区
 */
@TableName("t_region")
public class Region {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    @TableField("id")
    private Integer id;
    /**
     * 城市名称
     */
    @TableField("name")
    private String name;
    /**
     * 城市行政code
     */
    @TableField("code")
    private String code;
    /**
     * 区号code
     */
    @TableField("citycode")
    private String citycode;
    /**
     * 父级id
     */
    @TableField("parent_id")
    private Integer parentId;
    /**
     * 英文
     */
    @TableField("english")
    private String english;
    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 getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getCitycode() {
        return citycode;
    }
    public void setCitycode(String citycode) {
        this.citycode = citycode;
    }
    public Integer getParentId() {
        return parentId;
    }
    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }
    public String getEnglish() {
        return english;
    }
    public void setEnglish(String english) {
        this.english = english;
    }
    @Override
    public String toString() {
        return "Region{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", code='" + code + '\'' +
                ", citycode='" + citycode + '\'' +
                ", parentId=" + parentId +
                ", english='" + english + '\'' +
                '}';
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Relation.java
New file
@@ -0,0 +1,75 @@
package com.supersavedriving.driver.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 +
                "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/Role.java
New file
@@ -0,0 +1,127 @@
package com.supersavedriving.driver.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 +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/User.java
New file
@@ -0,0 +1,232 @@
package com.supersavedriving.driver.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 +
            "}";
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IBranchOfficeService.java
New file
@@ -0,0 +1,32 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.modular.system.model.BranchOffice;
import com.supersavedriving.driver.modular.system.warpper.OpenCityWarpper;
import java.util.List;
/**
* 分公司接口逻辑类
* @author pzb
* @Date 2023/2/3 14:49
*/
public interface IBranchOfficeService extends IService<BranchOffice> {
    /**
     * 获取开通省市数据
     * @return
     * @throws Exception
     */
    List<OpenCityWarpper> queryOpenCity() throws Exception;
    /**
     * 根据城市code获取开通区域
     * @param cityCode  城市code
     * @return
     * @throws Exception
     */
    List<OpenCityWarpper> queryOpenDistrict(String cityCode) throws Exception;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDeptService.java
New file
@@ -0,0 +1,33 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDictService.java
New file
@@ -0,0 +1,48 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IImgService.java
New file
@@ -0,0 +1,7 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.modular.system.model.Img;
public interface IImgService extends IService<Img> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/ILoginLogService.java
New file
@@ -0,0 +1,24 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IMenuService.java
New file
@@ -0,0 +1,94 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.core.node.MenuNode;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/INoticeService.java
New file
@@ -0,0 +1,23 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IOperationLogService.java
New file
@@ -0,0 +1,24 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IRelationService.java
New file
@@ -0,0 +1,16 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.modular.system.model.Relation;
/**
 * <p>
 * 角色和菜单关联表 服务类
 * </p>
 *
 * @author stylefeng123
 * @since 2018-02-22
 */
public interface IRelationService extends IService<Relation> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IRoleService.java
New file
@@ -0,0 +1,68 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IUserService.java
New file
@@ -0,0 +1,46 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.core.datascope.DataScope;
import com.supersavedriving.driver.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);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/BranchOfficeServiceImpl.java
New file
@@ -0,0 +1,91 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.BranchOfficeMapper;
import com.supersavedriving.driver.modular.system.model.BranchOffice;
import com.supersavedriving.driver.modular.system.service.IBranchOfficeService;
import com.supersavedriving.driver.modular.system.warpper.OpenCityWarpper;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 分公司逻辑类
* @author pzb
* @Date 2023/2/3 14:48
*/
@Service
public class BranchOfficeServiceImpl extends ServiceImpl<BranchOfficeMapper, BranchOffice> implements IBranchOfficeService {
    /**
     * 获取开通省市数据
     * @return
     * @throws Exception
     */
    @Override
    public List<OpenCityWarpper> queryOpenCity() throws Exception {
        List<BranchOffice> branchOffices = this.selectList(new EntityWrapper<BranchOffice>().eq("status", 1));
        List<OpenCityWarpper> province = new ArrayList<>();
        //遍历处理省级数据
        List<String> provinceCodes = new ArrayList<>();
        for (BranchOffice branchOffice : branchOffices) {
            String provinceCode = branchOffice.getProvinceCode();
            if(!provinceCodes.contains(provinceCode)){
                provinceCodes.add(provinceCode);
                OpenCityWarpper openCityWarpper = new OpenCityWarpper();
                openCityWarpper.setCode(provinceCode);
                openCityWarpper.setName(branchOffice.getProvinceName());
                province.add(openCityWarpper);
            }
        }
        //遍历处理省级对应的市级数据
        for (OpenCityWarpper openCityWarpper : province) {
            String code = openCityWarpper.getCode();
            List<OpenCityWarpper> city = new ArrayList<>();
            List<String> cityCodes = new ArrayList<>();
            for (BranchOffice branchOffice : branchOffices) {
                String provinceCode1 = branchOffice.getProvinceCode();
                String cityCode = branchOffice.getCityCode();
                if(code.equals(provinceCode1) && !cityCodes.contains(cityCode)){
                    cityCodes.add(cityCode);
                    OpenCityWarpper openCityWarpper1 = new OpenCityWarpper();
                    openCityWarpper1.setCode(cityCode);
                    openCityWarpper1.setName(branchOffice.getCityName());
                    city.add(openCityWarpper1);
                }
            }
            openCityWarpper.setSublevel(city);
        }
        return province;
    }
    /**
     * 根据城市code获取开通区域
     * @param cityCode  城市code
     * @return
     * @throws Exception
     */
    @Override
    public List<OpenCityWarpper> queryOpenDistrict(String cityCode) throws Exception {
        List<BranchOffice> branchOffices = this.selectList(new EntityWrapper<BranchOffice>().eq("cityCode", cityCode).eq("status", 1));
        List<OpenCityWarpper> district = new ArrayList<>();
        for (BranchOffice branchOffice : branchOffices) {
            OpenCityWarpper openCityWarpper = new OpenCityWarpper();
            openCityWarpper.setCode(branchOffice.getDistrictCode());
            openCityWarpper.setName(branchOffice.getDistrictName());
            district.add(openCityWarpper);
        }
        return district;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DeptServiceImpl.java
New file
@@ -0,0 +1,47 @@
package com.supersavedriving.driver.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.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.modular.system.dao.DeptMapper;
import com.supersavedriving.driver.modular.system.model.Dept;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DictServiceImpl.java
New file
@@ -0,0 +1,101 @@
package com.supersavedriving.driver.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.supersavedriving.driver.core.common.exception.BizExceptionEnum;
import com.supersavedriving.driver.core.exception.GunsException;
import com.supersavedriving.driver.modular.system.dao.DictMapper;
import com.supersavedriving.driver.modular.system.model.Dict;
import com.supersavedriving.driver.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.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/ImgServiceImpl.java
New file
@@ -0,0 +1,11 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.ImgMapper;
import com.supersavedriving.driver.modular.system.model.Img;
import com.supersavedriving.driver.modular.system.service.IImgService;
import org.springframework.stereotype.Service;
@Service
public class ImgServiceImpl extends ServiceImpl<ImgMapper, Img> implements IImgService {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/LoginLogServiceImpl.java
New file
@@ -0,0 +1,28 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.LoginLogMapper;
import com.supersavedriving.driver.modular.system.model.LoginLog;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/MenuServiceImpl.java
New file
@@ -0,0 +1,90 @@
package com.supersavedriving.driver.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.supersavedriving.driver.core.node.MenuNode;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.modular.system.dao.MenuMapper;
import com.supersavedriving.driver.modular.system.model.Menu;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/NoticeServiceImpl.java
New file
@@ -0,0 +1,27 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.NoticeMapper;
import com.supersavedriving.driver.modular.system.model.Notice;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/OperationLogServiceImpl.java
New file
@@ -0,0 +1,28 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.OperationLogMapper;
import com.supersavedriving.driver.modular.system.model.OperationLog;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/RelationServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.RelationMapper;
import com.supersavedriving.driver.modular.system.model.Relation;
import com.supersavedriving.driver.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 {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/RoleServiceImpl.java
New file
@@ -0,0 +1,73 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.core.node.ZTreeNode;
import com.supersavedriving.driver.core.util.Convert;
import com.supersavedriving.driver.modular.system.dao.RelationMapper;
import com.supersavedriving.driver.modular.system.dao.RoleMapper;
import com.supersavedriving.driver.modular.system.model.Relation;
import com.supersavedriving.driver.modular.system.model.Role;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/UserServiceImpl.java
New file
@@ -0,0 +1,48 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.core.datascope.DataScope;
import com.supersavedriving.driver.modular.system.dao.UserMapper;
import com.supersavedriving.driver.modular.system.model.User;
import com.supersavedriving.driver.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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/ManagerUser.java
New file
@@ -0,0 +1,97 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/ReqAddManager.java
New file
@@ -0,0 +1,76 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/ReqEditManager.java
New file
@@ -0,0 +1,60 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/transfer/UserDto.java
New file
@@ -0,0 +1,153 @@
package com.supersavedriving.driver.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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ALiApiUtil.java
New file
@@ -0,0 +1,51 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * 阿里云API接口工具类
 */
@Component
public class ALiApiUtil {
    @Autowired
    private HttpClientUtil httpClientUtil;
    /**
     * 身份认证接口
     * @param name  姓名
     * @param code  身份证号
     * @return
     */
    public boolean authentication(String name, String code){
        String url = "https://safrvcert.market.alicloudapi.com/safrv_2meta_id_name/";
        Map<String, String> header = new HashMap<>();
        header.put("Authorization", "APPCODE b7d32437d08149099457dcb50fb57df2");
        Map<String, Object> param = new HashMap<>();
        param.put("__userId", "1732960796168165");
        param.put("verifyKey", "IVO4js5kValcdt");
        param.put("userName", name);
        param.put("identifyNum", code);
        String get = httpClientUtil.pushHttpRequset("GET", url, param, header, "form");
        JSONObject jsonObject = JSON.parseObject(get);
        if(jsonObject.getIntValue("code") == 200){
            JSONObject value = jsonObject.getJSONObject("value");
            if(value.getString("bizCode").equals("0")){
                return true;
            }else{
                return false;
            }
        }else{
            System.err.println(jsonObject.getString("message"));
        }
        return false;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ALiSendSms.java
New file
@@ -0,0 +1,123 @@
package com.supersavedriving.driver.modular.system.util;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
 * 阿里云短信工具类
 */
@Component
public class ALiSendSms {
    // 设置鉴权参数,初始化客户端
    private DefaultProfile profile = DefaultProfile.getProfile(
            "cn-hangzhou",// 地域ID
            "LTAI4G9Zez9H4B36vakPXGy4",// 您的AccessKey ID
            "BOVPUeZndKVbrPOq6Ef5j6oiydB3XZ");// 您的AccessKey Secret
    private IAcsClient client = new DefaultAcsClient(profile);
    private static void log_print(String functionName, Object result) {
        Gson gson = new Gson();
        System.out.println("-------------------------------" + functionName + "-------------------------------");
        System.out.println(gson.toJson(result));
    }
    /**
     * 添加短信模板
     */
    public String addSmsTemplate() throws ClientException {
        CommonRequest addSmsTemplateRequest = new CommonRequest();
        addSmsTemplateRequest.setSysDomain("dysmsapi.aliyuncs.com");
        addSmsTemplateRequest.setSysAction("AddSmsTemplate");
        addSmsTemplateRequest.setSysVersion("2017-05-25");
        // 短信类型。0:验证码;1:短信通知;2:推广短信;3:国际/港澳台消息
        addSmsTemplateRequest.putQueryParameter("TemplateType", "0");
        // 模板名称,长度为1~30个字符
        addSmsTemplateRequest.putQueryParameter("TemplateName", "测试短信模板");
        // 模板内容,长度为1~500个字符
        addSmsTemplateRequest.putQueryParameter("TemplateContent", "您正在申请手机注册,验证码为:${code},5分钟内有效!");
        // 短信模板申请说明
        addSmsTemplateRequest.putQueryParameter("Remark", "测试");
        CommonResponse addSmsTemplateResponse = client.getCommonResponse(addSmsTemplateRequest);
        String data = addSmsTemplateResponse.getData();
        // 消除返回文本中的反转义字符
        String sData = data.replaceAll("'\'", "");
        log_print("addSmsTemplate", sData);
        Gson gson = new Gson();
        // 将字符串转换为Map类型,取TemplateCode字段值
        Map map = gson.fromJson(sData, Map.class);
        Object templateCode = map.get("TemplateCode");
        return templateCode.toString();
    }
    /**
     * 发送短信
     */
    public String sendSms(String phone, String templateCode, String json) throws ClientException {
        CommonRequest request = new CommonRequest();
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        // 接收短信的手机号码
        request.putQueryParameter("PhoneNumbers", phone);
        // 短信签名名称。请在控制台签名管理页面签名名称一列查看(必须是已添加、并通过审核的短信签名)。
        request.putQueryParameter("SignName", "OK出行");
        // 短信模板ID
        request.putQueryParameter("TemplateCode", templateCode);
        // 短信模板变量对应的实际值,JSON格式。
        request.putQueryParameter("TemplateParam", json);
        CommonResponse commonResponse = client.getCommonResponse(request);
        String data = commonResponse.getData();
        String sData = data.replaceAll("'\'", "");
        log_print("sendSms", sData);
        return sData;
    }
    /**
     * 查询发送详情
     */
    private void querySendDetails(String bizId) throws ClientException {
        CommonRequest request = new CommonRequest();
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("QuerySendDetails");
        // 接收短信的手机号码
        request.putQueryParameter("PhoneNumber", "156xxxxxxxx");
        // 短信发送日期,支持查询最近30天的记录。格式为yyyyMMdd,例如20191010。
        request.putQueryParameter("SendDate", "20191010");
        // 分页记录数量
        request.putQueryParameter("PageSize", "10");
        // 分页当前页码
        request.putQueryParameter("CurrentPage", "1");
        // 发送回执ID,即发送流水号。
        request.putQueryParameter("BizId", bizId);
        CommonResponse response = client.getCommonResponse(request);
        log_print("querySendDetails", response.getData());
    }
    public static void main(String[] args) {
        ALiSendSms sendSmsDemo = new ALiSendSms();
        try {
            // 创建短信模板
            String templateCode = sendSmsDemo.addSmsTemplate();
            // 使用刚创建的短信模板发送短信
            String sData = sendSmsDemo.sendSms("156xxxxxxxx", templateCode, "{\"code\":\"8888\"}");
            Gson gson = new Gson();
            Map map = gson.fromJson(sData, Map.class);
            String bizId = map.get("BizId").toString();
            // 根据短信发送流水号查询短信发送情况
            sendSmsDemo.querySendDetails(bizId);
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ApplicationRunnerUtil.java
New file
@@ -0,0 +1,20 @@
package com.supersavedriving.driver.modular.system.util;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
 * 项目启动执行类
 */
@Component
public class ApplicationRunnerUtil implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ChinaMobileUtil.java
New file
@@ -0,0 +1,128 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSONObject;
import com.supersavedriving.driver.core.util.MD5Util;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * 中国移动工具类
 */
@Component
public class ChinaMobileUtil {
    private String APIKey = "zj42494b1bdd416b9762229af6b5cbbd";
    private String SecretKey = "30323561316534653735613230316339";
    @Autowired
    private HttpClientUtil httpClientUtil;
    /**
     * 绑定小号
     * @param phoneA
     * @param phoneB
     * @param areaCode
     * @return
     * @throws Exception
     */
    public Map<String, String> midAxbBindSend(String phoneA, String phoneB, Integer areaCode) throws Exception{
        //组装请求对象-具体描述见开发文档-订单小号-AXB接口规范部分内容
        Map<String, Object> request = new HashMap<>();
        request.put("APPID", APIKey);
        request.put("bindtype", "AXB");
        request.put("requestId", UUIDUtil.getRandomCode(16));
        request.put("record", "0");
        //用户号码,必填,格式遵循国际电信联盟定义的E.164标准
        request.put("telA", "86" + phoneA);
        //用户号码B,必填,格式遵循国际电信联盟定义的E.164标准
        request.put("telB", "86" + phoneB);
        //需要选择的小号所属区号,当telX不写时必填,例如:杭州(571)
        request.put("areaCode", 571);
        //订单小号,非必填,当指定小号绑定时填写,格式遵循国际电信联盟定义的E.164标准
//        request.setTelX("8618867110000");
        //绑定关系过期失效时间,秒,取值必须大于0且最大值不超过4294967296
        request.put("expiration", Integer.valueOf(7 * 24 * 60 * 60));
        Map<String, String> header = new HashMap<String, String>(3);
        header.put("Authorization", "Basic " + new String(Base64.encodeBase64((APIKey + ":" + SecretKey).getBytes())));
        header.put("Content-Type", "application/json;charset=utf-8");
        String post = httpClientUtil.pushHttpRequset("POST", "https://ct.open.10086.cn/ordernumber/v1/binding", request, header, "json");
        Map<String, String> map1 = new HashMap<>();
        if(post.indexOf("0000") != -1){
            JSONObject jsonObject = JSONObject.parseObject(post);
            if(jsonObject.getString("code").equals("0000")){
                map1.put("code", "200");
                map1.put("msg", jsonObject.getString("message"));
                map1.put("telX", jsonObject.getString("x_no").substring(2));
                map1.put("bindId", jsonObject.getString("bindId"));
            }else{
                map1.put("code", jsonObject.getString("code"));
                map1.put("msg", jsonObject.getString("message"));
            }
        }else{
            map1.put("code", "-1");
            map1.put("msg", post);
        }
        return map1;
    }
    /**
     * 解绑小号关系
     * @param bindId    绑定关系id
     * @return
     * @throws Exception
     */
    public Map<String, String> midAxbUnBindSend(String bindId) throws Exception{
        //组装请求对象-具体描述见开发文档-订单小号-AXB接口规范部分内容
        Map<String, Object> request = new HashMap<>();
        //绑定关系ID
        request.put("APPID", APIKey);
        request.put("bindId", bindId);
        Map<String, String> header = new HashMap<String, String>(3);
        header.put("Authorization", "Basic " + new String(Base64.encodeBase64((APIKey + ":" + SecretKey).getBytes())));
        header.put("Content-Type", "application/json;charset=utf-8");
        String post = httpClientUtil.pushHttpRequset("POST", "https://ct.open.10086.cn/ordernumber/v1/unbinding", request, header, "json");
        JSONObject jsonObject = JSONObject.parseObject(post);
        Map<String, String> map1 = new HashMap<>();
        if(jsonObject.getString("code").equals("0000")){
            map1.put("code", "200");
            map1.put("msg", jsonObject.getString("message"));
        }else{
            map1.put("code", jsonObject.getString("code"));
            map1.put("msg", jsonObject.getString("message"));
        }
        return map1;
    }
    public Map<String, String> HeaderUtils(String APIKey, String SecretKey) throws Exception{
        Map<String, String> header = new HashMap<>();
        long time = System.currentTimeMillis();
        String signStr = MD5Util.encrypt(APIKey + SecretKey + time);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("apiKey", APIKey);
        jsonObject.put("time", time);
        jsonObject.put("sign", signStr);
        Base64 base64 = new Base64();
        String s = base64.encodeToString(jsonObject.toJSONString().getBytes("UTF-8"));
        header.put("header", s);
        jsonObject = new JSONObject();
        jsonObject.put("platformId", "");
        jsonObject.put("secret", "");
        s = base64.encodeToString(jsonObject.toJSONString().getBytes("UTF-8"));
        header.put("accessCode", s);
        return header;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/DateUtil.java
New file
@@ -0,0 +1,133 @@
package com.supersavedriving.driver.modular.system.util;
import com.supersavedriving.driver.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;
        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);
        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;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/GDFalconUtil.java
New file
@@ -0,0 +1,224 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
 * 高德猎鹰服务
 */
@Component
public class GDFalconUtil implements ApplicationRunner {
    private String key = "e17d799b2506d05faf7f88320a266803";
    @Autowired
    private RestTemplate restTemplate;
    private static String serverId = null;
    public String getServerId() {
        return serverId;
    }
    /**
     * 服务启动后执行的代码
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        this.init();
    }
    /**
     * 初始化创建服务
     */
    public void init(){
        if(serverId == null){
            JSONArray jsonArray = this.selectServer();
            if(null == jsonArray){
                serverId = this.createServer("server");
            }else{
                serverId = jsonArray.getJSONObject(0).getString("sid");
            }
        }
    }
    /**
     * 创建新的服务
     * @return
     */
    public String createServer(String name){
        String url = "https://tsapi.amap.com/v1/track/service/add";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("name", name);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
            if(null != data){
                return data.getString("sid");
            }
        }
        return null;
    }
    /**
     * 查询服务
     * @return
     */
    private JSONArray selectServer(){
        String url = "https://tsapi.amap.com/v1/track/service/list?key=" + key;
        String forObject = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
            if(null != data){
                return data.getJSONArray("results");
            }
        }
        return null;
    }
    /**
     * 创建终端数据
     * @param name
     * @return
     */
    public String createTerminal(String name){
        String tid = this.selectTerminal(name);
        if(tid != null){
            return tid;
        }
        String url = "https://tsapi.amap.com/v1/track/terminal/add";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("sid", serverId);
        params.add("name", name);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
            return data.getString("tid");
        }
        System.err.println(jsonObject.getString("errmsg"));
        return null;
    }
    /**
     * 查询终端
     * @param name
     * @return
     */
    public String selectTerminal(String name){
        String url = "https://tsapi.amap.com/v1/track/terminal/list?key=" + key + "&name=" + name;
        String forObject = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        if(jsonObject.getIntValue("errcode") == 10000){
            JSONObject data = jsonObject.getJSONObject("data");
            int count = 0;
            if(null != data){
                count = data.getIntValue("count");
            }
            if(count > 0){
                JSONObject results = data.getJSONArray("results").getJSONObject(0);
                return results.getString("tid");
            }else{
                return this.createTerminal(name);
            }
        }
        return null;
    }
    /**
     * 创建轨迹
     * @param tid   终端id
     * @return
     */
    public String createTrack(String tid){
        String url = "https://tsapi.amap.com/v1/track/trace/add";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("sid", serverId);
        params.add("tid", tid);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") == 10000){
            return jsonObject.getString("data");
        }
        System.err.println(jsonObject.getString("errmsg"));
        return null;
    }
    /**
     * 删除轨迹
     * @param tid       终端id
     * @param trid      轨迹id
     */
    public void deleteTrack(String tid, String trid){
        String url = "https://tsapi.amap.com/v1/track/trace/delete";
        //调用推送
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //将请求头部和参数合成一个请求
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", key);
        params.add("sid", serverId);
        params.add("tid", tid);
        params.add("trid", trid);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
        String s = restTemplate.postForObject(url, requestEntity , String.class);
        JSONObject jsonObject = JSON.parseObject(s);
        if(jsonObject.getIntValue("errcode") != 10000){
            System.err.println(jsonObject.getString("errmsg"));
        }
    }
//
//    public Map<String, Object> queryTrsearch(){
//
//    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/GeodesyUtil.java
New file
@@ -0,0 +1,71 @@
package com.supersavedriving.driver.modular.system.util;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * 计算两个金纬度坐标之间的直线距离
 */
@Component
public class GeodesyUtil {
    /**
     * 获取直线距离
     * @param fromLonLat
     * @param toLonLat
     * @return
     */
    public Map<String, Double> getDistance(String fromLonLat, String toLonLat){
        String[] from = fromLonLat.split(",");
        String[] to = toLonLat.split(",");
        GlobalCoordinates source = new GlobalCoordinates(Double.valueOf(from[1]), Double.valueOf(from[0]));
        GlobalCoordinates target = new GlobalCoordinates(Double.valueOf(to[1]), Double.valueOf(to[0]));
        double Sphere = getDistanceMeter(source, target, Ellipsoid.Sphere);
        double WGS84 = getDistanceMeter(source, target, Ellipsoid.WGS84);
        double GRS80 = getDistanceMeter(source, target, Ellipsoid.GRS80);
        double GRS67 = getDistanceMeter(source, target, Ellipsoid.GRS67);
        double ANS = getDistanceMeter(source, target, Ellipsoid.ANS);
        double WGS72 = getDistanceMeter(source, target, Ellipsoid.WGS72);
        double Clarke1858 = getDistanceMeter(source, target, Ellipsoid.Clarke1858);
        double Clarke1880 = getDistanceMeter(source, target, Ellipsoid.Clarke1880);
//        System.out.println("Sphere坐标系计算结果:"+Sphere + "米");
//        System.out.println("WGS84坐标系计算结果:"+WGS84 + "米");
//        System.out.println("GRS80坐标系计算结果:"+GRS80 + "米");
//        System.out.println("GRS67坐标系计算结果:"+GRS67 + "米");
//        System.out.println("ANS坐标系计算结果:"+ANS + "米");
//        System.out.println("WGS72坐标系计算结果:"+WGS72 + "米");
//        System.out.println("Clarke1858坐标系计算结果:"+Clarke1858 + "米");
//        System.out.println("Clarke1880坐标系计算结果:"+Clarke1880 + "米");
        Map<String, Double> map = new HashMap<>();
        map.put("Sphere", Sphere);
        map.put("WGS84", WGS84);
        map.put("GRS80", GRS80);
        map.put("GRS67", GRS67);
        map.put("ANS", ANS);
        map.put("WGS72", WGS72);
        map.put("Clarke1858", Clarke1858);
        map.put("Clarke1880", Clarke1880);
        return map;
    }
    private double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid){
        //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }
    public static void main(String[] ages){
        GeodesyUtil geodesyUtil = new GeodesyUtil();
        geodesyUtil.getDistance("115.481028,39.989643", "114.465302,40.004717");
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/HttpClientUtil.java
New file
@@ -0,0 +1,266 @@
package com.supersavedriving.driver.modular.system.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * http工具类
 */
@Component
public class HttpClientUtil {
    private CloseableHttpClient httpClient;
    private CloseableHttpResponse httpResponse;
    private RequestConfig requestConfig;
    /**
     * 创建一个httpClient对象
     */
    private void getHttpCline(){
        //1.创建连接池管理器
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(60000,
                TimeUnit.MILLISECONDS);
        connectionManager.setMaxTotal(1000);
        connectionManager.setDefaultMaxPerRoute(50);
        //2.创建httpclient对象
        this.httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .disableAutomaticRetries()
                .build();
    }
    private RequestConfig getRequestConfig(){
        return RequestConfig.custom()
                .setConnectTimeout(60000)
                .setSocketTimeout(60000)
                .build();
    }
    /**
     * 创建一个POST请求实例
     * @param url       请求地址
     * @param params    请求参数
     */
    private void setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType){
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(this.getRequestConfig());
        if(null != header){
            for(String key : header.keySet()){
                httpPost.setHeader(key, header.get(key));
            }
        }
        List<NameValuePair> list = new ArrayList<>();
        if(null != params){
            Set<String> keys = params.keySet();
            for(String key : keys){
                list.add(new BasicNameValuePair(key, params.get(key).toString()));
            }
        }
        try {
            switch (contentType){
                case "form":
                    httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
                    break;
                case "json":
                    ObjectMapper objectMapper = new ObjectMapper();
                    String s =objectMapper.writeValueAsString(params);
                    System.err.println(s);
                    httpPost.setEntity(new StringEntity(s, Charset.forName("UTF-8")));
                    break;
            }
            this.getHttpCline();
            if(null == this.httpClient){
                this.getHttpCline();
            }
            httpResponse = this.httpClient.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
            this.close();
        }
    }
    /**
     * 获取get请求实例
     * @param url       请求地址
     * @param params    请求参数
     */
    private void setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header){
        StringBuffer sb = new StringBuffer();
        String p = "";
        if(null != params){
            Set<String> keys = params.keySet();
            for(String key : keys){
                sb.append(key + "=" + params.get(key) + "&");
            }
            p = "?" + sb.substring(0, sb.length() - 1);
        }
        HttpGet httpGet = new HttpGet(url + p);
        if(null != header){
            for(String key : header.keySet()){
                httpGet.setHeader(key, header.get(key));
            }
        }
        this.getHttpCline();
        if(null == this.httpClient){
            this.getHttpCline();
        }
        try {
            httpResponse = this.httpClient.execute(httpGet);
        } catch (IOException e) {
            e.printStackTrace();
            this.close();
        }
    }
    /**
     * 发送http请求
     * @param mothed        "GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS"
     * @param url           请求地址
     * @param params        请求参数
     * @param header        请求头
     * @param contentType   参数请求方式form/json
     * @return
     */
    public String pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType){
        String content = null;
        switch (mothed){
            case "GET":
                this.setGetHttpRequset(url, params, header);
                break;
            case "POST":
                this.setPostHttpRequset(url, params, header, contentType);
                break;
        }
        if(httpResponse.getStatusLine().getStatusCode() == 200){
            try {
                content = EntityUtils.toString(httpResponse.getEntity());
                this.close();
                return content;
            } catch (IOException e) {
                e.printStackTrace();
                this.close();
            }
        }
        if(httpResponse.getStatusLine().getStatusCode() == 201){
            content = "{\"status\":201}";
            this.close();
            return content;
        }else{
            try {
                System.err.println("返回状态码:" + httpResponse.getStatusLine() + "。");
                content = EntityUtils.toString(httpResponse.getEntity());
                this.close();
                return content;
            } catch (IOException e) {
                e.printStackTrace();
                this.close();
            }
        }
        this.close();
        return content;
    }
    /**
     * 发送XML请求
     * @param url       请求地址
     * @param xml       XML数据
     * @param header    自定义请求头
     * @return
     */
    public String pushHttpRequsetXml(String url, String xml, Map<String, String> header){
        HttpPost httpPost = new HttpPost(url);
        for(String key : header.keySet()){
            httpPost.setHeader(key, header.get(key));
        }
        httpPost.setHeader("Content-Type", "application/xml");
        try {
            httpPost.setEntity(new StringEntity(xml, "UTF-8"));
            this.getHttpCline();
            if(null == this.httpClient){
                this.getHttpCline();
            }
            httpResponse = this.httpClient.execute(httpPost);
            String content = null;
            if(httpResponse.getStatusLine().getStatusCode() == 200){
                try {
                    content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
                    this.close();
                    return content;
                } catch (IOException e) {
                    e.printStackTrace();
                    this.close();
                }
            }else{
                try {
                    content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity());
                    this.close();
                    return content;
                } catch (IOException e) {
                    e.printStackTrace();
                    this.close();
                }
            }
            this.close();
            return content;
        } catch (IOException e) {
            e.printStackTrace();
            this.close();
        }
        return null;
    }
    /**
     * 关闭资源
     */
    private void close(){
        try {
            if(null != httpClient){
                httpClient.close();
            }
            if(null != httpResponse){
                httpResponse.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(null != httpClient){
                    httpClient.close();
                }
                if(null != httpResponse){
                    httpResponse.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/JuHeUtil.java
New file
@@ -0,0 +1,44 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * 聚合数据工具类
 */
@Component
public class JuHeUtil {
    @Value("${juhe.appKey}")
    private String key;
    @Autowired
    private HttpClientUtil httpClientUtil;
    /**
     * 身份证号码实名认证
     * @param name
     * @param idcard
     * @return
     */
    public boolean idcard(String name, String idcard){
        Map<String, Object> map = new HashMap<>();
        map.put("key", key);
        map.put("idcard", idcard);
        map.put("realname", name);
        String content = httpClientUtil.pushHttpRequset("GET", "http://op.juhe.cn/idcard/query", map, new HashMap<>(), "form");
        System.err.println(content);
        JSONObject jsonObject = JSON.parseObject(content);
        if(jsonObject.getIntValue("error_code") == 0){
            int res = jsonObject.getJSONObject("result").getIntValue("res");
            return res == 1 ? true : false;
        }
        return false;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MD5AndKL.java
New file
@@ -0,0 +1,112 @@
package com.supersavedriving.driver.modular.system.util;
import java.security.MessageDigest;
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")));
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MinistryOfTransport.java
New file
@@ -0,0 +1,1062 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
 * 交通部接口对接
 */
@Component
public class MinistryOfTransport {
    private final String CompanyId = "4502YSGSGK3Y";//公司标识
    private final String Source = "0";//消息来源标识
    private final String url = "http://172.19.5.101:8085";
    @Autowired
    private HttpClientUtil httpClientUtil;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    private SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
    private SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMddHHmmss");
    /**
     * 上传企业基础信息
     */
    public void baseInfoCompany(){
        String IPCType = "baseInfoCompany";
        String path = url + "/baseinfo/company";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("CompanyName", "广西云森科技有限公司");//公司名称
        jsonObject.put("Identifier", "91450200MA5K99GK3Y");//统一社会信用代码
        jsonObject.put("Address", 450204);//注册地行政区划代码
        jsonObject.put("BusinessScope", "网络预约出租汽车客运");//经营范围
        jsonObject.put("ContactAddress", "柳州市柳南区航银路8号万利大厦3楼303室");//通信地址
        jsonObject.put("EconomicType", "150");//经营业户经济类型
        jsonObject.put("RegCapital", "壹仟万圆整");//注册资本
        jsonObject.put("LegalName", "翁克顺");//法人代表姓名
        jsonObject.put("LegalID", "44052419650805207X");//法人代表身份证号
        jsonObject.put("LegalPhone", "13907728585");//法人代表电话
        jsonObject.put("LegalPhoto", "");//法人代表身份证扫描件文件编号
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车平台公司营运规模信息接口
     */
    public void baseInfoCompanyStat(){
        String IPCType = "baseInfoCompanyStat";
        String path = url + "/baseinfo/companystat";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("VehicleNum", 0);//平台注册网约车辆数
        jsonObject.put("DriverNum", 0);//平台注册驾驶员数
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车平台公司支付信息
     */
    public void baseInfoCompanyPay(){
        String IPCType = "baseInfoCompanyPay";
        String path = url + "/baseinfo/companypay";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("PayName", "");//银行或者非银行支付机构名称
        jsonObject.put("PayId", "");//非银行支付机构支付业务许可证编号
        jsonObject.put("PayType", "");//支付业务类型
        jsonObject.put("PayScope", "");//业务覆盖范围
        jsonObject.put("PrepareBank", "");//备付金存管银行
        jsonObject.put("CountDate", 1);//结算周期
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车平台公司服务机构
     */
    public void baseInfoCompanyService(){
        String IPCType = "baseInfoCompanyService";
        String path = url + "/baseinfo/companyservice";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//行政区划代码
        jsonObject.put("ServiceNae", "广西云森科技有限公司");//服务机构名称
        jsonObject.put("ServiceNo", "");//服务机构代码
        jsonObject.put("DetailAddress", "柳州市柳南区航银路8号万利大厦3楼303室");//服务机构地址
        jsonObject.put("ResponsibleName", "");//服务机构负责人姓名
        jsonObject.put("ResponsiblePhone", "");//负责人联系电话
        jsonObject.put("ManagerName", "");//服务机构管理人姓名
        jsonObject.put("ManagerPhone", "");//管理人联系电话
        jsonObject.put("ContactPhone", "");//服务机构紧急联系电话
        jsonObject.put("MailAddress", "");//行政文书送达邮寄地址
        jsonObject.put("CreateDate", 20150918);//服务机构设立日期
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车平台公司经营许可
     */
    public void baseInfoCompanyPermit(){
        String IPCType = "baseInfoCompanyPermit";
        String path = url + "/baseinfo/companypermit";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//许可地行政区划代码
        jsonObject.put("Certificate", "450200005403");//网络预约出租车经营许可证号
        jsonObject.put("OperationArea", "广西壮族自治州柳州市城区");//经营区域
        jsonObject.put("OwnerName", "广西云森科技有限公司");//公司名称
        jsonObject.put("Organization", "柳州市行政审批据");//发证机构名称
        jsonObject.put("StartDate", 20180330);//有效期起YYYYMMDD
        jsonObject.put("StopDate", 20220329);//有效期止YYYYMMDD
        jsonObject.put("CertifyDate", 0);//初次发证日期YYYYMMDD
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车平台公司运价信息
     */
    public void baseInfoCompanyFare(){
        String IPCType = "baseInfoCompanyFare";
        String path = url + "/baseinfo/companyfare";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//运价适用地行政区划代码
        jsonObject.put("FareType", "");//运价类型编码(由网约车平台公司统一编码,应确保唯一性)
        jsonObject.put("FareTypeNote", "");//运价类型说明
        jsonObject.put("FareValidOn", 0);//运价有效期起YYYYMMDDhhmmss
        jsonObject.put("FareValidOff", 0);//运价有效止YYYYMMDDhhmmss
        jsonObject.put("StartFare", 0);//起步价(元)
        jsonObject.put("StartMile", 0);//起步里程(km)
        jsonObject.put("UnitPricePerMile", 0);//计程单价(按公里/元)
        jsonObject.put("UnitPricePerMinute", 0);//计时单价(按分钟/元)
        jsonObject.put("UpPrice", 0);//单程加价单价(元)
        jsonObject.put("UpPriceStartMile", 0);//单程加价公里(km)
        jsonObject.put("MorningPeakTimeOn", "");//营运早高峰时间起(HHmm 24小时)
        jsonObject.put("MorningPeakTimeOff", "");//营运早高峰时间止(HHmm 24小时)
        jsonObject.put("EveningPeakTimeOn", "");//营运晚高峰时间起(HHmm 24小时)
        jsonObject.put("EveningPeakTimeOff", "");//营运晚高峰时间止(HHmm 24小时)
        jsonObject.put("OtherPeakTimeOn", "");//其他营运高等时间起(HHmm 24小时)
        jsonObject.put("OtherPeakTineOff", "");//其他营运高等时间止(HHmm 24小时)
        jsonObject.put("PeakUnitPrice", 0);//高峰时间单程加价单价(元)
        jsonObject.put("PeakPriceStartMile", 0);//高峰时间单程加价公里(km)
        jsonObject.put("LowSpeedPriceMinute", 0);//低速计时加价(按分钟 元)
        jsonObject.put("NightPricePerMile", 0);//夜间费(按公里 元)
        jsonObject.put("NightPricePerMinute", 0);//夜间费(按分钟 元)
        jsonObject.put("OtherPrice", 0);//其它加价金额(元)
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 车辆基本信息
     */
    public void baseInfoVehicle(){
        String IPCType = "baseInfoVehicle";
        String path = url + "/baseinfo/vehicle";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//车辆所在城市行政区划代码
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("PlateColor", "");//车牌颜色
        jsonObject.put("Seats", 5);//核定载客位
        jsonObject.put("Brand", "");//车辆厂牌
        jsonObject.put("Model", "");//车辆型号
        jsonObject.put("VehicleType", "");//车辆类型(以机动车行驶证为准)
        jsonObject.put("OwnerName", "");//车辆所有人(以机动车行驶证为准)
        jsonObject.put("VehicleColor", "");//车身颜色
        jsonObject.put("EngineId", "");//发送机号(以机动车行驶证为准)
        jsonObject.put("VIN", "");//车辆VIN码(以机动车行驶证为准)
        jsonObject.put("CertifyDateA", 0);//车辆注册日期(以机动车行驶证为准)
        jsonObject.put("FuelType", "");//车辆燃料类型
        jsonObject.put("EngineDisplace", "");//发送机排量(毫升)
        jsonObject.put("PhotoId", "");//车辆照片文件编号
        jsonObject.put("Certificate", "");//运输证字号
        jsonObject.put("TransAgency", "");//车辆运输证发证机构
        jsonObject.put("TransArea", "");//车辆经营区域
        jsonObject.put("TransDateStart", 0);//车辆运输证有效期起YYYYMMDD
        jsonObject.put("TransDateStop", 0);//车辆运输证有效期止YYYYMMDD
        jsonObject.put("CertifyDateB", 0);//车辆初次登记日期
        jsonObject.put("FixState", "");//车辆维修状态(0:未检修,1:已检修,2:未知)
        jsonObject.put("NextFixDate", 0);//车辆下次年检时间
        jsonObject.put("CheckState", "");//车辆年度审验状态
        jsonObject.put("FeePrintId", "");//发票打印设备序列号
        jsonObject.put("GPSBrand", "");//卫星定位装置品牌
        jsonObject.put("GPSModel", "");//卫星定位装置型号
        jsonObject.put("GPSIMEI", "");//卫星定位装置IMEI号
        jsonObject.put("GPSInstallDate", 0);//卫星定位设备安装日期YYYYMMDD
        jsonObject.put("RegisterDate", 0);//报备日期(车辆信息向服务所在地出租车行政主管部门报备日期YYYYMMDD)
        jsonObject.put("CommercialType", 0);//服务类型(1:网络预约出租车,2:巡游出租汽车,3:私人小客车合乘)
        jsonObject.put("FareType", "");//运价类型编码(与云间信息中一一对应)
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 2);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 车辆保险信息
     */
    public void baseInfoVehicleInsurance(){
        String IPCType = "baseInfoVehicleInsurance";
        String path = url + "/baseinfo/vehicleinsurance";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("InsurCom", "");//保险公司名称
        jsonObject.put("InsurNum", "");//保险号
        jsonObject.put("InsurType", "");//保险类型
        jsonObject.put("InsurCount", 0);//保险金额(元)
        jsonObject.put("InsurEff", 0);//保险生效时间YYYYMMDD
        jsonObject.put("InsurExp", 0);//保险到期时间YYYYMMDD
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车车辆里程信息
     */
    public void baseInfoVehicleTotalMile(){
        String IPCType = "baseInfoVehicleTotalMile";
        String path = url + "/baseinfo/vehicletotalmile";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//注册地行政区划代码
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("TotalMile", 0);//行驶总里程(km)
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 驾驶员基本信息
     */
    public void baseInfoDriver(){
        String IPCType = "baseInfoDriver";
        String path = url + "/baseinfo/driver";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//注册地行政区划代码
        jsonObject.put("DriverName", "");//机动车驾驶员姓名
        jsonObject.put("DriverPhone", "");//驾驶员手机号
        jsonObject.put("DriverGender", "");//驾驶员性别
        jsonObject.put("DriverBirthday", 0);//出生日期YYYYMMDD
        jsonObject.put("DriverNationality", "");//国籍
        jsonObject.put("DriverNation", "");//驾驶员民族
        jsonObject.put("DriverMaritalStatus", "");//驾驶员婚姻状况(未婚,已婚,离异)
        jsonObject.put("DriverLanguageLevel", "");//驾驶员外语能力
        jsonObject.put("DriverEducation", "");//驾驶员学历
        jsonObject.put("DriverCensus", "");//户口登记机关名称
        jsonObject.put("DriverAddress", "");//户口住址或长住地址
        jsonObject.put("DriverContactAddress", "");//驾驶员通信地址
        jsonObject.put("PhotoId", "");//驾驶员照片文件编号
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("LicensePhotoId", "");//机动车驾驶证扫描件文件编号
        jsonObject.put("DriverType", "");//准驾车型
        jsonObject.put("GetDriverLicenseDate", 0);//初次领取驾驶证日期YYYYMMDD
        jsonObject.put("DriverLicenseOn", 0);//驾驶证有效期限起YYYYMMDD
        jsonObject.put("DriverLicenseOff", 0);//驾驶证有效期限止YYYYMMDD
        jsonObject.put("TaxiDriver", 0);//是否巡游出租汽车驾驶员(1:是,2:否)
        jsonObject.put("CertificateNo", "");//网络预约出租汽车驾驶员资格证号
        jsonObject.put("NetworkCarIssueOrganization", "");//网络预约出租汽车驾驶员证发证机构
        jsonObject.put("NetworkCarIssueDate", 0);//资格证发证日期YYYYMMDD
        jsonObject.put("GetNetworkCarProofDate", 0);//初次领取资格证日期YYYYMMDD
        jsonObject.put("NetworkCarProofOn", 0);//资格证有效起始日期YYYYMMDD
        jsonObject.put("NetworkCarProofOff", 0);//资格证有截止日期YYYYMMDD
        jsonObject.put("RegisterDate", 0);//报备日期(驾驶员信息向服务所在地出租车行政主管部门报备日期)
        jsonObject.put("FullTimeDriver", 0);//是否专职驾驶员(1:是,0:否)
        jsonObject.put("InDriverBlacklist", 0);//是否在驾驶员黑名单内(1:是,0:否)
        jsonObject.put("CommercialType", 0);//服务类型(1:网络预约出租汽车,2:巡游出租汽车,3:私人小客车合乘)
        jsonObject.put("ContractCompany", "");//驾驶员合同签署公司
        jsonObject.put("ContractOn", 0);//合同有效期起YYYYMMDD
        jsonObject.put("ContractOff", 0);//合同有效期止YYYYMMDD
        jsonObject.put("EmergencyContact", "");//紧急情况联系人
        jsonObject.put("EmergencyContactPhone", "");//紧急情况联系人电话
        jsonObject.put("EmergencyContactAddress", "");//紧急情况联系人通信地址
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 网约车驾驶员培训信息
     */
    public void baseInfoDriverEducate(){
        String IPCType = "baseInfoDriverEducate";
        String path = url + "/baseinfo/drivereducate";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//注册地行政区划代码
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("CourseName", "");//驾驶员培训课程名称
        jsonObject.put("CourseDate", 0);//培训课程日期YYYYMMDD
        jsonObject.put("StartTime", "");//培训开始时间
        jsonObject.put("StopTime", "");//培训结束时间
        jsonObject.put("Duration", 0);//培训时长
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 驾驶员移动终端信息
     */
    public void baseInfoDriverApp(){
        String IPCType = "baseInfoDriverApp";
        String path = url + "/baseinfo/driverapp";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//注册地行政区划代码
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("DriverPhone", "");//驾驶员手机号
        jsonObject.put("NetType", 0);//手机运营商(1:中国联通,2:中国移动,3:中国电信,4:其他)
        jsonObject.put("AppVersion", "");//使用APP版本号
        jsonObject.put("MapType", 0);//使用地图类型(1:百度地图,2:高德地图,3:其他)
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 驾驶员统计信息
     */
    public void baseInfoDriverStat(){
        String IPCType = "baseInfoDriverStat";
        String path = url + "/baseinfo/driverstat";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 450204);//注册地行政区划代码
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("Cycle", 0);//统计周期(统计周期按月,内容填写统计月份YYYYMM)
        jsonObject.put("OrderCount", 0);//完成订单次数
        jsonObject.put("TrafficViolationCount", 0);//交通违章次数
        jsonObject.put("ComplainedCount", 0);//被投诉次数
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 乘客基本信息
     */
    public void baseInfoPassenger(){
        String IPCType = "baseInfoPassenger";
        String path = url + "/baseinfo/passenger";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("RegisterDate", 0);//注册日期YYYYMMDD
        jsonObject.put("PassengerPhone", "");//乘客手机号
        jsonObject.put("PassengerName", "");//乘客称谓
        jsonObject.put("PassengerGender", "");//乘客性别
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", Long.valueOf(sdf.format(new Date())));
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 订单发起接口
     */
    public void orderCreate(){
        String IPCType = "orderCreate";
        String path = url + "/order/create";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 0);//发起第行政区划代码
        jsonObject.put("OrderId", "");//订单编号
        jsonObject.put("DepartTime", 0);//预计用车时间YYYYMMDDhhmmss
        jsonObject.put("OrderTime", 0);//订单发起时间YYYYMMDDhhmmss
        jsonObject.put("PassengerNote", "");//乘客备注
        jsonObject.put("Departure", "");//预计出发地点详细地址
        jsonObject.put("DepLongitude", 0);//预计出发地点经度
        jsonObject.put("DepLatitude", 0);//预计出发地点纬度
        jsonObject.put("Destination", "");//预计目的地
        jsonObject.put("DestLongitude", 0);//预计目的地经度
        jsonObject.put("DestLatitude", 0);//预计目的地纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("FareType", "");//运价类型编码
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 订单成功接口
     */
    public void orderMatch(){
        String IPCType = "orderMatch";
        String path = url + "/order/match";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 0);//发起第行政区划代码
        jsonObject.put("OrderId", "");//订单编号
        jsonObject.put("Longitude", 0);//车辆经度
        jsonObject.put("Latitude", 0);//车辆纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("LicenseId", "");//机动车驾驶证编号
        jsonObject.put("DriverPhone", "");//驾驶员手机号
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("DistributeTime", 0);//派单成功时间YYYYMMDDhhmmss
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 订单撤销接口
     */
    public void orderCancel(){
        String IPCType = "orderCancel";
        String path = url + "/order/cancel";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 0);//上车地点行政区划代码
        jsonObject.put("OrderId", "");//订单编号
        jsonObject.put("OrderTime", 0);//订单时间YYYYMMDDhhmmss
        jsonObject.put("CancelTime", 0);//订单撤销时间YYYYMMDDhhmmss
        jsonObject.put("Operator", "");//撤销发起方(1:乘客,2:驾驶员,3:平台公司)
        jsonObject.put("CancelTypeCode", "");//机动车驾驶证编号
        jsonObject.put("DriverPhone", "");//撤销类型代码(1:乘客提前撤销,2:驾驶员提前撤销,3:平台公司撤销,4:乘客违约撤销,5:驾驶员违约撤销)
        jsonObject.put("CancelReason", "");//撤销或违约原因
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 车辆经营上线接口
     */
    public void operateLogin(){
        String IPCType = "operateLogin";
        String path = url + "/operate/login";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("LoginTime", 0);//车辆经营上线时间YYYYMMDDhhmmss
        jsonObject.put("Longitude", 0);//上线经度
        jsonObject.put("Latitude", 0);//上线纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 车辆经营下线接口
     */
    public void operateLogout(){
        String IPCType = "operateLogout";
        String path = url + "/operate/logout";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("LoginTime", 0);//车辆经营下线时间YYYYMMDDhhmmss
        jsonObject.put("Longitude", 0);//下线经度
        jsonObject.put("Latitude", 0);//下线纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 经营出发接口
     */
    public void operateDepart(){
        String IPCType = "operateDepart";
        String path = url + "/operate/depart";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("OrderId", "");//订单号
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("FareType", "");//运价类型编码
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("DepLongitude", 0);//车辆出发经度
        jsonObject.put("DepLatitude", 0);//车辆出发纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("DepTime", 0);//上车时间YYYYMMDDhhmmss
        jsonObject.put("WaitMile", 0);//空驶里程(km)
        jsonObject.put("WaitTime", 0);//等待时间(秒)
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 经营到达接口
     */
    public void operateArrive(){
        String IPCType = "operateArrive";
        String path = url + "/operate/arrive";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("OrderId", "");//订单号
        jsonObject.put("DestLongitude", 0);//车辆到达经度
        jsonObject.put("DestLatitude", 0);//车辆到达纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("DestTime", 0);//下车时间YYYYMMDDhhmmss
        jsonObject.put("DriveMile", 0);//载客里程(km)
        jsonObject.put("DriveTime", 0);//载客时间(秒)
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 经营支付接口
     */
    public void operatePay(){
        String IPCType = "operatePay";
        String path = url + "/operate/pay";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("OrderId", "");//订单号
        jsonObject.put("OnArea", 0);//上车位置行政区划代码
        jsonObject.put("DriverName", "");//机动车驾驶员
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("FareType", "");//运价类型编码(由网约车公司定义,与运价信息接口保持一街)
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("BookDepTime", 0);//预计上车时间YYYYMMDDhhmmss
        jsonObject.put("WaitTime", 0);//等待时间(秒)
        jsonObject.put("DepLongitude", 0);//车辆出发经度
        jsonObject.put("DepLatitude", 0);//车辆出发纬度
        jsonObject.put("DepArea", "");//上车点
        jsonObject.put("DepTime", 0);//上车时间YYYYMMDDhhmmss
        jsonObject.put("DestLongitude", 0);//车辆到达经度
        jsonObject.put("DestLatitude", 0);//车辆到达纬度
        jsonObject.put("DestArea", "");//下车地点
        jsonObject.put("DestTime", 0);//下车时间YYYYMMDDhhmmss
        jsonObject.put("BookModel", "");//预定车型
        jsonObject.put("DriveMile", 0);//载客里程(km)
        jsonObject.put("DriveTime", 0);//载客时间(秒)
        jsonObject.put("WaitMile", 0);//空驶里程(km)
        jsonObject.put("FactPrice", 0);//实收金额(元)
        jsonObject.put("Price", 0);//应收金额(元)
        jsonObject.put("CashPrice", 0);//现金支付金额(元)
        jsonObject.put("LineName", "");//电子支付机构
        jsonObject.put("LinePrice", 0);//电子支付金额(元)
        jsonObject.put("PosName", "");//POS机支付机构
        jsonObject.put("PosPrice", 0);//POS机支付金额(元)
        jsonObject.put("BenfitPrice", 0);//优惠金额(元)
        jsonObject.put("BookTip", 0);//预约服务费(元)
        jsonObject.put("PassengerTip", 0);//附加费(元)
        jsonObject.put("PeakUpPrice", 0);//高峰时段时间加价金额(元)
        jsonObject.put("NightUpPrice", 0);//夜间时段里程加价金额(元)
        jsonObject.put("FarUpPrice", 0);//远途加价金额(元)
        jsonObject.put("OtherUpPrice", 0);//其他加价金额(元)
        jsonObject.put("PayState", "");//结算状态(0:未结算,1:已结算,2:未知)
        jsonObject.put("PayTime", 0);//乘客结算时间YYYYMMDDhhmmss
        jsonObject.put("OrderMatchTime", 0);//订单完成时间YYYYMMDDhhmmss
        jsonObject.put("InvoiceStatus", "");//发票状态(0:未开票,1:已开票,2:未知)
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 驾驶员定位信息
     */
    public void positionDriver(){
        String IPCType = "positionDriver";
        String path = url + "/position/driver";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("DriverRegionCode", 0);//行政区划代码
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("PositionTime", 0);//定位时间(时间戳)
        jsonObject.put("Longitude", 0);//经度
        jsonObject.put("Latitude", 0);//纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("Direction", 0);//方向角
        jsonObject.put("Elevation", 0);//海拔高度
        jsonObject.put("Speed", 0);//瞬时速度(km/h)
        jsonObject.put("BizStatus", 0);//营运状态(1:载客,2:接单,3:空驶,4:停运)
        jsonObject.put("OrderId", "");//订单编号
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 车辆定位信息
     */
    public void positionVehicle(){
        String IPCType = "positionVehicle";
        String path = url + "/position/vehicle";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("VehicleRegionCode", 0);//行政区划代码
        jsonObject.put("PositionTime", 0);//定位时间(时间戳)
        jsonObject.put("Longitude", 0);//经度
        jsonObject.put("Latitude", 0);//纬度
        jsonObject.put("Speed", 0);//瞬时速度(km/h)
        jsonObject.put("Direction", 0);//方向角
        jsonObject.put("Elevation", 0);//海拔高度
        jsonObject.put("Mileage", 0);//行驶里程(KM)
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("WarnStatus", 0);//预警状态
        jsonObject.put("VehStatus", 0);//车辆状态
        jsonObject.put("BizStatus", 0);//营运状态(1:载客,2:接单,3:空驶,4:停运)
        jsonObject.put("OrderId", "");//订单编号(非营运状态下填"0")
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 乘客评价信息
     */
    public void ratedPassenger(){
        String IPCType = "ratedPassenger";
        String path = url + "/rated/passenger";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("OrderId", "");//订单号
        jsonObject.put("EvaluateTime", 0);//评价时间YYYYMMDDhhmms
        jsonObject.put("ServiceScore", 0);//服务满意度(五分制)
        jsonObject.put("DriverScore", 0);//驾驶员满意度(五分制)
        jsonObject.put("VehicleScore", 0);//车辆满意度(五分制)
        jsonObject.put("Detail", "");//评价内容
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 乘客投诉信息
     */
    public void ratedPassengerComplaint(){
        String IPCType = "ratedPassengerComplaint";
        String path = url + "/rated/passengercomplaint";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("OrderId", "");//订单号
        jsonObject.put("ComplaintTime", 0);//投诉时间YYYYMMDDhhmms
        jsonObject.put("Detail", "");//投诉内容
        jsonObject.put("Result", "");//处理结果
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 驾驶员处罚信息
     */
    public void ratedDriverPunish(){
        String IPCType = "ratedDriverPunish";
        String path = url + "/rated/driverpunish";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("LicenseId", "");//机动车驾驶证编号
        jsonObject.put("PunishTime", 0);//处罚时间YYYYMMDDhhmms
        jsonObject.put("PunishReason", "");//处罚原因
        jsonObject.put("PunishReault", "");//处罚结果
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 驾驶员信誉信息
     */
    public void ratedDriver(){
        String IPCType = "ratedDriver";
        String path = url + "/rated/driver";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("LicenseId", "");//机动车驾驶证编号
        jsonObject.put("Level", 0);//服务质量信誉等级(五分制)
        jsonObject.put("TestDate", 0);//服务质量信誉考核日期YYYYMMDD
        jsonObject.put("TestDepartment", "");//服务质量信誉考核机构
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 私人小客车合乘信息服务平台基本信息
     */
    public void shareCompany(){
        String IPCType = "shareCompany";
        String path = url + "/share/company";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("CompanyName", "");//公司名称
        jsonObject.put("Identifier", "");//统一社会信用代码
        jsonObject.put("Address", 0);//注册地行政区划代码
        jsonObject.put("ContactAddress", "");//通信地址
        jsonObject.put("EconomicType", "");//经营业户经济类型
        jsonObject.put("LegalName", "");//法人代表姓名(按照营业执照填写)
        jsonObject.put("LegalPhone", "");//法人代表电话
        jsonObject.put("State", 0);//状态(0:有效,1:失效)
        jsonObject.put("Flag", 1);//操作标识(1:新增,2:更新,3:删除)
        jsonObject.put("UpdateTime", 1);//更新时间YYYYMMDDhhmmss
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 私人小客车合乘驾驶员行程发布接口
     */
    public void shareRoute(){
        String IPCType = "shareRoute";
        String path = url + "/share/route";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 0);//行政区划代码
        jsonObject.put("RouteId", "");//驾驶员发起行程编号
        jsonObject.put("DriverName", "");//驾驶员姓名
        jsonObject.put("DriverPhone", "");//驾驶员手机号
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("Departure", "");//行程出发地点
        jsonObject.put("DepLongitude", 0);//车辆出发经度
        jsonObject.put("DepLatitude", 0);//车辆出发纬度
        jsonObject.put("Destination", "");//行程到达地点
        jsonObject.put("DestLongitude", 0);//到达地经度
        jsonObject.put("DestLatitude", 0);//到达纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("RouteCreateTime", 0);//行程发布时间YYYYMMDDhhmmss
        jsonObject.put("RouteMile", 0);//行程预计里程(km)
        jsonObject.put("RouteNote", "");//行程备注
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 此人小客车合乘订单接口
     */
    public void shareOrder(){
        String IPCType = "shareOrder";
        String path = url + "/share/order";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 0);//行政区划代码
        jsonObject.put("RouteId", "");//驾驶员发起行程编号
        jsonObject.put("OrderId", "");//乘客合乘订单号
        jsonObject.put("BookDepartTime", 0);//预计上车时间YYYYMMDDhhmmss
        jsonObject.put("Departure", "");//预计上车地点
        jsonObject.put("DepLongitude", 0);//预计上车地点经度
        jsonObject.put("DepLatitude", 0);//预计上车地点纬度
        jsonObject.put("Destination", "");//预计下车地点
        jsonObject.put("DestLongitude", 0);//预计下车地点经度
        jsonObject.put("DestLatitude", 0);//预计下车地点纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("OrderEnsureTime", 0);//订单确认时间YYYYMMDDhhmmss
        jsonObject.put("PassengerNum", 0);//乘客人数
        jsonObject.put("PassengerNote", "");//乘客备注
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
    /**
     * 私人小客车合乘订单支付接口
     */
    public void sharePay(){
        String IPCType = "sharePay";
        String path = url + "/share/pay";
        Map<String, Object> data = new HashMap<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("CompanyId", CompanyId);
        jsonObject.put("Address", 0);//行政区划代码
        jsonObject.put("RouteId", "");//驾驶员发起行程编号
        jsonObject.put("OrderId", "");//乘客合乘订单号
        jsonObject.put("DriverPhone", "");//驾驶员手机号
        jsonObject.put("LicenseId", "");//机动车驾驶证号
        jsonObject.put("VehicleNo", "");//车辆号牌
        jsonObject.put("FareType", "");//运价类型编码
        jsonObject.put("BookDepartTime", 0);//预计上车时间YYYYMMDDhhmmss
        jsonObject.put("DepartTime", 0);//实际上车时间YYYYMMDDhhmmss
        jsonObject.put("Departure", "");//上车地点
        jsonObject.put("DepLongitude", 0);//上车地点经度
        jsonObject.put("DepLatitude", 0);//上车地点纬度
        jsonObject.put("DestTime", 0);//下车时间YYYYMMDDhhmmss
        jsonObject.put("Destination", "");//下车地点
        jsonObject.put("DestLongitude", 0);//下车地点经度
        jsonObject.put("DestLatitude", "");//下车地点纬度
        jsonObject.put("Encrypt", 0);//坐标加密标识(1:GCJ-02测绘局标准,2:WGS84 GPS标准,3:BD-09百度标准,4:CGCS2000北斗标准,0:其他)
        jsonObject.put("DriveMile", 0);//载客里程(km)
        jsonObject.put("DriveTime", 0);//载客时间(秒)
        jsonObject.put("FactPrice", 0);//实收金额(元)
        jsonObject.put("Price", 0);//应收金额(元)
        jsonObject.put("CashPrice", 0);//现金支付金额(元)
        jsonObject.put("LineName", "");//电子支付机构
        jsonObject.put("LinePrice", 0);//电子支付金额(元)
        jsonObject.put("BenfitPrice", 0);//优惠金额(元)
        jsonObject.put("ShareFuelFee", 0);//燃料成本分摊金额(元)
        jsonObject.put("ShareHighwayToll", 0);//路桥通行分摊金额(元)
        jsonObject.put("PassengerTip", 0);//附加费(元)
        jsonObject.put("ShareOther", 0);//其他费用分摊金额(元)
        jsonObject.put("PayState", 0);//结算状态(0:未结算,1:已结算,2:未知)
        jsonObject.put("PassengerNum", 0);//乘客人数(元)
        jsonObject.put("PayTime", 0);//乘客结算时间YYYYMMDDhhmmss
        jsonObject.put("OrderMatchTime", 0);//订单完成时间YYYYMMDDhhmmss
        data.put("CompanyId", CompanyId);
        data.put("Source", Source);
        data.put("IPCType", IPCType);
        data.put("baseInfoCompany", jsonObject);
        String s = httpClientUtil.pushHttpRequset("POST", path, data, null, "json");
        System.err.println(s);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/PayMoneyUtil.java
New file
@@ -0,0 +1,809 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import org.apache.commons.collections.map.HashedMap;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.*;
/**
 * 第三方支付工具类
 */
@Component
public class PayMoneyUtil {
    @Value("${alipay.appid}")
    private String aliAppid;//支付宝appid
    @Value("${alipay.appPrivateKey}")
    private String appPrivateKey;//支付宝开发者应用私钥
    @Value("${alipay.alipayPublicKey}")
    private String alipayPublicKey;//支付宝应用公钥
    @Value("${alipay.alipay_public_key}")
    private String alipay_public_key;//支付宝支付公钥
    @Value("${wx.appid}")
    private String appid;//微信appid
    @Value("${wx.mchId}")
    private String mchId;//微信商户号
    @Value("${wx.key}")
    private String key;//微信商户号
    @Value("${callbackPath}")
    private String callbackPath;//支付回调网关地址
    @Autowired
    private HttpClientUtil httpClientUtil;
    private Map<String, JSONObject> order = new HashMap<>();//存储支付订单用于主动查询支付结果
    /**
     * 支付宝支付
     */
    public ResultUtil alipay(String body, String subject, String outTradeNo, String amount, String notifyUrl){
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipayPublicKey, "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
        model.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等。
        model.setOutTradeNo(outTradeNo);//商户网站唯一订单号
        model.setTimeoutExpress("30m");
        model.setTotalAmount(amount);//付款金额
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(callbackPath + notifyUrl);
        try {
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            Map<String, String> map = new HashMap<>();
            map.put("orderString", response.getBody());
            System.out.println(map);//就是orderString 可以直接给客户端请求,无需再做处理。
            return ResultUtil.success(map);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝扫码支付下单
     * @param body
     * @param subject
     * @param outTradeNo
     * @param amount
     * @param notifyUrl
     * @return
     */
    public ResultUtil aliScanCodePay(String body, String subject, String outTradeNo, String amount, String notifyUrl){
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); //获得初始化的AlipayClient
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//创建API对应的request类
        request.setBizContent("{" +
                "    \"out_trade_no\":\"" + outTradeNo + "\"," +//商户订单号
                "    \"total_amount\":\"" + 1 + "\"," +
                "    \"subject\":\"" + subject + "\"," +
                "    \"notify_url\":\"" + callbackPath + notifyUrl + "\"," +
                "    \"body\":\"" + body + "\"," +
                "    \"store_id\":\"NJ_001\"," +
                "    \"timeout_express\":\"90m\"}");//订单允许的最晚付款时间
        AlipayTradePrecreateResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        JSONObject alipay_trade_precreate_response = JSON.parseObject(response.getBody()).getJSONObject("alipay_trade_precreate_response");
        System.err.print(alipay_trade_precreate_response.getString("qr_code"));
        return ResultUtil.success(alipay_trade_precreate_response.getString("qr_code"));
    }
    /**
     * 支付成功后的回调处理逻辑
     * @param request
     */
    public Map<String, String> alipayCallback(HttpServletRequest request){
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        try {
            boolean flag = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8","RSA2");
            if(flag){
                Map<String, String> map = new HashMap<>();
                String out_trade_no = params.get("out_trade_no");
                String subject = params.get("subject");
                String total_amount = params.get("total_amount");
                String trade_no = params.get("trade_no");
                map.put("out_trade_no", out_trade_no);//商家订单号
                map.put("subject", subject);
                map.put("total_amount", total_amount);
                map.put("trade_no", trade_no);//支付宝交易号
                return map;
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝查询订单支付状态
     * @param out_trade_no
     * @return
     * @throws Exception
     */
    public ResultUtil queryALIOrder(String out_trade_no) throws Exception{
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2");
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":" + out_trade_no +
                "  }");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            String tradeStatus = response.getTradeStatus();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
            return ResultUtil.success(tradeStatus);
        } else {
            return ResultUtil.error(response.getMsg());
        }
    }
    /**
     * 微信统一下单
     * @param body          商品描述
     * @param attach        附加数据
     * @param out_trade_no  商户订单号
     * @param total_fee     标价金额
     * @param notify_url    通知地址
     * @param tradeType     交易类型
     * @return
     */
    public ResultUtil weixinpay(String body, String attach, String out_trade_no, String total_fee, String notify_url, String tradeType) throws Exception{
        int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            hostAddress = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String nonce_str = UUIDUtil.getRandomCode(16);
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);
        map.put("body", body);
        map.put("attach", attach);//存储订单id
        map.put("out_trade_no", out_trade_no);//存储的订单code
        map.put("total_fee", i);
        map.put("spbill_create_ip", hostAddress);
        map.put("notify_url", callbackPath + notify_url);
        map.put("trade_type", tradeType);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>());
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String prepay_id = map1.get("prepay_id");
                        //重新进行签名后返回给前端
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("appid", appid);
                        map2.put("noncestr", nonce_str);
                        map2.put("package", "Sign=WXPay");
                        map2.put("partnerid", mchId);
                        map2.put("prepayid", prepay_id);
                        map2.put("timestamp", new Date().getTime() / 1000);
                        String s1 = this.weixinSignature(map2);
                        map2.put("sign", s1);
                        System.err.println(map2);
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 微信支付成功后的回调处理
     * @param request
     */
    public Map<String, String> weixinpayCallback(HttpServletRequest request){
        try {
            String param = this.getParam(request);
            param = param.replaceAll("<!\\[CDATA\\[","");
            param = param.replaceAll("]]>", "");
            Map<String, String> map = this.xmlToMap(param, "UTF-8");
            String return_code = map.get("return_code");
            if("SUCCESS".equals(return_code)){
                String result_code = map.get("result_code");
                if("SUCCESS".equals(result_code)){
                    Map<String, String> map1 = new HashedMap();
                    map1.put("nonce_str", map.get("nonce_str"));
                    map1.put("out_trade_no", map.get("out_trade_no").split("_")[1]);//存储的订单code
                    map1.put("attach", map.get("attach"));//存储订单id
                    map1.put("total_fee", map.get("total_fee"));
                    map1.put("transaction_id", map.get("transaction_id"));//微信支付订单号
                    String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                    map1.put("result", result);
                    return map1;
                }else{
//                    System.err.println(map.get("err_code_des"));
                }
            }else{
//                System.err.println(map.get("return_msg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 微信扫码收款
     * @param body              商品描述
     * @param attach            附加数据
     * @param nonce_str         随机字符串
     * @param out_trade_no      商户订单号
     * @param total_fee         订单金额
     * @param auth_code         授权码    扫码支付授权码,设备读取用户微信中的条码或者二维码信息(注:用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头)
     * @return
     */
    public ResultUtil wxScanQRCodePay(String body, String attach, String nonce_str, String out_trade_no, String total_fee, String auth_code){
        int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            InetAddress address = InetAddress.getLocalHost();
            hostAddress = address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String randomCode = null;
        try {
            randomCode = UUIDUtil.getRandomCode(10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);//存储的支付人员id,员工扫描二维码支付的时候存储的是收款员工id
        map.put("body", body);
        map.put("attach", attach);//存储的费用月份数据,员工扫描二维码支付的时候存储的是收费项id
        map.put("out_trade_no", randomCode + "_" + out_trade_no);//存储的房间id
        map.put("total_fee", i);
        map.put("spbill_create_ip", hostAddress);
        map.put("auth_code", auth_code);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>());
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String prepay_id = map1.get("prepay_id");
                        //重新进行签名后返回给前端
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("appid", appid);
                        map2.put("noncestr", nonce_str);
                        map2.put("package", "Sign=WXPay");
                        map2.put("partnerid", mchId);
                        map2.put("prepayid", prepay_id);
                        map2.put("timestamp", new Date().getTime() + "");
                        String s1 = this.weixinSignature(map2);
                        map2.put("pac", "Sign=WXPay");
                        map2.put("sign", s1);
//                      System.err.println(map2);
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
//                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
//            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 支付宝扫码收款
     * @param data
     * @return
     */
    public Object aliScanQRCodePay(String data){
        return null;
    }
    /**
     * 微信退款申请
     * @param transaction_id    微信订单号。微信生成的订单号,在支付通知中有返回
     * @param out_refund_no     商户退款单号。商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
     * @param total_fee         订单金额。订单总金额,单位为分,只能为整数
     * @param refund_fee        退款金额。退款总金额,订单总金额,单位为分,只能为整数
     * @param notify_url        退款结果通知url。异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。
     * @return
     */
    public Map<String, String> wxRefund(String transaction_id, String out_refund_no, String total_fee, String refund_fee, String notify_url){
        int tf = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        int rf = new BigDecimal(refund_fee).multiply(new BigDecimal("100")).intValue();
        String nonce_str = UUIDUtil.getRandomCode();
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);
        map.put("transaction_id", transaction_id);
        map.put("out_refund_no", out_refund_no);
        map.put("total_fee", tf);
        map.put("refund_fee", rf);
        map.put("notify_url", callbackPath + notify_url);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>());
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        Map<String, String> map2 = new HashMap<>();
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                map2.put("return_code", result_code);
                map2.put("refund_id", String.valueOf(map1.get("refund_id")));//微信退款订单号
                map2.put("refund_fee", String.valueOf(map1.get("refund_fee")));//退款金额
                return map2;
            }else{
                map2.put("return_code", result_code);
                map2.put("return_msg", map1.get("err_code_des"));
                return map2;
            }
        }else{
            map2.put("return_code", return_code);
            map2.put("return_msg", map1.get("return_msg"));
            return map2;
        }
    }
    /**
     * 微信退款成功后的回调处理
     * @param request
     * @return
     */
    public Map<String, String> wxRefundCallback(HttpServletRequest request){
        try {
            String param = this.getParam(request);
            param = param.replaceAll("<!\\[CDATA\\[","");
            param = param.replaceAll("]]>", "");
            Map<String, String> map = this.xmlToMap(param, "UTF-8");
            String return_code = map.get("return_code");
            if("SUCCESS".equals(return_code)){
                String req_info = map.get("req_info");//加密信息请用商户秘钥进行解密
                String s = this.wxDecrypt(req_info);
                s = s.replaceAll("<!\\[CDATA\\[","");
                s = s.replaceAll("]]>", "");
                map = this.xmlToMap(s, "UTF-8");
                Map<String, String> map1 = new HashMap<>();
                map1.put("refund_id", map.get("refund_id"));
                map1.put("out_refund_no", map.get("out_refund_no"));
                return map1;
            }else{
//                System.err.println(map.get("return_msg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝退款
     * @param trade_no          支付宝交易号
     * @param refund_amount     退款金额
     * @return
     * @throws AlipayApiException
     */
    public Map<String, String> aliRefund(String trade_no, String refund_amount) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("trade_no", trade_no);
        jsonObject.put("refund_amount", refund_amount);
        request.setBizContent(jsonObject.toJSONString());
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        Map<String, String> map = new HashMap<>();
        if(response.isSuccess()){
            System.out.println("调用成功");
            String outTradeNo = response.getOutTradeNo();
            map.put("code", response.getCode());//10000
            map.put("trade_no", response.getTradeNo());//支付宝交易号
            map.put("out_trade_no", outTradeNo);//商户订单号
        } else {
            System.out.println("调用失败");
            map.put("code", response.getCode());
            map.put("msg", response.getSubMsg());
        }
        return map;
    }
    /**
     * 查询微信支付订单
     * @return
     * @throws Exception
     */
    public ResultUtil queryWXOrder() throws Exception{
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";
        String nonce_str = UUIDUtil.getRandomCode(16);
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("transaction_id", nonce_str);//微信订单号
        map.put("nonce_str", nonce_str);//随机字符串
        String s = this.weixinSignature(map);
        map.put("sign", s);
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>());
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String trade_state = map1.get("trade_state");
                        String time_end = map1.get("time_end");
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("trade_state", trade_state);//订单状态SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败)
                        map2.put("time_end", time_end);//订单支付时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 获取请求内容
     * @param request
     * @return
     * @throws IOException
     */
    private String getParam(HttpServletRequest request) throws IOException {
        // 读取参数
        InputStream inputStream;
        StringBuilder sb = new StringBuilder();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        return sb.toString();
    }
    /**
     * 微信下单的签名算法
     * @param map
     * @return
     */
    private String weixinSignature(Map<String, Object> map){
        try {
            Set<Map.Entry<String, Object>> entries = map.entrySet();
            List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries);
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, Object> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    Object val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key + "=" + val + "&");
                    }
                }
            }
            sb.append("key=" + key);
            String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 微信退款成功后的解密
     * @param req_info
     * @return
     */
    private String wxDecrypt(String req_info) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        byte[] decode = Base64.getDecoder().decode(req_info);
        String sign = MD5AndKL.MD5Encode(key, "UTF-8").toLowerCase();
        if (Security.getProvider("BC") == null){
            Security.addProvider(new BouncyCastleProvider());
        }
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        SecretKeySpec secretKeySpec = new SecretKeySpec(sign.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        return new String(cipher.doFinal(decode));
    }
    public static void main(String[] ages){
//        PayMoneyUtil payMoneyUtil = new PayMoneyUtil();
//        payMoneyUtil.weixinpay("测试", "123", "12.5", "");
    }
    /**
     * xml转map
     * @param xml
     * @param charset
     * @return
     * @throws UnsupportedEncodingException
     * @throws DocumentException
     */
    public static Map<String, String> xmlToMap(String xml, String charset) throws UnsupportedEncodingException, DocumentException {
        Map<String, String> respMap = new HashMap<String, String>();
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new ByteArrayInputStream(xml.getBytes(charset)));
        Element root = doc.getRootElement();
        xmlToMap(root, respMap);
        return respMap;
    }
    public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap){
        if (tmpElement.isTextOnly()) {
            respMap.put(tmpElement.getName(), tmpElement.getText());
            return respMap;
        }
        @SuppressWarnings("unchecked")
        Iterator<Element> eItor = tmpElement.elementIterator();
        while (eItor.hasNext()) {
            Element element = eItor.next();
            xmlToMap(element, respMap);
        }
        return respMap;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/RedisUtil.java
New file
@@ -0,0 +1,126 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.supersavedriving.driver.core.util.ToolUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
 * Redis工具类
 */
@Component
public class RedisUtil {
    @Autowired
    private RestTemplate internalRestTemplate;
    /**
     * 向redis中存储字符串没有过期时间
     * @param key
     * @param value
     */
    public void setStrValue(String key, String value){
        if(ToolUtil.isNotEmpty(key)){
            //发送验证码短信
            HttpHeaders headers = new HttpHeaders();
            // 以表单的方式提交
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            //将请求头部和参数合成一个请求
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            params.add("value", value);
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
            String s = internalRestTemplate.postForObject("http://zuul-gateway/redis/setValue_", requestEntity, String.class);
            JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
            if(jsonObject.getIntValue("code") != 200){
                System.err.println("调用redis出错了");
            }
        }
    }
    /**
     * 以分钟为单位设置存储值(设置过期时间)
     * @param key
     * @param value
     * @param time 秒
     */
    public void setStrValue(String key, String value, int time){
        if(ToolUtil.isNotEmpty(key)){
            //发送验证码短信
            HttpHeaders headers = new HttpHeaders();
            // 以表单的方式提交
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            //将请求头部和参数合成一个请求
            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            params.add("value", value);
            params.add("time", String.valueOf(time));
            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
            String s = internalRestTemplate.postForObject("http://zuul-gateway/redis/setValue", requestEntity, String.class);
            JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
            if(jsonObject.getIntValue("code") != 200){
                System.err.println("调用redis出错了");
            }
        }
    }
    /**
     * 从redis中获取值
     * @param key
     * @return
     */
    public String getValue(String key){
        if(ToolUtil.isNotEmpty(key)){
            HttpHeaders headers = new HttpHeaders();
            // 以表单的方式提交
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            //将请求头部和参数合成一个请求
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
            String s = internalRestTemplate.postForObject("http://zuul-gateway/redis/getValue",requestEntity , String.class);
            JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
            if(jsonObject.getIntValue("code") != 200){
                System.err.println("调用redis出错了");
            }
            return jsonObject.getString("data");
        }
        return null;
    }
    /**
     * 删除key
     * @param key
     */
    public String remove(String key){
        if(ToolUtil.isNotEmpty(key)){
            HttpHeaders headers = new HttpHeaders();
            // 以表单的方式提交
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            //将请求头部和参数合成一个请求
            MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
            params.add("key", key);
            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
            String s = internalRestTemplate.postForObject("http://zuul-gateway/redis/remove",requestEntity , String.class);
            JSONObject jsonObject = JSON.parseObject(s, JSONObject.class);
            if(jsonObject.getIntValue("code") != 200){
                System.err.println("调用redis出错了");
            }
            return jsonObject.getString("data");
        }
        return null;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/ResultUtil.java
New file
@@ -0,0 +1,187 @@
package com.supersavedriving.driver.modular.system.util;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
 * 定义统一返回对象
 */
@ApiModel(value = "统一返回结果集")
public class ResultUtil<T> {
    public static final Integer SUCCESS = 10000;
    public static final Integer PARAM_ERROR = 10010;
    public static final Integer SYSTEM_INFO = 10020;
    public static final Integer TOKEN_ERROR = 10030;
    public static final Integer SIGN_ERROR = 10040;
    public static final Integer RUNTIME_ERROR = 10050;
    public static final String Token = "TOKEN_INVALID";
    public static final String SIGN = "SIGN_INVALID";
    @ApiModelProperty(name = "code", value = "业务状态码 10000:成功,10010:参数错误,10020:系统提示, 10030:身份校验异常,10040:签名不通过,10050:系统运行异常")
    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.SYSTEM_INFO, mag, new Object());
    }
    /**
     * 错误信息
     * @return
     */
    public static <T> ResultUtil <T> error(String mag, T obj){
        return ResultUtil.getResult(ResultUtil.SYSTEM_INFO, mag, obj);
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, ResultUtil.Token, new Object());
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(String msg){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, msg, new Object());
    }
    /**
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "param_error", new Object());
    }
    /**
     * 参数异常
     * @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 Object());
    }
    /**
     * 运行异常
     * @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, "ok", new Object());
    }
    /**
     * 返回成功
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "ok", 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);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/SystemException.java
New file
@@ -0,0 +1,19 @@
package com.supersavedriving.driver.modular.system.util;
/**
 * 自定义系统异常类
 */
public class SystemException extends Exception {
    public SystemException(String message) {
        super(message);
    }
    public SystemException(String message, Throwable cause) {
        super(message, cause);
    }
    public SystemException(Throwable cause) {
        super(cause);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/TaskUtil.java
New file
@@ -0,0 +1,53 @@
package com.supersavedriving.driver.modular.system.util;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * 定时任务工具类
 */
@Component
public class TaskUtil {
    /**
     * 每隔一分钟去处理的定时任务
     */
    @Scheduled(fixedRate = 1000 * 60)
    public void taskMinute(){
        try {
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
//    /**
//     * 每天的凌晨执行的任务
//     */
//    @Scheduled(cron = "0 0 0 * * *")
//    public void taskDay(){
//        try {
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 每月第一天的1点执行的任务
//     */
//    @Scheduled(cron = "0 0 1 1 * *")
//    public void taskMonth(){
//        try {
//
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/UUIDUtil.java
New file
@@ -0,0 +1,78 @@
package com.supersavedriving.driver.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());
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/WeChatUtil.java
New file
@@ -0,0 +1,120 @@
package com.supersavedriving.driver.modular.system.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
 * 微信工具类
 */
@Component
public class WeChatUtil {
    @Value("${wx.appletsAppid}")
    private String wxAppletsAppid;
    @Value("${wx.appletsAppSecret}")
    private String wxAppletsAppSecret;
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 小程序使用jscode获取openid
     * @param jscode
     * @return
     */
    public Map<String, String> code2Session(String jscode){
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret
                + "&js_code=" + jscode + "&grant_type=authorization_code";
        String forObject = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        int errcode = jsonObject.getIntValue("errcode");
        Map<String, String> map = new HashMap<>();
        if(errcode == 0){//成功
            map.put("openid", jsonObject.getString("openid"));
            map.put("sessionKey", jsonObject.getString("session_key"));
            map.put("unionid", jsonObject.getString("unionid"));
            return map;
        }
        if(errcode == -1){//系统繁忙,此时请开发者稍候再试
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        if(errcode == 40029){//code 无效
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        if(errcode == 45011){//频率限制,每个用户每分钟100次
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        return null;
    }
    /**
     * 通过config接口注入权限验证配置(公众号)
     * 附录1-JS-SDK使用权限签名算法,
     * @return
     */
    public Map<String,Object> getSignatureConfig(String url){
        //获取token
        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String ticket = getJSApiTicket();
        String noncestr = UUIDUtil.getRandomCode();
        Long timestamp = System.currentTimeMillis();
        String content = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        String signature = DigestUtils.sha1Hex(content);
        Map<String,Object> map=new HashMap<>();
        map.put("appId", "wx0e72f86394831b34");
        map.put("timestamp", timestamp);
        map.put("nonceStr", noncestr);
        map.put("signature", signature);
        return  map;
    }
    /***
     * 获取jsapiTicket(公众号)
     * 来源 www.vxzsk.com
     * @return
     */
    public String getJSApiTicket(){
        //获取token
        String acess_token= this.getAccessToken();
        String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + acess_token + "&type=jsapi";
        String backData = restTemplate.getForObject(urlStr, String.class);
        System.out.println(backData);
        String ticket = JSONObject.parseObject(backData).getString("ticket");
        return  ticket;
    }
    /***
     * 获取acess_token (公众号)
     * 来源www.vxzsk.com
     * @return
     */
    public String getAccessToken(){
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx0e72f86394831b34&secret=930f857abc74f7bb5cbd89e1544c5669";
        String backData = restTemplate.getForObject(url, String.class);
        String accessToken = JSONObject.parseObject(backData).getString("access_token");
        return accessToken;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/BaseWarpper.java
New file
@@ -0,0 +1,18 @@
package com.supersavedriving.driver.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel
public class BaseWarpper {
    @ApiModelProperty("id")
    private Integer id;
    @ApiModelProperty(value = "编号", required = true, dataType = "string")
    private String code;
    @ApiModelProperty(value = "名称", required = true, dataType = "stirng")
    private String name;
    @ApiModelProperty(value = "地址")
    private String path;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/DeptWarpper.java
New file
@@ -0,0 +1,33 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.base.warpper.BaseControllerWarpper;
import com.supersavedriving.driver.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));
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/DictWarpper.java
New file
@@ -0,0 +1,36 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.modular.system.model.Dict;
import com.supersavedriving.driver.core.base.warpper.BaseControllerWarpper;
import com.supersavedriving.driver.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(),","));
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/LogWarpper.java
New file
@@ -0,0 +1,44 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.core.base.warpper.BaseControllerWarpper;
import com.supersavedriving.driver.core.util.Contrast;
import com.supersavedriving.driver.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);
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/MenuWarpper.java
New file
@@ -0,0 +1,28 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.base.warpper.BaseControllerWarpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.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")));
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/NoticeWrapper.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.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));
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/OpenCityWarpper.java
New file
@@ -0,0 +1,18 @@
package com.supersavedriving.driver.modular.system.warpper;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel
public class OpenCityWarpper {
    @ApiModelProperty("名称")
    private String name;
    @ApiModelProperty("编号")
    private String code;
    @ApiModelProperty("子级")
    private List<OpenCityWarpper> sublevel;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/ResponseWarpper.java
New file
@@ -0,0 +1,45 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.modular.system.util.ResultUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 统一返回实体
* @author pzb
* @Date 2023/2/3 10:46
*/
@Data
@ApiModel
public class ResponseWarpper<T> {
    @ApiModelProperty(value = "返回状态码(200/300/400/500)", required = true, dataType = "int")
    private Integer code;
    @ApiModelProperty(value = "结果备注", required = true, dataType = "string")
    private String message;
    @ApiModelProperty(value = "结果集对象", required = false)
    private ResultUtil<T> resultUtil;
    public ResponseWarpper() {
    }
    public ResponseWarpper(Integer code, String message) {
        this.code = code;
        this.message = message;
        this.resultUtil = ResultUtil.success();
    }
    public ResponseWarpper(Integer code, String message, ResultUtil<T> resultUtil) {
        this.code = code;
        this.message = message;
        this.resultUtil = resultUtil;
    }
    public static <T> ResponseWarpper<T> success(T data) {
        return new ResponseWarpper(200, "success", ResultUtil.success(data));
    }
    public static <T> ResponseWarpper<T> success(ResultUtil<T> resultUtil) {
        return new ResponseWarpper(200, "success", resultUtil);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/RoleWarpper.java
New file
@@ -0,0 +1,27 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.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")));
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/warpper/UserWarpper.java
New file
@@ -0,0 +1,29 @@
package com.supersavedriving.driver.modular.system.warpper;
import com.supersavedriving.driver.core.common.constant.factory.ConstantFactory;
import com.supersavedriving.driver.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")));
    }
}
driver/guns-admin/src/main/resources/META-INF/spring-devtools.properties
New file
@@ -0,0 +1 @@
restart.include.beetl=/beetl-2.8.5.jar
driver/guns-admin/src/main/resources/application.yml
New file
@@ -0,0 +1,122 @@
server:
  port: 8007
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:
  application:
    name: driver-server
  profiles:
    active: dev
#    active: produce
  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.supersavedriving.driver.modular
  configuration:
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
eureka:
  client:
    service-url: #注册中心地址
      defaultZone: http://sinata:sinata@127.0.0.1:8000/eureka #启用身份验证的方式连接
    register-with-eureka: true #在注册中心进行注册
    fetch-registry: true #从Eureka中获取注册信息。
---
#配置Swagger接口扫描范围
swagger:
  base-package: com.supersavedriving.driver.modular
#spring:
#  datasource:
#    url: jdbc:mysql://Rm-wz9rpe0t74ys3b1h8go.mysql.rds.aliyuncs.com:3306/oktravel?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai
#    username: root
#    password: Root2020!
#    db-name: guns #用来搜集数据库的所有表
#    filters: wall,mergeStat
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/super_save_driving?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
---
wx:
  grantType: authorization_code #填authorization_code
  appid: wx36c966d381cd5d62 #应用唯一标识,在微信开放平台提交应用审核通过后获得
  appSecret: cf4b21c7175356f41fa3c426f26c20e4 #应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
  appletsAppid: wx7608ef3dae49b691 #小程序APPid
  appletsAppSecret: 8ea5529ad9bc9703557ebfd6a95299f6 #
  mchId: 1593080081 #微信支付分配的商户号
  key: JnhREmZwHNKyFUQPEhijp1gdaCUzKg8P #key为商户平台设置的密钥key:
---
alipay:
  appid: 2021001161600393  #应用程序唯一标识
  appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCEbTcG2wz+kaYDo2YxflpHE59MvKc3rbl6RlBgO6i5GzgphzeRTv5kRWUpSVkKCsbxFvAYLcgFPmm5nY2fz5hCTKiRcYfpUjH/OougUbzYU3ilUc9JqMbmvy7KN+Kv7+kQYCGLvMqlyYPiJ7LrmJLpE/FUcNLDwo6xUmwJSxaF7M4TbD3ZQZdddki1iJp9GihlqehZCMWOBeotEXvPKDEzSEkYlnvHPQaaspVgeesGmlHDuOiZUokENutxpjo7klWe97NA49hXEtI+xlczNGJKdBr0keBX/kSMsnx8kMxYDjh4QTySBaR6zlO4RYPFekWv9QZ2CrfiKCS7AHUpZYZ5AgMBAAECggEAXjCoUPIBHhhOcowIJe/vGlr0lUohzdJ8+GGGzcvhSDf6DF+mwG3lN0C8oU8QS7o6okRkZW46tLAd1u4fS6oGbDHGPBz6RJQ4B4eGxHMe1OcaCsxTmdq4DmuxRhfV3rnPldwqQA/6O01HxtXhxvzwkWOj5SGSZ7a8c5diTIHh9ULd6neUI/rIFC97mH1TeW0uDIxAtyvswz0pIfDhAR+lsOyTg/8qzsIXjpBFG4gAVxhUeUqQA5HzbsFglC08V7ViDk1OEoWi3yIj1CmNdtntJI4cxqLgTK7MNB9udhbN2I9YasuIpZvlAcvPi5R9cYT8vvFBCFGM+i22wtcsQmxdAQKBgQDaD9y6WNmsp+IaAUG3FqbJC8SqwreGIiEflWwVjrd+LuN6yhyr45CobOmhbTz0de8gRJEZKgJZEJcywL1ScrPIC4n1JaG688lk5aR+0Lik5fy1+L6G/CydJoJqlh6KKdwPJmDGpVu/geLJcLkWcYOwL56IL7GK2JI1p607R0x6iQKBgQCbd0n4xG9GkpvW4LDAJiMEhwPu9QcCKIT0mXVXCgMFdWel9bY3+8RSZoziWutaofm9tRHFAqwjbRyOZ+EdckkNsWVkkTnkKGtAhYKgM0GaOwdMFxmvME5WYJ74a5t1jiezDmR3obUBtS2nyQ8CFPUnlimoTR9F6APrth3h8uvwcQKBgFWaCn1AqdrEYNbyjViRVNHxg7fBDohiV3xtjOt9hfzL7VLjipPTlpL3hlNvbZFNxpx1LjyhqCBMif5LeUanbnnmRbbtmeqpDvNDzupVh1Z8TlMlHa4hymW6m1G6MqzsN83es/jnKvgnxd5sGMx9rUN5vhMaHekykVrswu1VVOl5AoGAMDljh7gfMEv/7TqLeT8bM6dR8AivoNrCy0Di5hnj8AiIGzHJ0TnWnxzSbNB5GwcNeew109/NV7vb1MyiRskRoh657eUiiQSEqGIBsAHWQqo2zEKKJA6e7ipQhYyTj3aGGAPJ5FYT2LDDtb0nW6T2ms34pA0wOzYKKU63nEQHLfECgYEAgbbpZJRtPxWB1M/Dg7loguT5O/VUsKefS0JrSD+tJIqYkumH5mejvYW5YEeDdelkvBhAEFUW9JOkzL+1w1g3wz2QQ2aPV/r55cJE3EfOzbwgw6GsO+8UuyiavbFhS3pFZNI0pR5M3u1+SIcLqQCnYLbO11vnEXglB6wjw9/oxPE= #开发者应用私钥
  alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhG03BtsM/pGmA6NmMX5aRxOfTLynN625ekZQYDuouRs4KYc3kU7+ZEVlKUlZCgrG8RbwGC3IBT5puZ2Nn8+YQkyokXGH6VIx/zqLoFG82FN4pVHPSajG5r8uyjfir+/pEGAhi7zKpcmD4iey65iS6RPxVHDSw8KOsVJsCUsWhezOE2w92UGXXXZItYiafRooZanoWQjFjgXqLRF7zygxM0hJGJZ7xz0GmrKVYHnrBppRw7jomVKJBDbrcaY6O5JVnvezQOPYVxLSPsZXMzRiSnQa9JHgV/5EjLJ8fJDMWA44eEE8kgWkes5TuEWDxXpFr/UGdgq34igkuwB1KWWGeQIDAQAB #应用公钥
  alipay_public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzmDrvcNvhexu3KkxVS9bemdSn6pyQUFmpyOGMDOirGR+RbmldpH2N9bPegzZynb5+bmRHii4ib31XeoXc7M7r6UsPhmPeLoSBNwpC+Uig0VxPa0hmvHjAl6StArhB3eMib6Zo40nM6eCYZLLZ1kKpI5Ad/APov9uLrbSnoeZsgeRibQix07arvTEsZq6pJavNlA+UBjp65o6Bv0+kfQ65pMTpbu+jRtTzkTj1hoW9PjwlWrY21F1FvN67zDWkTB2LjGFsqan0Qoe4/X8nK3VsDvkjIm/ZQsnQr8ZzfcuTzQPrcZpo3h9DPZoHeiToEfXtyk7E0bQHEmYVpmrvk/IJwIDAQAB #支付宝公钥
---
juhe: #聚合数据
  appKey: 0d3fd83eddaa33e5563f548257648577 #
---
filePath: /usr/local/server/orderPostionFile/ #存储订单轨迹文件路径
#filePath: C:/orderPostionFile/  #存储订单轨迹文件路径
#支付回调地址
#正式环境
callbackPath: https://okyueche.com:443/user
#测试环境
#callbackPath: http://47.108.254.217:80/user
---
#交通部推送数据功能开关
pushMinistryOfTransport: false
driver/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" //硬盘最大缓存个数。
    -->
driver/guns-admin/src/main/resources/logback-spring.xml
New file
@@ -0,0 +1,225 @@
<?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="/usr/local/server/logs"/>-->
    <property name="log.path" value="d:/logs"/>
    <!--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}/${artifactId}/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}/${artifactId}/%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>15</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}/${artifactId}/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}/${artifactId}/%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>15</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}/${artifactId}/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}/${artifactId}/%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>15</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}/${artifactId}/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}/${artifactId}/%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>15</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}/${artifactId}/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}/${artifactId}/%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>15</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="debug">
            <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="ServiceLog" level="debug"/>
    </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="ServiceLog" level="debug"/>
    </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="ServiceLog" level="debug"/>
    </springProfile>
</configuration>
driver/guns-admin/src/main/resources/redis.properties
New file
@@ -0,0 +1,22 @@
#redisÅäÖÿªÊ¼
# RedisÊý¾Ý¿âË÷Òý£¨Ä¬ÈÏΪ0£©
spring.redis.database=0
# Redis·þÎñÆ÷µØÖ·
spring.redis.host=127.0.0.1
# Redis·þÎñÆ÷Á¬½Ó¶Ë¿Ú
spring.redis.port=6379
# Redis·þÎñÆ÷Á¬½ÓÃÜÂ루ĬÈÏΪ¿Õ£©
spring.redis.password=123456
#spring.redis.password=
# Á¬½Ó³Ø×î´óÁ¬½ÓÊý£¨Ê¹ÓøºÖµ±íʾûÓÐÏÞÖÆ£©
spring.redis.jedis.pool.max-active=1024
# Á¬½Ó³Ø×î´ó×èÈûµÈ´ýʱ¼ä£¨Ê¹ÓøºÖµ±íʾûÓÐÏÞÖÆ£©
spring.redis.jedis.pool.max-wait=10000
# Á¬½Ó³ØÖеÄ×î´ó¿ÕÏÐÁ¬½Ó
spring.redis.jedis.pool.max-idle=200
# Á¬½Ó³ØÖеÄ×îС¿ÕÏÐÁ¬½Ó
spring.redis.jedis.pool.min-idle=0
# Á¬½Ó³¬Ê±Ê±¼ä£¨ºÁÃ룩
spring.redis.timeout=10000
#redisÅäÖýáÊø
spring.redis.block-when-exhausted=true
driver/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>
driver/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>
@}
driver/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>
@}
driver/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>
driver/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>
driver/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>
driver/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>
driver/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>
driver/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>
driver/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>
driver/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>
@}
driver/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>
driver/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>
@}
driver/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>
@}
driver/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>
driver/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
driver/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>
driver/guns-admin/src/main/webapp/WEB-INF/view/login.html
New file
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <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.css?v=4.4.0" rel="stylesheet">
    <link href="${ctxPath}/static/css/style.css?v=4.1.0" rel="stylesheet">
    <script>if (window.top !== window.self) {
        window.top.location = window.location;
    }</script>
    <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>
</head>
<body class="gray-bg">
<div class="middle-box text-center loginscreen">
    <div style="padding: 100px 0px;">
        <div>
            <h1 class="logo-name">GS</h1>
        </div>
        <h3>欢迎使用 Guns</h3>
        <br/>
        <h4 style="color: red;">${tips!}</h4>
        <form class="m-t" role="form" action="${ctxPath}/login" method="post">
            <div class="form-group">
                <input type="text" name="username" class="form-control" placeholder="用户名" required="">
            </div>
            <div class="form-group">
                <input type="password" name="password" class="form-control" placeholder="密码" required="">
            </div>
            @if(kaptcha.getKaptchaOnOff() == true){
            <div class="form-group" style="float: left;">
                <div class="col-sm-8" style="padding-left: 0px; padding-right: 0px;">
                    <input class="form-control" type="text" name="kaptcha" placeholder="验证码" required="">
                </div>
                <div class="col-sm-4" style="padding-left: 0px; padding-right: 0px;">
                    <img src="${ctxPath}/kaptcha" id="kaptcha" width="100%" height="100%"/>
                </div>
            </div>
            @}
            <div class="form-group" style="float: left;">
                <div class="checkbox" style="text-align: left">
                    <label>
                        <input type="checkbox" name="remember" style="margin-top: 2px;">记住我
                    </label>
                </div>
            </div>
            <button type="submit" class="btn btn-primary block full-width m-b">登 录</button>
            </p>
        </form>
    </div>
</div>
<script>
    $(function () {
        $("#kaptcha").on('click', function () {
            $("#kaptcha").attr('src', '${ctxPath}/kaptcha?' + Math.floor(Math.random() * 100)).fadeIn();
        });
    });
</script>
</body>
</html>
driver/guns-admin/src/main/webapp/WEB-INF/view/system/code/code.html
New file
@@ -0,0 +1,47 @@
@layout("/common/_container.html"){
<div class="row">
    <div class="col-sm-6  col-sm-offset-3">
        <div class="ibox float-e-margins">
            <div class="ibox-title">
                <h5>代码生成</h5>
            </div>
            <div class="ibox-content">
                <div class="form-horizontal">
                    <div class="form-group">
                        <label class="col-sm-2 control-label">模块英文名称</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="moduleName"> <span class="help-block m-b-none">例如:system</span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">业务名称</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="bizChName"> <span class="help-block m-b-none">例如:测试</span>
                        </div>
                    </div>
                    <div class="hr-line-dashed"></div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">业务英文名称</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="bizEnName"> <span class="help-block m-b-none">例如:test</span>
                        </div>
                    </div>
                    <div class="hr-line-dashed"></div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">输出路径</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="path"> <span class="help-block m-b-none">默认路径为D:\ideaSpace\guns,可修改为您的项目的路径</span>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-sm-4 col-sm-offset-2">
                            <button class="btn btn-primary" onclick="Code.generate()">代码生成</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/code/code.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept.html
New file
@@ -0,0 +1,38 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-3">
                                <#NameCon id="condition" name="名称" />
                            </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="Dept.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="DeptTableToolbar" role="group">
                            @if(shiro.hasPermission("/dept/add")){
                                <#button name="添加" icon="fa-plus" clickFun="Dept.openAddDept()"/>
                            @}
                            @if(shiro.hasPermission("/dept/update")){
                                <#button name="修改" icon="fa-plus" clickFun="Dept.openDeptDetail()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/dept/delete")){
                                <#button name="删除" icon="fa-plus" clickFun="Dept.delete()" space="true"/>
                            @}
                        </div>
                        <#table id="DeptTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/dept/dept.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_add.html
New file
@@ -0,0 +1,42 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="deptInfoForm">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="simplename" name="部门名称" underline="true"/>
                    <#input id="fullname" name="部门全称" underline="true"/>
                    <#input id="tips" name="备注" underline="true"/>
                </div>
                <div class="col-sm-6">
                    <#input id="num" name="排序" underline="true"/>
                    <#input id="pName" name="上级部门" readonly="readonly" hidden="pid"
                            clickFun="DeptInfoDlg.showDeptSelectTree(); return false;"
                            style="background-color: #ffffff !important;"/>
                </div>
            </div>
            <!-- 父级部门的选择框 -->
            <div id="parentDeptMenu" class="menuContent"
                 style="display: none; position: absolute; z-index: 200;">
                <ul id="parentDeptMenuTree" class="ztree tree-box" style="width: 245px !important;"></ul>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="DeptInfoDlg.addSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="DeptInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/dept/dept_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dept/dept_edit.html
New file
@@ -0,0 +1,43 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="deptInfoForm">
            <input type="hidden" id="id" value="${dept.id}">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="simplename" name="部门名称" underline="true" value="${dept.simplename}"/>
                    <#input id="fullname" name="部门全称" underline="true" value="${dept.fullname}"/>
                    <#input id="tips" name="备注" underline="true" value="${dept.tips}"/>
                </div>
                <div class="col-sm-6">
                    <#input id="num" name="排序" underline="true" value="${dept.num}"/>
                    <#input id="pName" name="上级部门" readonly="readonly" hidden="pid"
                            hiddenValue="${dept.pid}" value="${pName}"
                            clickFun="DeptInfoDlg.showDeptSelectTree(); return false;"
                            style="background-color: #ffffff !important;"/>
                </div>
            </div>
            <!-- 父级部门的选择框 -->
            <div id="parentDeptMenu" class="menuContent"
                 style="display: none; position: absolute; z-index: 200;">
                <ul id="parentDeptMenuTree" class="ztree tree-box" style="width: 245px !important;"></ul>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="DeptInfoDlg.editSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="DeptInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/dept/dept_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict.html
New file
@@ -0,0 +1,38 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-3">
                                <#NameCon id="condition" name="名称" />
                            </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="Dict.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="DictTableToolbar" role="group">
                            @if(shiro.hasPermission("/dict/add")){
                                <#button name="添加" icon="fa-plus" clickFun="Dict.openAddDict()"/>
                            @}
                            @if(shiro.hasPermission("/dict/update")){
                                <#button name="修改" icon="fa-plus" clickFun="Dict.openDictDetail()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/dict/delete")){
                                <#button name="删除" icon="fa-plus" clickFun="Dict.delete()" space="true"/>
                            @}
                        </div>
                        <#table id="DictTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/dict/dict.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_add.html
New file
@@ -0,0 +1,64 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-12" id="itemsArea">
                    <div class="form-group">
                        <label class="col-sm-2 control-label">类型编码</label>
                        <div class="col-sm-2">
                            <input class="form-control" id="dictCode" type="text">
                        </div>
                        <label class="col-sm-2 control-label">类型名称</label>
                        <div class="col-sm-2">
                            <input class="form-control" id="dictName" type="text">
                        </div>
                        <div class="col-sm-2">
                            <#button btnCss="info" name="增加" icon="fa-plus" clickFun="DictInfoDlg.addItem()"/>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">备注</label>
                        <div class="col-sm-8">
                            <input class="form-control" id="dictTips" type="text">
                        </div>
                    </div>
                    <div class="hr-line-dashed"></div>
                </div>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="DictInfoDlg.addSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="DictInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
    <script type="text/template" id="itemTemplate">
        <div class="form-group" name="dictItem" id="dictItem">
            <label class="col-sm-1 control-label">值</label>
            <div class="col-sm-2">
                <input class="form-control" type="text" name="itemCode">
            </div>
            <label class="col-sm-1 control-label" >名称</label>
            <div class="col-sm-2">
                <input class="form-control" type="text" name="itemName">
            </div>
            <label class="col-sm-1 control-label" >序号</label>
            <div class="col-sm-2">
                <input class="form-control" type="text" name="itemNum">
            </div>
            <div class="col-sm-2">
                <#button btnCss="danger" name="删除" id="cancel" icon="fa-remove" clickFun="DictInfoDlg.deleteItem(event)"/>
            </div>
        </div>
    </script>
    <script src="${ctxPath}/static/modular/system/dict/dict_info.js"></script>
    @}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/dict/dict_edit.html
New file
@@ -0,0 +1,86 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-12" id="itemsArea">
                    <input type="hidden" id="itemSize" value="${subDicts.~size!0}" />
                    <div class="form-group">
                        <label class="col-sm-2 control-label">类型编码</label>
                        <div class="col-sm-2">
                            <input class="form-control" id="dictCode" type="text" value="${dict.code}">
                        </div>
                        <label class="col-sm-2 control-label">类型名称</label>
                        <div class="col-sm-2">
                            <input class="form-control" id="dictName" type="text" value="${dict.name}">
                            <input type="hidden" id="dictId" value="${dict.id}">
                        </div>
                        <div class="col-sm-2">
                            <#button btnCss="info" name="增加" icon="fa-plus" clickFun="DictInfoDlg.addItem()"/>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">备注</label>
                        <div class="col-sm-8">
                            <input class="form-control" id="dictTips" type="text" value="${dict.tips}">
                        </div>
                    </div>
                    <div class="hr-line-dashed"></div>
                    @for(item in subDicts){
                    <div class="form-group" name="dictItem" id="dictItem${itemLP.index}">
                        <label class="col-sm-1 control-label">值</label>
                        <div class="col-sm-2">
                            <input class="form-control" type="text" name="itemCode" value="${item.code}">
                        </div>
                        <label class="col-sm-1 control-label" >名称</label>
                        <div class="col-sm-2">
                            <input class="form-control" type="text" name="itemName" value="${item.name}">
                        </div>
                        <label class="col-sm-1 control-label" >序号</label>
                        <div class="col-sm-2">
                            <input class="form-control" type="text" name="itemNum" value="${item.num}">
                        </div>
                        <div class="col-sm-2">
                            <#button btnCss="danger" name="删除" id="cancel" icon="fa-remove" clickFun="DictInfoDlg.deleteItem(event)"/>
                        </div>
                    </div>
                    @}
                    </input>
                </div>
                <div class="row btn-group-m-t">
                    <div class="col-sm-10">
                        <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="DictInfoDlg.editSubmit()"/>
                        <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="DictInfoDlg.close()"/>
                    </div>
                </div>
            </div>
        </div>
        <script type="text/template" id="itemTemplate">
            <div class="form-group" name="dictItem" id="dictItem">
                <label class="col-sm-1 control-label">值</label>
                <div class="col-sm-2">
                    <input class="form-control" type="text" name="itemCode">
                </div>
                <label class="col-sm-1 control-label" >名称</label>
                <div class="col-sm-2">
                    <input class="form-control" type="text" name="itemName">
                </div>
                <label class="col-sm-1 control-label" >序号</label>
                <div class="col-sm-2">
                    <input class="form-control" type="text" name="itemNum">
                </div>
                <div class="col-sm-2">
                    <#button btnCss="danger" name="删除" id="cancel" icon="fa-remove" clickFun="DictInfoDlg.deleteItem(event)"/>
                </div>
            </div>
        </script>
        <script src="${ctxPath}/static/modular/system/dict/dict_info.js"></script>
        @}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/log/log.html
New file
@@ -0,0 +1,46 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-2">
                                <#TimeCon id="beginTime" name="开始时间" isTime="false" pattern="YYYY-MM-DD" />
                            </div>
                            <div class="col-sm-2">
                                <#TimeCon id="endTime" name="结束时间" isTime="false" pattern="YYYY-MM-DD" />
                            </div>
                            <div class="col-sm-2">
                                <#NameCon id="logName" name="日志名称" />
                            </div>
                            <div class="col-sm-2">
                                <#SelectCon id="logType" name="日志类型" >
                                    <option value="0">全部</option>
                                    <option value="1">业务日志</option>
                                    <option value="2">异常日志</option>
                                </#SelectCon>
                            </div>
                            <div class="col-sm-2">
                                <#button name="搜索" icon="fa-search" clickFun="OptLog.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="OptLogTableToolbar" role="group">
                            <#button name="查看详情" icon="fa-plus" clickFun="OptLog.detail()"/>
                            @if(shiro.hasPermission("/log/delLog")){
                                <#button name="清空日志" icon="fa-plus" clickFun="OptLog.delLog()" space="true"/>
                            @}
                        </div>
                        <#table id="OptLogTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/log/log.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/log/login_log.html
New file
@@ -0,0 +1,36 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-3">
                                <#TimeCon id="beginTime" name="开始时间" isTime="false" pattern="YYYY-MM-DD" />
                            </div>
                            <div class="col-sm-3">
                                <#TimeCon id="endTime" name="结束时间" isTime="false" pattern="YYYY-MM-DD" />
                            </div>
                            <div class="col-sm-3">
                                <#NameCon id="logName" name="日志名称" />
                            </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="LoginLog.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="LoginLogTableToolbar" role="group">
                            <#button name="清空日志" icon="fa-plus" clickFun="LoginLog.delLog()"/>
                        </div>
                        <#table id="LoginLogTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/log/login_log.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu.html
New file
@@ -0,0 +1,41 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-3">
                                <#NameCon id="menuName" name="菜单名称" />
                            </div>
                            <div class="col-sm-3">
                                <#NameCon id="level" name="层级" />
                            </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="Menu.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="menuTableToolbar" role="group">
                            @if(shiro.hasPermission("/menu/add")){
                                <#button name="添加" icon="fa-plus" clickFun="Menu.openAddMenu()"/>
                            @}
                            @if(shiro.hasPermission("/menu/edit")){
                                <#button name="修改" icon="fa-edit" clickFun="Menu.openChangeMenu()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/menu/remove")){
                                <#button name="删除" icon="fa-remove" clickFun="Menu.delMenu()" space="true"/>
                            @}
                        </div>
                        <#table id="menuTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/menu/menu.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_add.html
New file
@@ -0,0 +1,40 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="menuInfoForm">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="name" name="名称" underline="true" />
                    <#input id="code" name="菜单编号" underline="true" />
                    <#input id="pcodeName" name="父级编号" underline="true"
                            hidden="pcode" readonly="readonly"
                            clickFun="MenuInfoDlg.showMenuSelectTree(); return false;"
                            style="background-color: #ffffff !important;"
                            selectFlag="true" selectId="pcodeTreeDiv" selectTreeId="pcodeTree" selectStyle="width:244px !important;"/>
                    <#select id="ismenu" name="是否是菜单">
                        <option value="1">是</option>
                        <option value="0">不是</option>
                    </#select>
                </div>
                <div class="col-sm-6">
                    <#input id="url" name="请求地址" underline="true" />
                    <#input id="num" name="排序" underline="true" />
                    <#input id="icon" name="图标" underline="false" />
                </div>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="MenuInfoDlg.addSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="MenuInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/menu/menu_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/menu/menu_edit.html
New file
@@ -0,0 +1,42 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="menuInfoForm">
            <input type="hidden" id="id" value="${menu.id}">
            <input type="hidden" id="ismenuValue" value="${menu.ismenu}">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="name" name="名称" value="${menu.name}" underline="true" />
                    <#input id="code" name="菜单编号" value="${menu.code}" underline="true" />
                    <#input id="pcodeName" name="父级编号" value="${menu.pcodeName}" underline="true"
                            hidden="pcode" readonly="readonly" hiddenValue="${menu.pcode}"
                            clickFun="MenuInfoDlg.showMenuSelectTree(); return false;"
                            style="background-color: #ffffff !important;"
                            selectFlag="true" selectId="pcodeTreeDiv" selectTreeId="pcodeTree" selectStyle="width:244px !important;"/>
                    <#select id="ismenu" name="是否是菜单">
                        <option value="1">是</option>
                        <option value="0">不是</option>
                    </#select>
                </div>
                <div class="col-sm-6">
                    <#input id="url" name="请求地址" value="${menu.url}" underline="true" />
                    <#input id="num" name="排序" value="${menu.num}" underline="true" />
                    <#input id="icon" name="图标" underline="false" value="${menu.icon}"/>
                </div>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="MenuInfoDlg.editSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="MenuInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/menu/menu_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice.html
New file
@@ -0,0 +1,38 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-3">
                                <#NameCon id="condition" name="名称" />
                            </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="Notice.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="NoticeTableToolbar" role="group">
                            @if(shiro.hasPermission("/notice/add")){
                                <#button name="添加" icon="fa-plus" clickFun="Notice.openAddNotice()"/>
                            @}
                            @if(shiro.hasPermission("/notice/update")){
                                <#button name="修改" icon="fa-plus" clickFun="Notice.openNoticeDetail()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/notice/delete")){
                                <#button name="删除" icon="fa-plus" clickFun="Notice.delete()" space="true"/>
                            @}
                        </div>
                        <#table id="NoticeTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/notice/notice.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_add.html
New file
@@ -0,0 +1,39 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="noticeInfoForm">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-12">
                    <div class="form-group">
                        <label class="col-sm-1 control-label">标题</label>
                        <div class="col-sm-11">
                            <input class="form-control" id="title" name="title" type="text">
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-1 control-label">内容</label>
                        <div class="col-sm-11">
                            <div id="editor" class="editorHeight">
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="NoticeInfoDlg.addSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="NoticeInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript" src="//unpkg.com/wangeditor/release/wangEditor.min.js"></script>
<script src="${ctxPath}/static/modular/system/notice/notice_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/notice/notice_edit.html
New file
@@ -0,0 +1,39 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="noticeInfoForm">
            <input type="hidden" id="id" value="${notice.id}">
            <input type="hidden" id="contentVal" value='${notice.content}'>
            <div class="row">
                <div class="col-sm-12">
                    <div class="form-group">
                        <label class="col-sm-1 control-label">标题</label>
                        <div class="col-sm-11">
                            <input class="form-control" id="title" name="title" type="text" value="${notice.title}">
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-1 control-label">内容</label>
                        <div class="col-sm-11">
                            <div id="editor" class="editorHeight">
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="NoticeInfoDlg.editSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="NoticeInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript" src="${ctxPath}/static/js/plugins/wangEditor/wangEditor.js"></script>
<script src="${ctxPath}/static/modular/system/notice/notice_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role.html
New file
@@ -0,0 +1,41 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-sm-3">
                                <#NameCon id="roleName" name="角色名称" />
                            </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="Role.search()"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="roleTableToolbar" role="group">
                            @if(shiro.hasPermission("/role/add")){
                                <#button name="添加" icon="fa-plus" clickFun="Role.openAddRole()" />
                            @}
                            @if(shiro.hasPermission("/role/edit")){
                                <#button name="修改" icon="fa-edit" clickFun="Role.openChangeRole()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/role/remove")){
                                <#button name="删除" icon="fa-remove" clickFun="Role.delRole()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/role/setAuthority")){
                                <#button name="权限配置" icon="fa-user-secret" clickFun="Role.assign()" space="true"/>
                            @}
                        </div>
                        <#table id="roleTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/role/role.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role_add.html
New file
@@ -0,0 +1,47 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="roleInfoForm">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="name" name="角色名称" underline="true"/>
                    <#input id="pName" name="上级名称" underline="true" hidden="pid" readonly="readonly"
                            clickFun="RolInfoDlg.showPNameSelectTree(); return false;"
                            style="background-color: #ffffff !important;"/>
                    <#input id="deptName" name="部门名称" hidden="deptid" readonly="readonly"
                            clickFun="RolInfoDlg.showDeptSelectTree(); return false;"
                            style="background-color: #ffffff !important;"/>
                </div>
                <div class="col-sm-6">
                    <#input id="tips" name="别名" underline="true"/>
                    <#input id="num" name="排序"/>
                </div>
            </div>
            <!-- 这是部门下拉框 -->
            <div id="deptContent" class="menuContent"
                style="display: none; position: absolute; z-index: 200;">
                <ul id="deptTree" class="ztree tree-box" style="width: 250px !important;"></ul>
            </div>
            <!-- 这是父级菜单下拉框 -->
            <div id="pNameContent" class="menuContent"
                style="display: none; position: absolute; z-index: 200;">
                <ul id="pNameTree" class="ztree tree-box" style="width: 250px !important;"></ul>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="RolInfoDlg.addSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="RolInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/role/role_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role_assign.html
New file
@@ -0,0 +1,75 @@
@layout("/common/_container.html"){
<script type="text/javascript">
    $(function () {
        var index = parent.layer.getFrameIndex(window.name); //获取窗口索引
        $("#btn_close").bind("click", function () {
            parent.layer.close(index);
        });
        $("#btn_save").bind("click", function () {
            var ids = Feng.zTreeCheckedNodes("zTree");
            var ajax = new $ax(Feng.ctxPath + "/role/setAuthority", function (data) {
                Feng.success("分配角色成功!");
                window.parent.Role.table.refresh();
                parent.layer.close(index);
            }, function (data) {
                Feng.error("分配角色失败!"
                    + data.responseJSON.message + "!");
            });
            ajax.set("roleId", "${roleId}");
            ajax.set("ids", ids);
            ajax.start();
        });
        initZtree();
    });
    function initZtree() {
        var setting = {
            check: {
                enable: true,
                chkboxType: { "Y": "ps", "N": "ps" }
            },
            data: {
                simpleData: {
                    enable: true
                }
            }
        };
        var ztree = new $ZTree("zTree", "/menu/menuTreeListByRoleId/"
            + "${roleId}");
        ztree.setSettings(setting);
        ztree.init();
    }
</script>
<!-- 配置grid -->
<div class="container" style="padding:  0px 10px !important;margin-top: -10px;text-align: center !important;">
    <div class="row">
        <div class="ibox float-e-margins">
            <div class="ibox-title">
                <h5>${roleName!}</h5>
            </div>
            <div class="ibox-content">
                <ul id="zTree" class="ztree"></ul>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <button class="btn btn-sm btn-info" type="button" id="btn_save">
                <i class="ace-icon fa fa-check bigger-110"></i>保存
            </button>
            &nbsp;
            <button class="btn btn-sm btn-danger" type="button" id="btn_close">
                <i class="ace-icon fa fa-close bigger-110"></i>关闭
            </button>
        </div>
    </div>
</div>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/role/role_edit.html
New file
@@ -0,0 +1,47 @@
 @layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="roleInfoForm">
            <input type="hidden" id="id" value="${role.id}">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="name" name="角色名称" underline="true" value="${role.name}"/>
                    <#input id="pName" name="上级名称" underline="true" hidden="pid" hiddenValue="${role.pid}" readonly="readonly" value="${pName}"
                            clickFun="RolInfoDlg.showPNameSelectTree(); return false;"
                            style="background-color: #ffffff !important;"/>
                    <#input id="deptName" name="部门名称" hidden="deptid" hiddenValue="${role.deptid}" readonly="readonly" value="${deptName}"
                            clickFun="RolInfoDlg.showDeptSelectTree(); return false;"
                            style="background-color: #ffffff !important;"/>
                </div>
                <div class="col-sm-6">
                    <#input id="tips" name="别名" underline="true" value="${role.tips}"/>
                    <#input id="num" name="排序" value="${role.num}"/>
                </div>
            </div>
            <!-- 这是部门下拉框 -->
            <div id="deptContent" class="menuContent"
                style="display: none; position: absolute; z-index: 200;">
                <ul id="deptTree" class="ztree tree-box" style="width: 250px !important;"></ul>
            </div>
            <!-- 这是父级菜单下拉框 -->
            <div id="pNameContent" class="menuContent"
                style="display: none; position: absolute; z-index: 200;">
                <ul id="pNameTree" class="ztree tree-box" style="width: 250px !important;"></ul>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="RolInfoDlg.editSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="RolInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/role/role_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user.html
New file
@@ -0,0 +1,85 @@
@layout("/common/_container.html"){
<div class="row">
    <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="row">
                            <div class="col-lg-2 col-sm-3">
                                <div class="panel panel-default">
                                    <div class="panel-heading">组织机构</div>
                                    <div class="panel-body dept-tree">
                                        <ul id="deptTree" class="ztree"></ul>
                                    </div>
                                </div>
                            </div>
                            <div class="col-lg-10 col-sm-9">
                                <div class="row">
                                    <div class="col-lg-10 col-sm-9">
                                        <div class="row">
                                            <div class="col-lg-4 col-sm-12">
                                                <#NameCon id="name" name="用户名称" placeholder="帐号/姓名/手机号"/>
                                            </div>
                                            <div class="col-lg-4 col-sm-6">
                                                <#TimeCon id="beginTime" name="注册开始日期" isTime="false"/>
                                            </div>
                                            <div class="col-lg-4 col-sm-6">
                                                <#TimeCon id="endTime" name="注册结束日期" isTime="false"/>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-lg-2 col-sm-3">
                                        <div class="row">
                                            <div class="col-lg-12 col-sm-12">
                                                <#button name="搜索" icon="fa-search" clickFun="MgrUser.search()"/>
                                                <#button name="重置" icon="fa-trash" clickFun="MgrUser.resetSearch()" space="true"/>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="hidden-xs" id="managerTableToolbar" role="group">
                                    @if(shiro.hasPermission("/mgr/add")){
                                    <#button name="添加" icon="fa-plus" clickFun="MgrUser.openAddMgr()"/>
                                    @}
                                    @if(shiro.hasPermission("/mgr/edit")){
                                    <#button name="修改" icon="fa-edit" clickFun="MgrUser.openChangeUser()" space="true"/>
                                    @}
                                    @if(shiro.hasPermission("/mgr/delete")){
                                    <#button name="删除" icon="fa-remove" clickFun="MgrUser.delMgrUser()" space="true"/>
                                    @}
                                    @if(shiro.hasPermission("/mgr/reset")){
                                    <#button name="重置密码" icon="fa-refresh" clickFun="MgrUser.resetPwd()" space="true"/>
                                    @}
                                    @if(shiro.hasPermission("/mgr/freeze")){
                                    <#button name="冻结" icon="fa-warning" clickFun="MgrUser.freezeAccount()" space="true"/>
                                    @}
                                    @if(shiro.hasPermission("/mgr/unfreeze")){
                                    <#button name="解除冻结" icon="fa-check-circle" clickFun="MgrUser.unfreeze()" space="true"/>
                                    @}
                                    @if(shiro.hasPermission("/mgr/setRole")){
                                    <#button name="角色分配" icon="fa-user-secret" clickFun="MgrUser.roleAssign()" space="true"/>
                                    @}
                                </div>
                                <#table id="managerTable"/>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/user/user.js"></script>
<script>
    laydate.render({
        elem: '#beginTime'
    });
    laydate.render({
        elem: '#endTime'
    });
</script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_add.html
New file
@@ -0,0 +1,63 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="userInfoForm">
            <input type="hidden" id="id" value="">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="account" name="账户" underline="true"/>
                    <#select id="sex" name="性别" underline="true">
                        <option value="1">男</option>
                        <option value="2">女</option>
                    </#select>
                    <#input id="password" name="密码" underline="true" type="password"/>
                    <#input id="roleid" name="角色" underline="true" disabled="disabled"/>
                    <#input id="email" name="邮箱" type="email"/>
                </div>
                <div class="col-sm-6">
                    <div id="driverInfoContent">
                        <#input id="name" name="姓名" underline="true"/>
                        <#input id="birthday" name="出生日期" underline="true" type="text"/>
                        <#input id="rePassword" name="确认密码" type="password" underline="true"/>
                        <#input id="citySel" name="部门" underline="true" readonly="readonly" hidden="deptid"
                        clickFun="UserInfoDlg.showDeptSelectTree(); return false;"
                        style="background-color: #ffffff !important;"/>
                        <#input id="phone" name="电话"/>
                    </div>
                </div>
            </div>
            <!-- 这是部门选择的下拉框 -->
            <div id="menuContent" class="menuContent"
                 style="display: none; position: absolute; z-index: 200;">
                <ul id="treeDemo" class="ztree tree-box" style="width: 249px !important;"></ul>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="UserInfoDlg.addSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="UserInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/user/user_info.js"></script>
<script>
    laydate.render({
        elem: '#birthday'
    });
</script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_chpwd.html
New file
@@ -0,0 +1,34 @@
@layout("/common/_container.html"){
<div class="col-sm-4  col-sm-offset-4">
    <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="ibox float-e-margins">
                        <div class="ibox-content" style="border:none !important; ">
                            <div class="form-horizontal">
                                <div class="row">
                                    <div class="col-sm-12">
                                        <#input id="oldPwd" name="原密码" underline="true" type="password"/>
                                        <#input id="newPwd" name="新密码" underline="true" type="password"/>
                                        <#input id="rePwd" name="新密码验证" type="password"/>
                                    </div>
                                </div>
                                <div class="row btn-group-m-t">
                                    <div class="col-sm-10">
                                        <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="UserInfoDlg.chPwd()"/>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/user/user_info.js"></script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_edit.html
New file
@@ -0,0 +1,60 @@
@layout("/common/_container.html"){
<div class="ibox float-e-margins">
    <div class="ibox-content">
        <div class="form-horizontal" id="userInfoForm">
            <input type="hidden" id="id" value="${user.id}">
            <input type="hidden" id="sexValue" value="${user.sex}">
            <div class="row">
                <div class="col-sm-6 b-r">
                    <#input id="account" name="账户" underline="true" value="${user.account}"/>
                    <#select id="sex" name="性别" underline="true">
                        <option value="1">男</option>
                        <option value="2">女</option>
                    </#select>
                    <#input id="roleid" name="角色" underline="true" value="${roleName}" disabled="disabled"/>
                    <#input id="email" name="邮箱" type="email" value="${user.email}"/>
                </div>
                <div class="col-sm-6">
                    <div id="driverInfoContent">
                        <#input id="name" name="姓名" underline="true" value="${user.name}"/>
                        <#input id="birthday" name="出生日期" underline="true" type="text"
                        value="${user.birthday}"/>
                        <#input id="citySel" name="部门" underline="true" readonly="readonly" hidden="deptid" hiddenValue="${user.deptid}" value="${deptName}"
                        clickFun="UserInfoDlg.showDeptSelectTree(); return false;"
                        style="background-color: #ffffff !important;"/>
                        <#input id="phone" name="电话" value="${user.phone}"/>
                    </div>
                </div>
            </div>
            <!-- 这是部门选择的下拉框 -->
            <div id="menuContent" class="menuContent"
                 style="display: none; position: absolute; z-index: 200;">
                <ul id="treeDemo" class="ztree tree-box" style="width: 249px !important;"></ul>
            </div>
            <div class="row btn-group-m-t">
                <div class="col-sm-10">
                    <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="UserInfoDlg.editSubmit()"/>
                    <#button btnCss="danger" name="取消" id="cancel" icon="fa-eraser" clickFun="UserInfoDlg.close()"/>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/user/user_info.js"></script>
<script>
    laydate.render({
        elem: '#birthday'
    });
</script>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_roleassign.html
New file
@@ -0,0 +1,79 @@
@layout("/common/_container.html"){
<script type="text/javascript">
    $(function () {
        var index = parent.layer.getFrameIndex(window.name); //获取窗口索引
        $("#btn_close").bind("click", function () {
            parent.layer.close(index);
        });
        $("#btn_save").bind("click", function () {
            var ids = Feng.zTreeCheckedNodes("zTree");
            var ajax = new $ax(Feng.ctxPath + "/mgr/setRole", function (data) {
                Feng.success("分配角色成功!");
                window.parent.MgrUser.table.refresh();
                parent.layer.close(index);
            }, function (data) {
                Feng.error("分配角色失败!" + data.responseJSON.message + "!");
            });
            ajax.set("roleIds", ids);
            ajax.set("userId", "${userId}");
            ajax.start();
        });
        initZtree();
    });
    function initZtree() {
        var setting = {
            check: {
                enable: true,
                chkboxType: {
                    "Y": "",
                    "N": ""
                }
            },
            data: {
                simpleData: {
                    enable: true
                }
            }
        };
        var ztree = new $ZTree("zTree", "/role/roleTreeListByUserId/${userId}");
        ztree.setSettings(setting);
        ztree.init();
    }
</script>
<!-- 配置grid -->
<div class="container"
     style="padding:  0px 10px !important; margin-top: -10px; text-align: center !important;">
    <div class="row">
        <div class="ibox float-e-margins">
            <div class="ibox-title">
                <h5>${userAccount!}</h5>
            </div>
            <div class="ibox-content">
                <ul id="zTree" class="ztree"></ul>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <button class="btn btn-sm btn-info" type="button" id="btn_save">
                <i class="ace-icon fa fa-check bigger-110"></i> 保存
            </button>
            &nbsp;
            <button class="btn btn-sm btn-danger" type="button" id="btn_close">
                <i class="ace-icon fa fa-close bigger-110"></i> 关闭
            </button>
        </div>
    </div>
</div>
@}
driver/guns-admin/src/main/webapp/WEB-INF/view/system/user/user_view.html
New file
@@ -0,0 +1,75 @@
@layout("/common/_container.html"){
<div class="col-sm-6  col-sm-offset-3">
    <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="ibox float-e-margins">
                        <div class="ibox-content" style="border:none !important; ">
                            <div class="form-horizontal" id="userInfoForm">
                                <input type="hidden" id="id" value="${user.id}">
                                <input type="hidden" id="sexValue" value="${user.sex}">
                                <div class="row">
                                    <div class="col-sm-6 b-r">
                                        <#avatar id="avatar" name="头像" underline="true" avatarImg="${user.avatar}"/>
                                        <#input id="account" name="账户" underline="true" value="${user.account}" disabled="disabled" />
                                        <#select id="sex" name="性别" underline="true" value="${user.sex}">
                                            <option value="1">男</option>
                                            <option value="2">女</option>
                                        </#select>
                                        <#input id="roleid" name="角色" underline="true" value="${roleName}" disabled="disabled"/>
                                        <#input id="email" name="邮箱" type="email" value="${user.email}"/>
                                    </div>
                                    <div class="col-sm-6">
                                        <div id="driverInfoContent">
                                            <#input id="name" name="姓名" underline="true" value="${user.name}"/>
                                            <#input id="birthday" name="出生日期" underline="true" type="text"
                                                    value="${user.birthday}"/>
                                            <#input id="citySel" name="部门" underline="true" readonly="readonly" value="${deptName}"
                                                    hidden="deptid" hiddenValue="${user.deptid}"
                                                    clickFun="UserInfoDlg.showInfoDeptSelectTree(); return false;"
                                                    style="background-color: #ffffff !important;"
                                                    selectFlag="true" selectId="menuContent" selectTreeId="treeDemo" selectStyle="width:250px !important;"/>
                                            <#input id="phone" name="电话" value="${user.phone}"/>
                                        </div>
                                    </div>
                                </div>
                                <div class="progress progress-striped" id="progressTipArea" style="margin-top: 20px;">
                                    <div id="progressBar" style="width: 0%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" role="progressbar" class="progress-bar progress-bar-info">
                                    </div>
                                </div>
                                <div class="row btn-group-m-t">
                                    <div class="col-sm-10">
                                        <#button btnCss="info" name="提交" id="ensure" icon="fa-check" clickFun="UserInfoDlg.editSubmit()"/>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/user/user_info.js"></script>
<script>
    laydate.render({
        elem: '#birthday'
    });
</script>
@}
driver/guns-admin/src/main/webapp/static/css/_fstyle.css
New file
@@ -0,0 +1,65 @@
.button-margin {
    margin-left: 15px !important;
}
.input-none-margin {
    margin: 0px !important;
}
.btn-margin-left {
    margin-left: 15px !important;
}
.table-head {
    float: left;
    width: 100%;
    height: auto;
}
.head-scu-label {
    margin-top: 35px;
}
.head-scu-btn {
    margin-top: 68px;
}
.line-margin {
    margin: 8px 0 !important;
}
.be-driver-checkbox {
    margin-top: 7px;
}
.btn-group-m-t {
    margin-top: 20px;
}
.upload-btn {
    white-space: nowrap;
}
.tree-box {
    border-radius: 0px !important;
    box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2) !important;
    background: rgb(250, 250, 250) none repeat scroll 0% 0% !important;
    border: 1px solid rgb(204, 204, 204) !important;
    overflow-y: scroll !important;
    overflow-x: auto !important;
    margin-top: 0px !important;
    width: 224px !important;
    max-height: 160px !important;
    -moz-user-select: none !important;
}
.dept-tree {
    padding:10px
}
.w-e-text-container{
    height: 150px !important;
}
.editorHeight{
    height: 170px;
}
driver/guns-admin/src/main/webapp/static/css/bootstrap-rtl.css
New file
@@ -0,0 +1,1468 @@
/*******************************************************************************
 *              bootstrap-rtl (version 3.3.1)
 *      Author: Morteza Ansarinia (http://github.com/morteza)
 *  Created on: January 21,2015
 *     Project: bootstrap-rtl
 *   Copyright: Unlicensed Public Domain
 *******************************************************************************/
html {
  direction: rtl;
}
body {
  direction: rtl;
}
.list-unstyled {
  padding-right: 0;
  padding-left: initial;
}
.list-inline {
  padding-right: 0;
  padding-left: initial;
  margin-right: -5px;
  margin-left: 0;
}
dd {
  margin-right: 0;
  margin-left: initial;
}
@media (min-width: 768px) {
  .dl-horizontal dt {
    float: right;
    clear: right;
    text-align: left;
  }
  .dl-horizontal dd {
    margin-right: 180px;
    margin-left: 0;
  }
}
blockquote {
  border-right: 5px solid #eeeeee;
  border-left: 0;
}
.blockquote-reverse,
blockquote.pull-left {
  padding-left: 15px;
  padding-right: 0;
  border-left: 5px solid #eeeeee;
  border-right: 0;
  text-align: left;
}
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
  position: relative;
  min-height: 1px;
  padding-left: 15px;
  padding-right: 15px;
}
.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
  float: right;
}
.col-xs-12 {
  width: 100%;
}
.col-xs-11 {
  width: 91.66666667%;
}
.col-xs-10 {
  width: 83.33333333%;
}
.col-xs-9 {
  width: 75%;
}
.col-xs-8 {
  width: 66.66666667%;
}
.col-xs-7 {
  width: 58.33333333%;
}
.col-xs-6 {
  width: 50%;
}
.col-xs-5 {
  width: 41.66666667%;
}
.col-xs-4 {
  width: 33.33333333%;
}
.col-xs-3 {
  width: 25%;
}
.col-xs-2 {
  width: 16.66666667%;
}
.col-xs-1 {
  width: 8.33333333%;
}
.col-xs-pull-12 {
  left: 100%;
  right: auto;
}
.col-xs-pull-11 {
  left: 91.66666667%;
  right: auto;
}
.col-xs-pull-10 {
  left: 83.33333333%;
  right: auto;
}
.col-xs-pull-9 {
  left: 75%;
  right: auto;
}
.col-xs-pull-8 {
  left: 66.66666667%;
  right: auto;
}
.col-xs-pull-7 {
  left: 58.33333333%;
  right: auto;
}
.col-xs-pull-6 {
  left: 50%;
  right: auto;
}
.col-xs-pull-5 {
  left: 41.66666667%;
  right: auto;
}
.col-xs-pull-4 {
  left: 33.33333333%;
  right: auto;
}
.col-xs-pull-3 {
  left: 25%;
  right: auto;
}
.col-xs-pull-2 {
  left: 16.66666667%;
  right: auto;
}
.col-xs-pull-1 {
  left: 8.33333333%;
  right: auto;
}
.col-xs-pull-0 {
  left: auto;
  right: auto;
}
.col-xs-push-12 {
  right: 100%;
  left: 0;
}
.col-xs-push-11 {
  right: 91.66666667%;
  left: 0;
}
.col-xs-push-10 {
  right: 83.33333333%;
  left: 0;
}
.col-xs-push-9 {
  right: 75%;
  left: 0;
}
.col-xs-push-8 {
  right: 66.66666667%;
  left: 0;
}
.col-xs-push-7 {
  right: 58.33333333%;
  left: 0;
}
.col-xs-push-6 {
  right: 50%;
  left: 0;
}
.col-xs-push-5 {
  right: 41.66666667%;
  left: 0;
}
.col-xs-push-4 {
  right: 33.33333333%;
  left: 0;
}
.col-xs-push-3 {
  right: 25%;
  left: 0;
}
.col-xs-push-2 {
  right: 16.66666667%;
  left: 0;
}
.col-xs-push-1 {
  right: 8.33333333%;
  left: 0;
}
.col-xs-push-0 {
  right: auto;
  left: 0;
}
.col-xs-offset-12 {
  margin-right: 100%;
  margin-left: 0;
}
.col-xs-offset-11 {
  margin-right: 91.66666667%;
  margin-left: 0;
}
.col-xs-offset-10 {
  margin-right: 83.33333333%;
  margin-left: 0;
}
.col-xs-offset-9 {
  margin-right: 75%;
  margin-left: 0;
}
.col-xs-offset-8 {
  margin-right: 66.66666667%;
  margin-left: 0;
}
.col-xs-offset-7 {
  margin-right: 58.33333333%;
  margin-left: 0;
}
.col-xs-offset-6 {
  margin-right: 50%;
  margin-left: 0;
}
.col-xs-offset-5 {
  margin-right: 41.66666667%;
  margin-left: 0;
}
.col-xs-offset-4 {
  margin-right: 33.33333333%;
  margin-left: 0;
}
.col-xs-offset-3 {
  margin-right: 25%;
  margin-left: 0;
}
.col-xs-offset-2 {
  margin-right: 16.66666667%;
  margin-left: 0;
}
.col-xs-offset-1 {
  margin-right: 8.33333333%;
  margin-left: 0;
}
.col-xs-offset-0 {
  margin-right: 0%;
  margin-left: 0;
}
@media (min-width: 768px) {
  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
    float: right;
  }
  .col-sm-12 {
    width: 100%;
  }
  .col-sm-11 {
    width: 91.66666667%;
  }
  .col-sm-10 {
    width: 83.33333333%;
  }
  .col-sm-9 {
    width: 75%;
  }
  .col-sm-8 {
    width: 66.66666667%;
  }
  .col-sm-7 {
    width: 58.33333333%;
  }
  .col-sm-6 {
    width: 50%;
  }
  .col-sm-5 {
    width: 41.66666667%;
  }
  .col-sm-4 {
    width: 33.33333333%;
  }
  .col-sm-3 {
    width: 25%;
  }
  .col-sm-2 {
    width: 16.66666667%;
  }
  .col-sm-1 {
    width: 8.33333333%;
  }
  .col-sm-pull-12 {
    left: 100%;
    right: auto;
  }
  .col-sm-pull-11 {
    left: 91.66666667%;
    right: auto;
  }
  .col-sm-pull-10 {
    left: 83.33333333%;
    right: auto;
  }
  .col-sm-pull-9 {
    left: 75%;
    right: auto;
  }
  .col-sm-pull-8 {
    left: 66.66666667%;
    right: auto;
  }
  .col-sm-pull-7 {
    left: 58.33333333%;
    right: auto;
  }
  .col-sm-pull-6 {
    left: 50%;
    right: auto;
  }
  .col-sm-pull-5 {
    left: 41.66666667%;
    right: auto;
  }
  .col-sm-pull-4 {
    left: 33.33333333%;
    right: auto;
  }
  .col-sm-pull-3 {
    left: 25%;
    right: auto;
  }
  .col-sm-pull-2 {
    left: 16.66666667%;
    right: auto;
  }
  .col-sm-pull-1 {
    left: 8.33333333%;
    right: auto;
  }
  .col-sm-pull-0 {
    left: auto;
    right: auto;
  }
  .col-sm-push-12 {
    right: 100%;
    left: 0;
  }
  .col-sm-push-11 {
    right: 91.66666667%;
    left: 0;
  }
  .col-sm-push-10 {
    right: 83.33333333%;
    left: 0;
  }
  .col-sm-push-9 {
    right: 75%;
    left: 0;
  }
  .col-sm-push-8 {
    right: 66.66666667%;
    left: 0;
  }
  .col-sm-push-7 {
    right: 58.33333333%;
    left: 0;
  }
  .col-sm-push-6 {
    right: 50%;
    left: 0;
  }
  .col-sm-push-5 {
    right: 41.66666667%;
    left: 0;
  }
  .col-sm-push-4 {
    right: 33.33333333%;
    left: 0;
  }
  .col-sm-push-3 {
    right: 25%;
    left: 0;
  }
  .col-sm-push-2 {
    right: 16.66666667%;
    left: 0;
  }
  .col-sm-push-1 {
    right: 8.33333333%;
    left: 0;
  }
  .col-sm-push-0 {
    right: auto;
    left: 0;
  }
  .col-sm-offset-12 {
    margin-right: 100%;
    margin-left: 0;
  }
  .col-sm-offset-11 {
    margin-right: 91.66666667%;
    margin-left: 0;
  }
  .col-sm-offset-10 {
    margin-right: 83.33333333%;
    margin-left: 0;
  }
  .col-sm-offset-9 {
    margin-right: 75%;
    margin-left: 0;
  }
  .col-sm-offset-8 {
    margin-right: 66.66666667%;
    margin-left: 0;
  }
  .col-sm-offset-7 {
    margin-right: 58.33333333%;
    margin-left: 0;
  }
  .col-sm-offset-6 {
    margin-right: 50%;
    margin-left: 0;
  }
  .col-sm-offset-5 {
    margin-right: 41.66666667%;
    margin-left: 0;
  }
  .col-sm-offset-4 {
    margin-right: 33.33333333%;
    margin-left: 0;
  }
  .col-sm-offset-3 {
    margin-right: 25%;
    margin-left: 0;
  }
  .col-sm-offset-2 {
    margin-right: 16.66666667%;
    margin-left: 0;
  }
  .col-sm-offset-1 {
    margin-right: 8.33333333%;
    margin-left: 0;
  }
  .col-sm-offset-0 {
    margin-right: 0%;
    margin-left: 0;
  }
}
@media (min-width: 992px) {
  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
    float: right;
  }
  .col-md-12 {
    width: 100%;
  }
  .col-md-11 {
    width: 91.66666667%;
  }
  .col-md-10 {
    width: 83.33333333%;
  }
  .col-md-9 {
    width: 75%;
  }
  .col-md-8 {
    width: 66.66666667%;
  }
  .col-md-7 {
    width: 58.33333333%;
  }
  .col-md-6 {
    width: 50%;
  }
  .col-md-5 {
    width: 41.66666667%;
  }
  .col-md-4 {
    width: 33.33333333%;
  }
  .col-md-3 {
    width: 25%;
  }
  .col-md-2 {
    width: 16.66666667%;
  }
  .col-md-1 {
    width: 8.33333333%;
  }
  .col-md-pull-12 {
    left: 100%;
    right: auto;
  }
  .col-md-pull-11 {
    left: 91.66666667%;
    right: auto;
  }
  .col-md-pull-10 {
    left: 83.33333333%;
    right: auto;
  }
  .col-md-pull-9 {
    left: 75%;
    right: auto;
  }
  .col-md-pull-8 {
    left: 66.66666667%;
    right: auto;
  }
  .col-md-pull-7 {
    left: 58.33333333%;
    right: auto;
  }
  .col-md-pull-6 {
    left: 50%;
    right: auto;
  }
  .col-md-pull-5 {
    left: 41.66666667%;
    right: auto;
  }
  .col-md-pull-4 {
    left: 33.33333333%;
    right: auto;
  }
  .col-md-pull-3 {
    left: 25%;
    right: auto;
  }
  .col-md-pull-2 {
    left: 16.66666667%;
    right: auto;
  }
  .col-md-pull-1 {
    left: 8.33333333%;
    right: auto;
  }
  .col-md-pull-0 {
    left: auto;
    right: auto;
  }
  .col-md-push-12 {
    right: 100%;
    left: 0;
  }
  .col-md-push-11 {
    right: 91.66666667%;
    left: 0;
  }
  .col-md-push-10 {
    right: 83.33333333%;
    left: 0;
  }
  .col-md-push-9 {
    right: 75%;
    left: 0;
  }
  .col-md-push-8 {
    right: 66.66666667%;
    left: 0;
  }
  .col-md-push-7 {
    right: 58.33333333%;
    left: 0;
  }
  .col-md-push-6 {
    right: 50%;
    left: 0;
  }
  .col-md-push-5 {
    right: 41.66666667%;
    left: 0;
  }
  .col-md-push-4 {
    right: 33.33333333%;
    left: 0;
  }
  .col-md-push-3 {
    right: 25%;
    left: 0;
  }
  .col-md-push-2 {
    right: 16.66666667%;
    left: 0;
  }
  .col-md-push-1 {
    right: 8.33333333%;
    left: 0;
  }
  .col-md-push-0 {
    right: auto;
    left: 0;
  }
  .col-md-offset-12 {
    margin-right: 100%;
    margin-left: 0;
  }
  .col-md-offset-11 {
    margin-right: 91.66666667%;
    margin-left: 0;
  }
  .col-md-offset-10 {
    margin-right: 83.33333333%;
    margin-left: 0;
  }
  .col-md-offset-9 {
    margin-right: 75%;
    margin-left: 0;
  }
  .col-md-offset-8 {
    margin-right: 66.66666667%;
    margin-left: 0;
  }
  .col-md-offset-7 {
    margin-right: 58.33333333%;
    margin-left: 0;
  }
  .col-md-offset-6 {
    margin-right: 50%;
    margin-left: 0;
  }
  .col-md-offset-5 {
    margin-right: 41.66666667%;
    margin-left: 0;
  }
  .col-md-offset-4 {
    margin-right: 33.33333333%;
    margin-left: 0;
  }
  .col-md-offset-3 {
    margin-right: 25%;
    margin-left: 0;
  }
  .col-md-offset-2 {
    margin-right: 16.66666667%;
    margin-left: 0;
  }
  .col-md-offset-1 {
    margin-right: 8.33333333%;
    margin-left: 0;
  }
  .col-md-offset-0 {
    margin-right: 0%;
    margin-left: 0;
  }
}
@media (min-width: 1200px) {
  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
    float: right;
  }
  .col-lg-12 {
    width: 100%;
  }
  .col-lg-11 {
    width: 91.66666667%;
  }
  .col-lg-10 {
    width: 83.33333333%;
  }
  .col-lg-9 {
    width: 75%;
  }
  .col-lg-8 {
    width: 66.66666667%;
  }
  .col-lg-7 {
    width: 58.33333333%;
  }
  .col-lg-6 {
    width: 50%;
  }
  .col-lg-5 {
    width: 41.66666667%;
  }
  .col-lg-4 {
    width: 33.33333333%;
  }
  .col-lg-3 {
    width: 25%;
  }
  .col-lg-2 {
    width: 16.66666667%;
  }
  .col-lg-1 {
    width: 8.33333333%;
  }
  .col-lg-pull-12 {
    left: 100%;
    right: auto;
  }
  .col-lg-pull-11 {
    left: 91.66666667%;
    right: auto;
  }
  .col-lg-pull-10 {
    left: 83.33333333%;
    right: auto;
  }
  .col-lg-pull-9 {
    left: 75%;
    right: auto;
  }
  .col-lg-pull-8 {
    left: 66.66666667%;
    right: auto;
  }
  .col-lg-pull-7 {
    left: 58.33333333%;
    right: auto;
  }
  .col-lg-pull-6 {
    left: 50%;
    right: auto;
  }
  .col-lg-pull-5 {
    left: 41.66666667%;
    right: auto;
  }
  .col-lg-pull-4 {
    left: 33.33333333%;
    right: auto;
  }
  .col-lg-pull-3 {
    left: 25%;
    right: auto;
  }
  .col-lg-pull-2 {
    left: 16.66666667%;
    right: auto;
  }
  .col-lg-pull-1 {
    left: 8.33333333%;
    right: auto;
  }
  .col-lg-pull-0 {
    left: auto;
    right: auto;
  }
  .col-lg-push-12 {
    right: 100%;
    left: 0;
  }
  .col-lg-push-11 {
    right: 91.66666667%;
    left: 0;
  }
  .col-lg-push-10 {
    right: 83.33333333%;
    left: 0;
  }
  .col-lg-push-9 {
    right: 75%;
    left: 0;
  }
  .col-lg-push-8 {
    right: 66.66666667%;
    left: 0;
  }
  .col-lg-push-7 {
    right: 58.33333333%;
    left: 0;
  }
  .col-lg-push-6 {
    right: 50%;
    left: 0;
  }
  .col-lg-push-5 {
    right: 41.66666667%;
    left: 0;
  }
  .col-lg-push-4 {
    right: 33.33333333%;
    left: 0;
  }
  .col-lg-push-3 {
    right: 25%;
    left: 0;
  }
  .col-lg-push-2 {
    right: 16.66666667%;
    left: 0;
  }
  .col-lg-push-1 {
    right: 8.33333333%;
    left: 0;
  }
  .col-lg-push-0 {
    right: auto;
    left: 0;
  }
  .col-lg-offset-12 {
    margin-right: 100%;
    margin-left: 0;
  }
  .col-lg-offset-11 {
    margin-right: 91.66666667%;
    margin-left: 0;
  }
  .col-lg-offset-10 {
    margin-right: 83.33333333%;
    margin-left: 0;
  }
  .col-lg-offset-9 {
    margin-right: 75%;
    margin-left: 0;
  }
  .col-lg-offset-8 {
    margin-right: 66.66666667%;
    margin-left: 0;
  }
  .col-lg-offset-7 {
    margin-right: 58.33333333%;
    margin-left: 0;
  }
  .col-lg-offset-6 {
    margin-right: 50%;
    margin-left: 0;
  }
  .col-lg-offset-5 {
    margin-right: 41.66666667%;
    margin-left: 0;
  }
  .col-lg-offset-4 {
    margin-right: 33.33333333%;
    margin-left: 0;
  }
  .col-lg-offset-3 {
    margin-right: 25%;
    margin-left: 0;
  }
  .col-lg-offset-2 {
    margin-right: 16.66666667%;
    margin-left: 0;
  }
  .col-lg-offset-1 {
    margin-right: 8.33333333%;
    margin-left: 0;
  }
  .col-lg-offset-0 {
    margin-right: 0%;
    margin-left: 0;
  }
}
caption {
  text-align: right;
}
th {
  text-align: right;
}
@media screen and (max-width: 767px) {
  .table-responsive > .table-bordered {
    border: 0;
  }
  .table-responsive > .table-bordered > thead > tr > th:first-child,
  .table-responsive > .table-bordered > tbody > tr > th:first-child,
  .table-responsive > .table-bordered > tfoot > tr > th:first-child,
  .table-responsive > .table-bordered > thead > tr > td:first-child,
  .table-responsive > .table-bordered > tbody > tr > td:first-child,
  .table-responsive > .table-bordered > tfoot > tr > td:first-child {
    border-right: 0;
    border-left: initial;
  }
  .table-responsive > .table-bordered > thead > tr > th:last-child,
  .table-responsive > .table-bordered > tbody > tr > th:last-child,
  .table-responsive > .table-bordered > tfoot > tr > th:last-child,
  .table-responsive > .table-bordered > thead > tr > td:last-child,
  .table-responsive > .table-bordered > tbody > tr > td:last-child,
  .table-responsive > .table-bordered > tfoot > tr > td:last-child {
    border-left: 0;
    border-right: initial;
  }
}
.radio label,
.checkbox label {
  padding-right: 20px;
  padding-left: initial;
}
.radio input[type="radio"],
.radio-inline input[type="radio"],
.checkbox input[type="checkbox"],
.checkbox-inline input[type="checkbox"] {
  margin-right: -20px;
  margin-left: auto;
}
.radio-inline,
.checkbox-inline {
  padding-right: 20px;
  padding-left: 0;
}
.radio-inline + .radio-inline,
.checkbox-inline + .checkbox-inline {
  margin-right: 10px;
  margin-left: 0;
}
.has-feedback .form-control {
  padding-left: 42.5px;
  padding-right: 12px;
}
.form-control-feedback {
  left: 0;
  right: auto;
}
@media (min-width: 768px) {
  .form-inline label {
    padding-right: 0;
    padding-left: initial;
  }
  .form-inline .radio input[type="radio"],
  .form-inline .checkbox input[type="checkbox"] {
    margin-right: 0;
    margin-left: auto;
  }
}
@media (min-width: 768px) {
  .form-horizontal .control-label {
    text-align: left;
  }
}
.form-horizontal .has-feedback .form-control-feedback {
  left: 15px;
  right: auto;
}
.caret {
  margin-right: 2px;
  margin-left: 0;
}
.dropdown-menu {
  right: 0;
  left: auto;
  float: left;
  text-align: right;
}
.dropdown-menu.pull-right {
  left: 0;
  right: auto;
  float: right;
}
.dropdown-menu-right {
  left: auto;
  right: 0;
}
.dropdown-menu-left {
  left: 0;
  right: auto;
}
@media (min-width: 768px) {
  .navbar-right .dropdown-menu {
    left: auto;
    right: 0;
  }
  .navbar-right .dropdown-menu-left {
    left: 0;
    right: auto;
  }
}
.btn-group > .btn,
.btn-group-vertical > .btn {
  float: right;
}
.btn-group .btn + .btn,
.btn-group .btn + .btn-group,
.btn-group .btn-group + .btn,
.btn-group .btn-group + .btn-group {
  margin-right: -1px;
  margin-left: 0px;
}
.btn-toolbar {
  margin-right: -5px;
  margin-left: 0px;
}
.btn-toolbar .btn-group,
.btn-toolbar .input-group {
  float: right;
}
.btn-toolbar > .btn,
.btn-toolbar > .btn-group,
.btn-toolbar > .input-group {
  margin-right: 5px;
  margin-left: 0px;
}
.btn-group > .btn:first-child {
  margin-right: 0;
}
.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
  border-bottom-left-radius: 0;
  border-top-left-radius: 0;
}
.btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) {
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
}
.btn-group > .btn-group {
  float: right;
}
.btn-group.btn-group-justified > .btn,
.btn-group.btn-group-justified > .btn-group {
  float: none;
}
.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
  border-radius: 0;
}
.btn-group > .btn-group:first-child > .btn:last-child,
.btn-group > .btn-group:first-child > .dropdown-toggle {
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
  border-bottom-left-radius: 0;
  border-top-left-radius: 0;
}
.btn-group > .btn-group:last-child > .btn:first-child {
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
}
.btn .caret {
  margin-right: 0;
}
.btn-group-vertical > .btn + .btn,
.btn-group-vertical > .btn + .btn-group,
.btn-group-vertical > .btn-group + .btn,
.btn-group-vertical > .btn-group + .btn-group {
  margin-top: -1px;
  margin-right: 0;
}
.input-group .form-control {
  float: right;
}
.input-group .form-control:first-child,
.input-group-addon:first-child,
.input-group-btn:first-child > .btn,
.input-group-btn:first-child > .btn-group > .btn,
.input-group-btn:first-child > .dropdown-toggle,
.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
  border-bottom-right-radius: 4px;
  border-top-right-radius: 4px;
  border-bottom-left-radius: 0;
  border-top-left-radius: 0;
}
.input-group-addon:first-child {
  border-right-width: 1px;
  border-right-style: solid;
  border-left: 0px;
}
.input-group .form-control:last-child,
.input-group-addon:last-child,
.input-group-btn:last-child > .btn,
.input-group-btn:last-child > .btn-group > .btn,
.input-group-btn:last-child > .dropdown-toggle,
.input-group-btn:first-child > .btn:not(:first-child),
.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
  border-bottom-left-radius: 4px;
  border-top-left-radius: 4px;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
}
.input-group-addon:last-child {
  border-left-width: 1px;
  border-left-style: solid;
  border-right: 0px;
}
.input-group-btn > .btn + .btn {
  margin-right: -1px;
  margin-left: auto;
}
.input-group-btn:first-child > .btn,
.input-group-btn:first-child > .btn-group {
  margin-left: -1px;
  margin-right: auto;
}
.input-group-btn:last-child > .btn,
.input-group-btn:last-child > .btn-group {
  margin-right: -1px;
  margin-left: auto;
}
.nav {
  padding-right: 0;
  padding-left: initial;
}
.nav-tabs > li {
  float: right;
}
.nav-tabs > li > a {
  margin-left: auto;
  margin-right: -2px;
  border-radius: 4px 4px 0 0;
}
.nav-pills > li {
  float: right;
}
.nav-pills > li > a {
  border-radius: 4px;
}
.nav-pills > li + li {
  margin-right: 2px;
  margin-left: auto;
}
.nav-stacked > li {
  float: none;
}
.nav-stacked > li + li {
  margin-right: 0;
  margin-left: auto;
}
.nav-justified > .dropdown .dropdown-menu {
  right: auto;
}
.nav-tabs-justified > li > a {
  margin-left: 0;
  margin-right: auto;
}
@media (min-width: 768px) {
  .nav-tabs-justified > li > a {
    border-radius: 4px 4px 0 0;
  }
}
@media (min-width: 768px) {
  .navbar-header {
    float: right;
  }
}
.navbar-collapse {
  padding-right: 15px;
  padding-left: 15px;
}
.navbar-brand {
  float: right;
}
@media (min-width: 768px) {
  .navbar > .container .navbar-brand,
  .navbar > .container-fluid .navbar-brand {
    margin-right: -15px;
    margin-left: auto;
  }
}
.navbar-toggle {
  float: left;
  margin-left: 15px;
  margin-right: auto;
}
@media (max-width: 767px) {
  .navbar-nav .open .dropdown-menu > li > a,
  .navbar-nav .open .dropdown-menu .dropdown-header {
    padding: 5px 25px 5px 15px;
  }
}
@media (min-width: 768px) {
  .navbar-nav {
    float: right;
  }
  .navbar-nav > li {
    float: right;
  }
}
@media (min-width: 768px) {
  .navbar-left.flip {
    float: right !important;
  }
  .navbar-right:last-child {
    margin-left: -15px;
    margin-right: auto;
  }
  .navbar-right.flip {
    float: left !important;
    margin-left: -15px;
    margin-right: auto;
  }
  .navbar-right .dropdown-menu {
    left: 0;
    right: auto;
  }
}
@media (min-width: 768px) {
  .navbar-text {
    float: right;
  }
  .navbar-text.navbar-right:last-child {
    margin-left: 0;
    margin-right: auto;
  }
}
.pagination {
  padding-right: 0;
}
.pagination > li > a,
.pagination > li > span {
  float: right;
  margin-right: -1px;
  margin-left: 0px;
}
.pagination > li:first-child > a,
.pagination > li:first-child > span {
  margin-left: 0;
  border-bottom-right-radius: 4px;
  border-top-right-radius: 4px;
  border-bottom-left-radius: 0;
  border-top-left-radius: 0;
}
.pagination > li:last-child > a,
.pagination > li:last-child > span {
  margin-right: -1px;
  border-bottom-left-radius: 4px;
  border-top-left-radius: 4px;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
}
.pager {
  padding-right: 0;
  padding-left: initial;
}
.pager .next > a,
.pager .next > span {
  float: left;
}
.pager .previous > a,
.pager .previous > span {
  float: right;
}
.nav-pills > li > a > .badge {
  margin-left: 0px;
  margin-right: 3px;
}
.list-group-item > .badge {
  float: left;
}
.list-group-item > .badge + .badge {
  margin-left: 5px;
  margin-right: auto;
}
.alert-dismissable,
.alert-dismissible {
  padding-left: 35px;
  padding-right: 15px;
}
.alert-dismissable .close,
.alert-dismissible .close {
  right: auto;
  left: -21px;
}
.progress-bar {
  float: right;
}
.media > .pull-left {
  margin-right: 10px;
}
.media > .pull-left.flip {
  margin-right: 0;
  margin-left: 10px;
}
.media > .pull-right {
  margin-left: 10px;
}
.media > .pull-right.flip {
  margin-left: 0;
  margin-right: 10px;
}
.media-right,
.media > .pull-right {
  padding-right: 10px;
  padding-left: initial;
}
.media-left,
.media > .pull-left {
  padding-left: 10px;
  padding-right: initial;
}
.media-list {
  padding-right: 0;
  padding-left: initial;
  list-style: none;
}
.list-group {
  padding-right: 0;
  padding-left: initial;
}
.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
  border-top-right-radius: 3px;
  border-top-left-radius: 0;
}
.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
  border-top-left-radius: 3px;
  border-top-right-radius: 0;
}
.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
  border-bottom-left-radius: 3px;
  border-top-right-radius: 0;
}
.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
  border-bottom-right-radius: 3px;
  border-top-left-radius: 0;
}
.panel > .table-bordered > thead > tr > th:first-child,
.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
.panel > .table-bordered > tbody > tr > th:first-child,
.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
.panel > .table-bordered > tfoot > tr > th:first-child,
.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
.panel > .table-bordered > thead > tr > td:first-child,
.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
.panel > .table-bordered > tbody > tr > td:first-child,
.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
.panel > .table-bordered > tfoot > tr > td:first-child,
.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
  border-right: 0;
  border-left: none;
}
.panel > .table-bordered > thead > tr > th:last-child,
.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
.panel > .table-bordered > tbody > tr > th:last-child,
.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
.panel > .table-bordered > tfoot > tr > th:last-child,
.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
.panel > .table-bordered > thead > tr > td:last-child,
.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
.panel > .table-bordered > tbody > tr > td:last-child,
.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
.panel > .table-bordered > tfoot > tr > td:last-child,
.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
  border-right: none;
  border-left: 0;
}
.embed-responsive .embed-responsive-item,
.embed-responsive iframe,
.embed-responsive embed,
.embed-responsive object {
  right: 0;
  left: auto;
}
.close {
  float: left;
}
.modal-footer {
  text-align: left;
}
.modal-footer .btn + .btn {
  margin-left: auto;
  margin-right: 5px;
}
.modal-footer .btn-group .btn + .btn {
  margin-right: -1px;
  margin-left: auto;
}
.modal-footer .btn-block + .btn-block {
  margin-right: 0;
  margin-left: auto;
}
.popover {
  left: auto;
  text-align: right;
}
.popover.top > .arrow {
  right: 50%;
  left: auto;
  margin-right: -11px;
  margin-left: auto;
}
.popover.top > .arrow:after {
  margin-right: -10px;
  margin-left: auto;
}
.popover.bottom > .arrow {
  right: 50%;
  left: auto;
  margin-right: -11px;
  margin-left: auto;
}
.popover.bottom > .arrow:after {
  margin-right: -10px;
  margin-left: auto;
}
.carousel-control {
  right: 0;
  bottom: 0;
}
.carousel-control.left {
  right: auto;
  left: 0;
  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0%), color-stop(rgba(0, 0, 0, 0.0001) 100%));
  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
}
.carousel-control.right {
  left: auto;
  right: 0;
  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0%), color-stop(rgba(0, 0, 0, 0.5) 100%));
  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
}
.carousel-control .icon-prev,
.carousel-control .glyphicon-chevron-left {
  left: 50%;
  right: auto;
  margin-right: -10px;
}
.carousel-control .icon-next,
.carousel-control .glyphicon-chevron-right {
  right: 50%;
  left: auto;
  margin-left: -10px;
}
.carousel-indicators {
  right: 50%;
  left: 0;
  margin-right: -30%;
  margin-left: 0;
  padding-left: 0;
}
@media screen and (min-width: 768px) {
  .carousel-control .glyphicon-chevron-left,
  .carousel-control .icon-prev {
    margin-left: 0;
    margin-right: -15px;
  }
  .carousel-control .glyphicon-chevron-right,
  .carousel-control .icon-next {
    margin-left: 0;
    margin-right: -15px;
  }
  .carousel-caption {
    left: 20%;
    right: 20%;
    padding-bottom: 30px;
  }
}
.pull-right.flip {
  float: left !important;
}
.pull-left.flip {
  float: right !important;
}
/*# sourceMappingURL=bootstrap-rtl.css.map */
Diff truncated after the above file
driver/guns-admin/src/main/webapp/static/css/bootstrap.min.css driver/guns-admin/src/main/webapp/static/css/font-awesome.css driver/guns-admin/src/main/webapp/static/css/font-awesome.min.css driver/guns-admin/src/main/webapp/static/css/login.css driver/guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-1.png driver/guns-admin/src/main/webapp/static/css/patterns/header-profile-skin-3.png driver/guns-admin/src/main/webapp/static/css/patterns/header-profile.png driver/guns-admin/src/main/webapp/static/css/patterns/shattered.png driver/guns-admin/src/main/webapp/static/css/plugins/bootstrap-table/bootstrap-table.min.css driver/guns-admin/src/main/webapp/static/css/plugins/bootstrap-treetable/bootstrap-treetable.css driver/guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite.png driver/guns-admin/src/main/webapp/static/css/plugins/chosen/chosen-sprite@2x.png driver/guns-admin/src/main/webapp/static/css/plugins/chosen/chosen.css driver/guns-admin/src/main/webapp/static/css/plugins/iCheck/custom.css driver/guns-admin/src/main/webapp/static/css/plugins/iCheck/green.png driver/guns-admin/src/main/webapp/static/css/plugins/iCheck/green@2x.png driver/guns-admin/src/main/webapp/static/css/plugins/images/sprite-skin-flat.png driver/guns-admin/src/main/webapp/static/css/plugins/validate/bootstrapValidator.min.css driver/guns-admin/src/main/webapp/static/css/plugins/webuploader/webuploader.css driver/guns-admin/src/main/webapp/static/css/plugins/ztree/demo.css driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_close.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/1_open.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/2.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/3.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/4.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/5.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/6.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/7.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/8.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/diy/9.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/line_conn.gif driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/loading.gif driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.gif driver/guns-admin/src/main/webapp/static/css/plugins/ztree/img/zTreeStandard.png driver/guns-admin/src/main/webapp/static/css/plugins/ztree/zTreeStyle.css driver/guns-admin/src/main/webapp/static/css/style.css driver/guns-admin/src/main/webapp/static/favicon.ico driver/guns-admin/src/main/webapp/static/fonts/FontAwesome.otf driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.eot driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.svg driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.ttf driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff driver/guns-admin/src/main/webapp/static/fonts/fontawesome-webfont.woff2 driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.eot driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.svg driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.ttf driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff driver/guns-admin/src/main/webapp/static/fonts/glyphicons-halflings-regular.woff2 driver/guns-admin/src/main/webapp/static/img/bg.png driver/guns-admin/src/main/webapp/static/img/boy.gif driver/guns-admin/src/main/webapp/static/img/girl.gif driver/guns-admin/src/main/webapp/static/img/icons.png driver/guns-admin/src/main/webapp/static/img/loading-upload.gif driver/guns-admin/src/main/webapp/static/img/locked.png driver/guns-admin/src/main/webapp/static/img/user.png driver/guns-admin/src/main/webapp/static/js/bootstrap.min.js driver/guns-admin/src/main/webapp/static/js/common/DateUtils.js driver/guns-admin/src/main/webapp/static/js/common/Feng.js driver/guns-admin/src/main/webapp/static/js/common/ajax-object.js driver/guns-admin/src/main/webapp/static/js/common/bootstrap-table-object.js driver/guns-admin/src/main/webapp/static/js/common/select-list-object.js driver/guns-admin/src/main/webapp/static/js/common/tree-table-object.js driver/guns-admin/src/main/webapp/static/js/common/web-upload-object.js driver/guns-admin/src/main/webapp/static/js/common/ztree-object.js driver/guns-admin/src/main/webapp/static/js/contabs.js driver/guns-admin/src/main/webapp/static/js/content.js driver/guns-admin/src/main/webapp/static/js/hplus.js driver/guns-admin/src/main/webapp/static/js/jquery.min.js driver/guns-admin/src/main/webapp/static/js/jquery.min.map driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/bootstrap-table.min.js driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js driver/guns-admin/src/main/webapp/static/js/plugins/bootstrap-treetable/bootstrap-treetable.js driver/guns-admin/src/main/webapp/static/js/plugins/chosen/chosen.jquery.js driver/guns-admin/src/main/webapp/static/js/plugins/iCheck/icheck.min.js driver/guns-admin/src/main/webapp/static/js/plugins/laydate/laydate.js driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.eot driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.svg driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.ttf driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/font/iconfont.woff driver/guns-admin/src/main/webapp/static/js/plugins/laydate/theme/default/laydate.css driver/guns-admin/src/main/webapp/static/js/plugins/layer/layer.js driver/guns-admin/src/main/webapp/static/js/plugins/layer/mobile/layer.js driver/guns-admin/src/main/webapp/static/js/plugins/layer/mobile/need/layer.css driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon-ext.png driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/icon.png driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/layer.css driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-0.gif driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-1.gif driver/guns-admin/src/main/webapp/static/js/plugins/layer/theme/default/loading-2.gif driver/guns-admin/src/main/webapp/static/js/plugins/metisMenu/jquery.metisMenu.js driver/guns-admin/src/main/webapp/static/js/plugins/pace/pace.min.js driver/guns-admin/src/main/webapp/static/js/plugins/slimscroll/jquery.slimscroll.min.js driver/guns-admin/src/main/webapp/static/js/plugins/validate/additional-methods.min.js driver/guns-admin/src/main/webapp/static/js/plugins/validate/bootstrapValidator.min.js driver/guns-admin/src/main/webapp/static/js/plugins/validate/zh_CN.js driver/guns-admin/src/main/webapp/static/js/plugins/wangEditor/wangEditor.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/Uploader.swf driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.css driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.custom.min.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.fis.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.flashonly.min.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.html5only.min.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.min.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.noimage.min.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.nolog.min.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.js driver/guns-admin/src/main/webapp/static/js/plugins/webuploader/webuploader.withoutimage.min.js driver/guns-admin/src/main/webapp/static/js/plugins/ztree/jquery.ztree.all.min.js driver/guns-admin/src/main/webapp/static/modular/code/gen.js driver/guns-admin/src/main/webapp/static/modular/flowable/expense/expense.js driver/guns-admin/src/main/webapp/static/modular/flowable/expense/expense_info.js driver/guns-admin/src/main/webapp/static/modular/flowable/process/process.js driver/guns-admin/src/main/webapp/static/modular/flowable/process/process_info.js driver/guns-admin/src/main/webapp/static/modular/system/code/code.js driver/guns-admin/src/main/webapp/static/modular/system/dept/dept.js driver/guns-admin/src/main/webapp/static/modular/system/dept/dept_info.js driver/guns-admin/src/main/webapp/static/modular/system/dict/dict.js driver/guns-admin/src/main/webapp/static/modular/system/dict/dict_info.js driver/guns-admin/src/main/webapp/static/modular/system/log/log.js driver/guns-admin/src/main/webapp/static/modular/system/log/login_log.js driver/guns-admin/src/main/webapp/static/modular/system/menu/menu.js driver/guns-admin/src/main/webapp/static/modular/system/menu/menu_info.js driver/guns-admin/src/main/webapp/static/modular/system/notice/notice.js driver/guns-admin/src/main/webapp/static/modular/system/notice/notice_info.js driver/guns-admin/src/main/webapp/static/modular/system/role/role.js driver/guns-admin/src/main/webapp/static/modular/system/role/role_info.js driver/guns-admin/src/main/webapp/static/modular/system/user/user.js driver/guns-admin/src/main/webapp/static/modular/system/user/user_info.js driver/guns-core/pom.xml driver/guns-core/src/main/java/com/supersavedriving/driver/core/CoreFlag.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/aop/BaseControllerExceptionHandler.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/controller/BaseController.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/controller/GlobalController.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/controller/GunsErrorView.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/tips/ErrorTip.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/tips/SuccessTip.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/tips/Tip.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/base/warpper/BaseControllerWarpper.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/BaseCacheFactory.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/CacheKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/EhcacheFactory.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/ICache.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/cache/ILoader.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultFastjsonConfig.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultMultiConfig.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultProperties.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/DefaultWebConfig.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/properties/DruidProperties.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/config/properties/MutiDataSourceProperties.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/constant/IsMenu.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/datascope/DataScope.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/datascope/DataScopeInterceptor.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/db/Db.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/exception/GunsException.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/exception/GunsExceptionEnum.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/exception/ServiceExceptionEnum.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/DataSourceContextHolder.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/DynamicDataSource.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/annotion/DataSource.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/mutidatasource/aop/MultiSourceExAop.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/node/MenuNode.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/node/ZTreeNode.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/page/PageBT.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/page/PageInfoBT.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/ImgQrTool.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/MatrixToImageConfig.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/MatrixToImageWriter.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/qr/QrImage.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/BasicType.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/BeanKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/ClassKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/CollectionKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/DateTime.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/DateTimeKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/HexKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/HttpKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/ObjectKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/PageKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/StrKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/WafKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/WafRequestWrapper.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/support/exception/ToolBoxException.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/Convert.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/DateUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/FileUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/HttpSessionHolder.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/IdGenerator.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/MD5Util.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/NumUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/PingYinUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/RenderUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/ResKit.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/SimpleContrast.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/SpringContextHolder.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/SqlUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/util/ToolUtil.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/xss/XssFilter.java driver/guns-core/src/main/java/com/supersavedriving/driver/core/xss/XssHttpServletRequestWrapper.java driver/guns-core/src/main/resources/META-INF/spring.factories driver/guns-core/src/main/resources/default-config.properties driver/guns-generator/pom.xml driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/GunsCodeGenerator.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/config/AbstractGeneratorConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/config/GunsGeneratorConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/config/WebGeneratorConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/action/model/GenQo.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/SimpleTemplateEngine.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/base/AbstractTemplateEngine.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/base/GunsTemplateEngine.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/ContextConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/ControllerConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/DaoConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/Menu.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/PageConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/ServiceConfig.java driver/guns-generator/src/main/java/com/supersavedriving/driver/generator/engine/config/SqlConfig.java driver/guns-generator/src/main/resources/gunsTemplate/advanced/Controller.java.btl driver/guns-generator/src/main/resources/gunsTemplate/advanced/menu_sql.sql.btl driver/guns-generator/src/main/resources/gunsTemplate/advanced/page.html.btl driver/guns-generator/src/main/resources/gunsTemplate/advanced/page.js.btl driver/guns-generator/src/main/resources/gunsTemplate/advanced/page_add.html.btl driver/guns-generator/src/main/resources/gunsTemplate/advanced/page_edit.html.btl driver/guns-generator/src/main/resources/gunsTemplate/advanced/page_info.js.btl driver/pom.xml