From 90c71c40e1a2e62035446f30ef76dd01510e3bb5 Mon Sep 17 00:00:00 2001 From: Yen Date: Mon, 19 Sep 2022 17:19:42 +0800 Subject: [PATCH] init framework --- .gitignore | 8 + pom.xml | 223 +++++++++++ src/main/java/com/qs/serve/Application.java | 51 +++ .../CustomServletContextInitializer.java | 24 ++ .../common/config/DevEnvironmentConfig.java | 24 ++ .../com/qs/serve/common/config/JwtConfig.java | 23 ++ .../qs/serve/common/config/MyBatisConfig.java | 54 +++ .../qs/serve/common/config/RedisConfig.java | 70 ++++ .../serve/common/config/SecurityConfig.java | 64 +++ .../serve/common/config/SpringMvcConfig.java | 68 ++++ .../serve/common/config/ThreadPoolConfig.java | 56 +++ .../config/properties/PermitProperties.java | 32 ++ .../config/properties/RedisProperties.java | 25 ++ .../config/properties/UploadProperties.java | 24 ++ .../common/framework/aop/SysLogAspect.java | 210 ++++++++++ .../framework/exception/BaseException.java | 21 + .../exception/BusinessException.java | 25 ++ .../exception/UnifiedExceptionHandler.java | 118 ++++++ .../interceptor/ApiAuthInterceptor.java | 60 +++ .../interceptor/LimitSubmitInterceptor.java | 66 ++++ .../interceptor/RepeatSubmitInterceptor.java | 98 +++++ .../framework/manager/AsyncFactory.java | 36 ++ .../framework/manager/AsyncManager.java | 52 +++ .../mvc/HttpServletRequestFilter.java | 161 ++++++++ .../mybatis/handler/IdGeneratorHandler.java | 17 + .../mybatis/handler/SysMetaHandler.java | 36 ++ .../mybatis/handler/SysTenantHandler.java | 58 +++ .../handler/meta/JsonStringTypeHandler.java | 50 +++ .../handler/meta/SplitStringTypeHandler.java | 74 ++++ .../framework/mybatis/join/JoinUtil.java | 115 ++++++ .../mybatis/join/annotations/BindEntity.java | 36 ++ .../mybatis/join/enums/JoinType.java | 14 + .../mybatis/join/model/JoinFieldData.java | 17 + .../mybatis/query/AnnotationQueryStorage.java | 159 ++++++++ .../mybatis/query/annotations/QueryWrap.java | 32 ++ .../mybatis/query/model/QueryFieldData.java | 23 ++ .../query/model/QueryFieldDataValue.java | 25 ++ .../mybatis/query/model/QueryType.java | 40 ++ .../common/framework/redis/RedisService.java | 309 +++++++++++++++ .../filter/SecurityRequestFilter.java | 192 +++++++++ .../handler/SecurityAccessDeniedHandler.java | 22 ++ .../SecurityAuthenticationFailureHandler.java | 22 ++ .../handler/SecurityLogoutHandler.java | 36 ++ .../framework/security/model/LoginUser.java | 97 +++++ .../security/model/LoginUserDTO.java | 37 ++ .../security/model/LoginUserType.java | 34 ++ .../service/SysUserDetailsServiceImpl.java | 31 ++ .../security/util/SecurityPermitUtil.java | 28 ++ .../common/model/HttpResponsePrintUtil.java | 34 ++ .../common/model/annotation/LimitSubmit.java | 25 ++ .../common/model/annotation/RepeatSubmit.java | 20 + .../serve/common/model/annotation/SysLog.java | 35 ++ .../serve/common/model/consts/DateConst.java | 10 + .../serve/common/model/consts/GySysConst.java | 40 ++ .../serve/common/model/consts/OssConst.java | 32 ++ .../common/model/consts/RedisCacheKeys.java | 30 ++ .../model/consts/RedisListenerKeys.java | 12 + .../com/qs/serve/common/model/dto/PageVo.java | 46 +++ .../java/com/qs/serve/common/model/dto/R.java | 173 +++++++++ .../common/model/dto/SimpleKeyValue.java | 23 ++ .../qs/serve/common/model/dto/TreeNode.java | 30 ++ .../qs/serve/common/model/enums/BizType.java | 49 +++ .../common/model/enums/ExcelFilePath.java | 19 + .../qs/serve/common/model/enums/HttpCode.java | 44 +++ .../serve/common/model/enums/InterType.java | 21 + .../serve/common/model/enums/PolicyType.java | 35 ++ .../common/model/enums/SystemModule.java | 22 ++ .../serve/common/model/group/EditGroup.java | 8 + .../serve/common/model/group/SaveGroup.java | 8 + .../serve/common/model/group/SearchGroup.java | 8 + .../common/service/RedisBaseListenerImpl.java | 26 ++ .../common/service/RedisServiceListener.java | 33 ++ .../java/com/qs/serve/common/util/Assert.java | 28 ++ .../serve/common/util/AuthContextUtils.java | 109 ++++++ .../qs/serve/common/util/CollectionUtil.java | 90 +++++ .../com/qs/serve/common/util/CopierUtil.java | 95 +++++ .../com/qs/serve/common/util/DateUtils.java | 98 +++++ .../java/com/qs/serve/common/util/IdUtil.java | 51 +++ .../com/qs/serve/common/util/JsonUtil.java | 99 +++++ .../com/qs/serve/common/util/JwtUtils.java | 82 ++++ .../com/qs/serve/common/util/MinioUtil.java | 84 ++++ .../com/qs/serve/common/util/NanoIdUtils.java | 60 +++ .../com/qs/serve/common/util/PageUtil.java | 169 ++++++++ .../qs/serve/common/util/ServletUtils.java | 129 +++++++ .../qs/serve/common/util/SmsReflectUtil.java | 50 +++ .../com/qs/serve/common/util/SpringUtils.java | 148 +++++++ .../com/qs/serve/common/util/StringUtils.java | 50 +++ .../qs/serve/common/util/ThreadsUtils.java | 75 ++++ .../com/qs/serve/common/util/TokenUtil.java | 46 +++ .../com/qs/serve/common/util/TreeUtil.java | 74 ++++ .../com/qs/serve/common/util/UploadUtil.java | 53 +++ .../com/qs/serve/common/util/WarpUtil.java | 62 +++ .../com/qs/serve/common/util/WordUtil.java | 109 ++++++ .../common/util/model/DateFormatString.java | 24 ++ .../qs/serve/common/util/model/DesUtils.java | 125 ++++++ .../controller/AdminPortalController.java | 138 +++++++ .../com/qs/serve/controller/CommonApi.java | 26 ++ .../qs/serve/controller/CommonController.java | 103 +++++ .../qs/serve/controller/WxMpPortalApi.java | 129 +++++++ .../qs/serve/controller/WxSvcLoginApi.java | 97 +++++ .../serve/controller/dto/CounterResultVo.java | 27 ++ .../com/qs/serve/modules/package-info.java | 11 + .../qms/controller/QmsCategoryController.java | 116 ++++++ .../qms/controller/QmsFormController.java | 111 ++++++ .../controller/QmsFormSubmitController.java | 105 +++++ .../qms/controller/QmsGroupController.java | 209 ++++++++++ .../controller/api/QmsDraftApiController.java | 69 ++++ .../api/QmsSubmitApiController.java | 147 +++++++ .../serve/modules/qms/entity/QmsCategory.java | 68 ++++ .../qs/serve/modules/qms/entity/QmsDraft.java | 81 ++++ .../qs/serve/modules/qms/entity/QmsForm.java | 85 ++++ .../modules/qms/entity/QmsFormSubmit.java | 104 +++++ .../qs/serve/modules/qms/entity/QmsGroup.java | 115 ++++++ .../modules/qms/entity/QmsGroupScope.java | 45 +++ .../modules/qms/entity/bo/QmsDraftBo.java | 25 ++ .../modules/qms/entity/bo/QmsFormBo.java | 40 ++ .../modules/qms/entity/bo/QmsGroupBo.java | 38 ++ .../modules/qms/entity/bo/QmsSubmitBo.java | 30 ++ .../modules/qms/entity/vo/QmsDraftVo.java | 41 ++ .../modules/qms/mapper/QmsCategoryMapper.java | 14 + .../modules/qms/mapper/QmsDraftMapper.java | 14 + .../modules/qms/mapper/QmsFormMapper.java | 14 + .../qms/mapper/QmsFormSubmitMapper.java | 14 + .../modules/qms/mapper/QmsGroupMapper.java | 26 ++ .../qms/mapper/QmsGroupScopeMapper.java | 14 + .../qms/service/QmsCategoryService.java | 14 + .../modules/qms/service/QmsDraftService.java | 16 + .../modules/qms/service/QmsFormService.java | 14 + .../qms/service/QmsFormSubmitService.java | 21 + .../qms/service/QmsGroupScopeService.java | 23 ++ .../modules/qms/service/QmsGroupService.java | 14 + .../service/impl/QmsCategoryServiceImpl.java | 22 ++ .../qms/service/impl/QmsDraftServiceImpl.java | 32 ++ .../qms/service/impl/QmsFormServiceImpl.java | 22 ++ .../impl/QmsFormSubmitServiceImpl.java | 80 ++++ .../impl/QmsGroupScopeServiceImpl.java | 87 +++++ .../qms/service/impl/QmsGroupServiceImpl.java | 22 ++ .../sys/common/consts/SysStatusConst.java | 23 ++ .../sys/controller/SysAttachController.java | 115 ++++++ .../sys/controller/SysDeptController.java | 193 ++++++++++ .../sys/controller/SysDictController.java | 48 +++ .../sys/controller/SysMenuController.java | 188 +++++++++ .../sys/controller/SysNoticeController.java | 220 +++++++++++ .../controller/SysNoticeTypeController.java | 109 ++++++ .../controller/SysNoticeUserController.java | 75 ++++ .../controller/SysOperationLogController.java | 82 ++++ .../sys/controller/SysPermitController.java | 86 +++++ .../sys/controller/SysPostController.java | 124 ++++++ .../sys/controller/SysRoleController.java | 224 +++++++++++ .../sys/controller/SysTenantController.java | 98 +++++ .../sys/controller/SysUserController.java | 364 ++++++++++++++++++ .../serve/modules/sys/entity/SysAttach.java | 68 ++++ .../qs/serve/modules/sys/entity/SysDept.java | 80 ++++ .../qs/serve/modules/sys/entity/SysDict.java | 80 ++++ .../qs/serve/modules/sys/entity/SysMenu.java | 58 +++ .../modules/sys/entity/SysMenuPermit.java | 62 +++ .../serve/modules/sys/entity/SysNotice.java | 140 +++++++ .../modules/sys/entity/SysNoticeType.java | 55 +++ .../modules/sys/entity/SysNoticeUser.java | 94 +++++ .../modules/sys/entity/SysOperationLog.java | 116 ++++++ .../serve/modules/sys/entity/SysPermit.java | 55 +++ .../qs/serve/modules/sys/entity/SysPost.java | 71 ++++ .../qs/serve/modules/sys/entity/SysRole.java | 75 ++++ .../serve/modules/sys/entity/SysRoleMenu.java | 62 +++ .../serve/modules/sys/entity/SysTenant.java | 59 +++ .../qs/serve/modules/sys/entity/SysUser.java | 305 +++++++++++++++ .../serve/modules/sys/entity/SysUserRole.java | 57 +++ .../modules/sys/entity/SysUserTenant.java | 103 +++++ .../sys/entity/dto/SysDeptTranParam.java | 22 ++ .../sys/entity/dto/SysDeptTreeNode.java | 64 +++ .../sys/entity/dto/SysLoginByPhoneParam.java | 31 ++ .../modules/sys/entity/dto/SysLoginParam.java | 31 ++ .../sys/entity/dto/SysMenuPermitParam.java | 18 + .../sys/entity/dto/SysMenuTreeNode.java | 36 ++ .../sys/entity/dto/SysPermitTreeNode.java | 39 ++ .../entity/dto/SysResetPwdByPhoneParam.java | 18 + .../sys/entity/dto/SysRoleMenuParam.java | 25 ++ .../sys/entity/dto/SysRoleUserParam.java | 18 + .../sys/entity/dto/SysUserLeaveParam.java | 26 ++ .../sys/entity/dto/SysUserPwdParam.java | 20 + .../entity/dto/SysUserRewardPunishParam.java | 20 + .../sys/entity/dto/SysUserSimpleVo.java | 36 ++ .../entity/dto/SysUserTenantEditParam.java | 20 + .../sys/entity/dto/SysUserTranPostParam.java | 23 ++ .../modules/sys/entity/dto/SysUserVo.java | 48 +++ .../sys/entity/dto/UserRole4EditParam.java | 20 + .../modules/sys/mapper/SysAttachMapper.java | 14 + .../modules/sys/mapper/SysDeptMapper.java | 22 ++ .../modules/sys/mapper/SysDictMapper.java | 14 + .../modules/sys/mapper/SysMenuMapper.java | 42 ++ .../sys/mapper/SysMenuPermitMapper.java | 14 + .../modules/sys/mapper/SysNoticeMapper.java | 13 + .../sys/mapper/SysNoticeTypeMapper.java | 14 + .../sys/mapper/SysNoticeUserMapper.java | 42 ++ .../sys/mapper/SysOperationLogMapper.java | 23 ++ .../modules/sys/mapper/SysPermitMapper.java | 14 + .../modules/sys/mapper/SysPostMapper.java | 14 + .../modules/sys/mapper/SysRoleMapper.java | 13 + .../modules/sys/mapper/SysRoleMenuMapper.java | 42 ++ .../modules/sys/mapper/SysTenantMapper.java | 14 + .../modules/sys/mapper/SysUserMapper.java | 55 +++ .../modules/sys/mapper/SysUserRoleMapper.java | 15 + .../modules/sys/service/SysAttachService.java | 14 + .../modules/sys/service/SysDeptService.java | 38 ++ .../modules/sys/service/SysDictService.java | 14 + .../sys/service/SysMenuPermitService.java | 20 + .../modules/sys/service/SysMenuService.java | 14 + .../modules/sys/service/SysNoticeService.java | 26 ++ .../sys/service/SysNoticeTypeService.java | 14 + .../sys/service/SysNoticeUserService.java | 18 + .../sys/service/SysOperationLogService.java | 16 + .../modules/sys/service/SysPermitService.java | 22 ++ .../modules/sys/service/SysPostService.java | 14 + .../sys/service/SysRoleMenuService.java | 20 + .../modules/sys/service/SysRoleService.java | 31 ++ .../modules/sys/service/SysTenantService.java | 20 + .../sys/service/SysUserLoginService.java | 28 ++ .../sys/service/SysUserRoleService.java | 28 ++ .../modules/sys/service/SysUserService.java | 42 ++ .../service/impl/SysAttachServiceImpl.java | 22 ++ .../sys/service/impl/SysDeptServiceImpl.java | 68 ++++ .../sys/service/impl/SysDictServiceImpl.java | 22 ++ .../impl/SysMenuPermitServiceImpl.java | 38 ++ .../sys/service/impl/SysMenuServiceImpl.java | 22 ++ .../service/impl/SysNoticeServiceImpl.java | 89 +++++ .../impl/SysNoticeTypeServiceImpl.java | 22 ++ .../impl/SysNoticeUserServiceImpl.java | 31 ++ .../impl/SysOperationLogServiceImpl.java | 22 ++ .../service/impl/SysPermitServiceImpl.java | 30 ++ .../sys/service/impl/SysPostServiceImpl.java | 22 ++ .../service/impl/SysRoleMenuServiceImpl.java | 68 ++++ .../sys/service/impl/SysRoleServiceImpl.java | 94 +++++ .../service/impl/SysTenantServiceImpl.java | 37 ++ .../service/impl/SysUserLoginServiceImpl.java | 110 ++++++ .../service/impl/SysUserRoleServiceImpl.java | 65 ++++ .../sys/service/impl/SysUserServiceImpl.java | 138 +++++++ .../ums/controller/UmsUserController.java | 103 +++++ .../qs/serve/modules/ums/entity/UmsUser.java | 76 ++++ .../serve/modules/ums/entity/UmsWxRelate.java | 42 ++ .../modules/ums/mapper/UmsUserMapper.java | 14 + .../modules/ums/mapper/UmsWxRelateMapper.java | 14 + .../modules/ums/service/UmsUserService.java | 36 ++ .../ums/service/UmsWxRelateService.java | 14 + .../ums/service/impl/UmsUserServiceImpl.java | 61 +++ .../service/impl/UmsWxRelateServiceImpl.java | 22 ++ .../qs/serve/modules/wx/api/WxMpJsapiApi.java | 35 ++ .../qs/serve/modules/wx/api/WxMpMenuApi.java | 187 +++++++++ .../serve/modules/wx/api/WxMpRedirectApi.java | 39 ++ .../qs/serve/modules/wx/api/WxSvcUserApi.java | 87 +++++ .../wx/common/builder/mp/ImageBuilder.java | 23 ++ .../builder/mp/MpXmlMessageBuilder.java | 14 + .../wx/common/builder/mp/TextBuilder.java | 23 ++ .../modules/wx/common/conf/WxMpConfig.java | 129 +++++++ .../wx/common/consts/WxStatusConst.java | 34 ++ .../common/handler/mp/KfSessionHandler.java | 27 ++ .../wx/common/handler/mp/LocationHandler.java | 47 +++ .../wx/common/handler/mp/LogHandler.java | 32 ++ .../wx/common/handler/mp/MenuHandler.java | 37 ++ .../wx/common/handler/mp/MsgHandler.java | 54 +++ .../wx/common/handler/mp/NullHandler.java | 26 ++ .../wx/common/handler/mp/ScanHandler.java | 27 ++ .../handler/mp/StoreCheckNotifyHandler.java | 29 ++ .../common/handler/mp/SubscribeHandler.java | 72 ++++ .../common/handler/mp/UnsubscribeHandler.java | 31 ++ .../modules/wx/common/model/WxSmsProp.java | 19 + .../wx/controller/WxAppController.java | 93 +++++ .../controller/WxTemplateMsgController.java | 93 +++++ .../wx/controller/WxUserController.java | 91 +++++ .../com/qs/serve/modules/wx/entity/WxApp.java | 115 ++++++ .../modules/wx/entity/WxTemplateMsg.java | 73 ++++ .../qs/serve/modules/wx/entity/WxUser.java | 131 +++++++ .../modules/wx/entity/dto/SmsBaseDto.java | 8 + .../modules/wx/entity/dto/WxLoginUser.java | 17 + .../wx/entity/dto/WxPhoneBindParam.java | 20 + .../serve/modules/wx/mapper/WxAppMapper.java | 14 + .../wx/mapper/WxTemplateMsgMapper.java | 14 + .../serve/modules/wx/mapper/WxUserMapper.java | 14 + .../modules/wx/service/WxAppService.java | 14 + .../modules/wx/service/WxPushService.java | 36 ++ .../wx/service/WxTemplateMsgService.java | 22 ++ .../modules/wx/service/WxUserService.java | 36 ++ .../wx/service/impl/WxAppServiceImpl.java | 22 ++ .../wx/service/impl/WxPushServiceImpl.java | 75 ++++ .../impl/WxTemplateMsgServiceImpl.java | 32 ++ .../wx/service/impl/WxUserServiceImpl.java | 118 ++++++ src/main/resources/application-dev.yml | 27 ++ src/main/resources/application.yml | 69 ++++ src/main/resources/banner.txt | 4 + src/main/resources/log4j2.xml | 75 ++++ .../resources/mapper/qms/QmsGroupMapper.xml | 77 ++++ .../resources/mapper/sys/SysDeptMapper.xml | 51 +++ .../resources/mapper/sys/SysMenuMapper.xml | 34 ++ .../mapper/sys/SysNoticeUsermapper.xml | 61 +++ .../mapper/sys/SysOperationLogMapper.xml | 84 ++++ .../resources/mapper/sys/SysUserMapper.xml | 167 ++++++++ 295 files changed, 16902 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/com/qs/serve/Application.java create mode 100644 src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java create mode 100644 src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/JwtConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/MyBatisConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/RedisConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/SecurityConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/SpringMvcConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java create mode 100644 src/main/java/com/qs/serve/common/config/properties/PermitProperties.java create mode 100644 src/main/java/com/qs/serve/common/config/properties/RedisProperties.java create mode 100644 src/main/java/com/qs/serve/common/config/properties/UploadProperties.java create mode 100644 src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java create mode 100644 src/main/java/com/qs/serve/common/framework/exception/BaseException.java create mode 100644 src/main/java/com/qs/serve/common/framework/exception/BusinessException.java create mode 100644 src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/interceptor/ApiAuthInterceptor.java create mode 100644 src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java create mode 100644 src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java create mode 100644 src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java create mode 100644 src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java create mode 100644 src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java create mode 100644 src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java create mode 100644 src/main/java/com/qs/serve/common/framework/redis/RedisService.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java create mode 100644 src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java create mode 100644 src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java create mode 100644 src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java create mode 100644 src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java create mode 100644 src/main/java/com/qs/serve/common/model/annotation/SysLog.java create mode 100644 src/main/java/com/qs/serve/common/model/consts/DateConst.java create mode 100644 src/main/java/com/qs/serve/common/model/consts/GySysConst.java create mode 100644 src/main/java/com/qs/serve/common/model/consts/OssConst.java create mode 100644 src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java create mode 100644 src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java create mode 100644 src/main/java/com/qs/serve/common/model/dto/PageVo.java create mode 100644 src/main/java/com/qs/serve/common/model/dto/R.java create mode 100644 src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java create mode 100644 src/main/java/com/qs/serve/common/model/dto/TreeNode.java create mode 100644 src/main/java/com/qs/serve/common/model/enums/BizType.java create mode 100644 src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java create mode 100644 src/main/java/com/qs/serve/common/model/enums/HttpCode.java create mode 100644 src/main/java/com/qs/serve/common/model/enums/InterType.java create mode 100644 src/main/java/com/qs/serve/common/model/enums/PolicyType.java create mode 100644 src/main/java/com/qs/serve/common/model/enums/SystemModule.java create mode 100644 src/main/java/com/qs/serve/common/model/group/EditGroup.java create mode 100644 src/main/java/com/qs/serve/common/model/group/SaveGroup.java create mode 100644 src/main/java/com/qs/serve/common/model/group/SearchGroup.java create mode 100644 src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java create mode 100644 src/main/java/com/qs/serve/common/service/RedisServiceListener.java create mode 100644 src/main/java/com/qs/serve/common/util/Assert.java create mode 100644 src/main/java/com/qs/serve/common/util/AuthContextUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/CollectionUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/CopierUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/DateUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/IdUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/JsonUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/JwtUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/MinioUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/NanoIdUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/PageUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/ServletUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/SmsReflectUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/SpringUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/StringUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/ThreadsUtils.java create mode 100644 src/main/java/com/qs/serve/common/util/TokenUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/TreeUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/UploadUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/WarpUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/WordUtil.java create mode 100644 src/main/java/com/qs/serve/common/util/model/DateFormatString.java create mode 100644 src/main/java/com/qs/serve/common/util/model/DesUtils.java create mode 100644 src/main/java/com/qs/serve/controller/AdminPortalController.java create mode 100644 src/main/java/com/qs/serve/controller/CommonApi.java create mode 100644 src/main/java/com/qs/serve/controller/CommonController.java create mode 100644 src/main/java/com/qs/serve/controller/WxMpPortalApi.java create mode 100644 src/main/java/com/qs/serve/controller/WxSvcLoginApi.java create mode 100644 src/main/java/com/qs/serve/controller/dto/CounterResultVo.java create mode 100644 src/main/java/com/qs/serve/modules/package-info.java create mode 100644 src/main/java/com/qs/serve/modules/qms/controller/QmsCategoryController.java create mode 100644 src/main/java/com/qs/serve/modules/qms/controller/QmsFormController.java create mode 100644 src/main/java/com/qs/serve/modules/qms/controller/QmsFormSubmitController.java create mode 100644 src/main/java/com/qs/serve/modules/qms/controller/QmsGroupController.java create mode 100644 src/main/java/com/qs/serve/modules/qms/controller/api/QmsDraftApiController.java create mode 100644 src/main/java/com/qs/serve/modules/qms/controller/api/QmsSubmitApiController.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/QmsCategory.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/QmsDraft.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/QmsForm.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/QmsFormSubmit.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/QmsGroup.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/QmsGroupScope.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/bo/QmsDraftBo.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/bo/QmsFormBo.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/bo/QmsGroupBo.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/bo/QmsSubmitBo.java create mode 100644 src/main/java/com/qs/serve/modules/qms/entity/vo/QmsDraftVo.java create mode 100644 src/main/java/com/qs/serve/modules/qms/mapper/QmsCategoryMapper.java create mode 100644 src/main/java/com/qs/serve/modules/qms/mapper/QmsDraftMapper.java create mode 100644 src/main/java/com/qs/serve/modules/qms/mapper/QmsFormMapper.java create mode 100644 src/main/java/com/qs/serve/modules/qms/mapper/QmsFormSubmitMapper.java create mode 100644 src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupMapper.java create mode 100644 src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupScopeMapper.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/QmsCategoryService.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/QmsDraftService.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/QmsFormService.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/QmsFormSubmitService.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/QmsGroupScopeService.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/QmsGroupService.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/impl/QmsCategoryServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/impl/QmsDraftServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormSubmitServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupScopeServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysDept.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysDict.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysPost.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysRole.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysUser.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/SysUserTenant.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java create mode 100644 src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysDictService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysPostService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/SysUserService.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/ums/controller/UmsUserController.java create mode 100644 src/main/java/com/qs/serve/modules/ums/entity/UmsUser.java create mode 100644 src/main/java/com/qs/serve/modules/ums/entity/UmsWxRelate.java create mode 100644 src/main/java/com/qs/serve/modules/ums/mapper/UmsUserMapper.java create mode 100644 src/main/java/com/qs/serve/modules/ums/mapper/UmsWxRelateMapper.java create mode 100644 src/main/java/com/qs/serve/modules/ums/service/UmsUserService.java create mode 100644 src/main/java/com/qs/serve/modules/ums/service/UmsWxRelateService.java create mode 100644 src/main/java/com/qs/serve/modules/ums/service/impl/UmsUserServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/ums/service/impl/UmsWxRelateServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java create mode 100644 src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java create mode 100644 src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java create mode 100644 src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java create mode 100644 src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java create mode 100644 src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java create mode 100644 src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java create mode 100644 src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java create mode 100644 src/main/java/com/qs/serve/modules/wx/entity/WxApp.java create mode 100644 src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java create mode 100644 src/main/java/com/qs/serve/modules/wx/entity/WxUser.java create mode 100644 src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java create mode 100644 src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java create mode 100644 src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java create mode 100644 src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java create mode 100644 src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java create mode 100644 src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/WxAppService.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/WxPushService.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/WxUserService.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java create mode 100644 src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java create mode 100644 src/main/resources/application-dev.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/banner.txt create mode 100644 src/main/resources/log4j2.xml create mode 100644 src/main/resources/mapper/qms/QmsGroupMapper.xml create mode 100644 src/main/resources/mapper/sys/SysDeptMapper.xml create mode 100644 src/main/resources/mapper/sys/SysMenuMapper.xml create mode 100644 src/main/resources/mapper/sys/SysNoticeUsermapper.xml create mode 100644 src/main/resources/mapper/sys/SysOperationLogMapper.xml create mode 100644 src/main/resources/mapper/sys/SysUserMapper.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..013ac695 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.idea/ +logs/ +target/ +gyoa-java.iml +*.http +*.env.json +*.json +/src/test/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..8d5f3954 --- /dev/null +++ b/pom.xml @@ -0,0 +1,223 @@ + + + 4.0.0 + + com.qs + questionnaire + 1.0.0RELEASE + + + org.springframework.boot + spring-boot-starter-parent + 2.6.4 + + + + 2.6.4 + 8 + 8 + 2.3.0 + 5.7.19 + 3.10.3 + 4.5.7 + 3.1 + 1.2.49 + 3.4.1 + true + 4.2.0 + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + org.springframework.boot + spring-boot-starter-undertow + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-validation + + + + com.auth0 + java-jwt + ${jwt.version} + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + com.alibaba + fastjson + ${fastjson.version} + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.1 + + + org.mybatis + mybatis-spring + + + org.mybatis + mybatis + + + com.github.jsqlparser + jsqlparser + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + mysql + mysql-connector-java + 8.0.15 + + + + org.projectlombok + lombok + 1.18.12 + compile + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + + com.github.binarywang + weixin-java-mp + ${wx.java.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + + junit + junit + RELEASE + test + + + + com.github.shalousun + smart-doc + 2.4.0 + test + + + + + + serve + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + + + + + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + false + + + + diff --git a/src/main/java/com/qs/serve/Application.java b/src/main/java/com/qs/serve/Application.java new file mode 100644 index 00000000..a8e4d274 --- /dev/null +++ b/src/main/java/com/qs/serve/Application.java @@ -0,0 +1,51 @@ +package com.qs.serve; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.annotation.PostConstruct; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.util.TimeZone; + +/** + * @author YenHex + * @since 2022/2/24 + */ +@EnableAsync +@EnableScheduling +@EnableTransactionManagement +@EnableCaching +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + public static void main(String[] args) { + DevEnvironmentConfig.openDevEnv(true); + SpringApplication.run(Application.class,args); + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + super.onStartup(servletContext); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder.sources(Application.class); + } + + @PostConstruct + void started() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + } + +} diff --git a/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java b/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java new file mode 100644 index 00000000..26c2074f --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/CustomServletContextInitializer.java @@ -0,0 +1,24 @@ +package com.qs.serve.common.config; + +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.SessionTrackingMode; +import java.util.Collections; + + +/** + * 禁用jsessionid + * @author YenHex + * @since 2022/3/11 + */ +@Configuration +public class CustomServletContextInitializer implements ServletContextInitializer { + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE)); + } +} diff --git a/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java b/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java new file mode 100644 index 00000000..f3fbc14c --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/DevEnvironmentConfig.java @@ -0,0 +1,24 @@ +package com.qs.serve.common.config; + +import lombok.experimental.UtilityClass; + +/** + * @author YenHex + * @since 2022/3/11 + */ +@UtilityClass +public class DevEnvironmentConfig { + + private static Boolean devEnv = null; + public static void openDevEnv(Boolean open){ + if(devEnv==null){devEnv = open;} + } + + + public static boolean isDev(){ + if(devEnv==null){ + return false; + } + return devEnv; + } +} diff --git a/src/main/java/com/qs/serve/common/config/JwtConfig.java b/src/main/java/com/qs/serve/common/config/JwtConfig.java new file mode 100644 index 00000000..e33b28a3 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/JwtConfig.java @@ -0,0 +1,23 @@ +package com.qs.serve.common.config; + + +import lombok.Getter; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +public class JwtConfig { + + /** + * 单位分钟 + */ + private final Integer expire = 60; + + private final String iss = "KP_ISS"; + + private final String secret = "QiShenAa18n9VUcCxaSeSqLtFvsSCaRoVPKtBLaYxB0"; + +} diff --git a/src/main/java/com/qs/serve/common/config/MyBatisConfig.java b/src/main/java/com/qs/serve/common/config/MyBatisConfig.java new file mode 100644 index 00000000..deebb82e --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/MyBatisConfig.java @@ -0,0 +1,54 @@ +package com.qs.serve.common.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import com.qs.serve.common.framework.mybatis.handler.SysMetaHandler; +import com.qs.serve.common.framework.mybatis.handler.SysTenantHandler; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@MapperScan("com.qs.serve.modules.*.mapper") +@Configuration(proxyBeanMethods = false) +public class MyBatisConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 翻页拦截器 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + // 多租户、乐观锁等配置拦截 + interceptor.addInnerInterceptor(buildTenantHandler()); + // 添加防止全表更新与删除拦截器 + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + return interceptor; + } + + @Bean + public MetaObjectHandler sysMetaHandler(){ + return new SysMetaHandler(); + } + + public TenantLineInnerInterceptor buildTenantHandler(){ + String[] ignoreTable = new String[]{ + "sys_user", + "sys_user_tenant", + "sys_permit", + "sys_tenant", + "wx_app", + "sys_menu", + "sys_menu_permit" + }; + SysTenantHandler sysTenantHandler = new SysTenantHandler(ignoreTable); + return new TenantLineInnerInterceptor(sysTenantHandler); + } + +} diff --git a/src/main/java/com/qs/serve/common/config/RedisConfig.java b/src/main/java/com/qs/serve/common/config/RedisConfig.java new file mode 100644 index 00000000..ce7f564d --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/RedisConfig.java @@ -0,0 +1,70 @@ +package com.qs.serve.common.config; + + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.serializer.*; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + + +/** + * @author YenHex + * @since 2022/2/24 + */ +@EnableCaching +@Configuration(proxyBeanMethods = false) +public class RedisConfig extends CachingConfigurerSupport{ + + private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer(); + private static final GenericJackson2JsonRedisSerializer JACKSON__SERIALIZER = new GenericJackson2JsonRedisSerializer(); + + @Bean + public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { + //设置缓存过期时间 + RedisCacheConfiguration redisCacheCfg=RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofHours(1)) + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER)) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON__SERIALIZER)); + return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) + .cacheDefaults(redisCacheCfg) + .build(); + } + + @Bean + public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){ + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + return container; + } + + @Bean + @ConditionalOnMissingBean(name = "redisTemplate") + public RedisTemplate redisTemplate(RedisConnectionFactory factory){ + // 配置redisTemplate + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(factory); + // key序列化 + redisTemplate.setKeySerializer(STRING_SERIALIZER); + // value序列化 + redisTemplate.setValueSerializer(JACKSON__SERIALIZER); + // Hash key序列化 + redisTemplate.setHashKeySerializer(STRING_SERIALIZER); + // Hash value序列化 + redisTemplate.setHashValueSerializer(JACKSON__SERIALIZER); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } +} diff --git a/src/main/java/com/qs/serve/common/config/SecurityConfig.java b/src/main/java/com/qs/serve/common/config/SecurityConfig.java new file mode 100644 index 00000000..e8345490 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/SecurityConfig.java @@ -0,0 +1,64 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.config.properties.PermitProperties; +import com.qs.serve.common.framework.security.filter.SecurityRequestFilter; +import com.qs.serve.common.framework.security.handler.SecurityAccessDeniedHandler; +import com.qs.serve.common.framework.security.handler.SecurityLogoutHandler; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author YenHex + * @since 2021/6/13 + */ +@Configuration +@AllArgsConstructor +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + private final SecurityRequestFilter securityRequestFilter; + private final UserDetailsService userService; + private final PermitProperties permitProperties; + + @Override + protected void configure(HttpSecurity http) throws Exception { + List permitUrls = new ArrayList<>(); + if(permitProperties.getPermits()!=null){ permitUrls.addAll(permitProperties.getPermits()); } + if(permitProperties.getTenants()!=null){ permitUrls.addAll(permitProperties.getTenants()); } + permitUrls = permitUrls.stream().distinct().collect(Collectors.toList()); + String[] permit_urls = new String[permitUrls.size()]; + permitUrls.toArray(permit_urls); + http.csrf().disable(); + http.authorizeRequests() + .antMatchers(HttpMethod.OPTIONS.toString()).permitAll() + .antMatchers(permit_urls).permitAll() + //.antMatchers().permitAll() //测试用 + .anyRequest().authenticated(); + http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER); + http.logout() + .logoutUrl("/portal/logout") + .addLogoutHandler(new SecurityLogoutHandler()) + .invalidateHttpSession(true); + http.headers().cacheControl(); + http.addFilterBefore(securityRequestFilter, UsernamePasswordAuthenticationFilter.class); + http.exceptionHandling().accessDeniedHandler(new SecurityAccessDeniedHandler()); + //http.formLogin().failureHandler(new SecurityAuthenticationFailureHandler()); + } + + @Override + public UserDetailsService userDetailsService() { + return userService; + } + +} diff --git a/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java b/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java new file mode 100644 index 00000000..a08f1bbd --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/SpringMvcConfig.java @@ -0,0 +1,68 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.framework.interceptor.ApiAuthInterceptor; +import com.qs.serve.common.framework.interceptor.LimitSubmitInterceptor; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.multipart.MultipartResolver; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author YenHex + * @since 2022/2/24 + */ +@AllArgsConstructor +@Configuration(proxyBeanMethods = false) +public class SpringMvcConfig implements WebMvcConfigurer { + + private final LimitSubmitInterceptor limitSubmitInterceptor; + private final ApiAuthInterceptor apiAuthInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + //注册LimitSubmitInterceptor拦截器 + registry.addInterceptor(apiAuthInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/wx/login/*","/api/dev/**"); + registry.addInterceptor(limitSubmitInterceptor) + .addPathPatterns("/**"); + } + + /*@Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/static/**") + .addResourceLocations("classpath:/static/"); + }*/ + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + /*是否允许请求带有验证信息*/ + corsConfiguration.setAllowCredentials(true); + /*允许访问的客户端域名*/ + corsConfiguration.addAllowedOrigin("*"); + /*允许服务端访问的客户端请求头*/ + corsConfiguration.addAllowedHeader("*"); + /*允许访问的方法名,GET POST等*/ + corsConfiguration.addAllowedMethod("*"); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); + } + + //@Bean + public MultipartResolver multipartResolver(){ + CommonsMultipartResolver resolver = new CommonsMultipartResolver(); + resolver.setMaxInMemorySize(5120); + resolver.setMaxInMemorySize(300 * 1024 * 1024); + resolver.setDefaultEncoding("UTF-8"); + return resolver; + } + +} diff --git a/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java b/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java new file mode 100644 index 00000000..f1128d5d --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/ThreadPoolConfig.java @@ -0,0 +1,56 @@ +package com.qs.serve.common.config; + +import com.qs.serve.common.util.ThreadsUtils; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + + +/** + * 线程池配置 + * @author YenHex + * @since 2022/2/24 + */ +@Configuration +public class ThreadPoolConfig { + + /** 核心线程池大小 */ + private final int corePoolSize = 50; + + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() { + // 最大可创建的线程数 + int maxPoolSize = 200; + // 队列最大长度 + int queueCapacity = 1000; + // 线程池维护线程所允许的空闲时间 + int keepAliveSeconds = 300; + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** 执行周期性或定时任务 */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) { + @Override + protected void afterExecute(Runnable r, Throwable t) { + super.afterExecute(r, t); + ThreadsUtils.printException(r, t); + } + }; + } +} diff --git a/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java b/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java new file mode 100644 index 00000000..c6269b4f --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/PermitProperties.java @@ -0,0 +1,32 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: YenHex + * @Date: 2021/3/3 + * @Version: 1.0 + **/ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project.ignore-url") +public class PermitProperties { + + /** + * 可通过路径(适用于回调场景、无拦截场景等) + */ + private List permits = new ArrayList<>(); + + /** + * 默认租户拦截(适用于无需登录接口,但有租户拦截) + */ + private List tenants = new ArrayList<>(); + +} diff --git a/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java b/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java new file mode 100644 index 00000000..34cd197c --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/RedisProperties.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "spring.redis") +public class RedisProperties { + + private String host; + + private Integer port; + + private String password; + + private Integer database; +} diff --git a/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java b/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java new file mode 100644 index 00000000..a18b81e0 --- /dev/null +++ b/src/main/java/com/qs/serve/common/config/properties/UploadProperties.java @@ -0,0 +1,24 @@ +package com.qs.serve.common.config.properties; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author YenHex + * @since 2022/3/14 + */ +@Getter +@Setter +@Component +@ConfigurationProperties(prefix = "project.upload") +public class UploadProperties { + + private String tempPath; + + private String proxyUrl; + + private String logicalPath; + +} diff --git a/src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java b/src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java new file mode 100644 index 00000000..7d6ca24a --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/aop/SysLogAspect.java @@ -0,0 +1,210 @@ +package com.qs.serve.common.framework.aop; + +import com.alibaba.fastjson.JSON; +import com.qs.serve.common.framework.manager.AsyncFactory; +import com.qs.serve.common.framework.manager.AsyncManager; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.ServletUtils; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** + * 操作日志织入 + * @author YenHex + * @since 2022/3/8 + */ +@Slf4j +@Aspect +@Component +public class SysLogAspect { + + @Autowired + private SysUserService sysUserService; + + ThreadLocal startTimeIndex = new ThreadLocal<>(); + + @Pointcut("@annotation(com.qs.serve.common.model.annotation.SysLog)") + public void logPointCut() {} + + @Before("@annotation(com.qs.serve.common.model.annotation.SysLog)") + public void doBefore() { + startTimeIndex.set(System.currentTimeMillis()); + } + + /** + * 处理完请求后执行 + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) { + handleLog(joinPoint, null, jsonResult); + } + + /** + * 拦截异常操作 + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "logPointCut()", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Exception e) { + handleLog(joinPoint, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) { + try { + // 获得注解 + SysLog controllerLog = getAnnotationLog(joinPoint); + if (controllerLog == null) { + return; + } + HttpServletRequest request = ServletUtils.getRequest(); + // 获取当前的用户 + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + SysOperationLog operLog = new SysOperationLog(); + operLog.setReqIp(ServletUtils.getIp(request)); + operLog.setReqMethod(request.getMethod()); + operLog.setJsonResult(JSON.toJSONString(jsonResult)); + operLog.setReqUrl(request.getRequestURI()); + operLog.setUserAgent(request.getHeader(GySysConst.USER_AGENT_PROP)); + if (loginUser != null) { + operLog.setUserId(loginUser.getUserId()); + operLog.setUserType(loginUser.getTypeFlag().getCode()); + SysUser sysUser = sysUserService.getById(loginUser.getUserId()); + if(sysUser!=null){ + operLog.setCreatorName(sysUser.getName()); + } + } + if (e != null) { + operLog.setErrMsg(StringUtils.substring(e.getMessage(), 0, 2500)); + } + //耗时 + Long startTime = startTimeIndex.get(); + if(startTime!=null){ + operLog.setElapsedTime(System.currentTimeMillis()-startTime); + }else { + operLog.setElapsedTime(0L); + } + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setCodeMethod(className + "." + methodName + "()"); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog); + operLog.setTenantId(AuthContextUtils.getTenant()); + // 保存数据库 + AsyncManager.me().execute(AsyncFactory.saveOperationLog(operLog)); + } catch (Exception exp) { + // 记录本地异常日志 + log.error("==前置通知异常==\n异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 + * @param sysLog 日志 + * @param operationLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, SysLog sysLog, SysOperationLog operationLog) throws Exception { + operationLog.setBizType(sysLog.biz().getValue()); + operationLog.setInterType(sysLog.inter().name()); + operationLog.setTitle(sysLog.title()); + operationLog.setModule(sysLog.module().getVale()); + operationLog.setOptDesc(sysLog.desc()); + if (sysLog.saveReqParam()) { + setRequestValue(joinPoint, operationLog); + } + } + + /** + * 获取请求的参数,放到log中 + * @param operationLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperationLog operationLog) throws Exception { + String requestMethod = operationLog.getReqMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { + String params = argsArrayToString(joinPoint.getArgs()); + operationLog.setReqParam(StringUtils.substring(params, 0, 2500)); + } else { + Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operationLog.setReqParam(StringUtils.substring(paramsMap.toString(), 0, 2500)); + } + } + + /** 是否存在注解,如果存在就获取 */ + private SysLog getAnnotationLog(JoinPoint joinPoint){ + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + if (method != null) { + return method.getAnnotation(SysLog.class); + } + return null; + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) { + for (int i = 0; i < paramsArray.length; i++) { + if (paramsArray[i]!=null && !isFilterObject(paramsArray[i])) { + Object jsonObj = JSON.toJSON(paramsArray[i]); + params += jsonObj.toString() + " "; + } + } + } + return params.trim(); + } + + /** + * 判断是否需要过滤的对象。 + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) { + Class clazz = o.getClass(); + if (clazz.isArray()) { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } else if (Collection.class.isAssignableFrom(clazz)) { + Collection collection = (Collection) o; + for (Iterator iter = collection.iterator(); iter.hasNext(); ) { + return iter.next() instanceof MultipartFile; + } + } else if (Map.class.isAssignableFrom(clazz)) { + Map map = (Map) o; + for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry entry = (Map.Entry) iter.next(); + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/src/main/java/com/qs/serve/common/framework/exception/BaseException.java b/src/main/java/com/qs/serve/common/framework/exception/BaseException.java new file mode 100644 index 00000000..07d03534 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/exception/BaseException.java @@ -0,0 +1,21 @@ +package com.qs.serve.common.framework.exception; + +/** + * @author JcYen + * @date 2020/6/11 + * @version 1.0 + */ +public abstract class BaseException extends RuntimeException { + + public BaseException(String message){ + super(message); + } + + /** + * 错误代码 + * @return + */ + public abstract int getCode(); + + +} diff --git a/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java b/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java new file mode 100644 index 00000000..6679aca9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/exception/BusinessException.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.framework.exception; + +import java.io.Serializable; + +/** + * @author JcYen + * @Date 2020/6/11 + * @Version 1.0 + */ +public class BusinessException extends BaseException implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer status; + + public BusinessException(String message,Integer status) { + super(message); + this.status = status; + } + + @Override + public int getCode() { + return status; + } +} diff --git a/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java b/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java new file mode 100644 index 00000000..770547c9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/exception/UnifiedExceptionHandler.java @@ -0,0 +1,118 @@ +package com.qs.serve.common.framework.exception; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.HttpCode; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.sql.SQLIntegrityConstraintViolationException; + + +/** + * @Author JcYen + * @Date 2019/6/7 + * @Version 1.0 + */ +@Slf4j +@Component +@ControllerAdvice +public class UnifiedExceptionHandler { + + + @ExceptionHandler(value = BusinessException.class) + @ResponseBody + public R handleBindException(BusinessException e) { + return new R(e.getCode(),e.getMessage()); + } + + @ExceptionHandler(value = NullPointerException.class) + @ResponseBody + public R handleBindException(NullPointerException e) { + e.printStackTrace(); + return R.error("数据不存在或被移除"); + } + + @ExceptionHandler({ + AccessDeniedException.class + }) + @ResponseBody + public R handleAccessException(AccessDeniedException e) { + HttpCode hc = HttpCode.FORBIDDEN_403; + return new R(hc.getCode(),hc.getMsg()); + } + + @ExceptionHandler({ + UsernameNotFoundException.class, + }) + @ResponseBody + public R handlePrintMsgException(UsernameNotFoundException e) { + return R.error(); + } + + @ExceptionHandler({ + BadCredentialsException.class, + }) + @ResponseBody + public R handlePrintMsgException(Exception e) { + log.warn(e.getMessage()); + HttpCode hc = HttpCode.LOGIN_ERR_1; + return new R(hc.getCode(),hc.getMsg()); + } + + @ExceptionHandler({ + BindException.class, + MethodArgumentNotValidException.class, + HttpRequestMethodNotSupportedException.class + }) + @ResponseBody + public R handleDevPrintMsgException(Exception e) { + log.warn("参数校验异常:{}",e.getMessage()); + if(DevEnvironmentConfig.isDev()){return R.error(e.getMessage());} + return R.error(); + } + + @ExceptionHandler({ + DuplicateKeyException.class, + SQLIntegrityConstraintViolationException.class, + }) + @ResponseBody + public R handleSqlIntegrityException(Exception e) { + String msg = e.getMessage(); + e.printStackTrace(); + String[] tmps = msg.split("\\n"); + String msg2 = tmps.length>1?tmps[1]:null; + return new R(500,"数据库拦截"+(msg2==null?"":" : "+msg2)); + } + + /** + * 强制运行写入成功 + * @param e + * @return + */ + @ExceptionHandler(value = HttpMessageNotWritableException.class) + @ResponseBody + public R handleMsgException(HttpMessageNotWritableException e) { + return R.ok(); + } + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public R handleException(Exception e) { + log.error("Servlet异常\n异常类型:{}\n异常信息:{}\n异常体:",e.getClass().getSimpleName(),e.getMessage(),e); + if(DevEnvironmentConfig.isDev()){return R.error(e.getMessage());} + return R.error(); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/interceptor/ApiAuthInterceptor.java b/src/main/java/com/qs/serve/common/framework/interceptor/ApiAuthInterceptor.java new file mode 100644 index 00000000..c993c684 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/interceptor/ApiAuthInterceptor.java @@ -0,0 +1,60 @@ +package com.qs.serve.common.framework.interceptor; + +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserDTO; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.JsonUtil; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; + +/** + * API接口身份拦截器 + * @author YenHex + */ +@Configuration(proxyBeanMethods = false) +public class ApiAuthInterceptor implements HandlerInterceptor { + + + @Resource private RedisService redisService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String token = request.getHeader(GySysConst.APP_TOKEN_PROP); + String loginUserJson = redisService.getString(RedisCacheKeys.LOGIN_KEY_WX+token); + if(loginUserJson!=null){ + LoginUser loginUser = Objects.requireNonNull(JsonUtil.jsonToPojo(loginUserJson, LoginUserDTO.class)).loginUser(); + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + return true; + } + try { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS"); + response.setHeader("Access-Control-Max-Age", "86400"); + response.setHeader("Access-Control-Allow-Headers", "*"); + response.setStatus(200); + response.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().print("{\"status\":401,\"msg\":\"用户信息无效或过期了\"}"); + response.getWriter().flush(); + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java b/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java new file mode 100644 index 00000000..c778351e --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/interceptor/LimitSubmitInterceptor.java @@ -0,0 +1,66 @@ +package com.qs.serve.common.framework.interceptor; + +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.util.StringUtils; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.concurrent.TimeUnit; + +/** + * 防止重复提交拦截器 + * @author YenHex + */ +@Configuration(proxyBeanMethods = false) +public class LimitSubmitInterceptor implements HandlerInterceptor { + + public final String REPEAT_Limit_KEY = "repeatLimitKey"; + + @Resource + public RedisService redisService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + LimitSubmit annotation = method.getAnnotation(LimitSubmit.class); + if (annotation != null) { + if (this.LimitSubmit(request, annotation)) { + if(StringUtils.isNotEmpty(annotation.message())){ + HttpResponsePrintUtil.print(response,406,annotation.message()); + }else { + HttpResponsePrintUtil.print(response,406,"系统处理中,请勿频繁操作"); + } + return false; + } + } + return true; + } else { + return true; + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * @param request 请求对象 + * @param annotation 防复注解 + * @return + */ + public boolean LimitSubmit(HttpServletRequest request, LimitSubmit annotation) throws Exception { + String key = REPEAT_Limit_KEY+"_"+request.getRequestURI()+"_"+request.getRemoteHost(); + Object cache = redisService.get(key); + if(cache!=null){return true;} + redisService.set(key,"true",annotation.interval(), TimeUnit.MILLISECONDS); + return false; + } + + +} diff --git a/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java b/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 00000000..6825fe96 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,98 @@ +package com.qs.serve.common.framework.interceptor; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.model.annotation.RepeatSubmit; +import com.qs.serve.common.util.JsonUtil; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +/** + * 防止重复提交拦截器 + * @author YenHex + */ +@Configuration(proxyBeanMethods = false) +public class RepeatSubmitInterceptor implements HandlerInterceptor { + + public final String REPEAT_PARAMS = "repeatParams"; + public final String REPEAT_TIME = "repeatTime"; + public final String SESSION_REPEAT_KEY = "repeatData"; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) { + if (this.isRepeatSubmit(request, annotation)) { + HttpResponsePrintUtil.print(response,406,"系统正常处理,请勿重复提交"); + return false; + } + } + return true; + } else { + return true; + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * @param request 请求对象 + * @param annotation 防复注解 + * @return + */ + public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) throws Exception { + // 本次参数及系统时间 + String nowParams = JsonUtil.objectToJson(request.getParameterMap()); + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + // 请求地址(作为存放session的key值) + String url = request.getRequestURI(); + HttpSession session = request.getSession(); + Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY); + if (sessionObj != null) { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) { + return true; + } + } + } + Map sessionMap = new HashMap<>(); + sessionMap.put(url, nowDataMap); + session.setAttribute(SESSION_REPEAT_KEY, sessionMap); + return false; + } + + /** + * 判断参数是否相同 + */ + private boolean compareParams(Map nowMap, Map preMap) { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap, int interval) { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < interval) { + return true; + } + return false; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java b/src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java new file mode 100644 index 00000000..1a0125d9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/manager/AsyncFactory.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.manager; + + +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.mapper.SysOperationLogMapper; + +import java.util.TimerTask; + +/** + * 异步工厂 + * @author YenHex + * @since 2022/2/24 + */ +public class AsyncFactory { + + /** + * 操作日志记录 + * @param operationLog + * @return + */ + public static TimerTask saveOperationLog(final SysOperationLog operationLog) { + return new TimerTask() { + @Override + public void run() { + if(DevEnvironmentConfig.isDev()){ + System.out.println(JsonUtil.objectToJson(operationLog)); + } + SpringUtils.getBean(SysOperationLogMapper.class).saveLog(operationLog); + } + }; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java b/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java new file mode 100644 index 00000000..d82e34f0 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/manager/AsyncManager.java @@ -0,0 +1,52 @@ +package com.qs.serve.common.framework.manager; + +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.common.util.ThreadsUtils; + +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + + +/** + * 异步任务管理器 + * @author YenHex + * @since 2022/2/24 + */ +public class AsyncManager { + /** + * 操作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + + /** + * 异步操作任务调度线程池 + */ + private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 单例模式 + */ + private AsyncManager() { + } + + private static AsyncManager me = new AsyncManager(); + + public static AsyncManager me() { + return me; + } + + /** + * 执行任务 + * @param task 任务 + */ + public void execute(TimerTask task) { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** 停止任务线程池 */ + public void shutdown() { + ThreadsUtils.shutdownAndAwaitTermination(executor); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java b/src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java new file mode 100644 index 00000000..42062ac7 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mvc/HttpServletRequestFilter.java @@ -0,0 +1,161 @@ +package com.qs.serve.common.framework.mvc; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.DateUtils; +import com.qs.serve.common.util.ServletUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * HttpServletRequest 过滤器 + * 解决: request.getInputStream()只能读取一次的问题 + * 目标: 流可重复读 + * @Author YenHex + * @Date 2021/4/9 + * @Version: 1.0 + **/ +@Slf4j +@Component +@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/") +@Order(10000) +public class HttpServletRequestFilter implements Filter{ + + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + RequestWrapper requestWrapper = null; + if(servletRequest instanceof HttpServletRequest) { + //过滤文件URL + String url = ((HttpServletRequest) servletRequest).getRequestURI(); + if(!url.contains("import")&&!url.contains("upload")){ + requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); + } + } + long startTime = System.currentTimeMillis(); + if(null == requestWrapper) { + filterChain.doFilter(servletRequest, servletResponse); + } else { + filterChain.doFilter(requestWrapper, servletResponse); + } + long endTime = System.currentTimeMillis(); + double diffTime = DateUtils.diffTime(startTime,endTime); + assert servletRequest instanceof HttpServletRequest; + HttpServletRequest request = (HttpServletRequest)servletRequest; + String tenant = request.getHeader("tenant-id"); + String url = request.getRequestURL().toString(); + String method = request.getMethod(); + String queryStr = request.getQueryString(); + String reqBody = ""; + if (ServletUtils.isJsonRequest(request)) { + reqBody = requestWrapper.getBody(); + } + StringBuffer buffer = new StringBuffer("["+method+"] "+url + " IP: "+ServletUtils.getIp(request)); + buffer.append("\n校区编号: "+tenant); + try { + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + buffer.append("\n用户类型: "+ loginUser.getTypeFlag().getName()+" 用户ID: "+loginUser.getUserId()); + } + } catch (Exception e) {} + if(!StringUtils.isEmpty(queryStr)){ + buffer.append("\n参数: "+queryStr); + } + if(!StringUtils.isEmpty(reqBody)){ + buffer.append("\n请求体: "+reqBody); + } + buffer.append("\n耗时: "+diffTime+"秒"); + /*if(diffTime>4){ log.warn("访问速度:{}秒,接口:{},参数:{},请求体:{}",diffTime,"["+method+"] "+url,queryStr,reqBody);}*/ + System.out.println(buffer); + } + + @Override + public void destroy() { + + } + + /*** + * HttpServletRequest 包装器 + * 解决: request.getInputStream()只能读取一次的问题 + * 目标: 流可重复读 + */ + public class RequestWrapper extends HttpServletRequestWrapper { + + /** + * 请求体 + */ + private String mBody; + + public RequestWrapper(HttpServletRequest request) { + super(request); + mBody = getBody(request); + } + + /** + * 获取请求体 + * @param request 请求 + * @return 请求体 + */ + private String getBody(HttpServletRequest request) { + return ServletUtils.getBodyString(request); + } + + /** + * 获取请求体 + * @return 请求体 + */ + public String getBody() { + return mBody; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // 创建字节数组输入流 + final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes(StandardCharsets.UTF_8)); + + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + + @Override + public int read() throws IOException { + return bais.read(); + } + }; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java new file mode 100644 index 00000000..59b3b7af --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/IdGeneratorHandler.java @@ -0,0 +1,17 @@ +package com.qs.serve.common.framework.mybatis.handler; + +import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; +import com.qs.serve.common.util.NanoIdUtils; + +/** + * @author YenHex + * @since 2022/4/11 + */ +public class IdGeneratorHandler extends DefaultIdentifierGenerator { + + @Override + public String nextUUID(Object entity) { + return NanoIdUtils.randomNanoId(); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java new file mode 100644 index 00000000..78383992 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysMetaHandler.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.mybatis.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.util.AuthContextUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; + +import java.time.LocalDateTime; + +/** + * 自动注入列数据 + * @author YenHex + * @since 2022/3/1 + */ +@Slf4j +public class SysMetaHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + this.strictInsertFill(metaObject, "createBy", () -> loginUser.getUserId(), String.class); + } + this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); + } + + @Override + public void updateFill(MetaObject metaObject) { + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + this.strictUpdateFill(metaObject, "updateBy", () -> loginUser.getUserId(), String.class); + } + this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java new file mode 100644 index 00000000..8255dd95 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/SysTenantHandler.java @@ -0,0 +1,58 @@ +package com.qs.serve.common.framework.mybatis.handler; + +import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; + +import java.util.Arrays; + +/** + * @Author YenHex + * @Date 2021/5/7 + * @Version: 1.0 + **/ +public class SysTenantHandler implements TenantLineHandler { + + public SysTenantHandler(String[] ignoreTables){ + this.IGNORE_TABLES = Arrays.asList(ignoreTables); + } + + + final private java.util.List IGNORE_TABLES; + + @Override + public Expression getTenantId() { + String tenant = AuthContextUtils.getTenant(); + if(tenant==null){ + Assert.throwEx(HttpCode.LOGIN_ERR_4001); + } + return new StringValue(tenant); + } + + @Override + public String getTenantIdColumn() { + return GySysConst.TENANT_COLUMN; + } + + /** + * 判断是否忽略该表,默认全忽略,匹配到的不忽略 + * @param tableName + * @return + */ + @Override + public boolean ignoreTable(String tableName) { + for (String tb : this.IGNORE_TABLES) { + if(tableName.equalsIgnoreCase(tb)){ + return true; + } + } + return false; + } + + + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java new file mode 100644 index 00000000..9efe3ba7 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/JsonStringTypeHandler.java @@ -0,0 +1,50 @@ +package com.qs.serve.common.framework.mybatis.handler.meta; + +import cn.hutool.json.JSONUtil; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 存储到数据库, 将String数组转换成字符串; + * 从数据库获取数据, 将字符串转为LONG数组. + * @author YenHex + * @since 2022/3/1 + */ +@MappedTypes({String[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class JsonStringTypeHandler extends BaseTypeHandler { + + private static String[] l = new String[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, + String[] parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, JSONUtil.toJsonStr(parameter)); + } + + @Override + public String[] getNullableResult(ResultSet rs, String columnName) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnName)).toArray(l); + } + + @Override + public String[] getNullableResult(ResultSet rs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(rs.getString(columnIndex)).toArray(l); + } + + @Override + public String[] getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + return JSONUtil.parseArray(cs.getString(columnIndex)).toArray(l); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java new file mode 100644 index 00000000..ac022528 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/handler/meta/SplitStringTypeHandler.java @@ -0,0 +1,74 @@ +package com.qs.serve.common.framework.mybatis.handler.meta; + +import com.qs.serve.common.util.StringUtils; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; + +/** + * 存储到数据库, 将String数组转换成字符串; + * 从数据库获取数据, 将字符串转为LONG数组. + * @author YenHex + * @since 2022/3/1 + */ +@MappedTypes({String[].class}) +@MappedJdbcTypes({JdbcType.VARCHAR}) +public class SplitStringTypeHandler extends BaseTypeHandler { + + private static String[] l = new String[]{}; + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter, JdbcType jdbcType) throws SQLException { + if(parameter!=null&¶meter.length>1){ + StringBuffer buffer = new StringBuffer(); + for (int i1 = 0; i1 < parameter.length; i1++) { + buffer.append(parameter[i1]); + if(i1+1 val != null && val.trim().length() > 0) + .toArray(String[]::new); + } + return null; + } + + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java new file mode 100644 index 00000000..4e146199 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/JoinUtil.java @@ -0,0 +1,115 @@ +package com.qs.serve.common.framework.mybatis.join; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity; +import com.qs.serve.common.framework.mybatis.join.enums.JoinType; +import com.qs.serve.common.framework.mybatis.join.model.JoinFieldData; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.common.util.WordUtil; +import lombok.extern.slf4j.Slf4j; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author YenHex + * @since 2022/5/24 + */ +@Slf4j +public class JoinUtil { + + private static Map> CACHE_MAP = new ConcurrentHashMap<>(); + + private static List getJoinFields(List list) { + if(CollectionUtil.isEmpty(list)){ + return new ArrayList<>(); + } + String className = list.get(0).getClass().getName(); + List joinFieldDataList = new ArrayList<>(); + Class clazz = null; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + if(clazz==null){return null;} + Field[] fields = clazz.getDeclaredFields(); + Field fieldJoinVal = null; + Field fieldSetVal = null; + BindEntity bindEntity = null; + for (Field field : fields) { + for (Annotation annotation : field.getAnnotations()) { + if(annotation instanceof BindEntity){ + fieldSetVal = field; + bindEntity = (BindEntity) annotation; + break; + } + } + } + if(fieldSetVal!=null){ + for (Field field :fields){ + if(field.getName().equals(bindEntity.joinField())){ + fieldJoinVal = field; + break; + } + } + } + if(bindEntity!=null&&fieldJoinVal!=null){ + JoinFieldData fieldData = new JoinFieldData(); + fieldData.setFieldJoinVal(fieldJoinVal); + fieldData.setBindEntity(bindEntity); + fieldData.setFieldSetVal(fieldSetVal); + joinFieldDataList.add(fieldData); + } + CACHE_MAP.put(className,joinFieldDataList); + return joinFieldDataList; + } + + public static void relate(List list) { + List joinFieldData = getJoinFields(list); + HashMap tempCache = new HashMap<>(list.size()+1); + for (JoinFieldData fieldData : joinFieldData) { + for (Object object : list) { + try { + Field fieldJoinVal = fieldData.getFieldJoinVal(); + Field fieldSetVal = fieldData.getFieldSetVal(); + BindEntity bindEntity = fieldData.getBindEntity(); + fieldSetVal.setAccessible(true); + fieldJoinVal.setAccessible(true); + IService iService = SpringUtils.getBean(bindEntity.service()); + Object identity = fieldJoinVal.get(object); + if(identity==null){ + continue; + } + Object result = tempCache.get(identity.toString()); + if(result!=null){ + fieldSetVal.set(object,result); + continue; + } + if(bindEntity.joinType()== JoinType.List){ + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq(WordUtil.toLine(bindEntity.joinField()),identity); + result = iService.list(wrapper); + }else { + QueryWrapper wrapper = new QueryWrapper(); + wrapper.eq(WordUtil.toLine(bindEntity.selfField()),identity); + result = iService.getOne(wrapper,false); + } + fieldSetVal.set(object,result); + tempCache.put(identity.toString(),result); + } catch (IllegalAccessException e) { + log.warn("join 工具失败:",e); + } + } + } + tempCache = null; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java new file mode 100644 index 00000000..887fa1e1 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/annotations/BindEntity.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.mybatis.join.annotations; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.common.framework.mybatis.join.enums.JoinType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 实现left join + * @author YenHex + * @since 2022/5/24 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface BindEntity { + + Class service(); + + /** + * 关联的表 + * @return + */ + String joinField() default ""; + + /** + * 主表 + * @return + */ + String selfField() default "id"; + + JoinType joinType() default JoinType.Object; + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java new file mode 100644 index 00000000..df492696 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/enums/JoinType.java @@ -0,0 +1,14 @@ +package com.qs.serve.common.framework.mybatis.join.enums; + +/** + * @author YenHex + * @since 2022/5/24 + */ +public enum JoinType { + + /** + * 返回类型 + */ + Object,List + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java b/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java new file mode 100644 index 00000000..6d87537e --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/join/model/JoinFieldData.java @@ -0,0 +1,17 @@ +package com.qs.serve.common.framework.mybatis.join.model; + +import com.qs.serve.common.framework.mybatis.join.annotations.BindEntity; +import lombok.Data; + +import java.lang.reflect.Field; + +/** + * @author YenHex + * @since 2022/5/24 + */ +@Data +public class JoinFieldData { + Field fieldJoinVal; + Field fieldSetVal; + BindEntity bindEntity; +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java new file mode 100644 index 00000000..01dadfea --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/AnnotationQueryStorage.java @@ -0,0 +1,159 @@ +package com.qs.serve.common.framework.mybatis.query; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.mybatis.query.model.QueryFieldData; +import com.qs.serve.common.framework.mybatis.query.model.QueryFieldDataValue; +import com.qs.serve.common.framework.mybatis.query.model.QueryType; +import com.qs.serve.common.framework.mybatis.query.annotations.QueryWrap; +import com.qs.serve.common.util.WordUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author JcYen + * @Date 2017/10/28 + * @Version 1.0 + */ +@Slf4j +public class AnnotationQueryStorage { + + private static final Map> BEAN_QUERY_FIELD = new ConcurrentHashMap<>(); + + protected static List getQueryFieldList(String className){ + List queryFieldList = BEAN_QUERY_FIELD.get(className); + if(queryFieldList==null){ + Class clazz = null; + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + queryFieldList = new ArrayList<>(); + if(clazz==null){return queryFieldList;} + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + Annotation[] annotations = field.getAnnotations(); + boolean isExist = false; + boolean isIgnore = false; + for (Annotation annotation : annotations) { + if(annotation instanceof QueryWrap){ + QueryWrap queryWrap = (QueryWrap)annotation; + QueryFieldData queryField= handleQueryField(queryWrap.type(),field); + if(queryField!=null){ + isExist = true; + queryFieldList.add(queryField); + break; + } + } + if(annotation instanceof TableField){ + TableField tableField = (TableField) annotation; + isIgnore = tableField.exist(); + } + } + //不存在,添加默认 + if( !isExist && !isIgnore ){ + QueryFieldData queryField = new QueryFieldData(); + //系统默认使用格式。示例: userInfo -> user_info + queryField.setColumnName(WordUtil.toLine(field.getName())); + queryField.setField(field); + queryField.setFieldName(field.getName()); + queryField.setType(QueryType.NONE); + queryFieldList.add(queryField); + } + } + BEAN_QUERY_FIELD.put(className,queryFieldList); + if(queryFieldList.size()==0){ + log.warn("无匹配的注解字段,类名:"+className); + } + } + return queryFieldList; + } + + /** + * 处理查询列 + * @param queryType + * @param field + * @return + */ + private static QueryFieldData handleQueryField(QueryType queryType, Field field){ + String columnName = null; + if(queryType!=null){ + QueryFieldData queryField = new QueryFieldData(); + if(StringUtils.isEmpty(columnName)){ + columnName = WordUtil.toLine(field.getName()); + } + queryField.setFieldName(field.getName()); + queryField.setColumnName(columnName); + queryField.setField(field); + queryField.setType(queryType); + return queryField; + } + return null; + } + + + /** + * 加载查询对象生成配置值 + * @param query + * @return + */ + protected static List loadQueryFieldDataValues(Object query){ + String className = query.getClass().getName(); + List dataList = AnnotationQueryStorage.getQueryFieldList(className); + if(!CollectionUtils.isEmpty(dataList)){ + List valueList = new ArrayList<>(); + for (QueryFieldData fieldData : dataList) { + Field field = fieldData.getField(); + field.setAccessible(true); + Object value = null; + try { + value = field.get(query); + } catch (IllegalAccessException e) { + log.warn("查询类字段参数异常。查询类:{},字段:{}",className,field.getName()); + } + if(value!=null){ + QueryFieldDataValue dataValue = new QueryFieldDataValue(fieldData); + //通过列条件,重新赋值(赋值查询条件和格式) + dataValue.setValue(value); + valueList.add(dataValue); + } + } + return valueList; + } + return null; + } + + /** + * 初始化封装包参数 + * @param fieldValues + * @param queryWrapper + * @param + * @return 判断是否排序 + */ + protected static void initWrap(List fieldValues, QueryWrapper queryWrapper){ + for (QueryFieldDataValue fieldValue : fieldValues) { + QueryType queryType = fieldValue.getType(); + Object value = fieldValue.getValue(); + String column = fieldValue.getColumnName(); + if(queryType.equals(QueryType.EQ)){ queryWrapper.eq(column,value); } + if(queryType.equals(QueryType.GE)){ queryWrapper.ge(column,value); } + if(queryType.equals(QueryType.GT)){ queryWrapper.gt(column,value); } + if(queryType.equals(QueryType.In)){ queryWrapper.in(column,value); } + if(queryType.equals(QueryType.LE)){ queryWrapper.le(column,value); } + if(queryType.equals(QueryType.Like)){ queryWrapper.like(column,value); } + if(queryType.equals(QueryType.LT)){ queryWrapper.lt(column,value); } + if(queryType.equals(QueryType.NE)){ queryWrapper.ne(column,value); } + if(queryType.equals(QueryType.RightLike)){ queryWrapper.likeRight(column,value); } + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java new file mode 100644 index 00000000..96cc08fa --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/annotations/QueryWrap.java @@ -0,0 +1,32 @@ +package com.qs.serve.common.framework.mybatis.query.annotations; + +import com.qs.serve.common.framework.mybatis.query.model.QueryType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author JcYen + * @date 2020/5/26 + * SQL In条件注解 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface QueryWrap { + + /** + * 列名(默认为空字符串) + * 空字符串,采用字段转列策略 示例: userInfo -> user_info + * 非空时,采用列的值 + */ + String value() default ""; + + /** + * 查询类型(默认采用值相对) + */ + QueryType type() default QueryType.EQ; + +} + diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java new file mode 100644 index 00000000..1654861c --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldData.java @@ -0,0 +1,23 @@ +package com.qs.serve.common.framework.mybatis.query.model; + +import lombok.Getter; +import lombok.Setter; + +import java.lang.reflect.Field; + +/** + * 存储DTO + * @author JcYen + * @Date 2017/10/28 + * @Version 1.0 + */ +@Getter +@Setter +public class QueryFieldData { + + private Field field; + private QueryType type; + private String columnName; + private String fieldName; + +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java new file mode 100644 index 00000000..718b176c --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryFieldDataValue.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.framework.mybatis.query.model; + +import com.qs.serve.common.util.CopierUtil; +import lombok.Getter; +import lombok.Setter; + +/** + * 存储DTO + * @author JcYen + * @Date 2017/10/28 + * @Version 1.0 + */ +@Getter +@Setter +public class QueryFieldDataValue{ + + public QueryFieldDataValue(QueryFieldData data){ + CopierUtil.copy(data,this); + } + + private QueryType type; + private String columnName; + private String fieldName; + private Object value; +} diff --git a/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java new file mode 100644 index 00000000..d32cd45f --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/mybatis/query/model/QueryType.java @@ -0,0 +1,40 @@ +package com.qs.serve.common.framework.mybatis.query.model; + +/** + * @author JcYen + */ +public enum QueryType { + + /** + * 无 + */ + NONE, + + /** + * 通用的equals(Integer,Long,String) + */ + EQ, + NE, + + /** + * 比较修饰符,修饰日期,数值类型(Integer,Long,Double,BigDecimal) + */ + LT, + LE, + GT, + GE, + + /** + * 修饰List + */ + In, + NotIn, + + /** + * 修饰字符串 + */ + Like, + RightLike, + NotLike, + +} diff --git a/src/main/java/com/qs/serve/common/framework/redis/RedisService.java b/src/main/java/com/qs/serve/common/framework/redis/RedisService.java new file mode 100644 index 00000000..739f9af8 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/redis/RedisService.java @@ -0,0 +1,309 @@ +package com.qs.serve.common.framework.redis; + +import lombok.AllArgsConstructor; +import org.springframework.data.redis.core.*; +import org.springframework.stereotype.Service; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @author JcYen + * @since 2022/3/4 + */ +@Service +@AllArgsConstructor +public class RedisService { + + private RedisTemplate redisTemplate; + + private StringRedisTemplate stringRedisTemplate; + + + /** + * 写入缓存 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value) { + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + result = true; + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 写入缓存设置时效时间 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value, int expireTime) { + return set(key, value, expireTime,TimeUnit.SECONDS); + } + + /** + * 写入缓存设置时效时间 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value, int expireTime,TimeUnit unit) { + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + redisTemplate.expire(key, expireTime, unit); + result = true; + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 批量删除对应的value + * + * @param keys + */ + public void remove(final String... keys) { + for (String key : keys) { + remove(key); + } + } + + /** + * 批量删除key + * + * @param pattern + */ + public void removePattern(final String pattern) { + Set keys = redisTemplate.keys(pattern); + if (keys.size() > 0) + redisTemplate.delete(keys); + } + + /** + * 删除对应的value + * + * @param key + */ + public void remove(final String key) { + if (exists(key)) { + redisTemplate.delete(key); + } + } + + /** + * 判断缓存中是否有对应的value + * + * @param text + * @return + */ + public Set list(final String text) { + Set keySet = redisTemplate.keys("*" + text + "*"); + for (String key : keySet) { + System.out.println(key); + } + return keySet; + } + + + /** + * 获取所有数据 + * + * @return + */ + public Set list() { + Set keySet = redisTemplate.keys("*" + "#" +"*"); + for (String key : keySet) { + System.out.println(key); + } + return keySet; + } + + + /** + * 判断缓存中是否有对应的value + * + * @param text + * @return + */ + public void removeForLike(final String text) { + Set keySet = redisTemplate.keys("*" + text + "*"); + Iterator it = keySet.iterator(); + while(it.hasNext()){ + redisTemplate.delete(it.next()); + } + } + + + public Map cleanRedis() { + Map map = new HashMap<>(); + try { + // 获取所有key + Set keys = redisTemplate.keys("*"); + assert keys != null; + // 迭代 + Iterator it1 = keys.iterator(); + while (it1.hasNext()) { + // 循环删除 + stringRedisTemplate.delete(it1.next()); + } + map.put("code", 1); + map.put("msg", "清理全局缓存成功"); + return map; + } catch (Exception e) { + map.put("code", -1); + map.put("msg", "清理全局缓存失败"); + return map; + } + } + + + /** + * 判断缓存中是否有对应的value + * + * @param key + * @return + */ + public boolean exists(final String key) { + return redisTemplate.hasKey(key); + } + + /** + * 读取缓存 + * + * @param key + * @return + */ + public Object get(final String key) { + Object result = null; + ValueOperations operations = redisTemplate.opsForValue(); + result = operations.get(key); + return result; + } + + public String getString(final String key) { + Object result = null; + ValueOperations operations = redisTemplate.opsForValue(); + result = operations.get(key); + if(result!=null){ + return result.toString(); + + } + return null; + } + + public Integer getInteger(final String key) { + String result = getString(key); + if(result!=null){ + return Integer.parseInt(result); + } + return null; + } + + /** + * 哈希 添加 + * + * @param key + * @param hashKey + * @param value + */ + public void hmSet(String key, Object hashKey, Object value) { + HashOperations hash = redisTemplate.opsForHash(); + hash.put(key, hashKey, value); + } + + /** + * 哈希获取数据 + * + * @param key + * @param hashKey + * @return + */ + public Object hmGet(String key, Object hashKey) { + HashOperations hash = redisTemplate.opsForHash(); + return hash.get(key, hashKey); + } + + /** + * 列表添加 + * + * @param k + * @param v + */ + public void lPush(String k, Object v) { + ListOperations list = redisTemplate.opsForList(); + list.rightPush(k, v); + } + + /** + * 列表获取 + * + * @param k + * @param l + * @param l1 + * @return + */ + public List lRange(String k, long l, long l1) { + ListOperations list = redisTemplate.opsForList(); + return list.range(k, l, l1); + } + + /** + * 集合添加 + * + * @param key + * @param value + */ + public void add(String key, Object value) { + SetOperations set = redisTemplate.opsForSet(); + set.add(key, value); + } + + /** + * 集合获取 + * + * @param key + * @return + */ + public Set setMembers(String key) { + SetOperations set = redisTemplate.opsForSet(); + return set.members(key); + } + + /** + * 有序集合添加 + * + * @param key + * @param value + * @param scoure + */ + public void zAdd(String key, Object value, double scoure) { + ZSetOperations zset = redisTemplate.opsForZSet(); + zset.add(key, value, scoure); + } + + /** + * 有序集合获取 + * + * @param key + * @param scoure + * @param scoure1 + * @return + */ + public Set rangeByScore(String key, double scoure, double scoure1) { + ZSetOperations zset = redisTemplate.opsForZSet(); + return zset.rangeByScore(key, scoure, scoure1); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java b/src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java new file mode 100644 index 00000000..201c0144 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/filter/SecurityRequestFilter.java @@ -0,0 +1,192 @@ +package com.qs.serve.common.framework.security.filter; + +import com.qs.serve.common.config.DevEnvironmentConfig; +import com.qs.serve.common.config.properties.PermitProperties; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.JwtUtils; +import com.qs.serve.common.framework.security.util.SecurityPermitUtil; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 判断token情况 + * @Author JcYen + * @Date 2022/03/01 + * @Version 1.0 + */ +@Slf4j +@Component +public class SecurityRequestFilter extends OncePerRequestFilter { + + @Value("${server.servlet.context-path}") + public String contextPath; + + @Autowired + private SysUserService sysUserService; + + @Autowired + private PermitProperties permitProperties; + + @Autowired + private RedisService redisService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + //移除前缀 + String url = request.getRequestURI(); + if(!StringUtils.isEmpty(contextPath)&&!contextPath.equals("/")){ + url = url.replace(contextPath,""); + } + //分析拦截类型 + boolean ignorePermit = false; + for(String reg : permitProperties.getPermits()){ + if(SecurityPermitUtil.verify(reg,url)){ + ignorePermit=true; + break; + } + } + //分析拦截类型 + boolean ignoreTenant = false; + for(String reg : permitProperties.getTenants()){ + if(SecurityPermitUtil.verify(reg,url)){ + ignoreTenant = true; + break; + } + } + response.setHeader("Access-Control-Allow-Origin", "*"); + //登录拦截 + if ("OPTIONS".equals(request.getMethod())) { + HttpResponsePrintUtil.print(response,200,"success"); + return; + } + if(!ignoreTenant){ + boolean hasTenant = handleTenant(request,response); + if(!hasTenant){ + return; + } + } + if(ignorePermit){ + //try to doSecurityAuthor + tryDoSecurityAuthor(request, response, chain); + chain.doFilter(request,response); + }else { + doSecurityAuthor(request, response, chain); + } + } + + /** + * 尝试执行登录 + * @param request + * @param response + * @param chain + * @throws IOException + * @throws ServletException + */ + private void tryDoSecurityAuthor(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + String tenant = request.getHeader(GySysConst.TENANT_PROP); + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + if(tenant!=null&&token!=null&&JwtUtils.verify(token)){ + String userId = JwtUtils.getUserId(token); + String userType = JwtUtils.getUserType(token); + AuthContextUtils.setTenant(tenant); + if(SecurityContextHolder.getContext().getAuthentication()==null){ + UserDetails userDetails = null; + if(userType.equals(LoginUserType.SYS_USER.getCode()) + ||userType.equals(LoginUserType.SYS_SUP_USER.getCode())){ + //后台管理员登录 + userDetails = sysUserService.getLoginUserById(userId); + } + if(userDetails!=null){ + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + } + + + /** + * 执行登录 + * @param request + * @param response + * @param chain + * @throws IOException + * @throws ServletException + */ + private void doSecurityAuthor(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + String token = request.getHeader(GySysConst.AUTHORIZATION_PROP); + if(!JwtUtils.verify(token)){ + HttpResponsePrintUtil.print2(response,401,"身份凭证无效或过期"); + }else{ + String userId = JwtUtils.getUserId(token); + String userType = JwtUtils.getUserType(token); + String client = JwtUtils.getClient(token); + String redisKey = com.qs.serve.common.util.StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,userId); + String cacheToken = redisService.getString(redisKey); + if(!DevEnvironmentConfig.isDev()&&!token.equals(cacheToken)){ + redisService.remove(redisKey); + HttpResponsePrintUtil.print2(response,401,"异地登录,已被系统登出"); + //return解决:security.access.AccessDeniedException + return; + } + if(SecurityContextHolder.getContext().getAuthentication()==null){ + UserDetails userDetails = null; + if(userType.equals(LoginUserType.SYS_USER.getCode()) + ||userType.equals(LoginUserType.SYS_SUP_USER.getCode())){ + //后台管理员登录 + userDetails = sysUserService.getLoginUserById(userId); + } + if(userDetails==null){ + HttpResponsePrintUtil.print2(response,401,"登录信息无效,请重新登录"); + //return解决:security.access.AccessDeniedException + return; + }else { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + chain.doFilter(request, response); + } + } + + /** + * 多租户模式下使用 + * @param request + * @param response + * @throws IOException + * @throws ServletException + */ + private boolean handleTenant(HttpServletRequest request, HttpServletResponse response) throws IOException{ + String tenant = request.getHeader(GySysConst.TENANT_PROP); + if (tenant != null) { + AuthContextUtils.setTenant(tenant); + return true; + }else{ + HttpResponsePrintUtil.print2(response,4001,"校区信息错误"); + return false; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java new file mode 100644 index 00000000..eae472a2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAccessDeniedHandler.java @@ -0,0 +1,22 @@ +package com.qs.serve.common.framework.security.handler; + +import com.qs.serve.common.model.HttpResponsePrintUtil; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2022/3/3 + */ +public class SecurityAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + HttpResponsePrintUtil.print(response,403,"权限不足"); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java new file mode 100644 index 00000000..fa5cef6b --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityAuthenticationFailureHandler.java @@ -0,0 +1,22 @@ +package com.qs.serve.common.framework.security.handler; + +import com.qs.serve.common.model.HttpResponsePrintUtil; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2022/3/3 + */ +public class SecurityAuthenticationFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException { + HttpResponsePrintUtil.print(response,401,"登录信息已过期或失效"); + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java new file mode 100644 index 00000000..5d1f017b --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/handler/SecurityLogoutHandler.java @@ -0,0 +1,36 @@ +package com.qs.serve.common.framework.security.handler; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.HttpResponsePrintUtil; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.SpringUtils; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutHandler; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2021/12/22 + */ +public class SecurityLogoutHandler implements LogoutHandler { + + + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + SysUserMapper sysUserMapper = SpringUtils.getBean(SysUserMapper.class); + LoginUser loginUser = AuthContextUtils.getLoginUser(false); + if(loginUser!=null){ + sysUserMapper.updateYmTokenInt(loginUser.getUserId(),"#","#"); + } + try { + HttpResponsePrintUtil.print(response,200,"退出登录成功"); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java b/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java new file mode 100644 index 00000000..4744121d --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/model/LoginUser.java @@ -0,0 +1,97 @@ +package com.qs.serve.common.framework.security.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户登录信息 + * @author YenHex + * @since 2022/3/1 + */ +@Data +@AllArgsConstructor +public class LoginUser implements UserDetails { + + private String userId; + + private String nick; + + private String password; + + private String loginIp; + + /** 用户类型 */ + private LoginUserType typeFlag; + + private List authorList; + private List authorIds; + + private String tenant; + + @Override + public Collection getAuthorities() { + if(authorList!=null&&authorList.size()>0){ + return authorList + .stream() + .filter(n->n.length()>0) + .map(auth->new SimpleGrantedAuthority("ROLE_"+auth)) + .collect(Collectors.toList()); + } + return Collections.singletonList(new SimpleGrantedAuthority("NOT_ROLE")); + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return userId; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + public LoginUserDTO loginUserDTO(){ + return new LoginUserDTO(userId,nick,password,loginIp,typeFlag.getCode(),authorList,authorIds,tenant); + } + + public boolean verifyRole(String permitCode){ + return authorList.contains(permitCode); + } + + /** + * 是否拥有招生超管权限 + * @return + */ + public boolean hasRegSuperRole(){ + return verifyRole("edu:reg:admin"); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java new file mode 100644 index 00000000..2c847ca8 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserDTO.java @@ -0,0 +1,37 @@ +package com.qs.serve.common.framework.security.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 用户登录信息 + * @author YenHex + * @since 2022/3/1 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class LoginUserDTO { + + private String userId; + + private String nick; + + private String password; + + private String loginIp; + + private String typeFlagCode; + + private List authorList; + private List authorIds; + private String tenant; + + public LoginUser loginUser(){ + return new LoginUser(userId,nick,password,loginIp,LoginUserType.getByCode(typeFlagCode),authorList,authorIds,tenant); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java new file mode 100644 index 00000000..8538e038 --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/model/LoginUserType.java @@ -0,0 +1,34 @@ +package com.qs.serve.common.framework.security.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Getter +@AllArgsConstructor +public enum LoginUserType { + + /** + * 人员分类 + */ + APP_USER("00","微信用户"), + SYS_USER("01","系统人员"), + SYS_SUP_USER("02","超级管理员") + ; + + private String code; + private String name; + + public static LoginUserType getByCode(String code){ + for (LoginUserType value : LoginUserType.values()) { + if(value.getCode().equals(code)){ + return value; + } + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java b/src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java new file mode 100644 index 00000000..a32d674d --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/service/SysUserDetailsServiceImpl.java @@ -0,0 +1,31 @@ +package com.qs.serve.common.framework.security.service; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Service +@AllArgsConstructor +public class SysUserDetailsServiceImpl implements UserDetailsService { + + private final SysUserService sysUserService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return sysUserService.getLoginUserByAccount(username); + } + + public LoginUser buildLoginUser(SysUser sysUser){ + return sysUserService.buildLoginUser(sysUser); + } + +} diff --git a/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java b/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java new file mode 100644 index 00000000..b03fac8d --- /dev/null +++ b/src/main/java/com/qs/serve/common/framework/security/util/SecurityPermitUtil.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.framework.security.util; + +/** + * @Author JcYen + * @Date 2021/9/24 + * @Version 1.0 + */ +public class SecurityPermitUtil { + + public static boolean verify(String reg, String input){ + if ("/*".equals(reg)) return true; + String[] reg_split = reg.split("\\*"); + int index = 0, reg_len = reg_split.length; + boolean b = reg.charAt(reg.length() - 1) == '*' ? true : false; + while (input.length() > 0) { + if (index == reg_len) { + if (b) return true; + else return false; + } + String r = reg_split[index++]; + int indexOf = input.indexOf(r); + if (indexOf != 0) return false; + input = input.substring(indexOf + r.length()); + } + return true; + } + +} diff --git a/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java b/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java new file mode 100644 index 00000000..9aa883d4 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/HttpResponsePrintUtil.java @@ -0,0 +1,34 @@ +package com.qs.serve.common.model; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author YenHex + * @since 2022/3/30 + */ +public class HttpResponsePrintUtil { + + public static void print(HttpServletResponse response,Integer code ,String msg) throws IOException,SecurityException{ + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS"); + response.setHeader("Access-Control-Max-Age", "86400"); + response.setHeader("Access-Control-Allow-Headers", "*"); + response.setStatus(200); + response.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().print("{\"status\":"+code+",\"msg\":\""+msg+"\"}"); + response.getWriter().flush(); + } + + public static void print2(HttpServletResponse response,Integer code ,String msg)throws IOException,SecurityException{ + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().print("{\"status\":"+code+",\"msg\":\""+msg+"\"}"); + response.getWriter().flush(); + } + + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java b/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java new file mode 100644 index 00000000..8ec4ce59 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/LimitSubmit.java @@ -0,0 +1,25 @@ +package com.qs.serve.common.model.annotation; + +import java.lang.annotation.*; + +/** + * 防止表单重复提交 + * @author YenHex + * @since 2022-03-01 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface LimitSubmit { + + /** + * 间隔时间(ms),在世界间隔内超过执行次数,视为被限制 + */ + int interval() default 1000; + + /** + * 提示消息 + */ + String message() default ""; + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java b/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java new file mode 100644 index 00000000..5bd1eba4 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/RepeatSubmit.java @@ -0,0 +1,20 @@ +package com.qs.serve.common.model.annotation; + +/** + * 防止表单重复提交 + * @author YenHex + * @since 2022-03-01 + */ +public @interface RepeatSubmit { + + /** + * 间隔时间(ms),小于此时间视为重复提交 + */ + int interval() default 5000; + + /** + * 提示消息 + */ + String message() default "不允许重复提交,请稍后再试"; + +} diff --git a/src/main/java/com/qs/serve/common/model/annotation/SysLog.java b/src/main/java/com/qs/serve/common/model/annotation/SysLog.java new file mode 100644 index 00000000..cb30b557 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/annotation/SysLog.java @@ -0,0 +1,35 @@ +package com.qs.serve.common.model.annotation; + +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.model.enums.SystemModule; + +import java.lang.annotation.*; + +/** + * 记录用户登录操作 + * @author YenHex + * @since 2022-03-01 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SysLog { + + SystemModule module() default SystemModule.SYSTEM; + + /** 业务标题 */ + String title() default ""; + + /** 操作描述 */ + String desc() default ""; + + /** 操作类型 */ + BizType biz() default BizType.OTHER; + + /** 接口类型 */ + InterType inter() default InterType.ADMIN; + + boolean saveReqParam() default true; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/DateConst.java b/src/main/java/com/qs/serve/common/model/consts/DateConst.java new file mode 100644 index 00000000..6cf1d015 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/DateConst.java @@ -0,0 +1,10 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/2/24 + */ +public class DateConst { + + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/GySysConst.java b/src/main/java/com/qs/serve/common/model/consts/GySysConst.java new file mode 100644 index 00000000..34598ff4 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/GySysConst.java @@ -0,0 +1,40 @@ +package com.qs.serve.common.model.consts; + +/** + * 系统字段 + * @author YenHex + * @since 2022/2/24 + */ +public class GySysConst { + + /** 后台身份验证 */ + public static final String AUTHORIZATION_PROP = "Authorization"; + + /** API身份验证 */ + public static final String APP_TOKEN_PROP = "token"; + + /** 请求头参数 */ + public static final String USER_AGENT_PROP = "User-Agent"; + + public static final String TENANT_PROP = "tenant-id"; + + /** 系统租户数据库列 */ + public static final String TENANT_COLUMN = "tenant_id"; + + /** 第三方应用id。如:公众号 */ + public static final String APP_ID_PROP = "appid"; + + /** 通用参数 */ + public static final int STATUS_YES_1 = 1; + public static final int STATUS_NO_1 = 0; + + public static final String LANG_ZH_CN = "zh_CN"; + + + public static final String ROLE_ADMIN_OPT_LOG = "sys:operationLog:admin"; + public static final String ROLE_ADMIN_REG = "edu:reg:admin"; + + public static final String DEFAULT_PASSWORD = "12345678"; + + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/OssConst.java b/src/main/java/com/qs/serve/common/model/consts/OssConst.java new file mode 100644 index 00000000..6a8b2d2e --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/OssConst.java @@ -0,0 +1,32 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/5/10 + */ +public class OssConst { + + /** + * 访问类型 + */ + public static final String ACCESS_OWNER = "own"; + public static final String ACCESS_DEPT = "dept"; + + /** + * 文件夹前缀 + */ + public static final String OWNER_DIR = "owner/"; + public static final String DEPT_DIR = "dept/"; + public static final String SPLIT = "/"; + + /** + * Tag + */ + public static final String TAG_CREATOR = "creator"; + public static final String TAG_CREATE_BY = "create_by"; + + public static final String FILE_TYPE_DIR = "文件夹"; + + public static final String DIR_TYPE_UNKNOWN = "未知"; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java b/src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java new file mode 100644 index 00000000..85507a68 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/RedisCacheKeys.java @@ -0,0 +1,30 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public class RedisCacheKeys { + + /** 权限列表 */ + public final static String PERMIT_ALL_LIST = "expire_permit_list"; + + /** 租户列表 */ + public final static String Tenant_ALL_LIST = "expire_tenant_list"; + + /** 管理员登录key */ + public final static String LOGIN_KEY_ADMIN = "login_admin_:"; + + /** 家长登录key */ + public final static String LOGIN_KEY_WX = "login_wx_:"; + + /** 用户登录APP {}客户端 {}用户ID */ + public final static String LOGIN_KEY_APP = "login_app_{}:{}:"; + + /** 手机号验证吗 */ + public final static String PHONE_KEY = "phone_code_:"; + + /** 工号标识 */ + public final static String SYS_USER_CODE_KEY = "sys_user_code_:"; + +} diff --git a/src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java b/src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java new file mode 100644 index 00000000..26b244df --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/consts/RedisListenerKeys.java @@ -0,0 +1,12 @@ +package com.qs.serve.common.model.consts; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public class RedisListenerKeys { + + public final static String EXPIRED_TYPE = "__keyevent@*__:expired"; + + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/PageVo.java b/src/main/java/com/qs/serve/common/model/dto/PageVo.java new file mode 100644 index 00000000..c068305b --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/PageVo.java @@ -0,0 +1,46 @@ +package com.qs.serve.common.model.dto; + +import com.qs.serve.common.util.PageUtil; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class PageVo{ + + /** + * 页幅 + */ + private Integer pageSize; + + /** + * 页眉 + */ + private Integer pageNum; + + /** + * 总数据数 + */ + private Long total; + + /** + * 总页数 + */ + private Long totalPage; + + /** + * 数据列表 + */ + private List list; + + public void initPageByTotal(long total){ + this.total = total; + this.pageNum = PageUtil.getPageNum(); + this.pageSize = PageUtil.getPageSize(); + if(pageSize==null||pageSize==0){ return; } + this.totalPage = total%pageSize==0?total/pageSize:(total/pageSize+1); + } + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/R.java b/src/main/java/com/qs/serve/common/model/dto/R.java new file mode 100644 index 00000000..e2e67b87 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/R.java @@ -0,0 +1,173 @@ +package com.qs.serve.common.model.dto; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.pagehelper.PageInfo; +import com.qs.serve.common.util.PageUtil; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 统一返回封装 + * 1.替代旧版的ViewResult + * 2.支持SmartDoc + * @author JcYen + * @date 2021/4/22 + * @version 2.0 + */ +@Getter +@Setter +public class R implements Serializable { + + public R(int status, String msg) { + this.status = status; + this.msg = msg; + } + + public R(int status, String msg, T data) { + this.status = status; + this.msg = msg; + this.data = data; + } + + /** + * 状态码 + */ + private Integer status; + + /** + * 信息 + */ + private String msg; + + /** + * 数据 + */ + private T data; + + public static final int SUCCESS_STATUS = 200; + public static final int LOGOUT_STATUS = 401; + public static final int FORBIDDEN_STATUS = 403; + public static final int NOT_FOUND_STATUS = 434; + public static final int FAILED_STATUS = 500; + + public static final String SUCCESS_TIPS = "操作成功"; + public static final String FAILED_TIPS = "操作失败"; + public static final String FAILED_TIPS_2 = "业务操作失败"; + public static final String LOGOUT_TIPS = "登录无效"; + public static final String FORBIDDEN_TIPS = "无权限访问"; + public static final String NOT_FOUND_TIPS = "数据不存在或被移除"; + + public static R ok() { + return new R(SUCCESS_STATUS,SUCCESS_TIPS,null); + } + + public static R ok(String msg) { + return new R<>(SUCCESS_STATUS,msg,null); + } + + public static R ok(TYPE data) { + return new R<>(SUCCESS_STATUS,SUCCESS_TIPS,data); + } + + public static R ok(TYPE data,String message) { + return new R<>(SUCCESS_STATUS,message,data); + } + + public static R isTrue(Boolean bool){ + if(bool==null|| !bool){ + return error(); + } + return ok(); + } + + public static R isTrue(Boolean bool, String message){ + if(bool==null|| !bool){ + return error(message); + } + return ok(null,message); + } + + + public static R isNotNull(TYPE object){ + if(object==null){ + return error(); + } + return ok(object,SUCCESS_TIPS); + } + + public static R isOk(Boolean rs){ + if(rs==null){ + return error(); + } + return ok(); + } + + public static R isOk(Boolean rs,String errMsg){ + if(rs==null){ + return error(errMsg); + } + return ok(); + } + + public static R error(String message) { + return new R<>(FAILED_STATUS,message,null); + } + + public static R error() { + return new R<>(FAILED_STATUS,FAILED_TIPS,null); + } + + public static R error2() { + return new R<>(FAILED_STATUS,FAILED_TIPS_2,null); + } + + public static R> byMbpList(IPage page){ + PageVo pageVo = new PageVo<>(); + pageVo.initPageByTotal(page.getTotal()); + pageVo.setList(page.getRecords()); + return R.ok(pageVo); + } + + public static R> byMbpList(IPage page,List data){ + PageVo pageVo = new PageVo<>(); + pageVo.initPageByTotal(page.getTotal()); + pageVo.setList(data); + return R.ok(pageVo); + } + + public static R> byPageHelperList(List data){ + PageVo pageVo = new PageVo<>(); + PageInfo pageInfo = new PageInfo<>(data); + pageVo.setPageSize(pageInfo.getPageSize()); + pageVo.setPageNum(pageInfo.getPageNum()); + pageVo.setTotal(pageInfo.getTotal()); + pageVo.setList(data); + pageVo.setTotalPage(new Long(pageInfo.getPages())); + return R.ok(pageVo); + } + + public static R> byEmptyList(){ + PageVo pageVo = new PageVo<>(); + pageVo.setPageSize(PageUtil.getPageSize()); + pageVo.setPageNum(PageUtil.getPageNum()); + pageVo.setTotal(0L); + pageVo.setList(null); + pageVo.setTotalPage(0L); + return R.ok(pageVo); + } + + public static R> byPageHelperList(List sources,List details){ + PageVo pageVo = new PageVo<>(); + PageInfo pageInfo = new PageInfo<>(sources); + pageVo.setPageSize(pageInfo.getPageSize()); + pageVo.setPageNum(pageInfo.getPageNum()); + pageVo.setTotal(pageInfo.getTotal()); + pageVo.setList(details); + pageVo.setTotalPage(new Long(pageInfo.getPages())); + return R.ok(pageVo); + } + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java b/src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java new file mode 100644 index 00000000..3681dcc2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/SimpleKeyValue.java @@ -0,0 +1,23 @@ +package com.qs.serve.common.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Data +@AllArgsConstructor +public class SimpleKeyValue { + + /** 键 */ + private String label; + + /** 值 */ + private T value; + + /** 说明 */ + private String remark; + +} diff --git a/src/main/java/com/qs/serve/common/model/dto/TreeNode.java b/src/main/java/com/qs/serve/common/model/dto/TreeNode.java new file mode 100644 index 00000000..84174cb5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/dto/TreeNode.java @@ -0,0 +1,30 @@ +package com.qs.serve.common.model.dto; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 树节点 + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class TreeNode { + protected String id; + protected String parentId; + private Integer sort; + protected List children = new ArrayList<>(); + + public void addChildren(TreeNode treeNode) { + children.add(treeNode); + } + + public List getChildren() { + if(children.size()<=0){ + return null; + } + return children; + } +} diff --git a/src/main/java/com/qs/serve/common/model/enums/BizType.java b/src/main/java/com/qs/serve/common/model/enums/BizType.java new file mode 100644 index 00000000..278c6358 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/BizType.java @@ -0,0 +1,49 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/3/8 + */ +@Getter +@AllArgsConstructor +public enum BizType { + + /** 其它 */ + OTHER("其它"), + + /** 新增 */ + INSERT("新增"), + + /** 修改 */ + UPDATE("修改"), + + /** 删除 */ + DELETE("删除"), + + /** 授权 */ + GRANT("授权"), + + /** 强退 */ + FORCE("强退"), + + /** 清空数据 */ + CLEAN("清空"), + + /** 登录 */ + LOGIN("登录"), + + LOGOUT("登出"), + + UPLOAD("上传"), + + DOWNLOAD("下载"), + + QUERY("查询"), + + RESET("重置"); + + String value; +} diff --git a/src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java b/src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java new file mode 100644 index 00000000..982e41fc --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/ExcelFilePath.java @@ -0,0 +1,19 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; + +/** + * @author YenHex + * @since 2022/3/10 + */ +@AllArgsConstructor +public enum ExcelFilePath { + + /** 地址 */ + EDU_REG_ARCHIVE_IN("1000",""); + + String code; + + String path; + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/HttpCode.java b/src/main/java/com/qs/serve/common/model/enums/HttpCode.java new file mode 100644 index 00000000..edf94ee9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/HttpCode.java @@ -0,0 +1,44 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 请求状态码 + * @author YenHex + * @since 2022/2/28 + */ +@Getter +@AllArgsConstructor +public enum HttpCode { + + /** 基本参数 */ + SUCCESS(200,"操作成功"), + ERROR(500,"操作失败"), + DEV_ERR(500,"部分功能开发中..."), + WX_ERR(500,"微信服务调用异常"), + + LOGIN_ERR(401,"登录信息已过期或失效"), + LOGIN_ERR_2(500,"该账号已被停用,请联系系统管理员"), + LOGIN_ERR_1(500,"账号或登录密码不正确"), + LOGIN_ERR_4001(4001,"校区信息错误"), + LOGIN_ERR_4002(4002,"应用信息错误"), + + + /** 资源权限相关 */ + FORBIDDEN_403(403,"权限不足,无法访问"), + FORBIDDEN_403_1(403,"账套未注册,无权访问"), + FORBIDDEN_403_2(403,"客户端未注册,无权访问"), + FORBIDDEN_403_3(403,"IP地址未注册,无权访问"), + FORBIDDEN_403_4(403,"无招生超管权限,无权访问"), + FORBIDDEN_404(404,"资源不存在或被移除"), + FORBIDDEN_406(406,"系统正常处理,请勿重复提交"), + + + ERROR_EDU_SCHOOL_YEAR(5031,"当前学年信息错误,请重新设置当前学年"), + ; + + Integer code; + String msg; + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/InterType.java b/src/main/java/com/qs/serve/common/model/enums/InterType.java new file mode 100644 index 00000000..daf54951 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/InterType.java @@ -0,0 +1,21 @@ +package com.qs.serve.common.model.enums; + +/** + * @author YenHex + * @since 2022/3/8 + */ +public enum InterType { + + /** + * 前台接口 + */ + API, + + + + /** + * 后台接口 + */ + ADMIN + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/PolicyType.java b/src/main/java/com/qs/serve/common/model/enums/PolicyType.java new file mode 100644 index 00000000..d1a26a94 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/PolicyType.java @@ -0,0 +1,35 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * minio策略配置 + * @author YenHex + * @since 2022/5/10 + */ +@Getter +@AllArgsConstructor +public enum PolicyType { + + /** + * 只读 + */ + READ("read-only"), + + /** + * 只写 + */ + WRITE("write-only"), + + /** + * 读写 + */ + READ_WRITE("read-write"); + + /** + * 类型 + */ + private final String type; + +} diff --git a/src/main/java/com/qs/serve/common/model/enums/SystemModule.java b/src/main/java/com/qs/serve/common/model/enums/SystemModule.java new file mode 100644 index 00000000..e2ff16d2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/enums/SystemModule.java @@ -0,0 +1,22 @@ +package com.qs.serve.common.model.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/7/25 + */ +@Getter +@AllArgsConstructor +public enum SystemModule { + + QUESTION("qms","问卷"), + SYSTEM("sys","系统"), + UMS("ums","手机用户"); + + String code; + + String vale; + +} diff --git a/src/main/java/com/qs/serve/common/model/group/EditGroup.java b/src/main/java/com/qs/serve/common/model/group/EditGroup.java new file mode 100644 index 00000000..e2fab748 --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/group/EditGroup.java @@ -0,0 +1,8 @@ +package com.qs.serve.common.model.group; + +/** + * @author YenHex + * @since 2022/5/16 + */ +public interface EditGroup { +} diff --git a/src/main/java/com/qs/serve/common/model/group/SaveGroup.java b/src/main/java/com/qs/serve/common/model/group/SaveGroup.java new file mode 100644 index 00000000..e83376aa --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/group/SaveGroup.java @@ -0,0 +1,8 @@ +package com.qs.serve.common.model.group; + +/** + * @author YenHex + * @since 2022/5/16 + */ +public interface SaveGroup { +} diff --git a/src/main/java/com/qs/serve/common/model/group/SearchGroup.java b/src/main/java/com/qs/serve/common/model/group/SearchGroup.java new file mode 100644 index 00000000..2ddbdd2e --- /dev/null +++ b/src/main/java/com/qs/serve/common/model/group/SearchGroup.java @@ -0,0 +1,8 @@ +package com.qs.serve.common.model.group; + +/** + * @author YenHex + * @since 2022/5/16 + */ +public interface SearchGroup { +} diff --git a/src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java b/src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java new file mode 100644 index 00000000..d7fadaa0 --- /dev/null +++ b/src/main/java/com/qs/serve/common/service/RedisBaseListenerImpl.java @@ -0,0 +1,26 @@ +package com.qs.serve.common.service; + +import com.qs.serve.common.util.AuthContextUtils; + +/** + * @author YenHex + * @since 2022/7/4 + */ +public abstract class RedisBaseListenerImpl implements RedisServiceListener{ + + @Override + public String getKey(String pk) { + return getPrefix()+pk+"_"+ AuthContextUtils.getTenant(); + } + + public String getPk(String key){ + return key.replace(getPrefix(),"") + .replace("_"+AuthContextUtils.getTenant(),""); + } + + @Override + public void doJob(String key) { + String[] vals = key.split("_"); + AuthContextUtils.setTenant(vals[vals.length-1]); + } +} diff --git a/src/main/java/com/qs/serve/common/service/RedisServiceListener.java b/src/main/java/com/qs/serve/common/service/RedisServiceListener.java new file mode 100644 index 00000000..8741860b --- /dev/null +++ b/src/main/java/com/qs/serve/common/service/RedisServiceListener.java @@ -0,0 +1,33 @@ +package com.qs.serve.common.service; + +/** + * @author YenHex + * @since 2022/7/4 + */ +public interface RedisServiceListener { + + /** + * 业务前缀 + * @return + */ + String getPrefix(); + + /** + * 获取完整的key + * @param pk + * @return + */ + String getKey(String pk); + + /** + * 同步最近时间段任务,添加redis实现监听 + */ + void syncTask(); + + /** + * 监听过期得key + * @param key + */ + void doJob(String key); + +} diff --git a/src/main/java/com/qs/serve/common/util/Assert.java b/src/main/java/com/qs/serve/common/util/Assert.java new file mode 100644 index 00000000..d1f440bc --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/Assert.java @@ -0,0 +1,28 @@ +package com.qs.serve.common.util; + + +import com.qs.serve.common.framework.exception.BusinessException; +import com.qs.serve.common.model.enums.HttpCode; +import lombok.experimental.UtilityClass; + +/** + * 抛出异常工具类 + * @author YenHex + * @since 2022/2/25 + */ +@UtilityClass +public class Assert { + + public static void throwEx(Integer code,String msg){ + throw new BusinessException(msg, code); + } + + public static void throwEx(HttpCode httpCode){ + throw new BusinessException(httpCode.getMsg(),httpCode.getCode()); + } + + public static void throwEx(String msg){ + throw new BusinessException(msg,500); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/AuthContextUtils.java b/src/main/java/com/qs/serve/common/util/AuthContextUtils.java new file mode 100644 index 00000000..1e1f179c --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/AuthContextUtils.java @@ -0,0 +1,109 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.enums.HttpCode; +import lombok.experimental.UtilityClass; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.Objects; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@UtilityClass +public class AuthContextUtils { + + private final static ThreadLocal THREAD_TENANT = new ThreadLocal<>(); + + public static String getAppId(){ + return getAppId(true); + } + + public static String getAppId(boolean throwEx){ + String appId = ServletUtils.getHeader(GySysConst.APP_ID_PROP); + if(throwEx&&StringUtils.isEmpty(appId)){ + Assert.throwEx(HttpCode.LOGIN_ERR_4002); + } + return appId; + } + + /** + * 获取用户登录信息 + * @return + */ + public static LoginUser getLoginUser(){ + return getLoginUser(true); + } + + /** + * 获取微信用户ID + * @return + */ + public static String getAppUserId(){ + LoginUser loginUser = getLoginUser(); + if(loginUser.getTypeFlag().equals(LoginUserType.APP_USER)){ + return loginUser.getUserId(); + } + return null; + } + + /** + * 系统用户ID + * @return + */ + public static String getSysUserId(){ + LoginUser loginUser = getLoginUser(); + if(loginUser.getTypeFlag().equals(LoginUserType.SYS_SUP_USER) + ||loginUser.getTypeFlag().equals(LoginUserType.SYS_USER)){ + return loginUser.getUserId(); + } + return null; + } + + /** + * 判断是否超级管理员 + * @return + */ + public static boolean isSupAdmin(){ + return Objects.requireNonNull(getLoginUser(false)) + .getTypeFlag().equals(LoginUserType.SYS_SUP_USER); + } + + public static void setTenant(String value){THREAD_TENANT.set(value);} + + public static String getTenant(){return THREAD_TENANT.get();} + + public static void removeTenant(){THREAD_TENANT.remove();} + + public static LoginUser getLoginUser(boolean throwEx){ + UserDetails details = getUserDetail(throwEx); + if(details instanceof LoginUser){ + return (LoginUser) details; + } + return null; + } + + private static UserDetails getUserDetail(boolean throwEx){ + SecurityContext ctx = SecurityContextHolder.getContext(); + Authentication auth = ctx.getAuthentication(); + if (auth != null) { + Object authPri = auth.getPrincipal(); + if (authPri instanceof UserDetails) { + UserDetails details = (UserDetails) authPri; + return details; + } + } + if(throwEx){ + throw new UsernameNotFoundException("未登录或被登出"); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/CollectionUtil.java b/src/main/java/com/qs/serve/common/util/CollectionUtil.java new file mode 100644 index 00000000..b5662829 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/CollectionUtil.java @@ -0,0 +1,90 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/25 + */ +@UtilityClass +public class CollectionUtil extends cn.hutool.core.collection.CollectionUtil{ + + /** + * 去除list中的重复数据 + */ + public static List removeRepeat(List list) { + if (isEmpty(list)) { + return list; + } + List result = new ArrayList(); + for (T e : list) { + if (!result.contains(e)) { + result.add(e); + } + } + return result; + } + + public static boolean hasNull(Object... objects){ + for (int i = 0; i < objects.length; i++) { + if(objects[i]==null){return true;} + } + return false; + } + + public static boolean hasNotNull(Object... objects){ + for (int i = 0; i < objects.length; i++) { + if(objects[i]!=null){return true;} + } + return false; + } + + /** + * 将集合转换为String数组 + */ + public static String[] toArray(List list) { + if (isEmpty(list)) { + return null; + } + String[] result = new String[list.size()]; + for (int i = 0; i < list.size(); i++) { + result[i] = String.valueOf(list.get(i)); + } + return result; + } + + /** + * 将list拆分成多给指定的大小的list + */ + public static List> createList(List target, int size) { + List> listArr = new ArrayList<>(); + //获取被拆分的数组个数 + int arrSize = target.size()%size==0?target.size()/size:target.size()/size+1; + for(int i=0;i sub = new ArrayList(); + //把指定索引数据放入到list中 + for(int j=i*size;j<=size*(i+1)-1;j++) { + if(j<=target.size()-1) { + sub.add(target.get(j)); + } + } + listArr.add(sub); + } + return listArr; + } + + public static boolean isNotEmpty(T[] arr){ + return arr!=null && arr.length>0; + } + + public static T selectFirst(List list){ + if(isNotEmpty(list)){ + return list.get(0); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/CopierUtil.java b/src/main/java/com/qs/serve/common/util/CopierUtil.java new file mode 100644 index 00000000..a79c226a --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/CopierUtil.java @@ -0,0 +1,95 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; +import org.springframework.cglib.beans.BeanCopier; + +import java.io.*; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 取代BeanUtils.CP + * @Author JcYen + * @Date 2019/6/3 + * @Version 1.0 + */ +@UtilityClass +public class CopierUtil { + + private static final Map BEAN_COPIERS = new ConcurrentHashMap(); + + private static String genKey(Class source, Class target) { + return source.getName() + target.getName(); + } + + /** + * target字段值,会被source字段值覆盖(包括null) + * @param source + * @param target + */ + public static T copy(Object source, T target) { + String key = genKey(source.getClass(), target.getClass()); + BeanCopier copier; + if (!BEAN_COPIERS.containsKey(key)) { + copier = BeanCopier.create(source.getClass(), target.getClass(), false); + BEAN_COPIERS.put(key, copier); + } else { + copier = BEAN_COPIERS.get(key); + } + copier.copy(source, target, null); + return target; + } + + + /** + * 采用对象的序列化完成对象的深克隆 + * @param obj 待克隆的对象 + * @return + */ + @SuppressWarnings("unchecked") + public static T cloneObject(T obj) { + T cloneObj = null; + try { + // 写入字节流 + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream obs = new ObjectOutputStream(out); + obs.writeObject(obj); + obs.close(); + + // 分配内存,写入原始对象,生成新对象 + ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(ios); + // 返回生成的新对象 + cloneObj = (T) ois.readObject(); + ois.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return cloneObj; + } + + /** + * 利用序列化完成集合的深克隆 + * + * @param collection 待克隆的集合 + * @return + * @throws ClassNotFoundException + * @throws IOException + */ + @SuppressWarnings("unchecked") + public static Collection cloneCollection(Collection collection) throws ClassNotFoundException, IOException{ + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(collection); + out.close(); + + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + Collection dest = (Collection) in.readObject(); + in.close(); + + return dest; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/DateUtils.java b/src/main/java/com/qs/serve/common/util/DateUtils.java new file mode 100644 index 00000000..46da23fc --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/DateUtils.java @@ -0,0 +1,98 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.util.model.DateFormatString; +import lombok.experimental.UtilityClass; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Date; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@UtilityClass +public class DateUtils { + + public static String getString(DateFormatString format){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format.getValue()); + return LocalDateTime.now().format(formatter); + } + + /** + * 获取设置后得时间 + * @param time + * @param unit + * @param num + * @return + */ + public static LocalDateTime beSetTime(LocalDateTime time, ChronoUnit unit,int num){ + if(num>0){ + return time.plus(num,unit); + }else { + return time.minus(-num,unit); + } + } + + public static LocalDate beSetDate(LocalDate time,int days){ + return time.plusDays(days); + } + + public static Date toDate(String str,String format){ + SimpleDateFormat sdf = new SimpleDateFormat(format); + try { + return sdf.parse(str); + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + public static Date toDate(LocalDateTime time){ + return Date.from( time.atZone( ZoneId.systemDefault()).toInstant()); + } + + public static double diffTime(long beganTime, long endTime) { + return (double)(endTime - beganTime) / 1000.0D; + } + + public static String format(LocalDateTime localDateTime, DateFormatString format){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format.getValue()); + return localDateTime.format(formatter); + } + + public static String datePath(){ + return format(LocalDate.now(),DateFormatString.DATE); + } + + public static String format(LocalDate localDate, DateFormatString format){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format.getValue()); + return localDate.format(formatter); + } + + public static void main(String[] args) { + System.out.println(DateUtils.beSetTime(LocalDateTime.now(), ChronoUnit.DAYS,-2)); + // Get the LocalDateTime instance + LocalDateTime ldt + = LocalDateTime + .parse("2019-12-31T19:15:30"); + + // Get the String representation of this LocalDateTime + System.out.println("Original LocalDateTime: " + + ldt.toString()); + + // subtract 200 DAYS to LocalDateTime + LocalDateTime value + = ldt.minus(200, ChronoUnit.DAYS); + + // print result + System.out.println("LocalDateTime after subtracting DAYS: " + + value); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/IdUtil.java b/src/main/java/com/qs/serve/common/util/IdUtil.java new file mode 100644 index 00000000..d08da9d1 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/IdUtil.java @@ -0,0 +1,51 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.lang.Snowflake; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Random; + +/** + * @author YenHex + * @since 2022/3/3 + */ +public class IdUtil extends cn.hutool.core.util.IdUtil { + + private static final long BASE_DIFF_MILLIS = 1648013774104L; + + private static final Snowflake snowflake = getSnowflake(1,1); + + public static String timeStampId() { + long millis = System.currentTimeMillis(); + String prefix = String.format("%013d", millis-BASE_DIFF_MILLIS); + Random random = new Random(); + int end2 = random.nextInt(999); + return prefix + String.format("%03d", end2); + } + + public static Long timeStampLong() { + return System.currentTimeMillis()-BASE_DIFF_MILLIS; + } + + public static String dateTimeStampId() { + LocalDateTime localDateTime = LocalDateTime.now(); + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String localTime = df.format(localDateTime); + Random random = new Random(); + int end2 = random.nextInt(999); + return localTime + String.format("%03d", end2); + } + + public static String genCode(int len) { + int max = new Double(Math.pow(10, len)).intValue() - 1; + Random random = new Random(); + int end2 = random.nextInt(max); + return String.format("%0"+len+"d", end2); + } + + public static long getSnowFlakeId(){ + return snowflake.nextId(); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/JsonUtil.java b/src/main/java/com/qs/serve/common/util/JsonUtil.java new file mode 100644 index 00000000..2e7c66b7 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/JsonUtil.java @@ -0,0 +1,99 @@ +package com.qs.serve.common.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.experimental.UtilityClass; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +/** + * Jackson json序列化和反序列化工具类 + * @Author JcYen + * @Date 2019/6/3 + * @Version 1.0 + */ +@UtilityClass +public class JsonUtil { + + /** + * jackson对象 + */ + static final ObjectMapper MAPPER = new ObjectMapper(); + + static { + MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); + MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + /** + * 将对象转换成json字符串。 + */ + public static String objectToJson(Object data) { + try { + String string = MAPPER.writeValueAsString(data); + return string; + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 将json结果集转化为对象 + * + * @param jsonData json数据 + * @param beanType 对象中的object类型 + */ + public static T jsonToPojo(String jsonData, Class beanType) { + try { + T t = MAPPER.readValue(jsonData, beanType); + return t; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 将json数据转换成pojo对象list + */ + public static List jsonToList(String jsonData, Class beanType) { + JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); + try { + List list = MAPPER.readValue(jsonData, javaType); + return list; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Map jsonToMap(String jsonStr){ + Map json = JSONObject.parseObject(jsonStr, Map.class); + return json; + } + + public static Map objectToMap(Object object){ + Map map = JSONObject.parseObject(JSON.toJSONString(object)); + return map; + } + + public static List> listToMap(List objects){ + List> result = new ArrayList<>(); + for (T object : objects) { + Map map = objectToMap(object); + result.add(map); + } + return result; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/JwtUtils.java b/src/main/java/com/qs/serve/common/util/JwtUtils.java new file mode 100644 index 00000000..9f1c272e --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/JwtUtils.java @@ -0,0 +1,82 @@ +package com.qs.serve.common.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.qs.serve.common.config.JwtConfig; +import com.qs.serve.common.framework.security.model.LoginUserType; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.BadCredentialsException; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Slf4j +public class JwtUtils { + + private final static String USER_ID_CLAIM = "UID"; + private final static String USER_TYPE_CLAIM = "TYPE"; + private final static String USER_CLIENT_CLAIM = "CLIENT"; + + private final static JwtConfig jwtConfig = new JwtConfig(); + + public static String generateToken(String userId, LoginUserType userType,String client) { + LocalDateTime dateTime = LocalDateTime.now(); + LocalDateTime exTime = DateUtils.beSetTime(dateTime, ChronoUnit.DAYS,jwtConfig.getExpire()); + Algorithm algorithm = Algorithm.HMAC256(jwtConfig.getSecret()); + return JWT.create() + .withIssuer(jwtConfig.getIss()) + .withIssuedAt(DateUtils.toDate(dateTime)) + .withExpiresAt(DateUtils.toDate(exTime)) + .withClaim(USER_TYPE_CLAIM,userType.getCode()) + .withClaim(USER_ID_CLAIM,userId) + .withClaim(USER_CLIENT_CLAIM,client) + .sign(algorithm); + } + + public static boolean verify(String token) { + try{ + Algorithm algorithm = Algorithm.HMAC256(jwtConfig.getSecret()); + JWTVerifier verifier = JWT.require(algorithm) + .withIssuer(jwtConfig.getIss()) + .build(); + verifier.verify(token); + return true; + } catch (Exception ex){ + log.debug("令牌验证异常:{}",ex.getMessage()); + return false; + } + } + + public static String getUserId(String token) { + try{ + return JWT.decode(token).getClaim(USER_ID_CLAIM).asString(); + }catch (Exception ex){ + log.debug("方法:getUserId() 令牌验证异常:{}",ex.getMessage()); + throw new BadCredentialsException("调用凭证无效"); + } + } + + public static String getUserType(String token) { + try{ + return JWT.decode(token).getClaim(USER_TYPE_CLAIM).asString(); + }catch (Exception ex){ + log.debug("方法:getUserId() 令牌验证异常:{}",ex.getMessage()); + throw new BadCredentialsException("调用凭证无效"); + } + } + + public static String getClient(String token) { + try{ + return JWT.decode(token).getClaim(USER_CLIENT_CLAIM).asString(); + }catch (Exception ex){ + log.debug("方法:getUserId() 令牌验证异常:{}",ex.getMessage()); + throw new BadCredentialsException("调用凭证无效"); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/MinioUtil.java b/src/main/java/com/qs/serve/common/util/MinioUtil.java new file mode 100644 index 00000000..6425bff2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/MinioUtil.java @@ -0,0 +1,84 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.model.enums.PolicyType; +import lombok.experimental.UtilityClass; + +/** + * @author YenHex + * @since 2022/5/10 + */ +@UtilityClass +public class MinioUtil { + + public static String getPolicy(String bucketName, PolicyType policyType) { + StringBuilder builder = new StringBuilder(); + builder.append("{\n"); + builder.append(" \"Statement\": [\n"); + builder.append(" {\n"); + builder.append(" \"Action\": [\n"); + if (policyType == PolicyType.WRITE) { + builder.append(" \"s3:GetBucketLocation\",\n"); + builder.append(" \"s3:ListBucketMultipartUploads\"\n"); + } else if (policyType == PolicyType.READ_WRITE) { + builder.append(" \"s3:GetBucketLocation\",\n"); + builder.append(" \"s3:ListBucket\",\n"); + builder.append(" \"s3:ListBucketMultipartUploads\"\n"); + } else { + builder.append(" \"s3:GetBucketLocation\"\n"); + } + builder.append(" ],\n"); + builder.append(" \"Effect\": \"Allow\",\n"); + builder.append(" \"Principal\": \"*\",\n"); + builder.append(" \"Resource\": \"arn:aws:s3:::"); + builder.append(bucketName); + builder.append("\"\n"); + builder.append(" },\n"); + if (PolicyType.READ.equals(policyType)) { + builder.append(" {\n"); + builder.append(" \"Action\": [\n"); + builder.append(" \"s3:ListBucket\"\n"); + builder.append(" ],\n"); + builder.append(" \"Effect\": \"Deny\",\n"); + builder.append(" \"Principal\": \"*\",\n"); + builder.append(" \"Resource\": \"arn:aws:s3:::"); + builder.append(bucketName); + builder.append("\"\n"); + builder.append(" },\n"); + } + builder.append(" {\n"); + builder.append(" \"Action\": "); + switch (policyType) { + case WRITE: + builder.append("[\n"); + builder.append(" \"s3:AbortMultipartUpload\",\n"); + builder.append(" \"s3:DeleteObject\",\n"); + builder.append(" \"s3:ListMultipartUploadParts\",\n"); + builder.append(" \"s3:PutObject\"\n"); + builder.append(" ],\n"); + break; + case READ_WRITE: + builder.append("[\n"); + builder.append(" \"s3:AbortMultipartUpload\",\n"); + builder.append(" \"s3:DeleteObject\",\n"); + builder.append(" \"s3:GetObject\",\n"); + builder.append(" \"s3:ListMultipartUploadParts\",\n"); + builder.append(" \"s3:PutObject\"\n"); + builder.append(" ],\n"); + break; + default: + builder.append("\"s3:GetObject\",\n"); + break; + } + builder.append(" \"Effect\": \"Allow\",\n"); + builder.append(" \"Principal\": \"*\",\n"); + builder.append(" \"Resource\": \"arn:aws:s3:::"); + builder.append(bucketName); + builder.append("/*\"\n"); + builder.append(" }\n"); + builder.append(" ],\n"); + builder.append(" \"Version\": \"2012-10-17\"\n"); + builder.append("}\n"); + return builder.toString(); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/NanoIdUtils.java b/src/main/java/com/qs/serve/common/util/NanoIdUtils.java new file mode 100644 index 00000000..da8b07da --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/NanoIdUtils.java @@ -0,0 +1,60 @@ +package com.qs.serve.common.util; + +import java.security.SecureRandom; +import java.util.Random; + +/** + * @author YenHex + * @since 2022/4/11 + */ +public final class NanoIdUtils { + public static final SecureRandom DEFAULT_NUMBER_GENERATOR = new SecureRandom(); + public static final char[] DEFAULT_ALPHABET = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + public static final int DEFAULT_SIZE = 21; + + private NanoIdUtils() { + } + + public static String randomNanoId() { + return randomNanoId(DEFAULT_NUMBER_GENERATOR, DEFAULT_ALPHABET, 21); + } + + public static String randomNanoId(Random random, char[] alphabet, int size) { + if (random == null) { + throw new IllegalArgumentException("random cannot be null."); + } else if (alphabet == null) { + throw new IllegalArgumentException("alphabet cannot be null."); + } else if (alphabet.length != 0 && alphabet.length < 256) { + if (size <= 0) { + throw new IllegalArgumentException("size must be greater than zero."); + } else { + int mask = (2 << (int)Math.floor(Math.log((double)(alphabet.length - 1)) / Math.log(2.0D))) - 1; + int step = (int)Math.ceil(1.6D * (double)mask * (double)size / (double)alphabet.length); + StringBuilder idBuilder = new StringBuilder(); + + while(true) { + byte[] bytes = new byte[step]; + random.nextBytes(bytes); + + for(int i = 0; i < step; ++i) { + int alphabetIndex = bytes[i] & mask; + if (alphabetIndex < alphabet.length) { + idBuilder.append(alphabet[alphabetIndex]); + if (idBuilder.length() == size) { + return idBuilder.toString(); + } + } + } + } + } + } else { + throw new IllegalArgumentException("alphabet must contain between 1 and 255 symbols."); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 1000; i++) { + System.out.println(randomNanoId()); + } + } +} diff --git a/src/main/java/com/qs/serve/common/util/PageUtil.java b/src/main/java/com/qs/serve/common/util/PageUtil.java new file mode 100644 index 00000000..73a316aa --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/PageUtil.java @@ -0,0 +1,169 @@ +package com.qs.serve.common.util; + +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.pagehelper.PageHelper; +import com.qs.serve.common.framework.exception.BusinessException; +import lombok.experimental.UtilityClass; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 翻页工具类 + * @Author YenHex + * @Date 2021/6/9 + * @Version: 1.0 + **/ +@UtilityClass +public class PageUtil { + + private static final String PAGE_NUM = "pageNum"; + private static final String PAGE_SIZE = "pageSize"; + + private static final String ORDER_TYPE = "orderType"; + private static final String ORDER_PROP = "orderProp"; + + private static final String ORDER_TYPE_ASC = "ASC"; + private static final String ORDER_TYPE_DESC = "DESC"; + + private static final int MAX_PAGE_SIZE = 66; + + public static Page getMbpPage(){ + Integer pageNum = getPageNum(); + Integer pageSize = getPageSize(); + String orderProp = getOrderProp(); + String orderType = getOrderType(); + if ( pageNum ==null || pageNum<1 || pageSize==null || pageSize<1) { + throw new BusinessException("翻页参数异常",500); + } + Page page = new Page<>(); + page.setCurrent(pageNum); + page.setSize(pageSize); + if(StringUtils.hasText(orderProp)){ + OrderItem orderItem = new OrderItem(); + orderItem.setColumn(orderProp); + orderItem.setAsc(orderType.equals(ORDER_TYPE_ASC)); + List orderItems = new ArrayList<>(); + orderItems.add(orderItem); + page.setOrders(orderItems); + } + return page; + } + + public static Integer getPageNum(){ + Integer pageNum=null; + String pageNumStr = ServletUtils.getParameter(PAGE_NUM); + if(StringUtils.hasText(pageNumStr)){ + pageNum = Integer.parseInt(pageNumStr); + } + return pageNum; + } + + public static Integer getPageSize(){ + String pageSizeStr = ServletUtils.getParameter(PAGE_SIZE); + Integer pageSize = null; + if(StringUtils.hasText(pageSizeStr)){ + pageSize = Integer.parseInt(pageSizeStr); + } + if(pageSize!=null && pageSize > MAX_PAGE_SIZE){ + throw new BusinessException("超出数据额度",500); + } + return pageSize; + } + + public static String getOrderProp(){ + String orderProp = ServletUtils.getParameter(ORDER_PROP); + if(StringUtils.hasText(orderProp)){ + orderProp = orderProp.trim(); + if(orderProp.contains(".")){ + String[] strings = orderProp.split("\\."); + return strings[0]+"."+strings[1]; + } + return WordUtil.toLine(orderProp); + } + return null; + } + + public static String getOrderType(){ + String orderType = ServletUtils.getParameter(ORDER_TYPE); + if(StringUtils.hasText(orderType)){ + if(orderType.equalsIgnoreCase(ORDER_TYPE_DESC)){ + return ORDER_TYPE_DESC; + } + } + return ORDER_TYPE_ASC; + } + + public static Integer getStartRow(){ + Integer pageNum = getPageNum(); + Integer pageSize = getPageSize(); + if (pageNum==null || pageSize==null) { + throw new BusinessException("翻页参数异常",500); + } + return (pageNum-1)*pageSize; + } + + /** + * 启动翻页(翻页失败,会抛出异常) + * @return 是否使用翻页 + */ + public static boolean startPage(){ + return startPage(true); + } + + /** + * + * @param throwEx 是否抛异常 + * @return 是否使用翻页 + */ + public static boolean startPage(boolean throwEx){ + return startPage(null,null,throwEx); + } + + /** + * 执行翻页 + * @param object POJO + * @return 是否使用翻页 + */ + public static boolean startPage(T object){ + return startPage(object,null,true); + } + + public static boolean startPage(String prefix){ + return startPage(null,prefix,true); + } + /** + * + * @param throwEx 是否抛异常 + * @return 是否使用翻页 + */ + public static boolean startPage(T object,String prefix,boolean throwEx){ + Integer pageNum = getPageNum(); + Integer pageSize = getPageSize(); + String orderProp = getOrderProp(); + String orderType = getOrderType(); + if (pageNum!=null && pageNum>0 && pageSize!=null && pageSize>0) { + if(!StringUtils.isEmpty(orderProp)){ + if(prefix==null && object!=null){ + prefix = WordUtil.toLine(object.getClass().getSimpleName()); + } + if(prefix!=null){ + PageHelper.startPage(pageNum, pageSize).setOrderBy(prefix+"."+orderProp+" "+orderType); + }else { + PageHelper.startPage(pageNum, pageSize).setOrderBy(orderProp+" "+orderType); + } + return true; + } + PageHelper.startPage(pageNum, pageSize); + return true; + }else{ + if(throwEx){ + throw new BusinessException("翻页参数异常",500); + } + return false; + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/ServletUtils.java b/src/main/java/com/qs/serve/common/util/ServletUtils.java new file mode 100644 index 00000000..31cf4ca2 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/ServletUtils.java @@ -0,0 +1,129 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * Servlet容器工具类 + * @author YenHex + * @date 2021/6/9 + **/ +@UtilityClass +public class ServletUtils { + /** + * 获取String参数 + */ + public static String getParameter(String name) { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getHeader(String name) { + return getRequest().getHeader(name); + } + + /** + * 获取IP + * @return + */ + public static String getIp(HttpServletRequest request) { + if(request==null){ + request = getRequest(); + } + String ip = request.getHeader("x-forwarded-for"); + if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + + /** + * 判断本次请求的数据类型是否为json + * @param request request + * @return true: 是 JSON 数据; false: 非 json 数据 + */ + public static boolean isJsonRequest(HttpServletRequest request) { + if (request.getContentType() != null) { + return request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) || + request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE); + } + return false; + } + + /** + * 获取请求Body + * @param request + * @return + */ + public static String getBodyString(ServletRequest request) { + StringBuilder sb = new StringBuilder(); + InputStream inputStream = null; + BufferedReader reader = null; + try { + inputStream = request.getInputStream(); + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return sb.toString(); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + private static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/SmsReflectUtil.java b/src/main/java/com/qs/serve/common/util/SmsReflectUtil.java new file mode 100644 index 00000000..22b0dce5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/SmsReflectUtil.java @@ -0,0 +1,50 @@ +package com.qs.serve.common.util; + +import com.qs.serve.modules.wx.common.model.WxSmsProp; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/16 + */ +public class SmsReflectUtil { + + /** + * 反射获取WX_SMS配置 + * @param baseDto + * @param + * @return + */ + public static List getTemplateDataList(T baseDto){ + List dataList = new ArrayList<>(); + for (Field field : baseDto.getClass().getDeclaredFields()) { + WxSmsProp wxSmsProp = null; + for (Annotation annotation : field.getAnnotations()) { + if(annotation instanceof WxSmsProp){ + wxSmsProp = (WxSmsProp)annotation; + break; + } + } + try { + field.setAccessible(true); + Object fieldObject = field.get(baseDto); + String value = ""; + if(fieldObject!=null){ + value = fieldObject.toString(); + } + WxMpTemplateData templateData = new WxMpTemplateData(wxSmsProp.keyword(),value); + dataList.add(templateData); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return dataList; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/SpringUtils.java b/src/main/java/com/qs/serve/common/util/SpringUtils.java new file mode 100644 index 00000000..f38b8996 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/SpringUtils.java @@ -0,0 +1,148 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.collection.CollectionUtil; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +/** + * spring工具类 + * @author YenHex + * @since 2022/2/28 + */ +@Component +public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtils.applicationContext = applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return CollectionUtil.isNotEmpty(Arrays.asList(activeProfiles)) ? activeProfiles[0] : null; + } +} diff --git a/src/main/java/com/qs/serve/common/util/StringUtils.java b/src/main/java/com/qs/serve/common/util/StringUtils.java new file mode 100644 index 00000000..69d888b9 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/StringUtils.java @@ -0,0 +1,50 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; + +/** + * @author YenHex + * @since 2022/2/28 + */ +@UtilityClass +public class StringUtils extends org.springframework.util.StringUtils { + + /** 非空 */ + public static boolean isNotEmpty(String str){ + return !isEmpty(str); + } + + /** 含有空对象 */ + public static boolean hasEmpty(Object... strings){ + for (Object str : strings) { + if(isEmpty(str)){return true;} + } + return false; + } + + /** + * 格式化 + * @param exp 含{}的表达式 + * @param params 参数(注意跳过空值) + * @return + */ + public static String format(String exp,String... params){ + StringBuilder builder = new StringBuilder(exp); + int idx_p = 0; + while (hasText(builder,"{}")){ + int idx = builder.indexOf("{}"); + if(idx_p) { + try { + Future future = (Future) r; + if (future.isDone()) { + future.get(); + } + } catch (CancellationException ce) { + t = ce; + } catch (ExecutionException ee) { + t = ee.getCause(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + if (t != null) { + log.error(t.getMessage(), t); + } + } +} diff --git a/src/main/java/com/qs/serve/common/util/TokenUtil.java b/src/main/java/com/qs/serve/common/util/TokenUtil.java new file mode 100644 index 00000000..89aec72d --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/TokenUtil.java @@ -0,0 +1,46 @@ +package com.qs.serve.common.util; + + +import com.qs.serve.common.util.model.DesUtils; + +/** + * @author YenHex + * @since 2022/2/25 + */ +public class TokenUtil { + + private static final String secretKey = "N2aD7vLTJjeo71vCHwbqYsSF9rZPUh"; + + /** + * 加密 + * @param userId + * @return + */ + public static String desEncrypt(String userId){ + String formatStr = userId+"-N2aD7vLTJjeo71vCHwbqYsSF9rZPUh"; + DesUtils des = new DesUtils(secretKey); + try { + return des.encrypt(formatStr); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 解密 + * @param encryptText + * @return clientId + */ + public static String desDecrypt(String encryptText){ + DesUtils des = new DesUtils(secretKey); + try { + String formatStr = des.decrypt(encryptText); + return formatStr.split("-")[0]; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/TreeUtil.java b/src/main/java/com/qs/serve/common/util/TreeUtil.java new file mode 100644 index 00000000..99dd8e31 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/TreeUtil.java @@ -0,0 +1,74 @@ +package com.qs.serve.common.util; + +import com.qs.serve.common.model.dto.TreeNode; +import lombok.experimental.UtilityClass; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@UtilityClass +public class TreeUtil { + + public static final String DEFAULT_PID_STRING = "0"; + + /** + * 两层循环实现建树 + * @param treeNodes 传入的树节点列表 + * @param rootPid + * @return + * sorted(Comparator.comparingInt(DemoEntity::getSort)) + */ + public List build(List treeNodes, String rootPid) { + List trees = new ArrayList<>(); + for (T treeNode : treeNodes) { + if (rootPid.equals(treeNode.getParentId())) { + trees.add(treeNode); + } + for (T it : treeNodes) { + if (it.getParentId().equals(treeNode.getId())) { + treeNode.addChildren(it); + } + } + } + return trees; + } + + /** + * 使用递归方法建树 + * + * @param treeNodes + * @return + */ + public List buildByRecursive(List treeNodes, Object root) { + List trees = new ArrayList(); + for (T treeNode : treeNodes) { + if (root.equals(treeNode.getParentId())) { + trees.add(findChildren(treeNode, treeNodes)); + } + } + return trees; + } + + /** + * 递归查找子节点 + * + * @param treeNodes + * @return + */ + public T findChildren(T treeNode, List treeNodes) { + for (T it : treeNodes) { + if (treeNode.getId().equals(it.getParentId())) { + if (treeNode.getChildren() == null) { + treeNode.setChildren(new ArrayList<>()); + } + treeNode.addChildren(findChildren(it, treeNodes)); + } + } + return treeNode; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/UploadUtil.java b/src/main/java/com/qs/serve/common/util/UploadUtil.java new file mode 100644 index 00000000..09eb9e50 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/UploadUtil.java @@ -0,0 +1,53 @@ +package com.qs.serve.common.util; + +import cn.hutool.core.io.FileUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; + +/** + * @author YenHex + * @since 2022/3/14 + */ +@Slf4j +public class UploadUtil { + + /** + * 返回相对地址 + * @param uploadPath 物理路径 + * @param fileName2 文件名 + * @param request + * @return + */ + public static String put(String uploadPath,final String fileName2,HttpServletRequest request){ + String contentType = request.getContentType(); + MultipartFile file = null; + if (contentType != null && contentType.toLowerCase().startsWith("multipart")) { + MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class); + file = multipartHttpServletRequest.getFile("file"); + } + if (file==null||file.isEmpty()) { + Assert.throwEx("请选择文件"); + } + String fileOrgName = file.getOriginalFilename(); + String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf(".")); + String fileName = fileName2 + mimeType ; + String prefix = LocalDate.now().toString().replace("-","")+"/"; + try { + FileUtil.createTempFile(new File(uploadPath+prefix)); + File dest = new File(uploadPath + prefix + fileName); + file.transferTo(dest); + return prefix + fileName; + } catch (IOException e) { + log.error(e.toString(), e); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/common/util/WarpUtil.java b/src/main/java/com/qs/serve/common/util/WarpUtil.java new file mode 100644 index 00000000..f23e72c5 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/WarpUtil.java @@ -0,0 +1,62 @@ +package com.qs.serve.common.util; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.mybatis.query.AnnotationQueryStorage; +import com.qs.serve.common.framework.mybatis.query.model.QueryFieldDataValue; +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * 生成SQL条件包装对象 + * @author YenHex + * @date 2022/2/28 + **/ +@UtilityClass +@Slf4j +public class WarpUtil extends AnnotationQueryStorage { + + private static final String ORDER_PROP_NAME = "prop"; + private static final String ORDER_TYPE_NAME = "order"; + private static final String ORDER_DESC = "desc"; + private static final String CREATE_TIME = "create_time"; + + private static final String START_TIME = "startTime"; + private static final String END_TIME = "endTime"; + + public static QueryWrapper build(T query){ + return build(query,false); + } + + public static QueryWrapper build(T query,Boolean orderAble){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + List dataValues = loadQueryFieldDataValues(query); + assert dataValues != null; + initWrap(dataValues,queryWrapper); + initBetweenTime(queryWrapper); + if(orderAble){ + String columnsString = ServletUtils.getParameter(ORDER_PROP_NAME); + String orderType = ServletUtils.getParameter(ORDER_TYPE_NAME); + if(StringUtils.isNotEmpty(columnsString)){ + String[] columns = columnsString.split(","); + if(orderType.equals(ORDER_DESC)){ + queryWrapper.orderByDesc(columns); + }else { + queryWrapper.orderByAsc(columns); + } + } + } + return queryWrapper; + } + + public static void initBetweenTime(QueryWrapper queryWrapper){ + String startTime = ServletUtils.getParameter(START_TIME); + String endTime = ServletUtils.getParameter(END_TIME); + if(!StringUtils.hasEmpty(startTime,endTime)){ + queryWrapper.ge(CREATE_TIME,startTime); + queryWrapper.le(CREATE_TIME,endTime); + } + } + +} diff --git a/src/main/java/com/qs/serve/common/util/WordUtil.java b/src/main/java/com/qs/serve/common/util/WordUtil.java new file mode 100644 index 00000000..8c48f7a1 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/WordUtil.java @@ -0,0 +1,109 @@ +package com.qs.serve.common.util; + +import lombok.experimental.UtilityClass; +import org.springframework.util.StringUtils; + +/** + * 单词间转换工具类 + * @author JcYen + * @Date 2020/5/27 + * @Version 1.0 + */ +@UtilityClass +public class WordUtil { + + public static String lowerFirst(String className){ + return lowerFirst(className,null); + } + + /** + * 类名首字母小写 + * @param className 类名 + * @param rmPrefix 移除的前缀,不区分大小写 + * @return + */ + public static String lowerFirst(String className,String rmPrefix){ + if(className==null){throw new RuntimeException("className is null");} + if(rmPrefix!=null){ + String prefix = className.substring(0,rmPrefix.length()); + if(prefix.toLowerCase().equals(rmPrefix.toLowerCase())){ + className = className.substring(rmPrefix.length()); + } + } + char[]chars = className.toCharArray(); + chars[0] += 32; + return String.valueOf(chars); + } + + /** + * 数据库表名 转 类名 : ums_user_log ->> UmsUserLog + * 1.首字母转小写 + * 2.下横线后的字母大写,去掉"_"下横线, + * @param tableName + * @return + */ + public static String tableToClass(String tableName) { + if(StringUtils.isEmpty(tableName)){return null;} + char[] chars = tableName.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if(Character.isLowerCase(chars[i])&&i==0){ + chars[i] = Character.toUpperCase(chars[i]); + } + if(chars[i] == '_' && i+1> umsUserLog + * 1.首字母转小写 + * 2.下横线后的字母大写,去掉"_"下横线, + * @param columnName + * @return + */ + public static String columnToField(String columnName) { + if(StringUtils.isEmpty(columnName)){return null;} + char[] chars = columnName.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if(chars[i] == '_' && i+1> ums_user_log + * 1.首字母转小写 + * 2.字符非首个字母,添加"_"下横线,并大写字母转小写 + * @param fieldName + * @return + */ + public static String toLine(String fieldName) { + if(StringUtils.isEmpty(fieldName)){return null;} + columnToField(fieldName); + char[] chars = fieldName.toCharArray(); + int countUpper = 0; + for (int i = 0; i < chars.length; i++) { + if(Character.isUpperCase(chars[i])&&i!=0){ + countUpper ++ ; + } + } + char[] newChars = new char[chars.length+countUpper]; + //偏移量 + int offset = 0; + for (int i = 0; i < chars.length; i++) { + if(Character.isUpperCase(chars[i])){ + if(i!=0){ + newChars[i+offset] = '_'; + offset++; + } + } + newChars[i+offset] = Character.toLowerCase(chars[i]); + } + return String.valueOf(newChars); + } + +} diff --git a/src/main/java/com/qs/serve/common/util/model/DateFormatString.java b/src/main/java/com/qs/serve/common/util/model/DateFormatString.java new file mode 100644 index 00000000..d7df1b0f --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/model/DateFormatString.java @@ -0,0 +1,24 @@ +package com.qs.serve.common.util.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author YenHex + * @since 2022/3/17 + */ +@Getter +@AllArgsConstructor +public enum DateFormatString { + + DATE_TIME("yyyy-MM-dd HH:mm:ss"), + DATE_TIME_NUM("yyyyMMddHHmmss"), + DATE_TIME_CN("yyyy年MM月dd日 HH时mm分ss秒"), + + DATE("yyyy-MM-dd"), + DATE_NUM("yyyyMMdd"), + DATE_CN("yyyy年MM月dd日"); + + private String value; + +} diff --git a/src/main/java/com/qs/serve/common/util/model/DesUtils.java b/src/main/java/com/qs/serve/common/util/model/DesUtils.java new file mode 100644 index 00000000..2617af17 --- /dev/null +++ b/src/main/java/com/qs/serve/common/util/model/DesUtils.java @@ -0,0 +1,125 @@ +package com.qs.serve.common.util.model; + +import javax.crypto.Cipher; +import java.security.Key; + +/** + * 使用DES算法对字符串进行加密解密 (加密解密的操作步骤正好相反, 参考 {@link #encrypt(String)}, {@link #decrypt(String)}) + */ +public class DesUtils { + private static String defaultSecretKey = "default_secret_key"; //默认密钥 + private Cipher encryptCipher = null; //加密器 + private Cipher decryptCipher = null; //解密器 + + public DesUtils() throws Exception { + this(defaultSecretKey); + } + + /** + * @param secretKey 加密解密使用的密钥 + */ + public DesUtils(String secretKey) { + Key key; + try { + key = getKey(secretKey.getBytes()); + encryptCipher = Cipher.getInstance("DES"); + encryptCipher.init(Cipher.ENCRYPT_MODE, key); + decryptCipher = Cipher.getInstance("DES"); + decryptCipher.init(Cipher.DECRYPT_MODE, key); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 加密 (逻辑: 1. 将要加密的字符串转换为字节数组(byte array)
+ * 2. 将第一步的字节数组作为输入使用加密器(Cipher)的doFinal方法进行加密, 返回字节数组
+ * 3. 把加密后的字节数组转换成十六进制的字符串)
+ * @param strIn 要加密的字符串 + * @return 返回加密后的十六进制字符串 + * @throws Exception + */ + public String encrypt(String strIn) throws Exception { + return byteArr2HexStr(encrypt(strIn.getBytes())); + } + + public byte[] encrypt(byte[] arrB) throws Exception { + return encryptCipher.doFinal(arrB); + } + + /** + * 解密 (逻辑: 1. 把加密后的十六进制字符串转换成字节数组(byte array)
+ * 2. 将第一步的字节数组作为输入使用加密器(Cipher)的doFinal方法进行解密, 返回字节数组(byte array)
+ * 3. 把解密后的字节数组转换成字符串)
+ * @param strIn + * @return + * @throws Exception + */ + public String decrypt(String strIn) throws Exception { + return new String(decrypt(hexStr2ByteArr(strIn))); + } + + public byte[] decrypt(byte[] arrB) throws Exception { + return decryptCipher.doFinal(arrB); + } + + public static String byteArr2HexStr(byte[] arrB) throws Exception { + int iLen = arrB.length; + // 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍 + StringBuffer sb = new StringBuffer(iLen * 2); + for (int i = 0; i < iLen; i++) { + int intTmp = arrB[i]; + // 把负数转换为正数 + while (intTmp < 0) { + intTmp = intTmp + 256; + } + // 小于0F的数需要在前面补0 + if (intTmp < 16) { + sb.append("0"); + } + sb.append(Integer.toString(intTmp, 16)); + } + return sb.toString(); + } + + public static byte[] hexStr2ByteArr(String strIn) throws Exception { + byte[] arrB = strIn.getBytes(); + int iLen = arrB.length; + // 两个字符表示一个字节,所以字节数组长度是字符串长度除以2 + byte[] arrOut = new byte[iLen / 2]; + for (int i = 0; i < iLen; i = i + 2) { + String strTmp = new String(arrB, i, 2); + arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16); + } + return arrOut; + } + + private Key getKey(byte[] arrBTmp) throws Exception { + // 创建一个空的8位字节数组(默认值为0) + byte[] arrB = new byte[8]; + // 将原始字节数组转换为8位 + for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) { + arrB[i] = arrBTmp[i]; + } + // 生成密钥 + Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES"); + return key; + } + + + /** + * 用法实例 + */ + public static void main(String[] args) { + try { + String test = "liwc"; + DesUtils des = new DesUtils("leemenz"); //自定义密钥 + System.out.println("加密前的字符:" + test); + System.out.println("加密后的字符:" + des.encrypt(test)); + System.out.println("解密后的字符:" + des.decrypt(des.encrypt(test))); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/qs/serve/controller/AdminPortalController.java b/src/main/java/com/qs/serve/controller/AdminPortalController.java new file mode 100644 index 00000000..300b0cea --- /dev/null +++ b/src/main/java/com/qs/serve/controller/AdminPortalController.java @@ -0,0 +1,138 @@ +package com.qs.serve.controller; + +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.modules.sys.entity.SysTenant; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam; +import com.qs.serve.modules.sys.entity.dto.SysLoginParam; +import com.qs.serve.modules.sys.entity.dto.SysResetPwdByPhoneParam; +import com.qs.serve.modules.sys.mapper.SysNoticeUserMapper; +import com.qs.serve.modules.sys.service.SysTenantService; +import com.qs.serve.modules.sys.service.SysUserLoginService; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 门户:后台接口 + * @author YenHex + * @since 2022/3/2 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("portal") +public class AdminPortalController { + + private SysTenantService sysTenantService; + private SysUserLoginService sysUserLoginService; + private RedisService redisService; + private SysUserService sysUserService; + + /** + * 获取所有租户 + * @return + */ + @GetMapping("/listTenant") + public R> getList(){ + List list = sysTenantService.list2(); + return R.ok(list); + } + + + /** + * 登录接口 + * @return + */ + @LimitSubmit + @SysLog(title = "人员",desc = "后台登录",biz = BizType.LOGIN,saveReqParam = false) + @PostMapping("/login") + public R login(@RequestBody @Valid SysLoginParam param){ + return R.ok(sysUserLoginService.login(param)); + } + + /** + * 手机登陆 + * @return + */ + @LimitSubmit + @SysLog(title = "人员",desc = "手机登陆",biz = BizType.LOGIN,saveReqParam = false) + @PostMapping("/phoneLogin") + public R phoneLogin(@RequestBody @Valid SysLoginByPhoneParam param){ + return R.ok(sysUserLoginService.login(param)); + } + + /** + * 登出接口 + * @return + */ + @SysLog(title = "人员",desc = "退出登录",biz = BizType.LOGOUT,saveReqParam = false) + @GetMapping("/logout") + public R login(){ + return R.ok(); + } + + + /** + * 获取用户手机验证码 + */ + @LimitSubmit(interval = 10000,message = "请10秒后尝试") + @SysLog(title = "人员",desc = "获取用户手机验证码",biz = BizType.OTHER) + @GetMapping("/userPhoneCode/{phone}") + public R phoneCode(@PathVariable("phone") String phone){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,phone); + int count = sysUserService.count(wrapper); + if(count<1){ + return R.error("无效手机号,请重新输入"); + } + String key = RedisCacheKeys.PHONE_KEY+phone; + String code = redisService.getString(key); + if(code==null){ + code = IdUtil.genCode(6); + } + redisService.set(key,code,1, TimeUnit.MINUTES); + //TODO send msg + return R.ok(); + } + + /** + * 重置手机用户密码 + */ + @LimitSubmit(interval = 10000,message = "请10秒后尝试") + @SysLog(title = "人员",desc = "重置手机用户密码",biz = BizType.RESET) + @PostMapping("/resetPwdByPhone") + public R phoneCode(@RequestBody @Valid SysResetPwdByPhoneParam param){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,param.getPhone()); + List userList = sysUserService.list(wrapper); + if(userList.size()<1){ + return R.error("无效手机号,请重新输入"); + } + String key = RedisCacheKeys.PHONE_KEY+param.getPhone(); + String code = redisService.getString(key); + if(!param.getCode().equals(code)){ + return R.error("验证码无效或过期"); + } + SysUser sysUser = new SysUser(); + sysUser.setId(userList.get(0).getId()); + sysUser.setPassword(SecureUtil.md5(param.getNewPwd())); + sysUserService.updateById(sysUser); + return R.ok(); + } + + +} diff --git a/src/main/java/com/qs/serve/controller/CommonApi.java b/src/main/java/com/qs/serve/controller/CommonApi.java new file mode 100644 index 00000000..f3582fb0 --- /dev/null +++ b/src/main/java/com/qs/serve/controller/CommonApi.java @@ -0,0 +1,26 @@ +package com.qs.serve.controller; + +import com.qs.serve.common.model.dto.R; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; + +/** + * 门户:API通用接口 + * @author YenHex + * @since 2022/3/14 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/common") +public class CommonApi { + + + +} diff --git a/src/main/java/com/qs/serve/controller/CommonController.java b/src/main/java/com/qs/serve/controller/CommonController.java new file mode 100644 index 00000000..4312a24f --- /dev/null +++ b/src/main/java/com/qs/serve/controller/CommonController.java @@ -0,0 +1,103 @@ +package com.qs.serve.controller; + +import com.qs.serve.common.config.properties.UploadProperties; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +/** + * 门户:后台通用接口 + * @author YenHex + * @since 2022/3/14 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/common") +public class CommonController { + + private UploadProperties uploadProperties; + + + + /** + * 单图上传 + * @apiNote file不能为空 + * @param request + * @return + */ + @SysLog(title = "文件",biz = BizType.UPLOAD) + @PostMapping("/upload") + public R upload(HttpServletRequest request) { + String relativePath = UploadUtil.put(uploadProperties.getLogicalPath(),IdUtil.timeStampId(),request); + if(relativePath!=null){ + return R.ok(uploadProperties.getProxyUrl()+relativePath,"上传成功"); + } + return R.error("上传失败"); + } + + /** + * 验证token + * @param token + * @return + */ + @PostMapping("/validToken") + public R validToken(String token) { + return R.isOk(JwtUtils.verify(token),"无效token"); + } + + /** + * 多图上传 + * @apiNote files不能为空 + * @param request + * @return + */ + @SysLog(title = "文件",biz = BizType.UPLOAD) + @PostMapping( "/uploadMulti") + public R multiUpload(HttpServletRequest request) { + String contentType = request.getContentType(); + List files = null; + if (contentType != null && contentType.toLowerCase().startsWith("multipart")) { + MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class); + files = multipartHttpServletRequest.getFiles("files"); + } + if (files==null||files.isEmpty()) { + return R.error("请选择文件"); + } + List list = new ArrayList<>(); + for (int i = 0; i < files.size(); i++) { + MultipartFile file = files.get(i); + if (file.isEmpty()) { + return R.error("上传第" + (i++) + "个文件失败"); + } + String fileOrgName = file.getOriginalFilename(); + String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf(".")); + String filePath = LocalDate.now().toString().replace("-","")+"/"+ IdUtil.timeStampId()+mimeType; + String uploadPath = uploadProperties.getLogicalPath(); + File dest = new File(uploadPath + filePath); + try { + file.transferTo(dest); + list.add(uploadProperties.getProxyUrl()+filePath); + } catch (IOException e) { + log.error(e.toString(), e); + return R.error("上传第" + (i++) + "个文件失败"); + } + } + return R.ok(list); + } + +} diff --git a/src/main/java/com/qs/serve/controller/WxMpPortalApi.java b/src/main/java/com/qs/serve/controller/WxMpPortalApi.java new file mode 100644 index 00000000..8016d32a --- /dev/null +++ b/src/main/java/com/qs/serve/controller/WxMpPortalApi.java @@ -0,0 +1,129 @@ +package com.qs.serve.controller; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * 门户:微信公众号回调 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@AllArgsConstructor +//@RestController +//@RequestMapping("/api/wx/mp/portal/{appid}") +public class WxMpPortalApi { + + private final WxMpService wxService; + private final WxMpMessageRouter messageRouter; + + /** + * 校验身份 + * @param appid + * @param signature + * @param timestamp + * @param nonce + * @param echostr + * @return + */ + @GetMapping(produces = "text/plain;charset=utf-8") + public String authGet(@PathVariable String appid, + @RequestParam(name = "signature", required = false) String signature, + @RequestParam(name = "timestamp", required = false) String timestamp, + @RequestParam(name = "nonce", required = false) String nonce, + @RequestParam(name = "echostr", required = false) String echostr) { + + log.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, + timestamp, nonce, echostr); + if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { + throw new IllegalArgumentException("请求参数非法,请核实!"); + } + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + if (wxService.checkSignature(timestamp, nonce, signature)) { + return echostr; + } + return "非法请求"; + } + + /** + * 身份校验2 + * @param appid + * @param requestBody + * @param signature + * @param timestamp + * @param nonce + * @param openid + * @param encType + * @param msgSignature + * @return + */ + @PostMapping(produces = "application/xml; charset=UTF-8") + public String post(@PathVariable String appid, + @RequestBody String requestBody, + @RequestParam("signature") String signature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce, + @RequestParam("openid") String openid, + @RequestParam(name = "encrypt_type", required = false) String encType, + @RequestParam(name = "msg_signature", required = false) String msgSignature) { + log.info("\n接收微信请求:[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}]," + + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", + openid, signature, encType, msgSignature, timestamp, nonce, requestBody); + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + + if (!wxService.checkSignature(timestamp, nonce, signature)) { + throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); + } + String out = null; + if (encType == null) { + // 明文传输的消息 + WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody); + WxMpXmlOutMessage outMessage = this.route(inMessage); + if (outMessage == null) { + return ""; + } + out = outMessage.toXml(); + } else if ("aes".equalsIgnoreCase(encType)) { + // aes加密的消息 + WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(), + timestamp, nonce, msgSignature); + log.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); + WxMpXmlOutMessage outMessage = this.route(inMessage); + if (outMessage == null) { + return ""; + } + + out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage()); + } + + log.debug("\n组装回复信息:{}", out); + return out; + } + + private WxMpXmlOutMessage route(WxMpXmlMessage message) { + try { + return this.messageRouter.route(message); + } catch (Exception e) { + log.error("路由消息时出现异常!", e); + } + return null; + } + +} diff --git a/src/main/java/com/qs/serve/controller/WxSvcLoginApi.java b/src/main/java/com/qs/serve/controller/WxSvcLoginApi.java new file mode 100644 index 00000000..3e5298c9 --- /dev/null +++ b/src/main/java/com/qs/serve/controller/WxSvcLoginApi.java @@ -0,0 +1,97 @@ +package com.qs.serve.controller; + +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.ums.entity.UmsUser; +import com.qs.serve.modules.ums.service.UmsUserService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxLoginUser; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 门户:微信登录 + * @author YenHex + * @since 2022/3/7 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/wx/login") +public class WxSvcLoginApi { + + private final WxUserService wxUserService; + + private final RedisService redisService; + + private final UmsUserService umsUserService; + + + /** + * 公众号登录 + * @param wxLoginUser + * @return + * @throws Exception + */ + @SysLog(title = "公众号登录",biz = BizType.LOGIN,inter = InterType.API) + @PostMapping("/mp") + public R login(@RequestBody @Valid WxLoginUser wxLoginUser, HttpServletRequest request){ + Map objectMap = new HashMap<>(); + WxUser wxUser = null; + try { + wxUser = wxUserService.login(wxLoginUser); + } catch (Exception e) { + log.warn(e.getMessage()); + } + if(wxUser==null){ + Assert.throwEx(HttpCode.WX_ERR); + } + String token = IdUtil.fastSimpleUUID(); + String key = RedisCacheKeys.LOGIN_KEY_WX + token; + String wxUserId = wxUser.getId(); + UmsUser umsUser = umsUserService.getByWxUserId(wxUserId,wxUser); + LoginUser loginUser = new LoginUser(umsUser.getId()+"",umsUser.getName(),"", + ServletUtils.getIp(request), LoginUserType.SYS_USER,new ArrayList<>(),null,AuthContextUtils.getTenant()); + redisService.set(key, JsonUtil.objectToJson(loginUser.loginUserDTO()),2, TimeUnit.DAYS); + objectMap.put("token",token); + return R.ok(objectMap); + } + + /** + * 公众号测试登录 + */ + @PostMapping("/mptest") + public R login(HttpServletRequest request){ + Map objectMap = new HashMap<>(); + String token = TokenUtil.desEncrypt("1"); + String key = RedisCacheKeys.LOGIN_KEY_WX + token; + LoginUser loginUser = new LoginUser("1","微信测试用户","", + ServletUtils.getIp(request), LoginUserType.APP_USER,new ArrayList<>(),null,AuthContextUtils.getTenant()); + redisService.set(key, JsonUtil.objectToJson(loginUser.loginUserDTO()),2, TimeUnit.DAYS); + objectMap.put("token",token); + return R.ok(objectMap); + } + + + +} diff --git a/src/main/java/com/qs/serve/controller/dto/CounterResultVo.java b/src/main/java/com/qs/serve/controller/dto/CounterResultVo.java new file mode 100644 index 00000000..ce2fa7fb --- /dev/null +++ b/src/main/java/com/qs/serve/controller/dto/CounterResultVo.java @@ -0,0 +1,27 @@ +package com.qs.serve.controller.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2022/5/13 + */ +@Data +public class CounterResultVo { + + /** + * 待处理审批数 + */ + private Long apprCounter; + + /** + * 公告未读数 + */ + private Integer noticeCounter; + + /** + * 维修任务数 + */ + private Long repairCounter; + +} diff --git a/src/main/java/com/qs/serve/modules/package-info.java b/src/main/java/com/qs/serve/modules/package-info.java new file mode 100644 index 00000000..0551be05 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/package-info.java @@ -0,0 +1,11 @@ +package com.qs.serve.modules; +/** + * bpm 审核流程 + * cms 内容管理 + * edu 教学模块 + * sms 消息模块 + * job 任务调度模块 + * svc 第三方对接模块 + * sys 系统模块 + * wx 微信模块 + */ diff --git a/src/main/java/com/qs/serve/modules/qms/controller/QmsCategoryController.java b/src/main/java/com/qs/serve/modules/qms/controller/QmsCategoryController.java new file mode 100644 index 00000000..c03608de --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/controller/QmsCategoryController.java @@ -0,0 +1,116 @@ +package com.qs.serve.modules.qms.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.qms.entity.QmsCategory; +import com.qs.serve.modules.qms.service.QmsCategoryService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 问卷分类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("qms/category") +public class QmsCategoryController { + + private QmsCategoryService qmsCategoryService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('qms:category:query')") + public R> getPage(QmsCategory param){ + PageUtil.startPage(); + LambdaQueryWrapper categoryWrapper = new LambdaQueryWrapper<>(param); + List list = qmsCategoryService.list(categoryWrapper); + return R.byPageHelperList(list); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(QmsCategory param){ + LambdaQueryWrapper categoryWrapper = new LambdaQueryWrapper<>(param); + List list = qmsCategoryService.list(categoryWrapper); + return R.ok(list); + } + + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷分类", biz = BizType.QUERY) + @PreAuthorize("hasRole('qms:category:query')") + public R getById(@PathVariable("id") String id){ + QmsCategory qmsCategory = qmsCategoryService.getById(id); + return R.ok(qmsCategory); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.QUESTION, title = "问卷分类", biz = BizType.UPDATE) + @PreAuthorize("hasRole('qms:category:update')") + public R updateById(@RequestBody @Valid QmsCategory param){ + boolean result = qmsCategoryService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增问卷分类 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.QUESTION, title = "问卷分类", biz = BizType.INSERT) + @PreAuthorize("hasRole('qms:category:insert')") + public R save(@RequestBody @Valid QmsCategory param){ + boolean result = qmsCategoryService.save(param); + return R.isTrue(result); + } + + /** + * 删除问卷分类 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷分类", biz = BizType.DELETE) + @PreAuthorize("hasRole('qms:category:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = qmsCategoryService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/controller/QmsFormController.java b/src/main/java/com/qs/serve/modules/qms/controller/QmsFormController.java new file mode 100644 index 00000000..13385d99 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/controller/QmsFormController.java @@ -0,0 +1,111 @@ +package com.qs.serve.modules.qms.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.qms.entity.bo.QmsFormBo; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.qms.entity.QmsForm; +import com.qs.serve.modules.qms.service.QmsFormService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 问卷表单 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("qms/form") +public class QmsFormController { + + private QmsFormService qmsFormService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('qms:form:query')") + public R> getPage(QmsForm param){ + PageUtil.startPage(); + LambdaQueryWrapper formWrapper = new LambdaQueryWrapper<>(param); + List list = qmsFormService.list(formWrapper); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷表单", biz = BizType.QUERY) + @PreAuthorize("hasRole('qms:form:query')") + public R getById(@PathVariable("id") String id){ + QmsForm qmsForm = qmsFormService.getById(id); + return R.ok(qmsForm); + } + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.QUESTION, title = "问卷表单", biz = BizType.UPDATE) + @PreAuthorize("hasRole('qms:form:update')") + public R updateById(@RequestBody @Valid QmsFormBo param){ + QmsForm qmsForm = CopierUtil.copy(param,new QmsForm()); + QmsForm dbForm = qmsFormService.getById(qmsForm.getId()); + if(!qmsForm.getFormContext().equals(dbForm.getFormContext())){ + qmsForm.setVersion(dbForm.getVersion()+1); + } + boolean result = qmsFormService.updateById(qmsForm); + return R.isTrue(result); + } + + /** + * 新增问卷表单 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.QUESTION, title = "问卷表单", biz = BizType.INSERT) + @PreAuthorize("hasRole('qms:form:insert')") + public R save(@RequestBody @Valid QmsFormBo param){ + QmsForm qmsForm = CopierUtil.copy(param,new QmsForm()); + qmsForm.setVersion(1); + qmsFormService.save(qmsForm); + return R.ok(qmsForm); + } + + /** + * 删除问卷表单 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷表单", biz = BizType.DELETE) + @PreAuthorize("hasRole('qms:form:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = qmsFormService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/controller/QmsFormSubmitController.java b/src/main/java/com/qs/serve/modules/qms/controller/QmsFormSubmitController.java new file mode 100644 index 00000000..503d7043 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/controller/QmsFormSubmitController.java @@ -0,0 +1,105 @@ +package com.qs.serve.modules.qms.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.qms.entity.QmsDraft; +import com.qs.serve.modules.qms.service.QmsGroupService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.qms.entity.QmsFormSubmit; +import com.qs.serve.modules.qms.service.QmsFormSubmitService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 问卷提交记录 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("qms/formSubmit") +public class QmsFormSubmitController { + + private QmsFormSubmitService qmsFormSubmitService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('qms:formSubmit:query')") + public R> getPage(QmsFormSubmit param){ + PageUtil.startPage(); + LambdaQueryWrapper formSubmitWrapper = new LambdaQueryWrapper<>(param); + List list = qmsFormSubmitService.list(formSubmitWrapper); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.QUERY) + @PreAuthorize("hasRole('qms:formSubmit:query')") + public R getById(@PathVariable("id") String id){ + QmsFormSubmit qmsFormSubmit = qmsFormSubmitService.getById(id); + return R.ok(qmsFormSubmit); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.UPDATE) + @PreAuthorize("hasRole('qms:formSubmit:update')") + public R updateById(@RequestBody @Valid QmsFormSubmit param){ + boolean result = qmsFormSubmitService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增问卷提交记录 + * @param param + * @return + */ + //@PostMapping("/save") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.INSERT) + @PreAuthorize("hasRole('qms:formSubmit:insert')") + public R save(@RequestBody @Valid QmsFormSubmit param){ + boolean result = qmsFormSubmitService.save(param); + return R.isTrue(result); + } + + /** + * 删除问卷提交记录 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.DELETE) + @PreAuthorize("hasRole('qms:formSubmit:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = qmsFormSubmitService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/controller/QmsGroupController.java b/src/main/java/com/qs/serve/modules/qms/controller/QmsGroupController.java new file mode 100644 index 00000000..049da8fa --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/controller/QmsGroupController.java @@ -0,0 +1,209 @@ +package com.qs.serve.modules.qms.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.dto.SimpleKeyValue; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.qms.entity.QmsForm; +import com.qs.serve.modules.qms.entity.QmsGroupScope; +import com.qs.serve.modules.qms.entity.bo.QmsGroupBo; +import com.qs.serve.modules.qms.service.QmsFormService; +import com.qs.serve.modules.qms.service.QmsGroupScopeService; +import com.qs.serve.modules.sys.entity.SysDept; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysUserSimpleVo; +import com.qs.serve.modules.sys.service.SysDeptService; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.qms.entity.QmsGroup; +import com.qs.serve.modules.qms.service.QmsGroupService; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 问卷 发布组 后台接口 + * @author YenHex + * @since 2022-09-16 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("qms/group") +public class QmsGroupController { + + private QmsGroupService qmsGroupService; + private QmsFormService qmsFormService; + private QmsGroupScopeService qmsGroupScopeService; + private SysUserService sysUserService; + private SysDeptService sysDeptService; + + + /** + * 翻页 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('qms:group:query')") + public R> getPage(QmsGroup param){ + PageUtil.startPage(); + LambdaQueryWrapper groupWrapper = new LambdaQueryWrapper<>(param); + List list = qmsGroupService.list(groupWrapper); + return R.byPageHelperList(list); + } + + /** + * ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "发布组", biz = BizType.QUERY) + @PreAuthorize("hasRole('qms:group:query')") + public R getById(@PathVariable("id") String id){ + QmsGroup qmsGroup = qmsGroupService.getById(id); + qmsGroup.setFormInfo(qmsFormService.getById(qmsGroup.getFormId())); + List list = qmsGroupScopeService.listByGroupId(qmsGroup.getId()); + Map> scopeValuesMap = list.stream().collect(Collectors.groupingBy(QmsGroupScope::getScopeType)); + for (Integer scopeType : scopeValuesMap.keySet()) { + List scopeValues = scopeValuesMap.get(scopeType); + List ids = scopeValues.stream().map(QmsGroupScope::getScopeValue).distinct().collect(Collectors.toList()); + if(scopeType.equals(1)||scopeType.equals(3)){ + if(scopeType.equals(1)){ + qmsGroup.setScopeType(scopeType); + } + List userList = sysUserService.listByIds(ids); + List userSimpleVos = userList.stream().map(a->a.toSimpleVo(true)).collect(Collectors.toList()); + qmsGroup.setUserList(userSimpleVos); + }else if(scopeType.equals(2)){ + List deptList = sysDeptService.listByIds(ids); + List simpleKeyValues = deptList.stream().map(a->new SimpleKeyValue(a.getName(),a.getId(),null)).collect(Collectors.toList()); + qmsGroup.setDeptList(simpleKeyValues); + } + } + return R.ok(qmsGroup); + } + + /** + * 更新 + * @param param + * @return + */ + @LimitSubmit + @PostMapping("/updateById") + @SysLog(module = SystemModule.QUESTION, title = "发布组", biz = BizType.UPDATE) + public R updateById(@RequestBody @Valid QmsGroupBo param){ + QmsGroup qmsGroup = qmsGroupService.getById(param.getId()); + if(qmsGroup.getPublishState().equals(1)){ + return R.error("已发布不可以修改"); + } + CopierUtil.copy(param,qmsGroup); + QmsForm qmsForm = qmsFormService.getById(qmsGroup.getFormId()); + qmsGroup.setFormContext(qmsForm.getFormContext()); + qmsGroup.setVersion(qmsForm.getVersion()); + qmsGroupService.updateById(qmsGroup); + qmsGroupScopeService.removeById(qmsGroup.getFormId()); + qmsGroupScopeService.saveByBo(qmsGroup.getId(),param); + return R.ok(); + } + + + /** + * 发布 + * @param groupId + * @return + */ + @LimitSubmit + @GetMapping("/publish/{groupId}") + @SysLog(module = SystemModule.QUESTION, title = "发布组", biz = BizType.UPDATE) + public R publish(@PathVariable("groupId")Long groupId){ + QmsGroup qmsGroup = qmsGroupService.getById(groupId); + if(qmsGroup.getPublishState().equals(1)){ + return R.error("请勿重新发布"); + } + //TODO 发布 + return R.ok(); + } + + //TODO 催办 + + /** + * 催办列表 + * @param finished + * @param groupId + * @return + */ + @LimitSubmit + @GetMapping("/unfinishedList") + public R unfinishedList(String finished,String groupId){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + if(finished!=null){ + lqw.eq(QmsGroupScope::getFinished,finished); + } + if(groupId!=null){ + lqw.eq(QmsGroupScope::getGroupId,groupId); + } + lqw.in(QmsGroupScope::getScopeType,1,3); + PageUtil.startPage(); + List groupScopes = qmsGroupScopeService.list(lqw); + List list = new ArrayList<>(); + for (QmsGroupScope groupScope : groupScopes) { + SysUser sysUser = sysUserService.getById(groupScope.getScopeValue()); + SysUserSimpleVo simpleVo = sysUser.toSimpleVo(true); + simpleVo.setFinished(groupScope.getFinished()); + list.add(simpleVo); + } + return R.byPageHelperList(groupScopes,list); + } + + /** + * 新增 + * @param param + * @return + */ + @LimitSubmit + @PostMapping("/save") + @SysLog(module = SystemModule.QUESTION, title = "发布组", biz = BizType.INSERT) + @PreAuthorize("hasRole('qms:group:insert')") + public R save(@RequestBody @Valid QmsGroupBo param){ + QmsGroup qmsGroup = CopierUtil.copy(param,new QmsGroup()); + QmsForm qmsForm = qmsFormService.getById(qmsGroup.getFormId()); + qmsGroup.setFormContext(qmsForm.getFormContext()); + qmsGroup.setVersion(qmsForm.getVersion()); + qmsGroup.setPublishState(0); + qmsGroupService.save(qmsGroup); + qmsGroupScopeService.saveByBo(qmsGroup.getId(),param); + return R.ok(); + } + + /** + * 删除 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "发布组", biz = BizType.DELETE) + @PreAuthorize("hasRole('qms:group:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = qmsGroupService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/controller/api/QmsDraftApiController.java b/src/main/java/com/qs/serve/modules/qms/controller/api/QmsDraftApiController.java new file mode 100644 index 00000000..9b510e8c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/controller/api/QmsDraftApiController.java @@ -0,0 +1,69 @@ +package com.qs.serve.modules.qms.controller.api; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.modules.qms.entity.bo.QmsDraftBo; +import com.qs.serve.modules.qms.entity.vo.QmsDraftVo; +import com.qs.serve.modules.sys.entity.SysUser; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.qms.entity.QmsDraft; +import com.qs.serve.modules.qms.service.QmsDraftService; + +import javax.validation.Valid; + +/** + * API问卷草稿 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/draft") +public class QmsDraftApiController { + + private QmsDraftService qmsDraftService; + + /** + * 获取表单草稿 + * @param formId + * @return + */ + @GetMapping("/{groupId}") + public R getDraft(@PathVariable("groupId") Long formId){ + QmsDraft qmsDraft = qmsDraftService.getUserFormDraft(formId); + return R.ok(CopierUtil.copy(qmsDraft,new QmsDraftVo())); + } + + /** + * 保存草稿 + * @param param + * @return + */ + @PostMapping("/save") + public R saveDraft(@Valid @RequestBody QmsDraftBo param) { + QmsDraft qmsDraft = qmsDraftService.getUserFormDraft(param.getGroupId()); + if(qmsDraft==null){ + qmsDraft = new QmsDraft(); + qmsDraft.setGroupId(param.getGroupId()); + qmsDraft.setContext(param.getContext()); + qmsDraft.setUserId(AuthContextUtils.getAppUserId()); + qmsDraft.setVersion(param.getVersion()); + qmsDraft.setPubFlag("0"); + qmsDraftService.save(qmsDraft); + }else { + qmsDraft.setContext(param.getContext()); + qmsDraft.setVersion(param.getVersion()); + qmsDraftService.updateById(qmsDraft); + } + return R.ok(); + } + + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/controller/api/QmsSubmitApiController.java b/src/main/java/com/qs/serve/modules/qms/controller/api/QmsSubmitApiController.java new file mode 100644 index 00000000..dcc42d8d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/controller/api/QmsSubmitApiController.java @@ -0,0 +1,147 @@ +package com.qs.serve.modules.qms.controller.api; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.qms.entity.QmsFormSubmit; +import com.qs.serve.modules.qms.entity.QmsGroup; +import com.qs.serve.modules.qms.entity.QmsGroupScope; +import com.qs.serve.modules.qms.entity.bo.QmsSubmitBo; +import com.qs.serve.modules.qms.mapper.QmsGroupMapper; +import com.qs.serve.modules.qms.service.QmsFormSubmitService; +import com.qs.serve.modules.qms.service.QmsGroupScopeService; +import com.qs.serve.modules.qms.service.QmsGroupService; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysUserSimpleVo; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +/** + * API 问卷提交记录 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/submit") +public class QmsSubmitApiController { + + private QmsFormSubmitService qmsFormSubmitService; + private SysUserService userService; + private QmsGroupScopeService qmsGroupScopeService; + private QmsGroupService qmsGroupService; + + /** + * 我的代办、已办列表 + * @param finished + * @return + */ + @GetMapping("/myGroupList") + public R todoPage(String finished){ + String userId = AuthContextUtils.getAppUserId(); + PageUtil.startPage(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.in(QmsGroupScope::getScopeType,1,3); + lqw.eq(QmsGroupScope::getScopeValue,userId); + if(finished!=null){ + lqw.eq(QmsGroupScope::getFinished,finished); + } + PageUtil.startPage(); + List groupScopes = qmsGroupScopeService.list(lqw); + List result = new ArrayList<>(); + for (QmsGroupScope groupScope : groupScopes) { + QmsGroup qmsGroup = qmsGroupService.getById(groupScope.getGroupId()); + result.add(qmsGroup); + } + return R.byPageHelperList(groupScopes,result); + } + + /** + * 已提交列表 + * @param param + * @return + */ + @GetMapping("/page") + public R> getPage(QmsFormSubmit param){ + PageUtil.startPage(); + LambdaQueryWrapper formSubmitWrapper = new LambdaQueryWrapper<>(param); + formSubmitWrapper.eq(QmsFormSubmit::getUserId, AuthContextUtils.getAppUserId()); + List list = qmsFormSubmitService.list(formSubmitWrapper); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.QUERY, inter = InterType.API) + public R getById(@PathVariable("id") String id){ + QmsFormSubmit qmsFormSubmit = qmsFormSubmitService.getById(id); + if(!qmsFormSubmit.getUserId().equals(AuthContextUtils.getAppUserId())){ + return R.ok(); + } + return R.ok(qmsFormSubmit); + } + + + /** + * 根据表单ID查询 + * @param groupId + * @return + */ + @GetMapping("/getByFormId/{groupId}") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.QUERY, inter = InterType.API) + public R getByFormId(@PathVariable("groupId") String groupId){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(QmsFormSubmit::getGroupId,groupId); + lqw.eq(QmsFormSubmit::getUserId,AuthContextUtils.getAppUserId()); + QmsFormSubmit formSubmit = qmsFormSubmitService.getOne(lqw,false); + if(formSubmit==null || !formSubmit.getUserId().equals(AuthContextUtils.getAppUserId())){ + return R.ok(); + } + return R.ok(formSubmit); + } + + + /** + * 提交问卷 + * @param param + * @return + */ + @PostMapping("/submit") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.UPDATE, inter = InterType.API) + public R updateById(@RequestBody @Valid QmsSubmitBo param){ + qmsFormSubmitService.submit(param); + return R.ok(); + } + + /** + * 删除问卷提交记录 + * @param id + * @return + */ + //@DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.QUESTION, title = "问卷提交记录", biz = BizType.DELETE, inter = InterType.API) + public R deleteById(@PathVariable("id") String id){ + boolean result = qmsFormSubmitService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/QmsCategory.java b/src/main/java/com/qs/serve/modules/qms/entity/QmsCategory.java new file mode 100644 index 00000000..ab73c2e9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/QmsCategory.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.qms.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 问卷分类 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("qms_category") +public class QmsCategory implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 分类名称 */ + @NotBlank(message = "分类名称不能为空") + @Length(max = 30,message = "分类名称长度不能超过30字") + private String name; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/QmsDraft.java b/src/main/java/com/qs/serve/modules/qms/entity/QmsDraft.java new file mode 100644 index 00000000..d8c89889 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/QmsDraft.java @@ -0,0 +1,81 @@ +package com.qs.serve.modules.qms.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 问卷草稿 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("qms_draft") +public class QmsDraft implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 用户id */ + @Length(max = 32,message = "用户id长度不能超过32字") + private String userId; + + /** 发布内容id */ + private Long submitId; + + /** 发布标识 */ + private String pubFlag; + + /** 表单id */ + private Long groupId; + + private Integer version; + + /** 草稿内容 */ + private String context; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/QmsForm.java b/src/main/java/com/qs/serve/modules/qms/entity/QmsForm.java new file mode 100644 index 00000000..753a7829 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/QmsForm.java @@ -0,0 +1,85 @@ +package com.qs.serve.modules.qms.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 问卷表单 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("qms_form") +public class QmsForm implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 标题 */ + @NotBlank(message = "标题不能为空") + @Length(max = 40,message = "标题长度不能超过40字") + private String title; + + /** 子标题 */ + @Length(max = 255,message = "子标题长度不能超过255字") + private String subtitle; + + /** 分类id */ + private Long categoryId; + + /** 描述 */ + private String descr; + + /** 表单json */ + @NotBlank(message = "表单json不能为空") + private String formContext; + + /** 表单版本 */ + private Integer version; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/QmsFormSubmit.java b/src/main/java/com/qs/serve/modules/qms/entity/QmsFormSubmit.java new file mode 100644 index 00000000..5075c636 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/QmsFormSubmit.java @@ -0,0 +1,104 @@ +package com.qs.serve.modules.qms.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 问卷提交记录 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("qms_form_submit") +public class QmsFormSubmit implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 标题 */ + @NotBlank(message = "标题不能为空") + @Length(max = 40,message = "标题长度不能超过40字") + private String title; + + /** 子标题 */ + @Length(max = 255,message = "子标题长度不能超过255字") + private String subtitle; + + /** 分类id */ + private Long categoryId; + + /** 表单id */ + private Long groupId; + + private Long fromId; + + /** 用户id */ + @NotBlank(message = "用户id不能为空") + @Length(max = 32,message = "用户id长度不能超过32字") + private String userId; + + /** 用户名 */ + @Length(max = 20,message = "用户名长度不能超过20字") + private String userName; + + /** 表单json */ + @NotBlank(message = "表单json不能为空") + private String formContext; + + /** 表单版本 */ + private Integer version; + + /** 表单提交json */ + private String formSubmitContext; + + /** 表单提交时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime submitTime; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/QmsGroup.java b/src/main/java/com/qs/serve/modules/qms/entity/QmsGroup.java new file mode 100644 index 00000000..cea1d988 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/QmsGroup.java @@ -0,0 +1,115 @@ +package com.qs.serve.modules.qms.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.qs.serve.common.framework.mybatis.handler.meta.SplitStringTypeHandler; +import com.qs.serve.common.model.dto.SimpleKeyValue; +import com.qs.serve.modules.sys.entity.dto.SysUserSimpleVo; +import lombok.Data; +import org.apache.ibatis.type.JdbcType; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; +import java.util.List; +/** + * 实体类 + * @author YenHex + * @since 2022-09-16 + */ +@Data +@TableName(value = "qms_group",autoResultMap = true) +public class QmsGroup implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 标题 */ + @NotBlank(message = "标题不能为空") + @Length(max = 20,message = "标题长度不能超过20字") + private String name; + + /** 描述 */ + @Length(max = 50,message = "描述长度不能超过50字") + private String descr; + + /** 表单id */ + @NotNull(message = "表单id不能为空") + private Long formId; + + /** 表单json */ + @NotBlank(message = "表单json不能为空") + @Length(max = 0,message = "表单json长度不能超过0字") + private String formContext; + + /** 发布状态 */ + @NotNull(message = "发布状态不能为空") + private Integer publishState; + + /** 表单版本 */ + private Integer version; + + + /** 使用范围值 */ + //@TableField(typeHandler = SplitStringTypeHandler.class,jdbcType= JdbcType.VARCHAR) + //private String[] scopeValue; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + /** 适用范围 0-所有人可见;1-人员可见;2-部门可见 */ + @TableField(exist = false) + private Integer scopeType; + + @TableField(exist = false) + private List userList; + + + @TableField(exist = false) + private List deptList; + + @TableField(exist = false) + private QmsForm formInfo; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/QmsGroupScope.java b/src/main/java/com/qs/serve/modules/qms/entity/QmsGroupScope.java new file mode 100644 index 00000000..72df226f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/QmsGroupScope.java @@ -0,0 +1,45 @@ +package com.qs.serve.modules.qms.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 实体类 + * @author YenHex + * @since 2022-09-19 + */ +@Data +@TableName("qms_group_scope") +public class QmsGroupScope implements Serializable { + + private static final long serialVersionUID = 1L; + + /** */ + @TableId(type = IdType.AUTO) + private Long id; + + /** */ + private Long groupId; + + /** 适用范围 0-所有人可见;1-人员可见;2-部门可见;3-部门人员 */ + private Integer scopeType; + + private Integer finished; + + /** 使用范围值 */ + @Length(max = 32,message = "使用范围值长度不能超过32字") + private String scopeValue; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsDraftBo.java b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsDraftBo.java new file mode 100644 index 00000000..ed70b994 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsDraftBo.java @@ -0,0 +1,25 @@ +package com.qs.serve.modules.qms.entity.bo; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/9/13 + */ +@Data +public class QmsDraftBo { + + /** 表单id */ + @NotNull + private Long groupId; + + /** 草稿内容 */ + @NotNull + private String context; + + /** 草稿内容 */ + @NotNull + private Integer version; +} diff --git a/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsFormBo.java b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsFormBo.java new file mode 100644 index 00000000..3e8ec0a6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsFormBo.java @@ -0,0 +1,40 @@ +package com.qs.serve.modules.qms.entity.bo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +/** + * @author YenHex + * @since 2022/9/14 + */ +@Data +public class QmsFormBo { + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 标题 */ + @NotBlank(message = "标题不能为空") + @Length(max = 40,message = "标题长度不能超过40字") + private String title; + + /** 子标题 */ + @Length(max = 255,message = "子标题长度不能超过255字") + private String subtitle; + + /** 描述 */ + private String descr; + + /** 分类id */ + private Long categoryId; + + /** 表单json */ + @NotBlank(message = "表单json不能为空") + private String formContext; + +} diff --git a/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsGroupBo.java b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsGroupBo.java new file mode 100644 index 00000000..3bd491c9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsGroupBo.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.qms.entity.bo; + +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/9/16 + */ +@Data +public class QmsGroupBo { + + private Long id; + + /** 标题 */ + @Length(max = 20,message = "标题长度不能超过20字") + private String name; + + @Length(max = 50,message = "描述长度不能超过50字") + private String descr; + + /** 表单id */ + @NotNull(message = "表单id不能为空") + private Long formId; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 适用范围 0-所有人可见;1-人员可见;2-部门可见 */ + private Integer scopeType; + + /** 使用范围值 */ + private String[] scopeValue; + +} diff --git a/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsSubmitBo.java b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsSubmitBo.java new file mode 100644 index 00000000..557a16c3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/bo/QmsSubmitBo.java @@ -0,0 +1,30 @@ +package com.qs.serve.modules.qms.entity.bo; + +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * @author YenHex + * @since 2022/9/13 + */ +@Data +public class QmsSubmitBo { + + private Long id; + + /** 表单id */ + private Long groupId; + + /** 表单版本 */ + private Integer version; + + /** 表单提交json */ + private String submitContext; + + /** 适用范围 0-所有人可见;1-人员可见;2-部门可见 */ + //private String scope; + + /** 适用范围目标ID数组 */ + //private String[] scopeTargetIds; + +} diff --git a/src/main/java/com/qs/serve/modules/qms/entity/vo/QmsDraftVo.java b/src/main/java/com/qs/serve/modules/qms/entity/vo/QmsDraftVo.java new file mode 100644 index 00000000..3b23806e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/entity/vo/QmsDraftVo.java @@ -0,0 +1,41 @@ +package com.qs.serve.modules.qms.entity.vo; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 问卷草稿 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("qms_draft") +public class QmsDraftVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 表单id */ + private Long formId; + + /** 草稿内容 */ + private String context; + + /** 版本 */ + private Integer version; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/mapper/QmsCategoryMapper.java b/src/main/java/com/qs/serve/modules/qms/mapper/QmsCategoryMapper.java new file mode 100644 index 00000000..55016c88 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/mapper/QmsCategoryMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.qms.entity.QmsCategory; + +/** + * 问卷分类 Mapper + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsCategoryMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/mapper/QmsDraftMapper.java b/src/main/java/com/qs/serve/modules/qms/mapper/QmsDraftMapper.java new file mode 100644 index 00000000..5acd78e2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/mapper/QmsDraftMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.qms.entity.QmsDraft; + +/** + * 问卷草稿 Mapper + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsDraftMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/mapper/QmsFormMapper.java b/src/main/java/com/qs/serve/modules/qms/mapper/QmsFormMapper.java new file mode 100644 index 00000000..b5fef49f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/mapper/QmsFormMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.qms.entity.QmsForm; + +/** + * 问卷表单 Mapper + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsFormMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/mapper/QmsFormSubmitMapper.java b/src/main/java/com/qs/serve/modules/qms/mapper/QmsFormSubmitMapper.java new file mode 100644 index 00000000..c3f5e8e2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/mapper/QmsFormSubmitMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.qms.entity.QmsFormSubmit; + +/** + * 问卷提交记录 Mapper + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsFormSubmitMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupMapper.java b/src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupMapper.java new file mode 100644 index 00000000..0982a26b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupMapper.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.qms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.qms.entity.QmsGroup; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * Mapper + * @author YenHex + * @date 2022-09-16 + */ +public interface QmsGroupMapper extends BaseMapper { + + /** + * 加载用户的 + * @param userId + * @param deptId + * @return + */ + List listByUserIdOrDeptId(@Param("userId")String userId,@Param("deptId")String deptId); + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupScopeMapper.java b/src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupScopeMapper.java new file mode 100644 index 00000000..3c3c3a3b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/mapper/QmsGroupScopeMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.qms.entity.QmsGroupScope; + +/** + * Mapper + * @author YenHex + * @date 2022-09-19 + */ +public interface QmsGroupScopeMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/QmsCategoryService.java b/src/main/java/com/qs/serve/modules/qms/service/QmsCategoryService.java new file mode 100644 index 00000000..2f6b17fe --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/QmsCategoryService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.qms.entity.QmsCategory; + +/** + * 问卷分类 服务接口 + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsCategoryService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/QmsDraftService.java b/src/main/java/com/qs/serve/modules/qms/service/QmsDraftService.java new file mode 100644 index 00000000..3cdce3f7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/QmsDraftService.java @@ -0,0 +1,16 @@ +package com.qs.serve.modules.qms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.qms.entity.QmsDraft; + +/** + * 问卷草稿 服务接口 + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsDraftService extends IService { + + QmsDraft getUserFormDraft(Long groupId); + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/QmsFormService.java b/src/main/java/com/qs/serve/modules/qms/service/QmsFormService.java new file mode 100644 index 00000000..ece46634 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/QmsFormService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.qms.entity.QmsForm; + +/** + * 问卷表单 服务接口 + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsFormService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/QmsFormSubmitService.java b/src/main/java/com/qs/serve/modules/qms/service/QmsFormSubmitService.java new file mode 100644 index 00000000..d962e306 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/QmsFormSubmitService.java @@ -0,0 +1,21 @@ +package com.qs.serve.modules.qms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.qms.entity.QmsFormSubmit; +import com.qs.serve.modules.qms.entity.bo.QmsSubmitBo; + +/** + * 问卷提交记录 服务接口 + * @author YenHex + * @date 2022-09-13 + */ +public interface QmsFormSubmitService extends IService { + + /** + * 提交表单 + * @param param + */ + void submit(QmsSubmitBo param); + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/QmsGroupScopeService.java b/src/main/java/com/qs/serve/modules/qms/service/QmsGroupScopeService.java new file mode 100644 index 00000000..d7bbf4b1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/QmsGroupScopeService.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.qms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.qms.entity.QmsGroupScope; +import com.qs.serve.modules.qms.entity.bo.QmsGroupBo; + +import java.util.List; + +/** + * 服务接口 + * @author YenHex + * @date 2022-09-19 + */ +public interface QmsGroupScopeService extends IService { + + + List listByGroupId(Long groupId); + QmsGroupScope getByGroupAndUid(Long groupId,String userId); + void removeByGroupId(Long groupId); + void saveByBo(Long groupId,QmsGroupBo groupBo); + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/QmsGroupService.java b/src/main/java/com/qs/serve/modules/qms/service/QmsGroupService.java new file mode 100644 index 00000000..1975ea8f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/QmsGroupService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.qms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.qms.entity.QmsGroup; + +/** + * 服务接口 + * @author YenHex + * @date 2022-09-16 + */ +public interface QmsGroupService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/impl/QmsCategoryServiceImpl.java b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsCategoryServiceImpl.java new file mode 100644 index 00000000..22508256 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsCategoryServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.qms.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.qms.entity.QmsCategory; +import com.qs.serve.modules.qms.service.QmsCategoryService; +import com.qs.serve.modules.qms.mapper.QmsCategoryMapper; + +/** + * 问卷分类 服务实现类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class QmsCategoryServiceImpl extends ServiceImpl implements QmsCategoryService { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/impl/QmsDraftServiceImpl.java b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsDraftServiceImpl.java new file mode 100644 index 00000000..ef97dda6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsDraftServiceImpl.java @@ -0,0 +1,32 @@ +package com.qs.serve.modules.qms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.qms.entity.QmsDraft; +import com.qs.serve.modules.qms.mapper.QmsDraftMapper; +import com.qs.serve.modules.qms.service.QmsDraftService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 问卷草稿 服务实现类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class QmsDraftServiceImpl extends ServiceImpl implements QmsDraftService { + + @Override + public QmsDraft getUserFormDraft(Long groupId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(QmsDraft::getCreateBy, AuthContextUtils.getAppUserId()); + lqw.eq(QmsDraft::getGroupId,groupId); + lqw.eq(QmsDraft::getPubFlag,0); + return this.getOne(lqw,false); + } +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormServiceImpl.java b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormServiceImpl.java new file mode 100644 index 00000000..80fef268 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.qms.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.qms.entity.QmsForm; +import com.qs.serve.modules.qms.service.QmsFormService; +import com.qs.serve.modules.qms.mapper.QmsFormMapper; + +/** + * 问卷表单 服务实现类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class QmsFormServiceImpl extends ServiceImpl implements QmsFormService { + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormSubmitServiceImpl.java b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormSubmitServiceImpl.java new file mode 100644 index 00000000..25a23432 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsFormSubmitServiceImpl.java @@ -0,0 +1,80 @@ +package com.qs.serve.modules.qms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.modules.qms.entity.QmsForm; +import com.qs.serve.modules.qms.entity.QmsGroup; +import com.qs.serve.modules.qms.entity.QmsGroupScope; +import com.qs.serve.modules.qms.entity.bo.QmsSubmitBo; +import com.qs.serve.modules.qms.service.QmsFormService; +import com.qs.serve.modules.qms.service.QmsGroupScopeService; +import com.qs.serve.modules.qms.service.QmsGroupService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.qms.entity.QmsFormSubmit; +import com.qs.serve.modules.qms.service.QmsFormSubmitService; +import com.qs.serve.modules.qms.mapper.QmsFormSubmitMapper; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +/** + * 问卷提交记录 服务实现类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class QmsFormSubmitServiceImpl extends ServiceImpl implements QmsFormSubmitService { + + private final QmsFormService qmsFormService; + private final QmsGroupService qmsGroupService; + private final QmsGroupScopeService qmsGroupScopeService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void submit(QmsSubmitBo param) { + LoginUser loginUser = AuthContextUtils.getLoginUser(); + QmsGroup qmsGroup = qmsGroupService.getById(param.getGroupId()); + QmsForm form = qmsFormService.getById(qmsGroup.getFormId()); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(QmsFormSubmit::getGroupId,param.getGroupId()); + lqw.eq(QmsFormSubmit::getUserId,loginUser.getUserId()); + //lqw.eq(QmsFormSubmit::getVersion,param.getVersion()); + QmsFormSubmit formSubmit = this.getOne(lqw,false); + if(formSubmit==null){ + formSubmit = new QmsFormSubmit(); + } + //表单关联 + formSubmit.setGroupId(param.getGroupId()); + formSubmit.setFromId(form.getId()); + formSubmit.setTitle(form.getTitle()); + formSubmit.setSubtitle(form.getSubtitle()); + formSubmit.setCategoryId(form.getCategoryId()); + formSubmit.setFormContext(form.getFormContext()); + formSubmit.setVersion(form.getVersion()); + //参数关联 + formSubmit.setFormSubmitContext(param.getSubmitContext()); + //关联用户 + formSubmit.setUserId(loginUser.getUserId()); + formSubmit.setUserName(loginUser.getUsername()); + //时间 + formSubmit.setSubmitTime(LocalDateTime.now()); + if(formSubmit.getId()==null){ + this.save(formSubmit); + }else { + this.updateById(formSubmit); + } + //修改完成进度 + QmsGroupScope qmsGroupScope = qmsGroupScopeService.getByGroupAndUid(param.getGroupId(),loginUser.getUserId()); + qmsGroupScope.setFinished(1); + qmsGroupScopeService.updateById(qmsGroupScope); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupScopeServiceImpl.java b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupScopeServiceImpl.java new file mode 100644 index 00000000..db695300 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupScopeServiceImpl.java @@ -0,0 +1,87 @@ +package com.qs.serve.modules.qms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.qms.entity.bo.QmsGroupBo; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.qms.entity.QmsGroupScope; +import com.qs.serve.modules.qms.service.QmsGroupScopeService; +import com.qs.serve.modules.qms.mapper.QmsGroupScopeMapper; + +import java.util.ArrayList; + +import java.util.List; + +/** + * 服务实现类 + * @author YenHex + * @since 2022-09-19 + */ +@Slf4j +@Service +@AllArgsConstructor +public class QmsGroupScopeServiceImpl extends ServiceImpl implements QmsGroupScopeService { + + SysUserMapper sysUserMapper; + + @Override + public List listByGroupId(Long groupId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(QmsGroupScope::getGroupId,groupId); + return this.list(lqw); + } + + @Override + public QmsGroupScope getByGroupAndUid(Long groupId, String userId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(QmsGroupScope::getGroupId,groupId); + lqw.eq(QmsGroupScope::getScopeValue,userId); + lqw.in(QmsGroupScope::getScopeType,1,3); + return this.getOne(lqw); + } + + @Override + public void removeByGroupId(Long groupId) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(QmsGroupScope::getGroupId,groupId); + this.remove(lqw); + } + + @Override + public void saveByBo(Long groupId,QmsGroupBo groupBo) { + if((groupBo.getScopeType()==null||groupId==null)&& CollectionUtil.isNotEmpty(groupBo.getScopeValue())){ + Assert.throwEx("参数异常"); + } + List list = new ArrayList<>(); + for (String scopeValue : groupBo.getScopeValue()) { + QmsGroupScope groupScope = new QmsGroupScope(); + groupScope.setGroupId(groupId); + groupScope.setScopeType(groupBo.getScopeType()); + groupScope.setFinished(0); + groupScope.setScopeValue(scopeValue); + list.add(groupScope); + if(groupBo.getScopeType().equals(2)){ + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(SysUser::getDeptId,scopeValue); + lqw.select(SysUser::getId); + List sysUsers = sysUserMapper.selectList(lqw); + for (SysUser sysUser : sysUsers) { + QmsGroupScope groupScope2 = new QmsGroupScope(); + groupScope2.setGroupId(groupId); + groupScope2.setScopeType(3); + groupScope2.setFinished(0); + groupScope2.setScopeValue(sysUser.getId()); + list.add(groupScope); + } + } + } + this.saveBatch(list); + } +} + diff --git a/src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupServiceImpl.java b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupServiceImpl.java new file mode 100644 index 00000000..6e0c76d8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/qms/service/impl/QmsGroupServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.qms.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.qms.entity.QmsGroup; +import com.qs.serve.modules.qms.service.QmsGroupService; +import com.qs.serve.modules.qms.mapper.QmsGroupMapper; + +/** + * 服务实现类 + * @author YenHex + * @since 2022-09-16 + */ +@Slf4j +@Service +@AllArgsConstructor +public class QmsGroupServiceImpl extends ServiceImpl implements QmsGroupService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java b/src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java new file mode 100644 index 00000000..2ee7c7ef --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/common/consts/SysStatusConst.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.sys.common.consts; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public class SysStatusConst { + + /** 类型【0->菜单;1->按钮】 */ + public static final int SysPermission_Type_0 = 0; + public static final int SysPermission_Type_1 = 1; + + /** 超级管理标识【0->普通管理员;1->超级管理员】 */ + public static final int SysUser_SuperFlag_0 = 0; + public static final int SysUser_SuperFlag_1 = 1; + + + /** 可见类型【0->所有人可见;1->部分人员可见;2->部门可见】 */ + public static final int SysNotice_VisibleType_0 = 0; + public static final int SysNotice_VisibleType_1 = 1; + public static final int SysNotice_VisibleType_2 = 2; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java new file mode 100644 index 00000000..de3a07a7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysAttachController.java @@ -0,0 +1,115 @@ +package com.qs.serve.modules.sys.controller; + +import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.config.properties.UploadProperties; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.service.SysAttachService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.util.List; +import java.util.Locale; + +/** + * 系统:系统附件 + * @author YenHex + * @since 2022-03-24 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/attach") +public class SysAttachController { + + private SysAttachService sysAttachService; + + private UploadProperties uploadProperties; + + /** + * 附件上传 + * @param request + * @return + */ + @SysLog(title = "附件",biz = BizType.UPLOAD) + @PostMapping("/upload") + public R upload(HttpServletRequest request) { + String uploadPath = uploadProperties.getLogicalPath(); + String contentType = request.getContentType(); + MultipartFile file = null; + if (contentType != null && contentType.toLowerCase().startsWith("multipart")) { + MultipartHttpServletRequest multipartHttpServletRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class); + file = multipartHttpServletRequest.getFile("file"); + } + if (file==null||file.isEmpty()) { + Assert.throwEx("请选择文件"); + } + String fileOrgName = file.getOriginalFilename(); + String mimeType = fileOrgName.substring(fileOrgName.lastIndexOf(".")); + String prefix = LocalDate.now().toString().replace("-","")+"/"; + try { + FileUtil.createTempFile(new File(uploadPath+prefix)); + String newName = IdUtil.timeStampId(); + String fileType = mimeType.toLowerCase(Locale.ROOT); + File dest = new File(uploadPath + prefix + newName + fileType); + Long size = file.getSize(); + file.transferTo(dest); + String path = uploadProperties.getProxyUrl() + prefix + fileOrgName; + SysAttach attach = new SysAttach(); + attach.setName(fileOrgName); + attach.setPath(path); + attach.setSize(size); + attach.setFileType(fileType); + sysAttachService.save(attach); + return R.ok(attach); + } catch (IOException e) { + log.error(e.toString(), e); + } + return R.error("上传失败"); + } + + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(title = "附件",biz = BizType.QUERY) + public R getById(@PathVariable("id") String id){ + SysAttach sysattach = sysAttachService.getById(id); + return R.ok(sysattach); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:attach:query')") + public R> getPage(SysAttach param){ + PageUtil.startPage(); + List list = sysAttachService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java new file mode 100644 index 00000000..dc8567cb --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysDeptController.java @@ -0,0 +1,193 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysDept; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysDeptTranParam; +import com.qs.serve.modules.sys.entity.dto.SysDeptTreeNode; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysDeptService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:部门 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/dept") +public class SysDeptController { + + private SysDeptService sysDeptService; + private SysUserMapper sysUserMapper; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:dept:query')") + public R> getList(SysDept param){ + PageUtil.startPage(); + List list = sysDeptService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 查询所有部门 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:dept:query')") + public R> getListAll(SysDept param){ + List list = sysDeptService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + + /** + * 查询列表树 + * @param param + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:dept:query')") + public R getTreeList(SysDept param){ + List list = sysDeptService.listDept(param); + List treeNodes = list.stream().map(dept->{ + SysDeptTreeNode treeNode = CopierUtil.copy(dept,new SysDeptTreeNode()); + treeNode.setId(dept.getId()); + treeNode.setParentId(dept.getParentId()); + treeNode.setMgrUserName(dept.getMgrUserName()); + treeNode.setSort(0); + return treeNode; + }).collect(Collectors.toList()); + if(param.getLoadRepair()!=null&¶m.getLoadRepair().equals(1)){ + return R.ok(treeNodes); + } + treeNodes = TreeUtil.buildByRecursive(treeNodes,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeNodes); + } + + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "部门",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:dept:query')") + public R getById(@PathVariable("id") String id){ + SysDept sysDept = sysDeptService.getById(id); + if(sysDept.getMgrUserId()!=null){ + SysUser sysUser = sysUserMapper.selectById(sysDept.getMgrUserId()); + if(sysUser!=null){ + sysDept.setMgrUserName(sysUser.getName()); + } + } + return R.ok(sysDept); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "部门",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:dept:insert')") + public R save(@RequestBody @Valid SysDept param){ + boolean result = sysDeptService.save2(param); + return R.isTrue(result); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "部门",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:dept:update')") + public R updateById(@RequestBody @Valid SysDept param){ + sysDeptService.updateById(param); + return R.ok(); + } + + /** + * 部门迁移 + * @param param + * @return + */ + @SysLog(title = "部门",desc = "部门迁移",biz = BizType.UPDATE) + @PostMapping("/updateLevel") + @PreAuthorize("hasRole('sys:post:update')") + @Transactional(rollbackFor = Exception.class) + public R updateLevel(@RequestBody @Valid SysDeptTranParam param){ + SysDept dept = sysDeptService.getById(param.getSelectId()); + if(dept.getParentId().equals(param.getParentId())){ + return R.ok(); + } + String subLevelPath = ""; + if(!dept.getParentId().equals(TreeUtil.DEFAULT_PID_STRING)){ + SysDept orgParent = sysDeptService.getById(dept.getParentId()); + subLevelPath = orgParent.getLevelPath()+"_"; + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(SysDept::getId,SysDept::getParentId,SysDept::getLevelPath); + wrapper.likeRight(SysDept::getLevelPath,dept.getLevelPath()); + List deptList = sysDeptService.list(wrapper); + SysDept parent = null; + if(param.getParentId().equals(TreeUtil.DEFAULT_PID_STRING)){ + parent = sysDeptService.getById(param.getParentId()); + } + for (SysDept sysDept : deptList) { + if(sysDept.getId().equals(param.getSelectId())){ + sysDept.setParentId(param.getParentId()); + } + String levelPath = sysDept.getLevelPath().replace(subLevelPath,""); + if(parent==null){ + sysDept.setLevelPath(levelPath); + }else { + sysDept.setLevelPath(parent.getLevelPath()+"_"+levelPath); + } + } + sysDeptService.updateBatchById(deptList); + return R.ok(); + } + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "部门",biz = BizType.DELETE) + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:dept:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysDeptService.removeById(id); + return R.ok(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java new file mode 100644 index 00000000..402c7304 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysDictController.java @@ -0,0 +1,48 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysDict; +import com.qs.serve.modules.sys.service.SysDictService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 系统 字典 + * @author YenHex + * @since 2022-05-20 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/dict") +public class SysDictController { + + private SysDictService sysDictService; + + /** + * 列表查询 + * @param group 分组key + * @return + */ + @GetMapping("/list") + public R getList(String group){ + if(StringUtils.hasEmpty(group)){ + return R.error("查询参数为空"); + } + PageUtil.startPage(); + LambdaQueryWrapper dictWrapper = new LambdaQueryWrapper<>(); + dictWrapper.eq(SysDict::getGroupKey,group); + List list = sysDictService.list(dictWrapper); + return R.ok(list); + } + + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java new file mode 100644 index 00000000..72bb3001 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysMenuController.java @@ -0,0 +1,188 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.entity.SysMenuPermit; +import com.qs.serve.modules.sys.entity.dto.SysMenuPermitParam; +import com.qs.serve.modules.sys.entity.dto.SysMenuTreeNode; +import com.qs.serve.modules.sys.service.SysMenuPermitService; +import com.qs.serve.modules.sys.service.SysMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:系统菜单 + * @author YenHex + * @since 2022-03-15 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/menu") +public class SysMenuController { + + private SysMenuService sysMenuService; + private SysMenuPermitService sysMenuPermitService; + + + /** + * 获取人员权限菜单 + * @return + */ + @PostMapping("/userMenus") + public R> userMenus(Integer clientType){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + List menuIds = loginUser.getAuthorIds(); + if(CollectionUtil.isNotEmpty(menuIds)){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysMenu::getId,menuIds); + wrapper.eq(SysMenu::getClientType,clientType==null?1:clientType); + return R.ok(sysMenuService.list(wrapper)); + } + return R.ok(); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:menu:query')") + public R> getPage(SysMenu param){ + PageUtil.startPage(); + List list = sysMenuService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 列表查询 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:menu:query')") + public R> getList(SysMenu param){ + List list = sysMenuService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 树形列表 + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:permit:query')") + public R> getTree(Integer clientType){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if(clientType==null){ + wrapper.eq(SysMenu::getClientType,0); + }else { + wrapper.eq(SysMenu::getClientType,clientType); + } + wrapper.eq(SysMenu::getHideFlag,0); + wrapper.orderByAsc(SysMenu::getSort,SysMenu::getId); + List list = sysMenuService.list(wrapper); + List treeNodes = list.stream().map(permit->{ + SysMenuTreeNode treeNode = CopierUtil.copy(permit,new SysMenuTreeNode()); + treeNode.setId(permit.getId()+""); + treeNode.setParentId(permit.getPid()); + treeNode.setSort(permit.getSort()); + return treeNode; + }).collect(Collectors.toList()); + treeNodes = TreeUtil.buildByRecursive(treeNodes,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeNodes); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:menu:query')") + public R getById(@PathVariable("id") String id){ + SysMenu sysMenu = sysMenuService.getById(id); + List menuPermitList = sysMenuPermitService.listByMenuId(id); + sysMenu.setPermitIds(menuPermitList.stream().map(SysMenuPermit::getPermitId).distinct().collect(Collectors.toList())); + return R.ok(sysMenu); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "菜单",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:menu:update')") + public R updateById(@RequestBody @Valid SysMenu param){ + boolean result = sysMenuService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增系统菜单 + * @param param + * @return + */ + @SysLog(title = "菜单",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:menu:insert')") + public R save(@RequestBody @Valid SysMenu param){ + boolean result = sysMenuService.save(param); + return R.isTrue(result); + } + + /** + * 授权系统菜单 + * @param param + * @return + */ + @SysLog(title = "菜单",biz = BizType.GRANT) + @PostMapping("/grantMenu") + @PreAuthorize("hasRole('sys:menu:insert')") + public R save2(@RequestBody @Valid SysMenuPermitParam param){ + sysMenuPermitService.removeByMenuId(param.getMenuId()); + List menuPermitList = new ArrayList<>(); + for (String permitId : param.getPermitIds()) { + SysMenuPermit menuPermit = new SysMenuPermit(); + menuPermit.setMenuId(param.getMenuId()); + menuPermit.setPermitId(permitId); + menuPermitList.add(menuPermit); + } + sysMenuPermitService.saveBatch(menuPermitList); + return R.ok(); + } + + /** + * 删除系统菜单 + * @param id + * @return + */ + @SysLog(title = "菜单",biz = BizType.DELETE) + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:menu:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysMenuService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java new file mode 100644 index 00000000..e0c06c25 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeController.java @@ -0,0 +1,220 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.*; +import com.qs.serve.modules.sys.entity.dto.SysUserVo; +import com.qs.serve.modules.sys.service.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:公示(管理员) + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/notice") +public class SysNoticeController { + + private SysNoticeService sysNoticeService; + private SysDeptService sysDeptService; + private SysUserService sysUserService; + private SysAttachService sysAttachService; + private SysNoticeUserService sysNoticeUserService; + + /** + * 查询个人列表 + * @param param + * @return + */ + @GetMapping("/pageSelf") + public R> getPageSelf(SysNotice param){ + PageUtil.startPage(); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(param); + if(param.getQueryStartTime()!=null){ + wrapper.ge(SysNotice::getLastPublishTime,param.getQueryStartTime()); + } + if(param.getQueryEndTime()!=null){ + wrapper.le(SysNotice::getLastPublishTime,param.getQueryEndTime()); + } + wrapper.eq(SysNotice::getCreateBy, AuthContextUtils.getSysUserId()); + List list = sysNoticeService.list(wrapper); + return R.byPageHelperList(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:notice:query')") + public R> getPage(SysNotice param){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(param); + if(param.getQueryStartTime()!=null){ + wrapper.ge(SysNotice::getLastPublishTime,param.getQueryStartTime()); + } + if(param.getQueryEndTime()!=null){ + wrapper.le(SysNotice::getLastPublishTime,param.getQueryEndTime()); + } + PageUtil.startPage(); + List list = sysNoticeService.list(wrapper); + for (SysNotice notice : list) { + SysUser sysUser = sysUserService.getById(notice.getCreateBy()); + if(sysUser!=null){ + notice.setCreatorName(sysUser.getName()); + } + } + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "公告",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:notice:query')") + public R getById(@PathVariable("id") String id){ + SysNotice sysNotice = sysNoticeService.getById(id); + if(sysNotice==null){ + return R.error("资源不存在或被移除"); + } + String[] arr = sysNotice.getVisibleIds(); + if(CollectionUtil.isNotEmpty(arr)){ + if(sysNotice.getVisibleType().equals(1)){ + List sysUsers = sysUserService.listByIds(Arrays.asList(arr)); + List sysUserVoLIst = sysUsers.stream().map(SysUser::toSysUserVo).collect(Collectors.toList()); + sysNotice.setUserInfos(sysUserVoLIst); + }else if(sysNotice.getVisibleType().equals(2)){ + List deptList = sysDeptService.listByIds(Arrays.asList(arr)); + sysNotice.setDeps(deptList); + } + } + if(CollectionUtil.isNotEmpty(sysNotice.getDocIds())){ + List documents = sysAttachService.listByIds(Arrays.asList(sysNotice.getDocIds())); + sysNotice.setDocuments(documents); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysNoticeUser::getNoticeId,id); + wrapper.eq(SysNoticeUser::getUserId,AuthContextUtils.getSysUserId()); + SysNoticeUser sysNoticeUser = sysNoticeUserService.getOne(wrapper,false); + if(sysNoticeUser!=null){ + sysNoticeUser.setReadFlag(true); + sysNoticeUser.setReadCount(sysNoticeUser.getReadCount()==null?1:sysNoticeUser.getReadCount()+1); + sysNoticeUser.setReadTime(LocalDateTime.now()); + sysNoticeUserService.updateById(sysNoticeUser); + } + return R.ok(sysNotice); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "公告",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:notice:insert')") + public R save(@RequestBody @Valid SysNotice param){ + boolean result = sysNoticeService.save(param); + return R.isTrue(result); + } + + /** + * 发布 + * @param id + * @return + */ + @SysLog(title = "公告",desc = "发布公告",biz = BizType.OTHER) + @PostMapping("/publish/{id}") + @PreAuthorize("hasRole('sys:notice:publish')") + public R publish(@PathVariable("id") String id){ + sysNoticeService.publish(id); + return R.ok(); + } + + /** + * 撤销、下架 + * @param id + * @return + */ + @SysLog(title = "公告",desc = "撤销公告",biz = BizType.OTHER) + @PostMapping("/repeal/{id}") + @PreAuthorize("hasRole('sys:notice:repeal')") + @Transactional(rollbackFor = Exception.class) + public R repeal(@PathVariable("id") String id){ + sysNoticeService.removeUserRelate(id); + SysNotice notice = sysNoticeService.getById(id); + notice.setEnable(0); + updateById(notice); + return R.ok(); + } + + /** + * 保存并发布 + * @param param + * @return + */ + @SysLog(title = "公告",desc = "保存并发布",biz = BizType.INSERT) + @PostMapping("/saveAndPublish") + @PreAuthorize("hasRole('sys:notice:publish') and hasRole('sys:notice:insert')") + @Transactional(rollbackFor = Exception.class) + public R publish(@RequestBody @Valid SysNotice param){ + param.setEnable(1); + if(param.getId()!=null){ + sysNoticeService.updateById(param); + }else { + sysNoticeService.save(param); + } + sysNoticeService.publish(param.getId()); + return R.ok(); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "公告",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:notice:update')") + public R updateById(@RequestBody @Valid SysNotice param){ + boolean result = sysNoticeService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "公告",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:notice:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysNoticeService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java new file mode 100644 index 00000000..eaf9c777 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeTypeController.java @@ -0,0 +1,109 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysNoticeType; +import com.qs.serve.modules.sys.service.SysNoticeTypeService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:公示分类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/noticeType") +public class SysNoticeTypeController { + + private SysNoticeTypeService sysNoticeTypeService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:noticeType:query')") + public R> getPage(SysNoticeType param){ + PageUtil.startPage(); + List list = sysNoticeTypeService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(SysNoticeType param){ + List list = sysNoticeTypeService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "公告类型",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:noticeType:query')") + public R getById(@PathVariable("id") String id){ + SysNoticeType sysNoticeType = sysNoticeTypeService.getById(id); + return R.ok(sysNoticeType); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "公告类型",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:noticeType:insert')") + public R save(@RequestBody @Valid SysNoticeType param){ + boolean result = sysNoticeTypeService.save(param); + return R.isTrue(result); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "公告类型",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:noticeType:update')") + public R updateById(@RequestBody @Valid SysNoticeType param){ + boolean result = sysNoticeTypeService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "公告类型",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:noticeType:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysNoticeTypeService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java new file mode 100644 index 00000000..bb98583e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysNoticeUserController.java @@ -0,0 +1,75 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.entity.SysNotice; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import com.qs.serve.modules.sys.service.SysAttachService; +import com.qs.serve.modules.sys.service.SysNoticeService; +import com.qs.serve.modules.sys.service.SysNoticeUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; + +/** + * 系统:公示(用户) + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/noticeUser") +public class SysNoticeUserController { + + private SysNoticeUserService sysNoticeUserService; + + private SysNoticeService sysNoticeService; + + private SysAttachService sysAttachService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + public R> getList(SysNoticeUser param){ + param.setUserId(AuthContextUtils.getSysUserId()); + Page page = PageUtil.getMbpPage(); + IPage list = sysNoticeUserService.list2(page,param); + return R.byMbpList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + public R getById(@PathVariable("id") String id){ + SysNoticeUser sysNoticeUser = sysNoticeUserService.getById(id); + sysNoticeUser.setReadFlag(true); + sysNoticeUser.setReadCount(sysNoticeUser.getReadCount()==null?1:sysNoticeUser.getReadCount()+1); + sysNoticeUser.setReadTime(LocalDateTime.now()); + sysNoticeUserService.updateById(sysNoticeUser); + SysNotice notice = sysNoticeService.getById(sysNoticeUser.getNoticeId()); + if(CollectionUtil.isNotEmpty(notice.getDocIds())){ + List documents = sysAttachService.listByIds(Arrays.asList(notice.getDocIds())); + notice.setDocuments(documents); + } + return R.ok(notice); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java new file mode 100644 index 00000000..87f157e6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysOperationLogController.java @@ -0,0 +1,82 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.service.SysOperationLogService; +import com.qs.serve.modules.sys.service.SysUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:操作日志 + * @author YenHex + * @since 2022-03-08 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/operationLog") +public class SysOperationLogController { + + private SysOperationLogService sysOperationLogService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:operationLog:query')") + public R> getList(SysOperationLog param){ + //操作日志详情,当前账号只能查当前帐号日志,超管账号可查询全部 + LoginUser loginUser = AuthContextUtils.getLoginUser(); + if(!loginUser.verifyRole(GySysConst.ROLE_ADMIN_OPT_LOG)){ + param.setUserId(loginUser.getUserId()); + } + PageUtil.startPage(); + QueryWrapper wrapper = new QueryWrapper<>(param); + if(PageUtil.getOrderProp()==null){ + wrapper.orderByDesc("create_time"); + } + List list = sysOperationLogService.list(wrapper); + return R.byPageHelperList(list); + } + + /** + * 翻页查询(个人) + * @param param + * @return + */ + @GetMapping("/pageSelf") + public R> pageSelf(SysOperationLog param){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + param.setUserId(loginUser.getUserId()); + return this.getList(param); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:operationLog:query')") + public R getById(@PathVariable("id") String id){ + SysOperationLog sysOperationLog = sysOperationLogService.getById(id); + return R.ok(sysOperationLog); + } + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java new file mode 100644 index 00000000..793c18b2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysPermitController.java @@ -0,0 +1,86 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysPermit; +import com.qs.serve.modules.sys.entity.dto.SysPermitTreeNode; +import com.qs.serve.modules.sys.service.SysPermitService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:权限 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/permit") +public class SysPermitController { + + private SysPermitService sysPermitService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:permit:query')") + public R> getList(SysPermit param){ + PageUtil.startPage(); + param.setHideFlag(0); + List list = sysPermitService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 树形列表 + * @return + */ + @GetMapping("/tree") + @PreAuthorize("hasRole('sys:permit:query')") + public R> getTree(){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysPermit::getHideFlag,0); + List list = sysPermitService.list(wrapper); + List treeNodes = list.stream().map(permit->{ + SysPermitTreeNode treeNode = CopierUtil.copy(permit,new SysPermitTreeNode()); + treeNode.setId(permit.getId()+""); + treeNode.setParentId(permit.getPid()); + treeNode.setSort(0); + return treeNode; + }).collect(Collectors.toList()); + treeNodes = TreeUtil.buildByRecursive(treeNodes,TreeUtil.DEFAULT_PID_STRING); + return R.ok(treeNodes); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:permit:query')") + public R getById(@PathVariable("id") String id){ + SysPermit sysPermit = sysPermitService.getById(id); + return R.ok(sysPermit); + } + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java new file mode 100644 index 00000000..3e0f79e7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysPostController.java @@ -0,0 +1,124 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysPost; +import com.qs.serve.modules.sys.service.SysDeptService; +import com.qs.serve.modules.sys.service.SysPostService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:职务 + * @author YenHex + * @since 2022-04-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/post") +public class SysPostController { + + private SysPostService sysPostService; + private SysDeptService sysDeptService; + + + /** + * 列表查询 + * @param param + * @return + */ + @GetMapping("/list") + public R> getList(@Valid SysPost param){ + List list = sysPostService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:post:query')") + public R> getPage(SysPost param){ + PageUtil.startPage(); + List list = sysPostService.list(new QueryWrapper<>(param)); + for (SysPost sysPost : list) { + if(sysPost.getId()!=null&&!sysPost.getId().equals(0L)){ + sysPost.setSysDept(sysDeptService.getById(sysPost.getDeptId())); + } + } + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(title = "职务",biz = BizType.QUERY) + @PreAuthorize("hasRole('sys:post:query')") + public R getById(@PathVariable("id") String id){ + SysPost sysPost = sysPostService.getById(id); + if(sysPost.getId()!=null&&!sysPost.getId().equals(0L)){ + sysPost.setSysDept(sysDeptService.getById(sysPost.getDeptId())); + } + return R.ok(sysPost); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "职务",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:post:update')") + public R updateById(@RequestBody @Valid SysPost param){ + boolean result = sysPostService.updateById(param); + return R.isTrue(result); + } + + + + /** + * 新增系统职务 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(title = "职务",biz = BizType.INSERT) + @PreAuthorize("hasRole('sys:post:insert')") + public R save(@RequestBody @Valid SysPost param){ + boolean result = sysPostService.save(param); + return R.isTrue(result); + } + + /** + * 删除系统职务 + * @param id + * @return + */ + @SysLog(title = "职务",biz = BizType.DELETE) + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:post:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysPostService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java new file mode 100644 index 00000000..3e55ed58 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysRoleController.java @@ -0,0 +1,224 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysRole; +import com.qs.serve.modules.sys.entity.SysRoleMenu; +import com.qs.serve.modules.sys.entity.SysUserRole; +import com.qs.serve.modules.sys.entity.dto.SysRoleMenuParam; +import com.qs.serve.modules.sys.entity.dto.SysRoleUserParam; +import com.qs.serve.modules.sys.entity.dto.UserRole4EditParam; +import com.qs.serve.modules.sys.service.SysRoleMenuService; +import com.qs.serve.modules.sys.service.SysRoleService; +import com.qs.serve.modules.sys.service.SysUserRoleService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +/** + * 系统:角色 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/role") +public class SysRoleController { + + private SysRoleService sysRoleService; + private SysRoleMenuService sysRoleMenuService; + private SysUserRoleService sysUserRoleService; + + /** + * 查询列表(用于人员编辑) + * @return + */ + @GetMapping("/list4UserEdit") + public R> getList(){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRole::getUserVisible,1); + wrapper.eq(SysRole::getEnable,1); + List list = sysRoleService.list(wrapper); + return R.ok(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:role:query')") + public R> getPage(SysRole param){ + PageUtil.startPage(); + List list = sysRoleService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:role:query')") + public R> getList(SysRole param){ + List list = sysRoleService.list(new QueryWrapper<>(param)); + return R.ok(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:role:query')") + public R getById(@PathVariable("id") String id){ + SysRole sysRole = sysRoleService.getById(id); + sysRole.setMenuList(sysRoleMenuService.listByRoleId(id)); + return R.ok(sysRole); + } + + /** + * 保存角色 + * @param param + * @return + */ + @SysLog(title = "角色",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:role:insert')") + public R save(@RequestBody @Valid SysRole param){ + param.setIsDefault(null); + boolean result = sysRoleService.save(param); + return R.isTrue(result); + } + + /** + * 根据ID更新角色 + * @param param + * @return + */ + @SysLog(title = "角色",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:role:update')") + public R updateById(@RequestBody @Valid SysRole param){ + SysRole sysRole = sysRoleService.getById(param.getId()); + if(sysRole.getIsDefault().equals(1)){ + return R.error("系统默认角色不可修改"); + } + param.setIsDefault(null); + boolean result = sysRoleService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除角色 + * @param id + * @return + */ + @SysLog(title = "角色",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:role:delete')") + public R deleteById(@PathVariable("id") String id){ + SysRole sysRole = sysRoleService.getById(id); + if(sysRole.getIsDefault().equals(1)){ + return R.error("系统默认角色不可删除"); + } + boolean result = sysRoleService.removeById(id); + sysRoleMenuService.removeByRoleId(id,null); + return R.isTrue(result); + } + + + /** + * 角色菜单授权 + * @param param + * @return + */ + @SysLog(title = "角色",desc ="菜单授权",biz = BizType.GRANT) + @PostMapping("/saveRoleMenu") + @PreAuthorize("hasRole('sys:permit:grant')") + @Transactional(rollbackFor = Exception.class) + public R grantRoleMenu(@RequestBody @Valid SysRoleMenuParam param){ + sysRoleMenuService.removeByRoleId(param.getRoleId(),param.getClientType()); + List roleMenus = new ArrayList<>(); + for (String menuId : param.getMenuIds()) { + SysRoleMenu sysRoleMenu = new SysRoleMenu(); + sysRoleMenu.setRoleId(param.getRoleId()); + sysRoleMenu.setMenuId(menuId); + roleMenus.add(sysRoleMenu); + } + sysRoleMenuService.saveBatch(roleMenus); + return R.isTrue(true); + } + + /** + * 添加用户授权 + * @param param + * @return + */ + @SysLog(title = "角色",desc ="保存用户授权",biz = BizType.GRANT) + @PostMapping("/saveUserRole") + @PreAuthorize("hasRole('sys:userRole:grant')") + @Transactional(rollbackFor = Exception.class) + public R grantUser(@RequestBody @Valid SysRoleUserParam param){ + SysRole sysRole = sysRoleService.getById(param.getRoleId()); + if(sysRole.getIsDefault().equals(1)){ + return R.error("应用所有用户的系统默认角色,无需授权"); + } + List sysUserRoles = new ArrayList<>(); + List uids = sysUserRoleService.notDataUserIds(param.getRoleId(),param.getUserIds()); + for (String userId : uids) { + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(userId); + userRole.setRoleId(param.getRoleId()); + sysUserRoles.add(userRole); + } + sysUserRoleService.saveBatch(sysUserRoles); + return R.isTrue(true); + } + + /** + * 编辑页面关联用户角色 + * @param param + * @return + */ + @SysLog(title = "角色",desc ="编辑用户授权",biz = BizType.GRANT) + @PostMapping("/saveUserRole4Edit") + @PreAuthorize("hasRole('sys:userRole:editGrant')") + @Transactional(rollbackFor = Exception.class) + public R saveUserRole4Edit(@RequestBody @Valid UserRole4EditParam param){ + List roleIds = param.getRoleIds(); + String userId = param.getUserId(); + sysRoleService.saveUserRole4Edit(roleIds,userId); + return R.isTrue(true); + } + + /** + * 删除用户授权 + * @param sysRoleUserParam + * @return + */ + @SysLog(title = "角色",desc ="移除用户授权",biz = BizType.GRANT) + @PostMapping("/removeUserRole") + @PreAuthorize("hasRole('sys:userRole:delete')") + public R deleteById(@RequestBody @Valid SysRoleUserParam sysRoleUserParam){ + sysUserRoleService.remove(sysRoleUserParam.getRoleId(),sysRoleUserParam.getUserIds()); + return R.ok(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java new file mode 100644 index 00000000..2218438a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysTenantController.java @@ -0,0 +1,98 @@ +package com.qs.serve.modules.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.sys.entity.SysTenant; +import com.qs.serve.modules.sys.service.SysTenantService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 系统:租户 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/tenant") +public class SysTenantController { + + private SysTenantService sysTenantService; + + /** + * 查询列表 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:tenant:query')") + public R> getList(SysTenant param){ + PageUtil.startPage(); + List list = sysTenantService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "租户",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:tenant:query')") + public R getById(@PathVariable("id") String id){ + SysTenant sysTenant = sysTenantService.getById(id); + return R.ok(sysTenant); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "租户",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:tenant:insert')") + public R save(@RequestBody @Valid SysTenant param){ + boolean result = sysTenantService.save(param); + return R.isTrue(result); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "租户",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:tenant:update')") + public R updateById(@RequestBody @Valid SysTenant param){ + boolean result = sysTenantService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "租户",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:tenant:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysTenantService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java b/src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java new file mode 100644 index 00000000..4306d17d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/controller/SysUserController.java @@ -0,0 +1,364 @@ +package com.qs.serve.modules.sys.controller; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.*; +import com.qs.serve.modules.sys.entity.dto.*; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统:用户 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("sys/user") +public class SysUserController { + + private SysUserService sysUserService; + private SysUserMapper sysUserMapper; + private SysDeptService sysDeptService; + private SysPostService sysPostService; + private SysRoleService sysRoleService; + private RedisService redisService; + + + /** + * 个人登录信息 + * @return + */ + @PostMapping("/info") + public R info(){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser sysUser = sysUserService.getById(loginUser.getUserId()); + sysUser.setAuthorIds(loginUser.getAuthorIds()); + sysUser.setAuthorList(loginUser.getAuthorList()); + SysUserVo sysUserVo = sysUser.toSysUserVo(false); + SysDept dept = sysDeptService.getById(sysUser.getDeptId()); + sysUserVo.setDeptInfo(dept); + SysPost sysPost = sysPostService.getById(sysUser.getPositionId()); + sysUserVo.setPostInfo(sysPost); + return R.ok(sysUserVo); + } + + + /** + * 个人信息详细 + * @return + */ + @GetMapping("/detail") + public R detail(){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser sysUser = sysUserService.getById(loginUser.getUserId()); + sysUser.setAuthorIds(loginUser.getAuthorIds()); + sysUser.setAuthorList(loginUser.getAuthorList()); + sysUserService.relateInfo(sysUser); + return R.ok(sysUser); + } + + /** + * 个人信息更新 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "个人信息更新",biz = BizType.UPDATE) + @PostMapping("/updateInfo") + public R updateInfo(@RequestBody @Valid SysUser param){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser sysUser = new SysUser(); + sysUser.setId(loginUser.getUserId()); + sysUser.setEmerAddress(param.getEmerAddress()); + sysUser.setEmerName(param.getEmerName()); + sysUser.setEmerMobile(param.getEmerMobile()); + sysUser.setEmerRelate(param.getEmerRelate()); + sysUser.setEmerWorksapce(param.getEmerWorksapce()); + sysUser.setUpdateTime(LocalDateTime.now()); + sysUserService.updateById(sysUser); + return R.ok(); + } + + /** + * 个人密码更新 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "个人密码更新",biz = BizType.UPDATE) + @PostMapping("/updatePwd") + public R updatePwd(@RequestBody @Valid SysUserPwdParam param){ + LoginUser loginUser = AuthContextUtils.getLoginUser(); + SysUser dbUser = sysUserService.getById(loginUser.getUserId()); + if(dbUser.getPassword().equalsIgnoreCase(SecureUtil.md5(param.getOldPassword()))){ + SysUser sysUser = new SysUser(); + sysUser.setId(loginUser.getUserId()); + sysUser.setPassword(SecureUtil.md5(param.getNewPassword())); + sysUser.setUpdateTime(LocalDateTime.now()); + sysUserService.updateById(sysUser); + return R.ok(); + } + return R.error(); + + + } + + + /** + * 获取检测工号 + * @return + */ + @LimitSubmit(message = "请勿频繁操作!!") + @GetMapping("/getUserCode") + @PreAuthorize("hasRole('sys:user:query')") + public R getUserCode(){ + LocalDateTime localDateTime = LocalDateTime.now(); + String timeKey = localDateTime.getYear() + String.format("%02d",localDateTime.getMonthValue()); + String key = RedisCacheKeys.SYS_USER_CODE_KEY + timeKey; + Integer val = redisService.getInteger(key); + if(val==null){ + val = 1; + }else { + val +=1; + } + redisService.set(key,val); + return R.ok("A"+timeKey+val,R.SUCCESS_TIPS); + } + + + /** + * 检测工号是否已被使用 + * @param code + * @return + */ + @GetMapping("/checkCode") + @PreAuthorize("hasRole('sys:user:query')") + public R checkCode(String code){ + return R.ok(sysUserMapper.checkCode(code)>0L); + } + + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('sys:user:query')") + public R> getPage(SysUser param){ + param.setTenantId(AuthContextUtils.getTenant()); + if(CollectionUtil.isNotEmpty(param.getMultiDeptIds()) && param.getLoadChildDept()!=null && param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)){ + List deptList = sysDeptService.listDeptByIds(param.getMultiDeptIds(),param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)); + List deptIds = deptList.stream().map(SysDept::getId).distinct().collect(Collectors.toList()); + param.setMultiDeptIds(deptIds); + } + PageUtil.startPage(); + List list = sysUserService.listUser(param); + //前端页面展示参数 + list.forEach(a->sysUserService.relateInfo(a)); + return R.byPageHelperList(list); + } + + /** + * 翻页查询(通讯录,添加隐藏标识过滤) + * @param param + * @return + */ + //@GetMapping("/page2") + @PreAuthorize("hasRole('sys:user:contact')") + public R> getPage2(SysUser param){ + param.setTenantId(AuthContextUtils.getTenant()); + if(CollectionUtil.isNotEmpty(param.getMultiDeptIds()) && param.getLoadChildDept()!=null && param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)){ + List deptList = sysDeptService.listDeptByIds(param.getMultiDeptIds(),param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)); + List deptIds = deptList.stream().map(SysDept::getId).distinct().collect(Collectors.toList()); + param.setMultiDeptIds(deptIds); + } + PageUtil.startPage(); + List list = sysUserService.listUser(param); + //前端页面展示参数 + list.forEach(a->sysUserService.relateInfo(a)); + list.forEach(usr->usr.setPassword(null)); + return R.byPageHelperList(list); + } + + /** + * 列表查询 + * @param param + * @return + */ + @GetMapping("/list") + @PreAuthorize("hasRole('sys:user:query')") + public R> getList(SysUser param){ + param.setTenantId(AuthContextUtils.getTenant()); + if(CollectionUtil.isNotEmpty(param.getMultiDeptIds()) && param.getLoadChildDept()!=null && param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)){ + List deptList = sysDeptService.listDeptByIds(param.getMultiDeptIds(),param.getLoadChildDept().equals(GySysConst.STATUS_YES_1)); + List deptIds = deptList.stream().map(SysDept::getId).distinct().collect(Collectors.toList()); + param.setMultiDeptIds(deptIds); + } + List list = sysUserService.listUser(param); + list.forEach(usr->usr.setPassword(null)); + return R.ok(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @SysLog(title = "人员",desc = "用户查询",biz = BizType.QUERY) + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('sys:user:query')") + public R getById(@PathVariable("id") String id){ + SysUser sysUser = sysUserService.getById(id); + if(sysUser==null){ + return R.ok(); + } + sysUser.setPassword(null); + sysUserService.relateInfo(sysUser); + return R.ok(sysUser); + } + + /** + * 保存 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "用户新增",biz = BizType.INSERT) + @PostMapping("/save") + @PreAuthorize("hasRole('sys:user:insert')") + @Transactional(rollbackFor = Exception.class) + public R save(@RequestBody @Valid SysUser param){ + //设置普通管理员 + param.setSuperFlag(0); + param.setTenantId(AuthContextUtils.getTenant()); + //检查手机号是否已用 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getMobile,param.getMobile()); + int count = sysUserService.count(wrapper); + if(count>0){ + return R.error("手机号已被注册"); + } + param.setAccount(param.getMobile()); + param.setPassword(SecureUtil.md5(GySysConst.DEFAULT_PASSWORD)); + boolean result = sysUserService.save(param); + if(param.getId()!=null&& com.qs.serve.common.util.CollectionUtil.isNotEmpty(param.getRoleIds())){ + sysRoleService.saveUserRole4Edit(param.getRoleIds(),param.getId()); + } + return R.isTrue(result); + } + + /** + * 重置用户密码 + * @param uid + * @return + */ + @SysLog(title = "人员",desc = "重置密码",biz = BizType.RESET) + @PostMapping("/resetPwd/{uid}") + @PreAuthorize("hasRole('sys:user:reset')") + public R resetPwd(@PathVariable("uid") String uid){ + SysUser sysUser = sysUserService.getById(uid); + if(sysUser.getSuperFlag().equals(1)){ + Assert.throwEx("最高级管理员不可重置密码"); + } + SysUser sysUser1 = new SysUser(); + sysUser1.setId(uid); + sysUser1.setPassword(SecureUtil.md5(GySysConst.DEFAULT_PASSWORD)); + sysUserService.updateById(sysUser1); + return R.ok(); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "用户更新",biz = BizType.UPDATE) + @PostMapping("/updateById") + @PreAuthorize("hasRole('sys:user:update')") + @Transactional(rollbackFor = Exception.class) + public R updateById(@RequestBody @Valid SysUser param){ + if(param.getMobile()!=null){ + param.setAccount(param.getMobile()); + } + if(param.getLoginEnable()!=null){ + param.setServingState(param.getLoginEnable()==1?1:0); + } + param.setSuperFlag(null); + param.setPassword(null); + param.setUpdateTime(LocalDateTime.now()); + boolean result = sysUserService.updateById(param); + return R.isTrue(result); + } + + /** + * 删除 + * @param id + * @return + */ + @SysLog(title = "人员",desc = "用户删除",biz = BizType.DELETE) + @PostMapping("/deleteById/{id}") + @PreAuthorize("hasRole('sys:user:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = sysUserService.removeById(id); + return R.isTrue(result); + } + + + /** + * 人员职务调动 + * @param param + * @return + */ + @PostMapping("/tranPost") + @SysLog(title = "人员",desc = "职务调动") + @PreAuthorize("hasRole('sys:user:post')") + @LimitSubmit(interval = 5000) + public R tranPost(@RequestBody @Valid SysUserTranPostParam param){ + SysPost post = sysPostService.getById(param.getPostId()); + SysUser sysUser = sysUserService.getById(param.getUserId()); + sysUser.setDeptId(post.getDeptId()); + sysUser.setPositionId(post.getId()+""); + sysUserService.updateById(sysUser); + return R.ok(); + } + + /** + * 在职调动 + * @param param + * @return + */ + @SysLog(title = "人员",desc = "在职调动") + @PostMapping("/leave") + @PreAuthorize("hasRole('sys:user:leave')") + @LimitSubmit(interval = 5000) + public R leave(@RequestBody @Valid SysUserLeaveParam param){ + SysUser sysUser = sysUserService.getById(param.getUserId()); + sysUser.setServingState(param.getLeaveState()); + sysUserService.updateById(sysUser); + return R.ok(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java b/src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java new file mode 100644 index 00000000..3b3a4f89 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysAttach.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 系统附件 实体类 + * @author YenHex + * @since 2022-03-24 + */ +@Data +@TableName("sys_attach") +public class SysAttach implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 文件名称 */ + private String name; + + /** 保存路径 */ + private String path; + + /** 大小 */ + private Long size; + + /** 文件类型 */ + private String fileType; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @NotNull(message = "删除标识不能为空") + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysDept.java b/src/main/java/com/qs/serve/modules/sys/entity/SysDept.java new file mode 100644 index 00000000..486ea245 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysDept.java @@ -0,0 +1,80 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 部门信息 实体类 + * @author YenHex + * @since 2022-02-28 + */ +@Data +@TableName("sys_dept") +public class SysDept implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 部门编号 */ + @NotNull(message = "部门编号不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String parentId; + + /** 负责人 */ + private String mgrUserId; + + /** 级别路径 */ + private String levelPath; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** 负责人信息 */ + @TableField(exist = false) + private String mgrUserName; + + /** 是否用于维修加载 */ + @TableField(exist = false) + private Integer loadRepair; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysDict.java b/src/main/java/com/qs/serve/modules/sys/entity/SysDict.java new file mode 100644 index 00000000..8c278b68 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysDict.java @@ -0,0 +1,80 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 字典 实体类 + * @author YenHex + * @since 2022-05-20 + */ +@Data +@TableName("sys_dict") +public class SysDict implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** */ + @Length(max = 50,message = "长度不能超过50字") + private String groupKey; + + /** */ + @TableField(value = "key_val") + @Length(max = 50,message = "长度不能超过50字") + private String key; + + /** */ + @Length(max = 50,message = "长度不能超过50字") + private String label; + + /** 排序 */ + private Integer sort; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java b/src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java new file mode 100644 index 00000000..92c5c4da --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysMenu.java @@ -0,0 +1,58 @@ +package com.qs.serve.modules.sys.entity; + +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 系统菜单 实体类 + * @author YenHex + * @since 2022-03-15 + */ +@Data +@TableName("sys_menu") +public class SysMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.INPUT) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 排序 */ + private Integer sort; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型不能为空") + private Integer type; + + /** 是否隐藏 */ + @NotNull(message = "是否隐藏不能为空") + private Integer hideFlag; + + /** 客户端类型 */ + @NotNull(message = "客户端类型不能为空") + private Integer clientType; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @TableField(exist = false) + private List permitIds; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java b/src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java new file mode 100644 index 00000000..7451e628 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysMenuPermit.java @@ -0,0 +1,62 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 菜单权限 实体类 + * @author YenHex + * @since 2022-03-15 + */ +@Data +@TableName("sys_menu_permit") +public class SysMenuPermit implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 菜单ID */ + private String menuId; + + /** 权限ID */ + private String permitId; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @NotNull(message = "删除标识不能为空") + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java b/src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java new file mode 100644 index 00000000..4c7c51c0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysNotice.java @@ -0,0 +1,140 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.qs.serve.common.framework.mybatis.handler.meta.JsonStringTypeHandler; +import lombok.Data; +import org.apache.ibatis.type.JdbcType; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 注意信息 实体类 + * @author YenHex + * @since 2022-02-28 + */ +@Data +@TableName(value = "sys_notice",autoResultMap = true) +public class SysNotice implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 标题 */ + @NotNull + @TableField(condition = SqlCondition.LIKE) + @Length(max = 255,message = "输入内容不能超过50字") + private String title; + + /** 类型ID */ + private String typeId; + + /** 内容 */ + @NotNull + private String content; + + /** + * 是否启用 + */ + private Integer enable; + + /** + * 可见类型【0->所有人可见;1->部分人员可见;2->部门可见】 + */ + @NotNull + private Integer visibleType; + + /** + * 最新的发布时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime lastPublishTime; + + /** + * 可见目标id集合 + */ + @TableField(typeHandler = JsonStringTypeHandler.class,jdbcType = JdbcType.VARCHAR) + private String[] visibleIds; + + /** + * 附件id集合 + */ + @TableField(typeHandler = JsonStringTypeHandler.class,jdbcType = JdbcType.VARCHAR) + private String[] docIds; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** + * 附件列表 + */ + @TableField(exist = false) + private Object documents; + + /** + * 可见部门 + */ + @TableField(exist = false) + private Object deps; + + /** + * 可见人 + */ + @TableField(exist = false) + private Object userInfos; + + /** + * 开始时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryStartTime; + + /** + * 结束时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryEndTime; + + /** + * 创建人名称 + */ + @TableField(exist = false) + private String creatorName; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java new file mode 100644 index 00000000..8b34676f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeType.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 注意信息分类 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_notice_type") +public class SysNoticeType implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** name */ + @TableField(condition = SqlCondition.LIKE) + private String name; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java new file mode 100644 index 00000000..58d0e942 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysNoticeUser.java @@ -0,0 +1,94 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 注意信息&用户关系 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_notice_user") +public class SysNoticeUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 标题 */ + private String noticeId; + + /** 用户ID */ + private String userId; + + /** 阅读标识【0->未读;1->已读】 */ + private Boolean readFlag; + + /** 阅读时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime readTime; + + /** + * 阅读统计 + */ + private Integer readCount; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @JsonIgnore + private String tenantId; + + /** 标题 */ + @TableField(exist = false) + private String title; + + /** + * 开始时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryStartTime; + + /** + * 结束时间 + */ + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryEndTime; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java b/src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java new file mode 100644 index 00000000..1585b3df --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysOperationLog.java @@ -0,0 +1,116 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 操作日志 实体类 + * @author YenHex + * @since 2022-03-08 + */ +@Data +@TableName("sys_operation_log") +public class SysOperationLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 模块 */ + private String module; + + /** 模块标题 */ + @TableField(condition = SqlCondition.LIKE) + private String title; + + /** 业务类型 */ + private String bizType; + + private String optDesc; + + /** 接口类型 */ + private String interType; + + /** 代码方法 */ + private String codeMethod; + + /** 请求方式 */ + private String reqMethod; + + /** 请求地址 */ + private String reqUrl; + + /** 请求参数 */ + private String reqParam; + + /** 访问IP */ + private String reqIp; + + /** 用户类型 */ + private String userType; + + /** 用户ID */ + private String userId; + + /** 错误信息 */ + private String errMsg; + + /** 返回参数 */ + private String jsonResult; + + /** 耗时(单位毫秒) */ + private Long elapsedTime; + + /** 用户代理 */ + private String userAgent; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** 创建人名称 */ + @TableField(condition = SqlCondition.LIKE) + private String creatorName; + + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryStartTime; + + @TableField(exist = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime queryEndTime; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java b/src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java new file mode 100644 index 00000000..0e6d6a91 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysPermit.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 系统权限 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_permit") +public class SysPermit implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 编码 */ + @NotBlank(message = "编码不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型【0->菜单;1->按钮】不能为空") + private Integer type; + + private String url; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @JsonIgnore + private Integer hideFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysPost.java b/src/main/java/com/qs/serve/modules/sys/entity/SysPost.java new file mode 100644 index 00000000..a0a3da60 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysPost.java @@ -0,0 +1,71 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 系统职务 实体类 + * @author YenHex + * @since 2022-04-01 + */ +@Data +@TableName("sys_post") +public class SysPost implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 部门ID */ + @NotNull + private String deptId; + + /** 名称 */ + @TableField(condition = SqlCondition.LIKE) + private String name; + + /** 备注 */ + private String remark; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @TableField(exist = false) + private SysDept sysDept; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysRole.java b/src/main/java/com/qs/serve/modules/sys/entity/SysRole.java new file mode 100644 index 00000000..973c4945 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysRole.java @@ -0,0 +1,75 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 系统角色 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_role") +public class SysRole implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 角色名称 */ + @NotNull(message = "角色名称不能为空") + private String name; + + /** 是否可用 */ + private Integer enable; + + /** 是否默认 */ + private Integer isDefault; + + /** 是否默认 */ + private Integer userVisible; + + /** 显示人员模板中 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + @JsonIgnore + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + @TableField(exist = false) + private List menuList; + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java b/src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java new file mode 100644 index 00000000..bbea7317 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysRoleMenu.java @@ -0,0 +1,62 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 菜单用户 实体类 + * @author YenHex + * @since 2022-03-16 + */ +@Data +@TableName("sys_role_menu") +public class SysRoleMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 角色ID */ + private String menuId; + + /** 角色ID */ + private String roleId; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + @NotNull(message = "删除标识不能为空") + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java b/src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java new file mode 100644 index 00000000..e3554ea5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysTenant.java @@ -0,0 +1,59 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * 系统租户 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_tenant") +public class SysTenant implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 租户id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 租户名称 */ + @TableField(condition = SqlCondition.LIKE) + private String name; + + /** 校区电话 */ + private String callNum; + + /** 校区地址 */ + private String address; + + /** 创建时间 */ + @JsonIgnore + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @JsonIgnore + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @JsonIgnore + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @JsonIgnore + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUser.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUser.java new file mode 100644 index 00000000..4d67864b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUser.java @@ -0,0 +1,305 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.io.Serializable; +import java.util.List; + +import cn.hutool.core.util.DesensitizedUtil; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.qs.serve.common.util.CopierUtil; +import com.qs.serve.modules.sys.entity.dto.SysUserSimpleVo; +import com.qs.serve.modules.sys.entity.dto.SysUserVo; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; + +/** + * 系统用户 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_user") +public class SysUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 手机号 */ + @NotBlank(message = "手机号不能为空") + @Length(max = 64,message = "手机号长度不能超过64字") + private String mobile; + + /** 账号 */ + @Length(max = 64,message = "账号长度不能超过64字") + private String account; + + /** 昵称 */ + @Length(max = 64,message = "昵称长度不能超过64字") + private String name; + + /** 编号/工号 */ + @Length(max = 64,message = "编号/工号长度不能超过64字") + private String code; + + /** 密码 */ + @Length(max = 64,message = "密码长度不能超过64字") + private String password; + + /** 头像 */ + @Length(max = 255,message = "头像长度不能超过255字") + private String icon; + + /** 部门ID */ + @Length(max = 64,message = "部门ID长度不能超过64字") + private String deptId; + + /** 职位ID */ + @Length(max = 64,message = "部门ID长度不能超过64字") + private String positionId; + + /** 超级管理标识【0->普通管理员;1->超级管理员】 */ + private Integer superFlag; + + /** 系统登录权限【0->停用;1->启用】 */ + private Integer loginEnable; + + /** 在职状态【0->离职;1->在职】 */ + private Integer servingState; + + /** 身份证号码 */ + @Length(max = 45,message = "身份证号码长度不能超过45字") + private String identityNo; + + /** 入职日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate enterDate; + + /** 转正时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate formalDate; + + /** 正式员工【0->试用期;1->正式】 */ + private Integer formalStatus; + + /** 备注 */ + @Length(max = 255,message = "备注长度不能超过255字") + private String remark; + + /** 紧急联系人名称 */ + @Length(max = 255,message = "紧急联系人名称长度不能超过255字") + private String emerName; + + /** 紧急联系人与本人关系 */ + @Length(max = 255,message = "紧急联系人与本人关系长度不能超过255字") + private String emerRelate; + + /** 紧急联系人电话 */ + @Length(max = 500,message = "紧急联系人电话长度不能超过500字") + private String emerMobile; + + /** 紧急联系人工作单位 */ + @Length(max = 255,message = "紧急联系人工作单位长度不能超过255字") + private String emerWorksapce; + + /** 紧急联系人住址 */ + @Length(max = 255,message = "紧急联系人住址长度不能超过255字") + private String emerAddress; + + /** 本地类型【0->本地;1->外地】 */ + private Integer localType; + + /** 户口性质【0->非农业;1->农业】 */ + private Integer houseType; + + /** 国籍 */ + @Length(max = 45,message = "国籍长度不能超过45字") + private String nation; + + /** 民族 */ + @Length(max = 20,message = "民族长度不能超过20字") + private String national; + + /** 籍贯 */ + @Length(max = 45,message = "籍贯长度不能超过45字") + private String nativePlace; + + /** 户籍所在地 */ + @Length(max = 100,message = "户籍所在地长度不能超过100字") + private String nativeAddress; + + /** 现居住详细地址 */ + @Length(max = 100,message = "现居住详细地址长度不能超过100字") + private String currAddress; + + /** 政治面貌 */ + @Length(max = 20,message = "政治面貌长度不能超过20字") + private String politicsStatus; + + /** 婚姻状态【0->未婚;1->已婚】 */ + private Integer marriedFlag; + + /** 性别【0->女;1->男】 */ + private Integer gender; + + /** 出生年月日 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate birthday; + + /** 毕业学校 */ + @Length(max = 255,message = "毕业学校长度不能超过255字") + private String eduSchool; + + /** 最高学历【0->未知;1->高中及以下;2->中专;3->大专;4->本科;5->硕士;6->博士】 */ + private Integer eduLevel; + + /** 毕业专业 */ + @Length(max = 255,message = "毕业专业长度不能超过255字") + private String eduProfession; + + /** 登陆客户端标识:android,ios */ + @Length(max = 20,message = "登陆客户端标识:android,ios长度不能超过20字") + private String appClient; + + /** app推送token */ + @Length(max = 255,message = "友盟推送token长度不能超过255字") + private String appToken; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; + + /** 校区id */ + @JsonIgnore + private String tenantId; + + + /** 查询参数 */ + @TableField(exist = false) + private String searchValue; + + /** 查询参数:部门ID多选 */ + @TableField(exist = false) + private List multiDeptIds; + + /** 查询参数:角色ID多选,新增用户时用 */ + @TableField(exist = false) + private List roleIds; + + /** 查询参数:是否加载部门子项参数 */ + @TableField(exist = false) + private Integer loadChildDept; + + /** 部门信息 */ + @TableField(exist = false) + private SysDept deptInfo; + + /** 角色信息 */ + @TableField(exist = false) + private List roleList; + + /** 权限编码 */ + @TableField(exist = false) + private List authorList; + + /** 权限ID */ + @TableField(exist = false) + private List authorIds; + + /** 选中ID */ + @TableField(exist = false) + private List selectIds; + + /** 拼音排序 */ + @TableField(exist = false) + private Integer orderByPinYin; + + /** 职务名称 */ + @TableField(exist = false) + private String positionVal; + + /** 职务名称 */ + @TableField(exist = false) + private String deptcode; + + @TableField(exist = false) + private List tenantInfo; + + /** + * 返回前端,过滤敏感信息 + * @return + */ + public SysUserVo toSysUserVo() { + return toSysUserVo(true); + } + + /** + * 返回前端,过滤敏感信息 + * @return + */ + public SysUserVo toSysUserVo(boolean desensitize) { + SysUserVo sysUserVo = CopierUtil.copy(this,new SysUserVo()); + if(desensitize){ + sysUserVo.setMobile(DesensitizedUtil.mobilePhone(sysUserVo.getMobile())); + sysUserVo.setAccount(DesensitizedUtil.mobilePhone(sysUserVo.getMobile())); + } + return sysUserVo; + } + + /** + * 返回前端,过滤敏感信息 + * @return + */ + public SysUserSimpleVo toSimpleVo(boolean desensitize) { + SysUserSimpleVo sysUserVo = CopierUtil.copy(this,new SysUserSimpleVo()); + if(desensitize){ + sysUserVo.setMobile(DesensitizedUtil.mobilePhone(sysUserVo.getMobile())); + } + return sysUserVo; + } + + public SysUserTenant toSysUserTenant(String tenantId) { + SysUserTenant userTenant = new SysUserTenant(); + userTenant.setTenantId(tenantId); + userTenant.setId(this.getId()); + userTenant.setEnterDate(this.getEnterDate()); + userTenant.setFormalDate(this.getFormalDate()); + userTenant.setFormalStatus(this.getFormalStatus()); + userTenant.setServingState(this.getServingState()); + userTenant.setDeptId(this.getDeptId()); + return userTenant; + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java new file mode 100644 index 00000000..bf78e739 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUserRole.java @@ -0,0 +1,57 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 用户角色 实体类 + * @author YenHex + * @since 2022-03-01 + */ +@Data +@TableName("sys_user_role") +public class SysUserRole implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 用户ID */ + private String userId; + + /** 角色ID */ + private String roleId; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 更新时间 */ + @TableField(fill = FieldFill.UPDATE) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/SysUserTenant.java b/src/main/java/com/qs/serve/modules/sys/entity/SysUserTenant.java new file mode 100644 index 00000000..a81b6f7a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/SysUserTenant.java @@ -0,0 +1,103 @@ +package com.qs.serve.modules.sys.entity; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 用户校区信息 实体类 + * @author YenHex + * @since 2022-05-23 + */ +@Data +@TableName("sys_user_tenant") +public class SysUserTenant implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 用户id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** IC卡号 */ + private String icCard; + + /** 入职日期 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate enterDate; + + /** 合同时间开始时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate servingPactDate; + + /** 合同时间结束时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate servingPactDateEnd; + + /** 转正时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") + private LocalDate formalDate; + + /** 正式员工【0->试用期;1->正式】 */ + private Integer formalStatus; + + /** 在职状态【0->离职;1->在职】 */ + private Integer servingState; + + /** 校区id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + + @TableField(exist = false) + private String tenant; + + /** 部门ID */ + private String deptId; + + /** 人事管理类型 */ + private Integer hrType; + + /** 岗位 */ + private Long positionId; + + /** 职工类型【0->管理员;1->教师;2->职工】 */ + private Integer positionType; +} + diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java new file mode 100644 index 00000000..1f2ebb2d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTranParam.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2022/4/14 + */ +@Data +public class SysDeptTranParam { + + /** + * 迁移的父级ID,根节点传0 + */ + private String parentId; + + /** + * 选中的部门ID + */ + private String selectId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java new file mode 100644 index 00000000..e523795a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysDeptTreeNode.java @@ -0,0 +1,64 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author YenHex + * @since 2022/3/3 + */ +@Data +public class SysDeptTreeNode extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 部门编号 */ + @NotNull(message = "部门编号不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String parentId; + + /** 负责人id */ + private String mgrUserId; + + private Integer isRepair; + + /** 类型【0集团部门 01校区部门 】 */ + @NotNull(message = "类型不能为空") + private Integer type; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime createTime; + + /** 创建人 */ + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime updateTime; + + /** 更新人 */ + private String updateBy; + + /** 负责人 */ + private String mgrUserName; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java new file mode 100644 index 00000000..74cfe0b5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginByPhoneParam.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysLoginByPhoneParam { + + @NotNull + private String phone; + + @NotNull + private String code; + + /** + * 友盟token + */ + private String ymToken; + + /** + * 登陆类型:ios、pc、android + */ + @NotNull + private String loginType; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java new file mode 100644 index 00000000..07ec0a85 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysLoginParam.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysLoginParam { + + @NotNull + private String account; + + @NotNull + private String password; + + /** + * 友盟token + */ + private String ymToken; + + /** + * 登陆类型:ios、pc、android + */ + @NotNull + private String loginType; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java new file mode 100644 index 00000000..3c84fd6f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuPermitParam.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author JcYen + * @date 2022/3/12 + */ +@Data +public class SysMenuPermitParam { + + String menuId; + + List permitIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java new file mode 100644 index 00000000..dab3c6e9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysMenuTreeNode.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/16 + */ +@Data +public class SysMenuTreeNode extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 排序 */ + private Integer sort; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型【0->菜单;1->按钮】不能为空") + private Integer type; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java new file mode 100644 index 00000000..ec68bfc2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysPermitTreeNode.java @@ -0,0 +1,39 @@ +package com.qs.serve.modules.sys.entity.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.qs.serve.common.model.dto.TreeNode; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/11 + */ +@Data +public class SysPermitTreeNode extends TreeNode { + + /** id */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 名称 */ + @NotNull(message = "名称不能为空") + private String name; + + /** 编码 */ + @NotNull(message = "编码不能为空") + private String code; + + /** 父级ID */ + @NotNull(message = "父级ID不能为空") + private String pid; + + /** 类型【0->菜单;1->按钮】 */ + @NotNull(message = "类型【0->菜单;1->按钮】不能为空") + private Integer type; + + private String url; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java new file mode 100644 index 00000000..847d8bb3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysResetPwdByPhoneParam.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +/** + * @author YenHex + * @since 2022/4/7 + */ +@Data +public class SysResetPwdByPhoneParam { + + private String phone; + + private String code; + + private String newPwd; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java new file mode 100644 index 00000000..c1681d0f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleMenuParam.java @@ -0,0 +1,25 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author JcYen + * @date 2022/3/12 + */ +@Data +public class SysRoleMenuParam { + + @NotNull + String roleId; + + List menuIds; + + /** + * 客户端类型 0-PC 1-APP + */ + @NotNull + Integer clientType; +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java new file mode 100644 index 00000000..fb17480a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysRoleUserParam.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author JcYen + * @date 2022/3/12 + */ +@Data +public class SysRoleUserParam { + + String roleId; + + List userIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java new file mode 100644 index 00000000..9c5628df --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserLeaveParam.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/4/1 + */ +@Data +public class SysUserLeaveParam { + + @NotNull + private String userId; + + /** + * 是否离职 + */ + @NotNull + private Integer leaveState; + + //@NotNull + private String apprId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java new file mode 100644 index 00000000..d8529566 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserPwdParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/17 + */ +@Data +public class SysUserPwdParam { + + @NotNull + private String oldPassword; + + @NotNull + private String newPassword; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java new file mode 100644 index 00000000..af549758 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserRewardPunishParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/4/1 + */ +@Data +public class SysUserRewardPunishParam { + + @NotNull + private String userId; + + @NotNull + private String apprId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java new file mode 100644 index 00000000..3b706f6b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserSimpleVo.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysUserSimpleVo { + + /** id */ + private String id; + + /** 手机号 */ + private String mobile; + + /** 编号 */ + private String code; + + private String deptId; + + /** 昵称 */ + private String name; + + /** 头像 */ + private String icon; + + /** 性别【0->女;1->男】 */ + private Integer gender; + + /** 完成状态 */ + private Integer finished; +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java new file mode 100644 index 00000000..f9ee9dea --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTenantEditParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/5/31 + */ +@Data +public class SysUserTenantEditParam { + + @NotNull + private String userId; + + @NotNull + private String[] tenantIds; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java new file mode 100644 index 00000000..e31f54dd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserTranPostParam.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/4/1 + */ +@Data +public class SysUserTranPostParam { + + @NotNull + private String userId; + + @NotNull + private String postId; + + //@NotNull + private String apprId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java new file mode 100644 index 00000000..e497cf95 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/SysUserVo.java @@ -0,0 +1,48 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Data +public class SysUserVo { + + /** id */ + private String id; + + /** 手机号 */ + private String mobile; + + /** 账号 */ + private String account; + + /** 编号 */ + private String code; + + /** 昵称 */ + private String name; + + /** 头像 */ + private String icon; + + /** 性别【0->女;1->男】 */ + private Integer gender; + + /** 在职状态【0->离职;1->在职】 */ + private Integer servingState; + + /** 权限编码 */ + private List authorList; + + /** 权限ID */ + private List authorIds; + + private Object deptInfo; + + private Object postInfo; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java b/src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java new file mode 100644 index 00000000..2926a0f3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/entity/dto/UserRole4EditParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author YenHex + * @since 2022/4/12 + */ +@Data +public class UserRole4EditParam { + + private List roleIds; + + @NotNull + private String userId; + +} diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java new file mode 100644 index 00000000..02346e42 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysAttachMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysAttach; + +/** + * 系统附件 Mapper + * @author YenHex + * @date 2022-03-24 + */ +public interface SysAttachMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java new file mode 100644 index 00000000..5c00a27c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysDeptMapper.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysDept; + +import java.util.List; + +/** + * 部门信息 Mapper + * @author YenHex + * @date 2022-02-28 + */ +public interface SysDeptMapper extends BaseMapper { + + /** + * 查询列表 + * @param sysDept + * @return + */ + List listDept(SysDept sysDept); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java new file mode 100644 index 00000000..29c0c9f5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysDictMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysDict; + +/** + * 字典 Mapper + * @author YenHex + * @date 2022-05-20 + */ +public interface SysDictMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java new file mode 100644 index 00000000..bd4baa1e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuMapper.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysMenu; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 系统菜单 Mapper + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuMapper extends BaseMapper { + + /** + * 查询用户所有菜单ID + * @param userId + * @return + */ + @Select("select distinct srm.menu_id from sys_user_role sur " + + " LEFT JOIN sys_role_menu srm ON sur.role_id = srm.role_id WHERE sur.user_id = #{userId}" + + " and srm.menu_id is not null and sur.del_flag = b'0' and srm.del_flag = b'0'") + List searchUserMenuIds(@Param("userId") String userId); + + /** + * 加载角色菜单id + * @param roleIds + * @return + */ + List searchDefaultMenuIds(@Param("roleIds") List roleIds); + + /** + * 查询所有菜单ID + * @return + */ + @Select("select id from sys_menu where del_flag = b'0'") + List searchMenuIds(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java new file mode 100644 index 00000000..0ba03539 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysMenuPermitMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysMenuPermit; + +/** + * 菜单权限 Mapper + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuPermitMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java new file mode 100644 index 00000000..0c882013 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeMapper.java @@ -0,0 +1,13 @@ +package com.qs.serve.modules.sys.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysNotice; + +/** + * 注意信息 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java new file mode 100644 index 00000000..4358758c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeTypeMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysNoticeType; + +/** + * 注意信息分类 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeTypeMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java new file mode 100644 index 00000000..80111ebb --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysNoticeUserMapper.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 注意信息&用户关系 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeUserMapper extends BaseMapper { + + IPage list2(Page page, @Param("query") SysNoticeUser grouponUser); + + /** + * 统计未读公告 + * @param userId + * @param tenant + * @return + */ + @Select("SELECT " + + " notice.id " + + "FROM " + + " sys_notice_user notice_user " + + " LEFT JOIN sys_notice notice ON notice_user.notice_id = notice.id " + + "WHERE " + + " notice.del_flag = b'0' " + + " AND notice.tenant_id = #{tenant} " + + " AND notice_user.read_flag = '0' " + + " AND notice_user.user_id = #{userId} GROUP BY notice.id ") + @InterceptorIgnore(tenantLine = "1") + List countMyRead(@Param("userId") String userId, @Param("tenant") String tenant); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java new file mode 100644 index 00000000..586e1369 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysOperationLogMapper.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysOperationLog; + +/** + * 操作日志 Mapper + * @author YenHex + * @date 2022-03-08 + */ +public interface SysOperationLogMapper extends BaseMapper { + + /** + * 保存日志 + * @param log + * @return + */ + @InterceptorIgnore(tenantLine = "true") + boolean saveLog(SysOperationLog log); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java new file mode 100644 index 00000000..d813a8d6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysPermitMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPermit; + +/** + * 系统权限 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysPermitMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java new file mode 100644 index 00000000..a9d6926f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysPostMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPost; + +/** + * 系统职务 Mapper + * @author YenHex + * @date 2022-04-01 + */ +public interface SysPostMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java new file mode 100644 index 00000000..b65a9bee --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMapper.java @@ -0,0 +1,13 @@ +package com.qs.serve.modules.sys.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysRole; + +/** + * 系统角色 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysRoleMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java new file mode 100644 index 00000000..dbbb50d0 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysRoleMenuMapper.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysPermit; +import com.qs.serve.modules.sys.entity.SysRoleMenu; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 菜单用户 Mapper + * @author YenHex + * @date 2022-03-16 + */ +public interface SysRoleMenuMapper extends BaseMapper { + + /** + * 查询权限编码 + * @param roleIds + * @return + */ + @Select("") + @InterceptorIgnore(tenantLine = "1") + List listPermitCode(List roleIds); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java new file mode 100644 index 00000000..3a55a39c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysTenantMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysTenant; + +/** + * 系统租户 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysTenantMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java new file mode 100644 index 00000000..d90405c9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserMapper.java @@ -0,0 +1,55 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUser; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import java.util.List; + +/** + * 系统用户 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserMapper extends BaseMapper { + + /** + * 检测是否有编号 + * @param code + * @return + */ + @InterceptorIgnore(tenantLine = "1") + @Select("SELECT count(1) FROM `sys_user` sys_user where sys_user.code = #{code}") + long checkCode(@Param("code") String code); + + /** + * 更新友盟token + * @param uid + * @param token + * @param appClient + */ + @InterceptorIgnore(tenantLine = "1") + @Update("update `sys_user` sys_user set app_token = #{token}, app_client=#{appClient} where id = #{uid}") + void updateYmTokenInt(@Param("uid")String uid,@Param("token")String token,@Param("appClient")String appClient); + + /** + * 移除友盟遗留的token,登录时调用 + * @param token + */ + @InterceptorIgnore(tenantLine = "1") + @Update("update `sys_user` sys_user set sys_user.app_token = '#' where sys_user.app_token = #{token}") + void clearYmToken(@Param("token")String token); + + /** + * 查询用户 + * @param sysUser + * @return + */ + @InterceptorIgnore(tenantLine = "1") + List listUser(@Param("query") SysUser sysUser); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java new file mode 100644 index 00000000..076e8ba5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/mapper/SysUserRoleMapper.java @@ -0,0 +1,15 @@ +package com.qs.serve.modules.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.sys.entity.SysUserRole; + + +/** + * 用户角色 Mapper + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserRoleMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java b/src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java new file mode 100644 index 00000000..50b945bd --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysAttachService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysAttach; + +/** + * 系统附件 服务接口 + * @author YenHex + * @date 2022-03-24 + */ +public interface SysAttachService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java b/src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java new file mode 100644 index 00000000..cf59c864 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysDeptService.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysDept; + +import java.util.List; + +/** + * 部门信息 服务接口 + * @author YenHex + * @date 2022-02-28 + */ +public interface SysDeptService extends IService { + + /** + * 保存 + * @param dept + * @return + */ + boolean save2(SysDept dept); + + /** + * 列表查询 + * @param sysDept + * @return + */ + List listDept(SysDept sysDept); + + /** + * id查询部门 + * @param ids + * @param loadChild + * @return + */ + List listDeptByIds(List ids,boolean loadChild); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysDictService.java b/src/main/java/com/qs/serve/modules/sys/service/SysDictService.java new file mode 100644 index 00000000..3763f1d6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysDictService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysDict; + +/** + * 字典 服务接口 + * @author YenHex + * @date 2022-05-20 + */ +public interface SysDictService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java b/src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java new file mode 100644 index 00000000..344cde38 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysMenuPermitService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysMenuPermit; + +import java.util.List; + +/** + * 菜单权限 服务接口 + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuPermitService extends IService { + + void removeByMenuId(String menuId); + + List listByMenuId(String menuId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java b/src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java new file mode 100644 index 00000000..0af8250c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysMenuService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysMenu; + +/** + * 系统菜单 服务接口 + * @author YenHex + * @date 2022-03-15 + */ +public interface SysMenuService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java new file mode 100644 index 00000000..2d58faee --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeService.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysNotice; + +/** + * 注意信息 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeService extends IService { + + /** + * 发布 + * @param id + */ + void publish(String id); + + /** + * 删除用户关联 + * @param id + */ + void removeUserRelate(String id); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java new file mode 100644 index 00000000..3c5acaf3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeTypeService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysNoticeType; + +/** + * 注意信息分类 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeTypeService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java new file mode 100644 index 00000000..283baef1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysNoticeUserService.java @@ -0,0 +1,18 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysNoticeUser; + +/** + * 注意信息&用户关系 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysNoticeUserService extends IService { + + IPage list2(Page page,SysNoticeUser grouponUser); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java b/src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java new file mode 100644 index 00000000..9eb70231 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysOperationLogService.java @@ -0,0 +1,16 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysOperationLog; + +/** + * 操作日志 服务接口 + * @author YenHex + * @date 2022-03-08 + */ +public interface SysOperationLogService extends IService { + + + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java b/src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java new file mode 100644 index 00000000..772c4a03 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysPermitService.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysPermit; + +import java.util.List; + +/** + * 系统权限 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysPermitService extends IService { + + /** + * 权限列表 + * @return + */ + List listByCache(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysPostService.java b/src/main/java/com/qs/serve/modules/sys/service/SysPostService.java new file mode 100644 index 00000000..b09e88d7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysPostService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysPost; + +/** + * 系统职务 服务接口 + * @author YenHex + * @date 2022-04-01 + */ +public interface SysPostService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java b/src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java new file mode 100644 index 00000000..aeb3ee49 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysRoleMenuService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.entity.SysRoleMenu; + +import java.util.List; + +/** + * 菜单用户 服务接口 + * @author YenHex + * @date 2022-03-16 + */ +public interface SysRoleMenuService extends IService { + + boolean removeByRoleId(String roleId,Integer clientType); + + List listByRoleId(String roleId); +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java b/src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java new file mode 100644 index 00000000..47483c75 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysRoleService.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysRole; + +import java.util.List; + +/** + * 系统角色 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysRoleService extends IService { + + /** + * 加载可用角色 + * @param ids + * @return + */ + List getEnableByIds(List ids); + + /** + * 默认的角色 + * @return + */ + List getDefaultRole(); + + void saveUserRole4Edit(List roleIds,String userId); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java b/src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java new file mode 100644 index 00000000..19ef731d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysTenantService.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysTenant; + +import java.util.List; + +/** + * 系统租户 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysTenantService extends IService { + + List list2(); + + SysTenant getCurrent(); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java new file mode 100644 index 00000000..bf920532 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserLoginService.java @@ -0,0 +1,28 @@ +package com.qs.serve.modules.sys.service; + +import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam; +import com.qs.serve.modules.sys.entity.dto.SysLoginParam; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022/3/1 + */ +public interface SysUserLoginService { + + + /** + * 登录 + * @param loginParam + * @return + */ + Map login(SysLoginParam loginParam); + + /** + * 手机登陆 + * @param loginParam + * @return + */ + Map login(SysLoginByPhoneParam loginParam); +} diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java new file mode 100644 index 00000000..64b7f0e4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserRoleService.java @@ -0,0 +1,28 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.sys.entity.SysUserRole; + +import java.util.List; + +/** + * 用户角色 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserRoleService extends IService { + /** + * 用户查询列表 + * @param uid + * @return + */ + List listByUid(String uid); + + List notDataUserIds(String roleId,List userIds); + + boolean removeByRoleId(String roleId); + + boolean remove(String roleId,List userIds); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/SysUserService.java b/src/main/java/com/qs/serve/modules/sys/service/SysUserService.java new file mode 100644 index 00000000..c789195f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/SysUserService.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.sys.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.modules.sys.entity.SysUser; + +import java.util.List; + +/** + * 系统用户 服务接口 + * @author YenHex + * @date 2022-03-01 + */ +public interface SysUserService extends IService { + + + /** + * 账号查询 + * @param acc + * @return + */ + SysUser getByAccount(String acc); + + SysUser getByIdentityNo(String acc); + + LoginUser getLoginUserByAccount(String account); + + LoginUser getLoginUserById(String id); + + /** + * 用户列表 + * @param sysUser + * @return + */ + List listUser(SysUser sysUser); + + void relateInfo(SysUser sysUser); + + LoginUser buildLoginUser(SysUser sysUser); + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java new file mode 100644 index 00000000..740a8b7a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysAttachServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysAttach; +import com.qs.serve.modules.sys.mapper.SysAttachMapper; +import com.qs.serve.modules.sys.service.SysAttachService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 系统附件 服务实现类 + * @author YenHex + * @since 2022-03-24 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysAttachServiceImpl extends ServiceImpl implements SysAttachService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java new file mode 100644 index 00000000..5d8c4b79 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.common.util.TreeUtil; +import com.qs.serve.modules.sys.entity.SysDept; +import com.qs.serve.modules.sys.mapper.SysDeptMapper; +import com.qs.serve.modules.sys.service.SysDeptService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 部门信息 服务实现类 + * @author YenHex + * @since 2022-02-28 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysDeptServiceImpl extends ServiceImpl implements SysDeptService { + + @Override + public boolean save2(SysDept dept) { + dept.setId(IdUtil.timeStampId()); + if(dept.getParentId().equals(TreeUtil.DEFAULT_PID_STRING)){ + dept.setLevelPath(dept.getId()); + }else{ + SysDept parentDept = getById(dept.getParentId()); + dept.setLevelPath(parentDept.getLevelPath()+"_"+dept.getId()); + } + save(dept); + return true; + } + + @Override + public List listDept(SysDept sysDept) { + return baseMapper.listDept(sysDept); + } + + @Override + public List listDeptByIds(List ids, boolean loadChild) { + if(CollectionUtil.isEmpty(ids)){return null;} + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(SysDept::getId,ids); + List list = list(wrapper); + if(loadChild){ + final List levels = list.stream().map(SysDept::getLevelPath).collect(Collectors.toList()); + LambdaQueryWrapper deptQueryWrapper = new LambdaQueryWrapper<>(); + deptQueryWrapper.and(wq->{ + for (int i = 0; i < levels.size(); i++) { + if(i != 0 ){ + wq.or(); + } + wq.likeRight(SysDept::getLevelPath,levels.get(i)); + } + }); + return list(deptQueryWrapper); + } + return list; + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java new file mode 100644 index 00000000..b7768f6b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysDictServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.sys.entity.SysDict; +import com.qs.serve.modules.sys.service.SysDictService; +import com.qs.serve.modules.sys.mapper.SysDictMapper; + +/** + * 字典 服务实现类 + * @author YenHex + * @since 2022-05-20 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysDictServiceImpl extends ServiceImpl implements SysDictService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java new file mode 100644 index 00000000..c8be3823 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuPermitServiceImpl.java @@ -0,0 +1,38 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysMenuPermit; +import com.qs.serve.modules.sys.mapper.SysMenuPermitMapper; +import com.qs.serve.modules.sys.service.SysMenuPermitService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 菜单权限 服务实现类 + * @author YenHex + * @since 2022-03-15 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysMenuPermitServiceImpl extends ServiceImpl implements SysMenuPermitService { + + @Override + public void removeByMenuId(String menuId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysMenuPermit::getMenuId,menuId); + remove(wrapper); + } + + @Override + public List listByMenuId(String menuId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysMenuPermit::getMenuId,menuId); + return list(wrapper); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java new file mode 100644 index 00000000..2347fe67 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.mapper.SysMenuMapper; +import com.qs.serve.modules.sys.service.SysMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 系统菜单 服务实现类 + * @author YenHex + * @since 2022-03-15 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysMenuServiceImpl extends ServiceImpl implements SysMenuService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 00000000..3712ede6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,89 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.sys.common.consts.SysStatusConst; +import com.qs.serve.modules.sys.entity.SysNotice; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.mapper.SysNoticeMapper; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysNoticeService; +import com.qs.serve.modules.sys.service.SysNoticeUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 注意信息 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysNoticeServiceImpl extends ServiceImpl implements SysNoticeService { + + private SysUserMapper sysUserMapper; + private SysNoticeUserService sysNoticeUserService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void publish(String id) { + SysNotice notice = getById(id); + //移除旧记录 + removeUserRelate(id); + LambdaQueryWrapper userLambdaQueryWrapper = new LambdaQueryWrapper<>(); + userLambdaQueryWrapper.select(SysUser::getId); + List userIds = null; + if(notice.getVisibleType().equals(SysStatusConst.SysNotice_VisibleType_0)){ + List userList = sysUserMapper.selectList(userLambdaQueryWrapper); + userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList()); + }else if (notice.getVisibleType().equals(SysStatusConst.SysNotice_VisibleType_1)){ + if(notice.getVisibleIds()==null||notice.getVisibleIds().length<1){ + Assert.throwEx("请设置可见人员"); + } + userIds = Arrays.asList(notice.getVisibleIds()); + }else if(notice.getVisibleType().equals(SysStatusConst.SysNotice_VisibleType_2)){ + if(notice.getVisibleIds()==null||notice.getVisibleIds().length<1){ + Assert.throwEx("请设置可见部门"); + } + userLambdaQueryWrapper.in(SysUser::getDeptId,Arrays.asList(notice.getVisibleIds())); + List userList = sysUserMapper.selectList(userLambdaQueryWrapper); + userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList()); + } + if(userIds!=null){ + List noticeUserList = new ArrayList<>(); + for (String userId : userIds) { + SysNoticeUser noticeUser = new SysNoticeUser(); + noticeUser.setUserId(userId); + noticeUser.setNoticeId(id); + noticeUserList.add(noticeUser); + } + List> tmpList = CollectionUtil.createList(noticeUserList,50); + for (List sysNoticeUsers : tmpList) { + sysNoticeUserService.saveBatch(sysNoticeUsers); + } + //TODO gyApiService.sendYmMsg("广雅公告消息",userIds,notice.getId(), GyApiConst.Notice); + notice.setLastPublishTime(LocalDateTime.now()); + updateById(notice); + } + } + + @Override + public void removeUserRelate(String id) { + LambdaQueryWrapper delWarp = new LambdaQueryWrapper<>(); + delWarp.eq(SysNoticeUser::getNoticeId,id); + sysNoticeUserService.remove(delWarp); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java new file mode 100644 index 00000000..d913db61 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeTypeServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysNoticeType; +import com.qs.serve.modules.sys.mapper.SysNoticeTypeMapper; +import com.qs.serve.modules.sys.service.SysNoticeTypeService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 注意信息分类 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysNoticeTypeServiceImpl extends ServiceImpl implements SysNoticeTypeService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java new file mode 100644 index 00000000..9cfe1dfb --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysNoticeUserServiceImpl.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.sys.entity.SysNoticeUser; +import com.qs.serve.modules.sys.mapper.SysNoticeUserMapper; +import com.qs.serve.modules.sys.service.SysNoticeUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 注意信息&用户关系 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysNoticeUserServiceImpl extends ServiceImpl implements SysNoticeUserService { + + @Override + public IPage list2(Page page, SysNoticeUser grouponUser) { + grouponUser.setTenantId(AuthContextUtils.getTenant()); + return baseMapper.list2(page, grouponUser); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java new file mode 100644 index 00000000..1447f08f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysOperationLogServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysOperationLog; +import com.qs.serve.modules.sys.mapper.SysOperationLogMapper; +import com.qs.serve.modules.sys.service.SysOperationLogService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 操作日志 服务实现类 + * @author YenHex + * @since 2022-03-08 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysOperationLogServiceImpl extends ServiceImpl implements SysOperationLogService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java new file mode 100644 index 00000000..0654bbe5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPermitServiceImpl.java @@ -0,0 +1,30 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysPermit; +import com.qs.serve.modules.sys.mapper.SysPermitMapper; +import com.qs.serve.modules.sys.service.SysPermitService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统权限 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysPermitServiceImpl extends ServiceImpl implements SysPermitService { + + @Override + //@Cacheable(cacheNames = RedisCacheKeys.PERMIT_ALL_LIST) + public List listByCache() { + return list(); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java new file mode 100644 index 00000000..c4e31ab9 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysPostServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysPost; +import com.qs.serve.modules.sys.mapper.SysPostMapper; +import com.qs.serve.modules.sys.service.SysPostService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 系统职务 服务实现类 + * @author YenHex + * @since 2022-04-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysPostServiceImpl extends ServiceImpl implements SysPostService { + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java new file mode 100644 index 00000000..bfed947c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleMenuServiceImpl.java @@ -0,0 +1,68 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.sys.entity.SysMenu; +import com.qs.serve.modules.sys.entity.SysRoleMenu; +import com.qs.serve.modules.sys.mapper.SysRoleMenuMapper; +import com.qs.serve.modules.sys.service.SysMenuService; +import com.qs.serve.modules.sys.service.SysRoleMenuService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 菜单用户 服务实现类 + * @author YenHex + * @since 2022-03-16 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysRoleMenuServiceImpl extends ServiceImpl implements SysRoleMenuService { + + private SysMenuService sysMenuService; + + @Override + public boolean removeByRoleId(String roleId,Integer clientType) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRoleMenu::getRoleId,roleId); + if(clientType!=null){ + List sysRoleMenus = list(wrapper); + List menuIds = sysRoleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()); + LambdaQueryWrapper menuLambdaQueryWrapper = new LambdaQueryWrapper<>(); + menuLambdaQueryWrapper.eq(SysMenu::getClientType,clientType); + if(CollectionUtil.isNotEmpty(menuIds)){ + menuLambdaQueryWrapper.in(SysMenu::getId,menuIds); + } + List menuList = sysMenuService.list(menuLambdaQueryWrapper); + menuIds = menuList.stream().map(SysMenu::getId).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(menuIds)){ + wrapper.in(SysRoleMenu::getMenuId,menuIds); + }else { + return true; + } + } + remove(wrapper); + return true; + } + + @Override + public List listByRoleId(String roleId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRoleMenu::getRoleId,roleId); + List roleMenus = list(wrapper); + List menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId).distinct().collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(menuIds)){ + LambdaQueryWrapper wrapper2 = new LambdaQueryWrapper<>(); + wrapper2.in(SysMenu::getId,menuIds); + return sysMenuService.list(wrapper2); + } + return null; + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java new file mode 100644 index 00000000..8ad31f1e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,94 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.sys.entity.SysRole; +import com.qs.serve.modules.sys.entity.SysUserRole; +import com.qs.serve.modules.sys.mapper.SysRoleMapper; +import com.qs.serve.modules.sys.mapper.SysUserRoleMapper; +import com.qs.serve.modules.sys.service.SysRoleService; +import com.qs.serve.modules.sys.service.SysUserRoleService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统角色 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysRoleServiceImpl extends ServiceImpl implements SysRoleService { + + private SysRoleMapper sysRoleMapper; + private SysUserRoleMapper sysUserRoleMapper; + private SysUserRoleService sysUserRoleService; + @Override + public List getEnableByIds(List ids) { + if(CollectionUtil.isEmpty(ids)){return new ArrayList<>();} + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(SysRole::getId,ids); + wrapper.eq(SysRole::getEnable,1); + return list(wrapper); + } + + @Override + public List getDefaultRole() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysRole::getIsDefault,1); + wrapper.eq(SysRole::getTenantId, AuthContextUtils.getTenant()); + return list(wrapper); + } + + @Override + public void saveUserRole4Edit(List roleIds, String userId) { + //适配空选项移除角色 + if(CollectionUtil.isEmpty(roleIds)){ + LambdaQueryWrapper roleWrap = new LambdaQueryWrapper<>(); + roleWrap.eq(SysRole::getEnable,1); + roleWrap.eq(SysRole::getIsDefault,0); + List list = list(roleWrap); + roleIds = list.stream().map(SysRole::getId).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(list)){ + //移除用户关联的用户板块的可见角色关联 + LambdaQueryWrapper delUserRole = new LambdaQueryWrapper<>(); + delUserRole.eq(SysUserRole::getUserId,userId); + delUserRole.in(SysUserRole::getRoleId,roleIds); + sysUserRoleMapper.delete(delUserRole); + } + } + //校验ID是否正常 + LambdaQueryWrapper roleWrap = new LambdaQueryWrapper<>(); + roleWrap.in(SysRole::getId,roleIds); + roleWrap.eq(SysRole::getEnable,1); + roleWrap.eq(SysRole::getUserVisible,1); + int count = baseMapper.selectCount(roleWrap); + if(count!=roleIds.size()){ + Assert.throwEx("数据不配"); + } + //移除用户关联的用户板块的可见角色关联 + LambdaQueryWrapper delUserRole = new LambdaQueryWrapper<>(); + delUserRole.eq(SysUserRole::getUserId,userId); + delUserRole.in(SysUserRole::getRoleId,roleIds); + sysUserRoleMapper.delete(delUserRole); + //重新关联已有的角色 + List sysUserRoles = new ArrayList<>(); + for (String roleId : roleIds) { + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(userId); + userRole.setRoleId(roleId); + sysUserRoles.add(userRole); + } + sysUserRoleService.saveBatch(sysUserRoles); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java new file mode 100644 index 00000000..b8223c93 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,37 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.sys.entity.SysTenant; +import com.qs.serve.modules.sys.mapper.SysTenantMapper; +import com.qs.serve.modules.sys.service.SysTenantService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统租户 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysTenantServiceImpl extends ServiceImpl implements SysTenantService { + + @Override + @Cacheable(cacheNames = RedisCacheKeys.Tenant_ALL_LIST) + public List list2() { + return list(); + } + + @Override + public SysTenant getCurrent() { + return getById(AuthContextUtils.getTenant()); + } +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java new file mode 100644 index 00000000..40117bf1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserLoginServiceImpl.java @@ -0,0 +1,110 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.crypto.SecureUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.service.SysUserDetailsServiceImpl; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.JwtUtils; +import com.qs.serve.common.util.StringUtils; +import com.qs.serve.modules.sys.entity.SysUser; +import com.qs.serve.modules.sys.entity.dto.SysLoginByPhoneParam; +import com.qs.serve.modules.sys.entity.dto.SysLoginParam; +import com.qs.serve.modules.sys.mapper.SysTenantMapper; +import com.qs.serve.modules.sys.mapper.SysUserMapper; +import com.qs.serve.modules.sys.service.SysUserLoginService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author YenHex + * @since 2022/3/1 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserLoginServiceImpl implements SysUserLoginService { + + private final SysUserDetailsServiceImpl userDetailsService; + + private final SysTenantMapper sysTenantMapper; + + private final SysUserMapper sysUserMapper; + + private final RedisService redisService; + + @Override + public Map login(SysLoginParam loginParam) { + UserDetails userDetails = userDetailsService.loadUserByUsername(loginParam.getAccount()); + if(userDetails == null || !userDetails.getPassword().equalsIgnoreCase(SecureUtil.md5(loginParam.getPassword()))){ + throw new BadCredentialsException("账号或登录密码不正确"); + } + return buildResultMap(userDetails, loginParam.getLoginType(), loginParam.getYmToken()); + } + + @Override + public Map login(SysLoginByPhoneParam loginParam) { + String key = RedisCacheKeys.PHONE_KEY+loginParam.getPhone(); + String code = redisService.getString(key); + if(!loginParam.getCode().equals(code)){ + Assert.throwEx("验证码无效或过期"); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,loginParam.getPhone()); + List list = sysUserMapper.selectList(wrapper); + SysUser sysUser = null; + if(list.size()>0){ + if(list.size()>1){ + log.warn("用户表电话号码[{}]重复!!",loginParam.getPhone()); + } + sysUser = list.get(0); + } + AuthContextUtils.setTenant(sysUser.getTenantId()); + UserDetails userDetails = userDetailsService.buildLoginUser(sysUser); + return buildResultMap(userDetails, loginParam.getLoginType(), loginParam.getYmToken()); + } + + + private Map buildResultMap(UserDetails userDetails,String loginType,String ymToken){ + LoginUser loginUser = (LoginUser)userDetails; + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + String appClient = null; + if("android".equalsIgnoreCase(loginType)){ + appClient = "android"; + }else if("ios".equalsIgnoreCase(loginType)){ + appClient = "ios"; + } + if(appClient!=null&&StringUtils.isNotEmpty(ymToken)){ + sysUserMapper.clearYmToken(ymToken); + sysUserMapper.updateYmTokenInt(loginUser.getUserId(),ymToken,appClient); + } + String client = appClient==null?"pc":"app"; + String redisKey = StringUtils.format(RedisCacheKeys.LOGIN_KEY_APP,client,loginUser.getUserId()); + //更新管理员最后登录时间 + Map tokenMap = new HashMap<>(10); + String token = JwtUtils.generateToken(loginUser.getUserId(),loginUser.getTypeFlag(),client); + redisService.set(redisKey,token); + tokenMap.put("token", token); + tokenMap.put("userId", loginUser.getUserId()); + tokenMap.put("IP", loginUser.getLoginIp()); + tokenMap.put("tenant", sysTenantMapper.selectById(loginUser.getTenant())); + tokenMap.put("loginType",loginType); + tokenMap.put("client",client); + return tokenMap; + } + +} diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java new file mode 100644 index 00000000..fcf1d359 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserRoleServiceImpl.java @@ -0,0 +1,65 @@ +package com.qs.serve.modules.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.CollectionUtil; +import com.qs.serve.modules.sys.entity.SysUserRole; +import com.qs.serve.modules.sys.mapper.SysUserRoleMapper; +import com.qs.serve.modules.sys.service.SysUserRoleService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户角色 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserRoleServiceImpl extends ServiceImpl implements SysUserRoleService { + + @Override + public boolean removeByRoleId(String roleId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUserRole::getRoleId,roleId); + remove(wrapper); + return true; + } + + @Override + public List listByUid(String uid) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUserRole::getUserId,uid); + return list(wrapper); + } + + @Override + public List notDataUserIds(String roleId, final List userIds) { + if(CollectionUtil.isEmpty(userIds)){ + return new ArrayList<>(); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(SysUserRole::getUserId); + wrapper.in(SysUserRole::getUserId,userIds); + wrapper.eq(SysUserRole::getRoleId,roleId); + List sysUserRoles = list(wrapper); + List dbUserIds = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList()); + return userIds.stream().filter(uid->!dbUserIds.contains(uid)).collect(Collectors.toList()); + } + + @Override + public boolean remove(String roleId, List userIds) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(SysUserRole::getUserId,userIds); + wrapper.eq(SysUserRole::getRoleId,roleId); + return remove(wrapper); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java new file mode 100644 index 00000000..3c36dc25 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/sys/service/impl/SysUserServiceImpl.java @@ -0,0 +1,138 @@ +package com.qs.serve.modules.sys.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.DesensitizedUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.util.*; +import com.qs.serve.modules.sys.entity.*; +import com.qs.serve.modules.sys.mapper.*; +import com.qs.serve.modules.sys.service.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统用户 服务实现类 + * @author YenHex + * @since 2022-03-01 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysUserServiceImpl extends ServiceImpl implements SysUserService { + + private final SysUserRoleService sysUserRoleService; + private final SysRoleMenuMapper sysRoleMenuMapper; + private final SysPermitService sysPermitService; + private final SysRoleService sysRoleService; + private final SysDeptMapper sysDeptMapper; + private final SysMenuMapper sysMenuMapper; + + + + @Override + public SysUser getByAccount(String acc) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getAccount,acc); + return getOne(wrapper,false); + } + + @Override + public SysUser getByIdentityNo(String acc) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysUser::getIdentityNo,acc); + return getOne(wrapper,false); + } + + @Override + public LoginUser getLoginUserByAccount(String account) { + SysUser sysUser = getByAccount(account); + if(AuthContextUtils.getTenant()==null){ + AuthContextUtils.setTenant(sysUser.getTenantId()); + } + return buildLoginUser(sysUser); + } + + @Override + public LoginUser getLoginUserById(String id) { + SysUser sysUser = getById(id); + return buildLoginUser(sysUser); + } + + @Override + public List listUser(SysUser sysUser) { + List list = baseMapper.listUser(sysUser); + list.forEach(usr->{ + usr.setMobile(DesensitizedUtil.mobilePhone(usr.getMobile())); + usr.setAccount(DesensitizedUtil.mobilePhone(usr.getMobile())); + usr.setPassword(null); + }); + return list; + } + + @Override + public void relateInfo(SysUser sysUser) { + if(sysUser==null){return;} + sysUser.setPassword(null); + List userRoles = sysUserRoleService.listByUid(sysUser.getId()); + List roleIds = userRoles.stream().map(SysUserRole::getRoleId).distinct().collect(Collectors.toList()); + List sysRoles = new ArrayList<>(); + if(CollectionUtil.isNotEmpty(roleIds)){ + sysRoles = sysRoleService.getEnableByIds(roleIds); + } + sysUser.setRoleList(sysRoles); + if(sysUser.getDeptId()!=null){ + sysUser.setDeptInfo(sysDeptMapper.selectById(sysUser.getDeptId())); + } + } + + + + @Override + public LoginUser buildLoginUser(SysUser sysUser){ + if(sysUser==null){return null;} + if(sysUser.getLoginEnable().equals(0)){ + Assert.throwEx(HttpCode.LOGIN_ERR_2); + } + List authorCodes = new ArrayList<>(); + List menuIds = new ArrayList<>(); + if(sysUser.getSuperFlag().equals(1)){ + List sysRolePermits = sysPermitService.listByCache(); + authorCodes = sysRolePermits.stream().map(SysPermit::getCode).distinct().collect(Collectors.toList()); + menuIds = sysMenuMapper.searchMenuIds(); + }else { + List userRoles = sysUserRoleService.listByUid(sysUser.getId()); + List roleIds = userRoles.stream().map(SysUserRole::getRoleId).distinct().collect(Collectors.toList()); + //添加默认的角色ID + List defaultRole = sysRoleService.getDefaultRole(); + List defaultRoleIds = defaultRole.stream().map(SysRole::getId).collect(Collectors.toList()); + roleIds.addAll(defaultRoleIds); + List sysRoles = sysRoleService.getEnableByIds(roleIds); + List sysRolePermits = new ArrayList<>(); + if(CollectionUtil.isNotEmpty(sysRoles)){ + //listPermitCode + sysRolePermits = sysRoleMenuMapper.listPermitCode(sysRoles.stream().map(SysRole::getId).collect(Collectors.toList())); + } + for (SysPermit sysRolePermit : sysRolePermits) { + if(sysRolePermit==null){continue;} + authorCodes.add(sysRolePermit.getCode()); + } + menuIds = sysMenuMapper.searchUserMenuIds(sysUser.getId()); + List defaultRoleMenuIds = sysMenuMapper.searchDefaultMenuIds(defaultRoleIds); + menuIds.addAll(defaultRoleMenuIds); + } + LoginUserType userType = sysUser.getSuperFlag()==0?LoginUserType.SYS_USER:LoginUserType.SYS_SUP_USER; + return new LoginUser(sysUser.getId(),sysUser.getName(),sysUser.getPassword(), ServletUtils.getIp(null),userType,authorCodes,menuIds,sysUser.getTenantId()); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/controller/UmsUserController.java b/src/main/java/com/qs/serve/modules/ums/controller/UmsUserController.java new file mode 100644 index 00000000..94034a83 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/controller/UmsUserController.java @@ -0,0 +1,103 @@ +package com.qs.serve.modules.ums.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.SystemModule; +import com.qs.serve.common.util.PageUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.qs.serve.modules.ums.entity.UmsUser; +import com.qs.serve.modules.ums.service.UmsUserService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 手机用户 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("ums/user") +public class UmsUserController { + + private UmsUserService umsUserService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('ums:user:query')") + public R> getPage(UmsUser param){ + PageUtil.startPage(); + LambdaQueryWrapper userWrapper = new LambdaQueryWrapper<>(param); + List list = umsUserService.list(userWrapper); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @SysLog(module = SystemModule.UMS, title = "手机用户", biz = BizType.QUERY) + @PreAuthorize("hasRole('ums:user:query')") + public R getById(@PathVariable("id") String id){ + UmsUser umsUser = umsUserService.getById(id); + return R.ok(umsUser); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @SysLog(module = SystemModule.UMS, title = "手机用户", biz = BizType.UPDATE) + @PreAuthorize("hasRole('ums:user:update')") + public R updateById(@RequestBody @Valid UmsUser param){ + boolean result = umsUserService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增手机用户 + * @param param + * @return + */ + @PostMapping("/save") + @SysLog(module = SystemModule.UMS, title = "手机用户", biz = BizType.INSERT) + @PreAuthorize("hasRole('ums:user:insert')") + public R save(@RequestBody @Valid UmsUser param){ + boolean result = umsUserService.save(param); + return R.isTrue(result); + } + + /** + * 删除手机用户 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @SysLog(module = SystemModule.UMS, title = "手机用户", biz = BizType.DELETE) + @PreAuthorize("hasRole('ums:user:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = umsUserService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/entity/UmsUser.java b/src/main/java/com/qs/serve/modules/ums/entity/UmsUser.java new file mode 100644 index 00000000..5c51e656 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/entity/UmsUser.java @@ -0,0 +1,76 @@ +package com.qs.serve.modules.ums.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 手机用户 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("ums_user") +public class UmsUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** id */ + @TableId(type = IdType.AUTO) + private Long id; + + /** 名称 */ + @NotBlank(message = "名称不能为空") + @Length(max = 20,message = "名称长度不能超过20字") + private String name; + + /** 手机号 */ + @Length(max = 12,message = "手机号长度不能超过12字") + private String mobile; + + /** 头像 */ + @Length(max = 255,message = "头像长度不能超过255字") + private String avatar; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + @JsonIgnore + @JsonProperty + private String tenantId; + + /** 删除标识 */ + @JsonIgnore + @JsonProperty + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/entity/UmsWxRelate.java b/src/main/java/com/qs/serve/modules/ums/entity/UmsWxRelate.java new file mode 100644 index 00000000..a6ad2529 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/entity/UmsWxRelate.java @@ -0,0 +1,42 @@ +package com.qs.serve.modules.ums.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; + +/** + * 微信用户关联 实体类 + * @author YenHex + * @since 2022-09-13 + */ +@Data +@TableName("ums_wx_relate") +public class UmsWxRelate implements Serializable { + + private static final long serialVersionUID = 1L; + + /** */ + @TableId(type = IdType.AUTO) + private Long id; + + /** */ + @NotBlank(message = "不能为空") + @Length(max = 32,message = "长度不能超过32字") + private String wxUserId; + + /** */ + @NotNull(message = "不能为空") + private Long appUserId; + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/mapper/UmsUserMapper.java b/src/main/java/com/qs/serve/modules/ums/mapper/UmsUserMapper.java new file mode 100644 index 00000000..5aca620a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/mapper/UmsUserMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.ums.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.ums.entity.UmsUser; + +/** + * 手机用户 Mapper + * @author YenHex + * @date 2022-09-13 + */ +public interface UmsUserMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/mapper/UmsWxRelateMapper.java b/src/main/java/com/qs/serve/modules/ums/mapper/UmsWxRelateMapper.java new file mode 100644 index 00000000..c9cd1c9a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/mapper/UmsWxRelateMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.ums.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.ums.entity.UmsWxRelate; + +/** + * 微信用户关联 Mapper + * @author YenHex + * @date 2022-09-13 + */ +public interface UmsWxRelateMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/service/UmsUserService.java b/src/main/java/com/qs/serve/modules/ums/service/UmsUserService.java new file mode 100644 index 00000000..458fd664 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/service/UmsUserService.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.ums.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.ums.entity.UmsUser; +import com.qs.serve.modules.wx.entity.WxUser; + +/** + * 手机用户 服务接口 + * @author YenHex + * @date 2022-09-13 + */ +public interface UmsUserService extends IService { + + /** + * 通过微信用户获取App用户 + * @param wxUserId + * @param wxUser + * @return + */ + UmsUser getByWxUserId(String wxUserId,WxUser wxUser); + + /** + * 获取当前app用户 + * @return + */ + UmsUser getCurrentAppUser(); + + /** + * 创建用户 + * @param wxUser + * @return + */ + UmsUser createByWxUser(WxUser wxUser); + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/service/UmsWxRelateService.java b/src/main/java/com/qs/serve/modules/ums/service/UmsWxRelateService.java new file mode 100644 index 00000000..e2212563 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/service/UmsWxRelateService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.ums.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.ums.entity.UmsWxRelate; + +/** + * 微信用户关联 服务接口 + * @author YenHex + * @date 2022-09-13 + */ +public interface UmsWxRelateService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/ums/service/impl/UmsUserServiceImpl.java b/src/main/java/com/qs/serve/modules/ums/service/impl/UmsUserServiceImpl.java new file mode 100644 index 00000000..64ebab32 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/service/impl/UmsUserServiceImpl.java @@ -0,0 +1,61 @@ +package com.qs.serve.modules.ums.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.modules.ums.entity.UmsWxRelate; +import com.qs.serve.modules.ums.mapper.UmsWxRelateMapper; +import com.qs.serve.modules.ums.service.UmsWxRelateService; +import com.qs.serve.modules.wx.entity.WxUser; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.ums.entity.UmsUser; +import com.qs.serve.modules.ums.service.UmsUserService; +import com.qs.serve.modules.ums.mapper.UmsUserMapper; + +/** + * 手机用户 服务实现类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class UmsUserServiceImpl extends ServiceImpl implements UmsUserService { + + private final UmsWxRelateService umsWxRelateService; + + @Override + public UmsUser getByWxUserId(String wxUserId,WxUser wxUser) { + LambdaQueryWrapper lqwRelate = new LambdaQueryWrapper<>(); + lqwRelate.eq(UmsWxRelate::getWxUserId,wxUserId); + UmsWxRelate wxRelate = umsWxRelateService.getOne(lqwRelate,false); + if(wxRelate!=null){ + return this.getById(wxRelate.getAppUserId()); + }else { + UmsUser umsUser = this.createByWxUser(wxUser); + wxRelate = new UmsWxRelate(); + wxRelate.setAppUserId(umsUser.getId()); + wxRelate.setWxUserId(wxUser.getId()); + umsWxRelateService.save(wxRelate); + } + return null; + } + + @Override + public UmsUser getCurrentAppUser() { + return this.getById(AuthContextUtils.getAppUserId()); + } + + @Override + public UmsUser createByWxUser(WxUser wxUser) { + UmsUser umsUser = new UmsUser(); + umsUser.setName(wxUser.getNickName()); + umsUser.setAvatar(wxUser.getHeadimgUrl()); + umsUser.setMobile(wxUser.getPhone()); + this.save(umsUser); + return umsUser; + } +} + diff --git a/src/main/java/com/qs/serve/modules/ums/service/impl/UmsWxRelateServiceImpl.java b/src/main/java/com/qs/serve/modules/ums/service/impl/UmsWxRelateServiceImpl.java new file mode 100644 index 00000000..98cb654a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/ums/service/impl/UmsWxRelateServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.ums.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import com.qs.serve.modules.ums.entity.UmsWxRelate; +import com.qs.serve.modules.ums.service.UmsWxRelateService; +import com.qs.serve.modules.ums.mapper.UmsWxRelateMapper; + +/** + * 微信用户关联 服务实现类 + * @author YenHex + * @since 2022-09-13 + */ +@Slf4j +@Service +@AllArgsConstructor +public class UmsWxRelateServiceImpl extends ServiceImpl implements UmsWxRelateService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java new file mode 100644 index 00000000..8edfb635 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpJsapiApi.java @@ -0,0 +1,35 @@ +package com.qs.serve.modules.wx.api; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + + +/** + * API 微信公众号JSAPI + * @author YenHex + * @since 2022-03-07 + */ +@AllArgsConstructor +//@RestController +//@RequestMapping("/api/mp/jsapi/{appid}") +public class WxMpJsapiApi { + private final WxMpService wxService; + + /** + * 获取票据 + * @param appid + * @return + * @throws WxErrorException + */ + @GetMapping("/getJsapiTicket") + public String getJsapiTicket(@PathVariable String appid) throws WxErrorException { + final WxJsapiSignature jsapiSignature = this.wxService.switchoverTo(appid).createJsapiSignature("111"); + System.out.println(jsapiSignature); + return this.wxService.getJsapiTicket(true); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java new file mode 100644 index 00000000..b49426e3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpMenuApi.java @@ -0,0 +1,187 @@ +package com.qs.serve.modules.wx.api; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.menu.WxMenu; +import me.chanjar.weixin.common.bean.menu.WxMenuButton; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; +import me.chanjar.weixin.mp.bean.menu.WxMpMenu; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.net.MalformedURLException; +import java.net.URL; + +import static me.chanjar.weixin.common.api.WxConsts.MenuButtonType; + +/** + * API 微信公众号菜单 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@AllArgsConstructor +//@RestController +//@RequestMapping("/api/mp/menu/{appid}") +public class WxMpMenuApi { + private final WxMpService wxService; + + /** + * 自定义菜单创建接口 + * @apiNote
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
+     * 如果要创建个性化菜单,请设置matchrule属性
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * @return 如果是个性化菜单,则返回menuid,否则返回null + */ + @PostMapping("/create") + public String menuCreate(@PathVariable String appid, @RequestBody WxMenu menu) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuCreate(menu); + } + + //@GetMapping("/createByData") + public String menuCreateSample(@PathVariable String appid) throws WxErrorException, MalformedURLException { + WxMenu menu = new WxMenu(); + WxMenuButton button1 = new WxMenuButton(); + button1.setType(MenuButtonType.CLICK); + button1.setName("今日歌曲"); + button1.setKey("V1001_TODAY_MUSIC"); + +// WxMenuButton button2 = new WxMenuButton(); +// button2.setType(WxConsts.BUTTON_MINIPROGRAM); +// button2.setName("小程序"); +// button2.setAppId("wx286b93c14bbf93aa"); +// button2.setPagePath("pages/lunar/index.html"); +// button2.setUrl("http://mp.weixin.qq.com"); + + WxMenuButton button3 = new WxMenuButton(); + button3.setName("菜单"); + + menu.getButtons().add(button1); +// menu.getButtons().add(button2); + menu.getButtons().add(button3); + + WxMenuButton button31 = new WxMenuButton(); + button31.setType(MenuButtonType.VIEW); + button31.setName("搜索"); + button31.setUrl("http://www.soso.com/"); + + WxMenuButton button32 = new WxMenuButton(); + button32.setType(MenuButtonType.VIEW); + button32.setName("视频"); + button32.setUrl("http://v.qq.com/"); + + WxMenuButton button33 = new WxMenuButton(); + button33.setType(MenuButtonType.CLICK); + button33.setName("赞一下我们"); + button33.setKey("V1001_GOOD"); + + WxMenuButton button34 = new WxMenuButton(); + button34.setType(MenuButtonType.VIEW); + button34.setName("获取用户信息"); + + ServletRequestAttributes servletRequestAttributes = + (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (servletRequestAttributes != null) { + HttpServletRequest request = servletRequestAttributes.getRequest(); + URL requestURL = new URL(request.getRequestURL().toString()); + String url = this.wxService.switchoverTo(appid).getOAuth2Service().buildAuthorizationUrl( + String.format("%s://%s/wx/redirect/%s/greet", requestURL.getProtocol(), requestURL.getHost(), appid), + WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); + button34.setUrl(url); + } + + button3.getSubButtons().add(button31); + button3.getSubButtons().add(button32); + button3.getSubButtons().add(button33); + button3.getSubButtons().add(button34); + + this.wxService.switchover(appid); + return this.wxService.getMenuService().menuCreate(menu); + } + + /** + * + * 自定义菜单创建接口 + * @apiNote
详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN
+     * 如果要创建个性化菜单,请设置matchrule属性
+     * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * @return 如果是个性化菜单,则返回menuid,否则返回null + */ + @PostMapping("/createByJson") + public String menuCreate(@PathVariable String appid, @RequestBody String json) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuCreate(json); + } + + /** + * 自定义菜单删除接口 + * @apiNote
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN
+     * 
+ */ + @GetMapping("/delete") + public void menuDelete(@PathVariable String appid) throws WxErrorException { + this.wxService.switchoverTo(appid).getMenuService().menuDelete(); + } + + /** + * 删除个性化菜单接口 + * @apiNote
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN
+     * 
+ * @param menuId 个性化菜单的menuid + */ + @GetMapping("/delete/{menuId}") + public void menuDelete(@PathVariable String appid, @PathVariable String menuId) throws WxErrorException { + this.wxService.switchoverTo(appid).getMenuService().menuDelete(menuId); + } + + /** + * 自定义菜单查询接口 + * @apiNote
+     * 详情请见: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN
+     * 
+ */ + @GetMapping("/get") + public WxMpMenu menuGet(@PathVariable String appid) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuGet(); + } + + /** + * 测试个性化菜单匹配结果 + * @apiNote
+     * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
+     * 
+ * + * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 + */ + @GetMapping("/menuTryMatch/{userid}") + public WxMenu menuTryMatch(@PathVariable String appid, @PathVariable String userid) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().menuTryMatch(userid); + } + + /** + * 获取自定义菜单配置接口 + * @apiNote
+     * 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过API调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。
+     * 请注意:
+     * 1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。
+     * 2、本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。
+     * 3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。
+     * 4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。
+     * 5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。
+     *  接口调用请求说明:
+     * http请求方式: GET(请使用https协议)
+     * https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
+     * 
+ */ + @GetMapping("/getSelfMenuInfo") + public WxMpGetSelfMenuInfoResult getSelfMenuInfo(@PathVariable String appid) throws WxErrorException { + return this.wxService.switchoverTo(appid).getMenuService().getSelfMenuInfo(); + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java new file mode 100644 index 00000000..15878199 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxMpRedirectApi.java @@ -0,0 +1,39 @@ +package com.qs.serve.modules.wx.api; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * 微信公众号重定向 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@AllArgsConstructor +//@Controller +//@RequestMapping("/api/mp/redirect/{appid}") +public class WxMpRedirectApi { + private final WxMpService wxService; + + @RequestMapping("/greet") + public String greetUser(@PathVariable String appid, @RequestParam String code, ModelMap map) { + if (!this.wxService.switchover(appid)) { + throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); + } + + try { + WxOAuth2AccessToken accessToken = wxService.getOAuth2Service().getAccessToken(code); + WxOAuth2UserInfo user = wxService.getOAuth2Service().getUserInfo(accessToken, null); + map.put("user", user); + } catch (WxErrorException e) { + e.printStackTrace(); + } + return "greet_user"; + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java b/src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java new file mode 100644 index 00000000..abe54618 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/api/WxSvcUserApi.java @@ -0,0 +1,87 @@ +package com.qs.serve.modules.wx.api; + +import com.qs.serve.common.framework.redis.RedisService; +import com.qs.serve.common.model.annotation.LimitSubmit; +import com.qs.serve.common.model.annotation.SysLog; +import com.qs.serve.common.model.consts.RedisCacheKeys; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.model.enums.BizType; +import com.qs.serve.common.model.enums.InterType; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.IdUtil; +import com.qs.serve.modules.ums.entity.UmsUser; +import com.qs.serve.modules.ums.service.UmsUserService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxPhoneBindParam; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.concurrent.TimeUnit; + +/** + * 微信:API 微信用户 + * @author YenHex + * @since 2022/3/8 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/api/wx/user") +public class WxSvcUserApi { + + private WxUserService wxUserService; + private RedisService redisService; + private UmsUserService umsUserService; + /** + * 用户信息 + */ + @GetMapping("/info") + public R info(){ + return R.ok(umsUserService.getCurrentAppUser()); + } + + /** + * 获取手机绑定验证码 + */ + @LimitSubmit(interval = 60000,message = "短信已发送,请60秒后尝试") + @SysLog(title = "手机绑定验证码",inter = InterType.API) + @GetMapping("/phoneCode/{phone}") + public R phoneCode(@PathVariable("phone") String phone){ + String key = RedisCacheKeys.PHONE_KEY+phone; + String code = redisService.getString(key); + if(code==null){ + code = IdUtil.genCode(6); + } + log.debug("手机验证码:{}",code); + redisService.set(key,code,10, TimeUnit.MINUTES); + //TODO send msg + return R.ok(); + } + + /** + * 手机号绑定 + * @param param + * @return + */ + @SysLog(title = "手机绑定",biz = BizType.UPDATE, inter = InterType.API) + @PostMapping("/bindPhone") + public R phoneCode(@RequestBody @Valid WxPhoneBindParam param){ + String key = RedisCacheKeys.PHONE_KEY+param.getPhone(); + String code = redisService.getString(key); + if(!param.getCode().equals(code)){ + return R.error("验证码无效或过期"); + } +// UmsUser wxUser = wxUserService.getCurrentWxUser(); +// wxUser.setPhone(param.getPhone()); +// wxUserService.updateById(wxUser); + //TODO 修改用户相关信息 + UmsUser wxUser = umsUserService.getCurrentAppUser(); + wxUser.setMobile(param.getPhone()); + umsUserService.updateById(wxUser); + return R.ok(); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java new file mode 100644 index 00000000..e74f58c5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/ImageBuilder.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.wx.common.builder.mp; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +public class ImageBuilder implements MpXmlMessageBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + return m; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java new file mode 100644 index 00000000..efbece06 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/MpXmlMessageBuilder.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.common.builder.mp; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +public interface MpXmlMessageBuilder { + + WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, WxMpService service); +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java new file mode 100644 index 00000000..2e5f9f1b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/builder/mp/TextBuilder.java @@ -0,0 +1,23 @@ +package com.qs.serve.modules.wx.common.builder.mp; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +public class TextBuilder implements MpXmlMessageBuilder { + + @Override + public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage, + WxMpService service) { + WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + return m; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java b/src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java new file mode 100644 index 00000000..59b28946 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/conf/WxMpConfig.java @@ -0,0 +1,129 @@ +package com.qs.serve.modules.wx.common.conf; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.qs.serve.common.config.properties.RedisProperties; +import com.qs.serve.modules.wx.common.consts.WxStatusConst; +import com.qs.serve.modules.wx.common.handler.mp.*; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.service.WxAppService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpMessageRouter; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.stream.Collectors; + +import static me.chanjar.weixin.common.api.WxConsts.EventType; +import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE; +import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE; +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT; +import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*; +import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY; +/** + * 微信公众号配置 + * @author YenHex + * @since 2022/3/7 + */ +@Slf4j +@AllArgsConstructor +//@Configuration(proxyBeanMethods = false) +public class WxMpConfig { + + private final LogHandler logHandler; + private final NullHandler nullHandler; + private final KfSessionHandler kfSessionHandler; + private final StoreCheckNotifyHandler storeCheckNotifyHandler; + private final LocationHandler locationHandler; + private final MenuHandler menuHandler; + private final MsgHandler msgHandler; + private final UnsubscribeHandler unsubscribeHandler; + private final SubscribeHandler subscribeHandler; + private final ScanHandler scanHandler; + private final WxAppService wxAppService; + private final RedisProperties redisProperties; + + @Bean + public WxMpService wxMpService() { + //超时时间 + LambdaQueryWrapper appWrapper = new LambdaQueryWrapper<>(); + appWrapper.eq(WxApp::getAppType, WxStatusConst.WxApp_AppType_2); + List wxAppList = wxAppService.list(appWrapper); + if (CollectionUtil.isEmpty(wxAppList)) { + log.warn("公众号配置为空"); + } + WxMpService service = new WxMpServiceImpl(); + service.setMultiConfigStorages(wxAppList + .stream().map(app -> { + WxMpDefaultConfigImpl configStorage; +// JedisPoolConfig poolConfig = new JedisPoolConfig(); +// JedisPool jedisPool = new JedisPool( +// poolConfig, +// redisProperties.getHost(), +// redisProperties.getPort(), +// timeout, +// redisProperties.getPassword(), +// redisProperties.getDatabase()); +// configStorage = new WxMpRedisConfigImpl(new JedisWxRedisOps(jedisPool), app.getId()); + configStorage = new WxMpDefaultConfigImpl(); + configStorage.setAppId(app.getId()); + configStorage.setSecret(app.getSecret()); + configStorage.setToken(app.getToken()); + configStorage.setAesKey(app.getAesKey()); + return configStorage; + }).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o))); + return service; + } + + @Bean + public WxMpMessageRouter messageRouter(WxMpService wxMpService) { + final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService); + + // 记录所有事件的日志 (异步执行) + newRouter.rule().handler(this.logHandler).next(); + + // 接收客服会话管理事件 + newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION) + .handler(this.kfSessionHandler).end(); + newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION) + .handler(this.kfSessionHandler).end(); + newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION) + .handler(this.kfSessionHandler).end(); + + // 门店审核事件 + newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end(); + + // 自定义菜单事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end(); + + // 点击菜单连接事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end(); + + // 关注事件 + newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end(); + + // 取消关注事件 + newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end(); + + // 上报地理位置事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end(); + + // 接收地理位置消息 + newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end(); + + // 扫码事件 + newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end(); + + // 默认 + newRouter.rule().async(false).handler(this.msgHandler).end(); + + return newRouter; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java b/src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java new file mode 100644 index 00000000..2e54055d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/consts/WxStatusConst.java @@ -0,0 +1,34 @@ +package com.qs.serve.modules.wx.common.consts; + +/** + * 微信字段 + * @author YenHex + * @since 2022/3/7 + */ +public class WxStatusConst { + + /** wx */ + /** 应用类型【1->小程序;2->公众号】 */ + public static final int WxUser_AppType_1 = 1; + public static final int WxUser_AppType_2 = 2; + + /** 是否订阅【1->是;0->否;2->网页授权用户】 */ + public static final int WxUser_Subscribe_1 = 1; + public static final int WxUser_Subscribe_0 = 0; + public static final int WxUser_Subscribe_2 = 2; + + /** 应用类型【1->小程序;2->公众号】 */ + public static final int WxApp_AppType_1 = 1; + public static final int WxApp_AppType_2 = 2; + + /** 是否第三方平台应用【1->是;0->否】 */ + public static final int WxApp_IsComponent_1 = 1; + public static final int WxApp_IsComponent_0 = 0; + + /** 【0->订阅号;1->由历史老帐号升级后的订阅号;2->服务号】 */ + public static final int WxApp_WeixinType_0 = 0; + public static final int WxApp_WeixinType_1 = 1; + public static final int WxApp_WeixinType_2 = 2; + + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java new file mode 100644 index 00000000..b2f32ad3 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/KfSessionHandler.java @@ -0,0 +1,27 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class KfSessionHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + //TODO 对会话做处理 + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java new file mode 100644 index 00000000..c1c9520c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LocationHandler.java @@ -0,0 +1,47 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import com.qs.serve.modules.wx.common.builder.mp.TextBuilder; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class LocationHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) { + //TODO 接收处理用户发送的地理位置消息 + try { + String content = "感谢反馈,您的的地理位置已收到!"; + return new TextBuilder().build(content, wxMessage, null); + } catch (Exception e) { + log.error("位置消息接收处理失败", e); + return null; + } + } + + //上报地理位置事件 + log.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",wxMessage.getLatitude(), wxMessage.getLongitude(), wxMessage.getPrecision()); + + //TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用 + + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java new file mode 100644 index 00000000..c433c05a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/LogHandler.java @@ -0,0 +1,32 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import com.qs.serve.common.util.JsonUtil; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class LogHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + log.info("\n接收到请求消息,内容:{}", JsonUtil.objectToJson(wxMessage)); + return null; + } + + + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java new file mode 100644 index 00000000..a4070fe5 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MenuHandler.java @@ -0,0 +1,37 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.EventType; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class MenuHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + String msg = String.format("type:%s, event:%s, key:%s", + wxMessage.getMsgType(), wxMessage.getEvent(), + wxMessage.getEventKey()); + if (EventType.VIEW.equals(wxMessage.getEvent())) { + return null; + } + + return WxMpXmlOutMessage.TEXT().content(msg) + .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser()) + .build(); + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java new file mode 100644 index 00000000..9ed90cdf --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/MsgHandler.java @@ -0,0 +1,54 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.modules.wx.common.builder.mp.TextBuilder; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class MsgHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) { + + if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) { + //TODO 可以选择将消息保存到本地 + } + + //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服 + try { + if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服") + && weixinService.getKefuService().kfOnlineList() + .getKfOnlineList().size() > 0) { + return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE() + .fromUser(wxMessage.getToUser()) + .toUser(wxMessage.getFromUser()).build(); + } + } catch (WxErrorException e) { + e.printStackTrace(); + } + + //TODO 组装回复消息 + String content = "收到信息内容:" + JsonUtil.objectToJson(wxMessage); + + return new TextBuilder().build(content, wxMessage, weixinService); + + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java new file mode 100644 index 00000000..fe761881 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/NullHandler.java @@ -0,0 +1,26 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class NullHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java new file mode 100644 index 00000000..00156867 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/ScanHandler.java @@ -0,0 +1,27 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import java.util.Map; + +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import org.springframework.stereotype.Component; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Component +public class ScanHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map map, + WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException { + // 扫码事件处理 + return null; + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java new file mode 100644 index 00000000..d6f5d7a6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/StoreCheckNotifyHandler.java @@ -0,0 +1,29 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + + + /** + * 门店审核事件处理 + * @author YenHex + * @since 2022-03-07 +*/ +@Component +public class StoreCheckNotifyHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + // TODO 处理门店审核事件 + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java new file mode 100644 index 00000000..4d0dc132 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/SubscribeHandler.java @@ -0,0 +1,72 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import java.util.Map; + +import com.qs.serve.modules.wx.common.builder.mp.TextBuilder; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import org.springframework.stereotype.Component; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import me.chanjar.weixin.mp.bean.result.WxMpUser; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class SubscribeHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService weixinService, + WxSessionManager sessionManager) throws WxErrorException { + + log.info("新关注用户 OPENID: " + wxMessage.getFromUser()); + // 获取微信用户基本信息 + try { + WxMpUser userWxInfo = weixinService.getUserService() + .userInfo(wxMessage.getFromUser(), null); + if (userWxInfo != null) { + // TODO 可以添加关注用户到本地数据库 + } + } catch (WxErrorException e) { + if (e.getError().getErrorCode() == 48001) { + log.info("该公众号没有获取用户信息权限!"); + } + } + WxMpXmlOutMessage responseResult = null; + try { + responseResult = this.handleSpecial(wxMessage); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + if (responseResult != null) { + return responseResult; + } + + try { + return new TextBuilder().build("感谢关注", wxMessage, weixinService); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + return null; + } + + /** + * 处理特殊请求,比如如果是扫码进来的,可以做相应处理 + */ + private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) + throws Exception { + //TODO + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java new file mode 100644 index 00000000..5ae0c728 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/handler/mp/UnsubscribeHandler.java @@ -0,0 +1,31 @@ +package com.qs.serve.modules.wx.common.handler.mp; + +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.session.WxSessionManager; +import me.chanjar.weixin.mp.api.WxMpMessageHandler; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; +import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Component +public class UnsubscribeHandler implements WxMpMessageHandler { + + @Override + public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, + Map context, WxMpService wxMpService, + WxSessionManager sessionManager) { + String openId = wxMessage.getFromUser(); + log.info("取消关注用户 OPENID: " + openId); + // TODO 可以更新本地数据库为取消关注状态 + return null; + } + +} diff --git a/src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java b/src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java new file mode 100644 index 00000000..4369ff3e --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/common/model/WxSmsProp.java @@ -0,0 +1,19 @@ +package com.qs.serve.modules.wx.common.model; + +import java.lang.annotation.*; + +/** + * 微信发送模板参数 + * @author YenHex + * @since 2022-03-16 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface WxSmsProp { + + String keyword() default ""; + + String value() default ""; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java new file mode 100644 index 00000000..143e9d21 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxAppController.java @@ -0,0 +1,93 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.service.WxAppService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信应用 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +//@AllArgsConstructor +//@RestController +//@RequestMapping("wx/app") +public class WxAppController { + + private WxAppService wxAppService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('wx:app:query')") + public R> getList(WxApp param){ + PageUtil.startPage(); + List list = wxAppService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('wx:app:query')") + public R getById(@PathVariable("id") String id){ + WxApp wxApp = wxAppService.getById(id); + return R.ok(wxApp); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @PreAuthorize("hasRole('wx:app:update')") + public R updateById(@RequestBody @Valid WxApp param){ + boolean result = wxAppService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增微信应用 + * @param param + * @return + */ + @PostMapping("/save") + @PreAuthorize("hasRole('wx:app:insert')") + public R save(@RequestBody @Valid WxApp param){ + boolean result = wxAppService.save(param); + return R.isTrue(result); + } + + /** + * 删除微信应用 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('wx:app:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = wxAppService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java new file mode 100644 index 00000000..68316df7 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxTemplateMsgController.java @@ -0,0 +1,93 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; +import com.qs.serve.modules.wx.service.WxTemplateMsgService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信模板/订阅消息 后台接口 + * @author YenHex + * @since 2022-03-23 + */ +@Slf4j +//@AllArgsConstructor +//@RestController +//@RequestMapping("wx/templateMsg") +public class WxTemplateMsgController { + + private WxTemplateMsgService wxTemplateMsgService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('wx:templateMsg:query')") + public R> getPage(WxTemplateMsg param){ + PageUtil.startPage(); + List list = wxTemplateMsgService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('wx:templateMsg:query')") + public R getById(@PathVariable("id") String id){ + WxTemplateMsg wxTemplateMsg = wxTemplateMsgService.getById(id); + return R.ok(wxTemplateMsg); + } + + + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @PreAuthorize("hasRole('wx:templateMsg:update')") + public R updateById(@RequestBody @Valid WxTemplateMsg param){ + boolean result = wxTemplateMsgService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增微信模板/订阅消息 + * @param param + * @return + */ + @PostMapping("/save") + @PreAuthorize("hasRole('wx:templateMsg:insert')") + public R save(@RequestBody @Valid WxTemplateMsg param){ + boolean result = wxTemplateMsgService.save(param); + return R.isTrue(result); + } + + /** + * 删除微信模板/订阅消息 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('wx:templateMsg:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = wxTemplateMsgService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java b/src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java new file mode 100644 index 00000000..c59b5c4f --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/controller/WxUserController.java @@ -0,0 +1,91 @@ +package com.qs.serve.modules.wx.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qs.serve.common.model.dto.PageVo; +import com.qs.serve.common.model.dto.R; +import com.qs.serve.common.util.PageUtil; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 微信用户 后台接口 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +//@AllArgsConstructor +//@RestController +//@RequestMapping("wx/user") +public class WxUserController { + + private WxUserService wxUserService; + + /** + * 翻页查询 + * @param param + * @return + */ + @GetMapping("/page") + @PreAuthorize("hasRole('wx:user:query')") + public R> getList(WxUser param){ + PageUtil.startPage(); + List list = wxUserService.list(new QueryWrapper<>(param)); + return R.byPageHelperList(list); + } + + /** + * 根据ID查询 + * @param id + * @return + */ + @GetMapping("/getById/{id}") + @PreAuthorize("hasRole('wx:user:query')") + public R getById(@PathVariable("id") String id){ + WxUser wxUser = wxUserService.getById(id); + return R.ok(wxUser); + } + + /** + * 根据ID更新 + * @param param + * @return + */ + @PostMapping("/updateById") + @PreAuthorize("hasRole('wx:user:update')") + public R updateById(@RequestBody @Valid WxUser param){ + boolean result = wxUserService.updateById(param); + return R.isTrue(result); + } + + /** + * 新增微信用户 + * @param param + * @return + */ + @PostMapping("/save") + @PreAuthorize("hasRole('wx:user:insert')") + public R save(@RequestBody @Valid WxUser param){ + boolean result = wxUserService.save(param); + return R.isTrue(result); + } + + /** + * 删除微信用户 + * @param id + * @return + */ + @DeleteMapping("/deleteById/{id}") + @PreAuthorize("hasRole('wx:user:delete')") + public R deleteById(@PathVariable("id") String id){ + boolean result = wxUserService.removeById(id); + return R.isTrue(result); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxApp.java b/src/main/java/com/qs/serve/modules/wx/entity/WxApp.java new file mode 100644 index 00000000..76f12c27 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxApp.java @@ -0,0 +1,115 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 微信应用 实体类 + * @author YenHex + * @since 2022-03-07 + */ +@Data +@TableName("wx_app") +public class WxApp implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 应用ID */ + @TableId(type = IdType.INPUT) + private String id; + + /** 机构ID */ + @NotNull(message = "机构ID不能为空") + private String organId; + + /** 微信原始标识 */ + @NotNull(message = "微信原始标识不能为空") + private String weixinSign; + + /** 应用类型【1->小程序;2->公众号】 */ + private Integer appType; + + /** 应用密钥 */ + private String secret; + + /** token */ + private String token; + + /** EncodingAESKey */ + private String aesKey; + + /** 微信号名称 */ + private String name; + + /** 是否第三方平台应用【1->是;0->否】 */ + private Integer isComponent; + + /** 【0->订阅号;1->由历史老帐号升级后的订阅号;2->服务号】 */ + private Integer weixinType; + + /** 公众号微信号 */ + private String weixinHao; + + /** 认证类型 */ + private Integer verifyType; + + /** logo */ + private String logo; + + /** 二维码 */ + private String qrCode; + + /** 主体名称 */ + private String principalName; + + /** 微社区URL */ + private String community; + + /** 备注信息 */ + private String remarks; + + /** 绑定的会员卡ID */ + private String vipCardId; + + /** 微信支付商户号 */ + private String mchId; + + /** 微信支付商户密钥 */ + private String mchKey; + + /** p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头) */ + private String keyPath; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java b/src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java new file mode 100644 index 00000000..83df80b8 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxTemplateMsg.java @@ -0,0 +1,73 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 微信模板/订阅消息 实体类 + * @author YenHex + * @since 2022-03-23 + */ +@Data +@TableName("wx_template_msg") +public class WxTemplateMsg implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键 */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 微信应用id */ + @NotNull(message = "微信应用id不能为空") + private String appId; + + /** 模板ID */ + @NotNull(message = "模板ID不能为空") + private String templateId; + + /** 模版标题 */ + @NotNull(message = "模版标题不能为空") + private String title; + + /** 跳转地址 */ + private String jumpUrl; + + /** 是否启用 */ + private Integer enable; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 租户id */ + private String tenantId; + + /** 删除标识 */ + private Boolean delFlag; + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/WxUser.java b/src/main/java/com/qs/serve/modules/wx/entity/WxUser.java new file mode 100644 index 00000000..b5f12800 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/WxUser.java @@ -0,0 +1,131 @@ +package com.qs.serve.modules.wx.entity; + +import java.time.LocalDateTime; +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; + +/** + * 微信用户 实体类 + * @author YenHex + * @since 2022-03-07 + */ +@Data +@TableName("wx_user") +public class WxUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** 主键 */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** 公众号配置ID、小程序AppID */ + @NotNull(message = "公众号配置ID、小程序AppID不能为空") + private String appId; + + /** 应用类型【1->小程序;2->公众号】 */ + private Integer appType; + + /** 是否订阅【1->是;0->否;2->网页授权用户】 */ + private Integer subscribe; + + /** 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENEPROFILE LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_OTHERS 其他 */ + private String subscribeScene; + + /** 关注时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime subscribeTime; + + /** 关注次数 */ + private Integer subscribeNum; + + /** 取消关注时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + private LocalDateTime cancelSubscribeTime; + + /** 用户标识 */ + @NotNull(message = "用户标识不能为空") + private String openId; + + /** 昵称 */ + private String nickName; + + /** 性别(1:男,2:女,0:未知) */ + private String sex; + + /** 所在城市 */ + private String city; + + /** 所在国家 */ + private String country; + + /** 所在省份 */ + private String province; + + /** 手机号码 */ + private String phone; + + /** 用户语言 */ + private String language; + + /** 头像 */ + private String headimgUrl; + + /** union_id */ + private String unionId; + + /** 用户组 */ + private String groupId; + + /** 标签列表 */ + private String tagidList; + + /** 二维码扫码场景 */ + private String qrSceneStr; + + /** 地理位置纬度 */ + private Double latitude; + + /** 地理位置经度 */ + private Double longitude; + + /** 地理位置精度 */ + private Double precisionVal; + + /** 会话密钥 */ + private String sessionKey; + + /** 创建时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** 创建人 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 更新时间 */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** 更新人 */ + @TableField(fill = FieldFill.UPDATE) + private String updateBy; + + /** 删除标识 */ + @JsonIgnore + private Boolean delFlag; +} + diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java new file mode 100644 index 00000000..7ffd7ec2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/SmsBaseDto.java @@ -0,0 +1,8 @@ +package com.qs.serve.modules.wx.entity.dto; + +/** + * @author YenHex + * @since 2022/7/25 + */ +public abstract class SmsBaseDto { +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java new file mode 100644 index 00000000..761a4026 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxLoginUser.java @@ -0,0 +1,17 @@ +package com.qs.serve.modules.wx.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/7 + */ +@Data +public class WxLoginUser { + + @NotNull + private String code; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java new file mode 100644 index 00000000..b3b3c05d --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/entity/dto/WxPhoneBindParam.java @@ -0,0 +1,20 @@ +package com.qs.serve.modules.wx.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author YenHex + * @since 2022/3/11 + */ +@Data +public class WxPhoneBindParam { + + @NotNull + private String phone; + + @NotNull + private String code; + +} diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java new file mode 100644 index 00000000..2833bff4 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxAppMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxApp; + +/** + * 微信应用 Mapper + * @author YenHex + * @date 2022-03-07 + */ +public interface WxAppMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java new file mode 100644 index 00000000..e9ca153b --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxTemplateMsgMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; + +/** + * 微信模板/订阅消息 Mapper + * @author YenHex + * @date 2022-03-23 + */ +public interface WxTemplateMsgMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java b/src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java new file mode 100644 index 00000000..51599d4a --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/mapper/WxUserMapper.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qs.serve.modules.wx.entity.WxUser; + +/** + * 微信用户 Mapper + * @author YenHex + * @date 2022-03-07 + */ +public interface WxUserMapper extends BaseMapper { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxAppService.java b/src/main/java/com/qs/serve/modules/wx/service/WxAppService.java new file mode 100644 index 00000000..134ab148 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxAppService.java @@ -0,0 +1,14 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxApp; + +/** + * 微信应用 服务接口 + * @author YenHex + * @date 2022-03-07 + */ +public interface WxAppService extends IService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxPushService.java b/src/main/java/com/qs/serve/modules/wx/service/WxPushService.java new file mode 100644 index 00000000..8b1ad2b2 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxPushService.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.wx.service; + +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; + +/** + * @author YenHex + * @since 2022/3/16 + */ +public interface WxPushService { + + /** + * 发送微信模板信息 + * @param appId + * @param message + * @return 是否推送成功 + */ + boolean sendWxMsg(String appId,WxMpTemplateMessage message); + + boolean sendWxMsg(WxUser wxUser, String title, SmsBaseDto body); + + boolean sendWxMsg(WxUser wxUser,String title,SmsBaseDto body,Boolean jumpUrl); + + /** + * 通用方法 + * @param wxUser + * @param title + * @param body + * @param jumpUrl + * @param key + * @return + */ + boolean sendWxMsg(WxUser wxUser,String title,SmsBaseDto body,Boolean jumpUrl,String key); + +} diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java b/src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java new file mode 100644 index 00000000..74ef16d1 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxTemplateMsgService.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; + +/** + * 微信模板/订阅消息 服务接口 + * @author YenHex + * @date 2022-03-23 + */ +public interface WxTemplateMsgService extends IService { + + /** + * 标题查询 + * @param appId + * @param title + * @return + */ + WxTemplateMsg getByTitle(String appId,String title); + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/WxUserService.java b/src/main/java/com/qs/serve/modules/wx/service/WxUserService.java new file mode 100644 index 00000000..c1a0eff6 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/WxUserService.java @@ -0,0 +1,36 @@ +package com.qs.serve.modules.wx.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxLoginUser; + +/** + * 微信用户 服务接口 + * @author YenHex + * @date 2022-03-07 + */ +public interface WxUserService extends IService { + + /** + * 获取当前微信用户 + * @return + */ + WxUser getCurrentWxUser(); + + /** + * 用户登录 + * @param wxLoginUser + * @return + * @throws Exception + */ + WxUser login(WxLoginUser wxLoginUser) throws Exception; + + /** + * openId查询 + * @param openId + * @return + */ + WxUser getByOpenId(String openId); + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java new file mode 100644 index 00000000..40838580 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxAppServiceImpl.java @@ -0,0 +1,22 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.mapper.WxAppMapper; +import com.qs.serve.modules.wx.service.WxAppService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 微信应用 服务实现类 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxAppServiceImpl extends ServiceImpl implements WxAppService { + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java new file mode 100644 index 00000000..d4288f94 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxPushServiceImpl.java @@ -0,0 +1,75 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.common.util.SmsReflectUtil; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.SmsBaseDto; +import com.qs.serve.modules.wx.service.WxPushService; +import com.qs.serve.modules.wx.service.WxTemplateMsgService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; +import org.springframework.stereotype.Service; + +/** + * 微信推送 + * @author YenHex + * @since 2022/3/16 + */ +@Slf4j +//@Service +@AllArgsConstructor +public class WxPushServiceImpl implements WxPushService { + + private final WxMpService wxMpService; + + private final WxTemplateMsgService wxTemplateMsgService; + + @Override + public boolean sendWxMsg(String appId,WxMpTemplateMessage message) { + String msgId = null; + try { + // 发送模板消息 + msgId = wxMpService.switchoverTo(appId).getTemplateMsgService().sendTemplateMsg(message); + } catch (WxErrorException e) { + e.printStackTrace(); + } + log.warn("推送微信模板信息:{}\n{}", msgId != null ? "成功" : "失败", JsonUtil.objectToJson(message)); + return msgId != null; + } + + @Override + public boolean sendWxMsg(WxUser wxUser, String title, SmsBaseDto body) { + return sendWxMsg(wxUser, title, body,false); + } + + @Override + public boolean sendWxMsg(WxUser wxUser, String title, SmsBaseDto body, Boolean jumpUrl) { + return sendWxMsg(wxUser, title, body, jumpUrl,null); + } + + @Override + public boolean sendWxMsg(WxUser wxUser, String title, SmsBaseDto body, Boolean jumpUrl, String key) { + try { + WxTemplateMsg wxTemplateMsg = wxTemplateMsgService.getByTitle(wxUser.getAppId(),title); + if(wxTemplateMsg!=null){ + WxMpTemplateMessage wxMpTemplateMessage = + WxMpTemplateMessage.builder().templateId(wxTemplateMsg.getTemplateId()) + .toUser(wxUser.getOpenId()) + .data(SmsReflectUtil.getTemplateDataList(body)).build(); + if(jumpUrl){ + wxMpTemplateMessage.setUrl(key==null?wxTemplateMsg.getJumpUrl():wxTemplateMsg.getJumpUrl()+key); + } + sendWxMsg(wxUser.getAppId(),wxMpTemplateMessage); + }else { + log.warn("AppId:{},无可用的微信通知模板:[{}]",wxUser.getAppId(),title); + } + } catch (Exception e) { + log.warn(e.getMessage()); + } + return false; + } +} diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java new file mode 100644 index 00000000..42eac09c --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxTemplateMsgServiceImpl.java @@ -0,0 +1,32 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.modules.wx.entity.WxTemplateMsg; +import com.qs.serve.modules.wx.mapper.WxTemplateMsgMapper; +import com.qs.serve.modules.wx.service.WxTemplateMsgService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 微信模板/订阅消息 服务实现类 + * @author YenHex + * @since 2022-03-23 + */ +@Slf4j +@Service +@AllArgsConstructor +public class WxTemplateMsgServiceImpl extends ServiceImpl implements WxTemplateMsgService { + + @Override + public WxTemplateMsg getByTitle(String appId,String title) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(WxTemplateMsg::getTitle,title); + wrapper.eq(WxTemplateMsg::getAppId,appId); + wrapper.eq(WxTemplateMsg::getEnable,1); + return getOne(wrapper,false); + } + +} + diff --git a/src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java b/src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java new file mode 100644 index 00000000..667d2108 --- /dev/null +++ b/src/main/java/com/qs/serve/modules/wx/service/impl/WxUserServiceImpl.java @@ -0,0 +1,118 @@ +package com.qs.serve.modules.wx.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.qs.serve.common.framework.security.model.LoginUser; +import com.qs.serve.common.framework.security.model.LoginUserType; +import com.qs.serve.common.model.consts.GySysConst; +import com.qs.serve.common.model.enums.HttpCode; +import com.qs.serve.common.util.Assert; +import com.qs.serve.common.util.AuthContextUtils; +import com.qs.serve.common.util.JsonUtil; +import com.qs.serve.modules.wx.common.conf.WxMpConfig; +import com.qs.serve.modules.wx.common.consts.WxStatusConst; +import com.qs.serve.modules.wx.entity.WxApp; +import com.qs.serve.modules.wx.entity.WxUser; +import com.qs.serve.modules.wx.entity.dto.WxLoginUser; +import com.qs.serve.modules.wx.mapper.WxUserMapper; +import com.qs.serve.modules.wx.service.WxAppService; +import com.qs.serve.modules.wx.service.WxUserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.service.WxOAuth2Service; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 微信用户 服务实现类 + * @author YenHex + * @since 2022-03-07 + */ +@Slf4j +@Service +public class WxUserServiceImpl extends ServiceImpl implements WxUserService { + + @Autowired(required = false) + private WxMpConfig wxMpConfig; + + @Autowired(required = false) + private WxAppService wxAppService; + + @Override + public WxUser getCurrentWxUser() { + LoginUser loginUser = AuthContextUtils.getLoginUser(); + if(loginUser.getTypeFlag().equals(LoginUserType.APP_USER)){ + WxUser wxUser = getById(loginUser.getUserId()); + if(wxUser==null){ + Assert.throwEx(HttpCode.LOGIN_ERR); + } +// String appId = AuthContextUtils.getAppId(); +// try { +// WxMpService wxMpService = wxMpConfig.wxMpService().switchoverTo(appId); +// WxMpUser wxMpUser = wxMpService.getUserService().userInfo(wxUser.getOpenId(), GySysConst.LANG_ZH_CN); +// wxUser.setSubscribe(wxMpUser.getSubscribe()?1:0); +// wxUser.setSubscribeScene(wxMpUser.getSubscribeScene()); +// wxUser.setTagidList(JsonUtil.objectToJson(wxMpUser.getTagIds())); +// } catch (WxErrorException e) { +// e.printStackTrace(); +// } + return wxUser; + } + return null; + } + + @Override + public WxUser login(WxLoginUser wxLoginUser){ + String code = wxLoginUser.getCode(); + String appId = AuthContextUtils.getAppId(); + WxApp wxApp = wxAppService.getById(appId); + WxUser wxUser = null; + if(wxApp.getAppType().equals(WxStatusConst.WxApp_AppType_1)){ + Assert.throwEx(HttpCode.DEV_ERR); + }else if(wxApp.getAppType().equals(WxStatusConst.WxApp_AppType_2)){ + WxMpService wxMpService = wxMpConfig.wxMpService().switchoverTo(appId); + WxOAuth2Service auth2Service = wxMpService.getOAuth2Service(); + try { + WxOAuth2AccessToken auth2AccessToken = auth2Service.getAccessToken(code); + WxOAuth2UserInfo auth2UserInfo = auth2Service.getUserInfo(auth2AccessToken, GySysConst.LANG_ZH_CN); + wxUser = this.getByOpenId(auth2UserInfo.getOpenid()); + if(wxUser == null){ + wxUser = new WxUser(); + wxUser.setAppId(wxApp.getId()); + wxUser.setAppType(wxApp.getAppType()); + wxUser.setNickName(auth2UserInfo.getNickname()); + wxUser.setUnionId(auth2UserInfo.getUnionId()); + wxUser.setHeadimgUrl(auth2UserInfo.getHeadImgUrl()); + wxUser.setOpenId(auth2UserInfo.getOpenid()); + } + /*wxUser.setSubscribe(wxMpUser.getSubscribe()?1:0); + wxUser.setSubscribeScene(wxMpUser.getSubscribeScene()); + wxUser.setTagidList(JsonUtil.objectToJson(wxMpUser.getTagIds()));*/ + //wxUser.setSubscribeTime(wxMpUser.getSubscribeTime()); + //wxUser.setGroupId(wxMpUser.getGroupId()); + if(wxUser.getId()==null){ + save(wxUser); + }else { + updateById(wxUser); + } + } catch (WxErrorException e) { + e.printStackTrace(); + } + } + //TODO 登录日志 + return wxUser; + } + + @Override + public WxUser getByOpenId(String openId) { + LambdaQueryWrapper wxUserLambdaQueryWrapper = new LambdaQueryWrapper<>(); + wxUserLambdaQueryWrapper.eq(WxUser::getOpenId,openId); + return getOne(wxUserLambdaQueryWrapper,false); + } +} + diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 00000000..4aa78f99 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,27 @@ +#服务配置 +server: + port: 7400 + servlet: + context-path: / +#SpringBoot相关 +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://192.168.0.9:3333/qs-base-questionnaire?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai + #url: jdbc:mysql://192.168.0.9:3333/qs-base-questionnaire?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: root + password: 123456 + redis: + database: 4 + host: 127.0.0.1 + port: 6379 + password: + #工作流配置 +flowable: + database-schema-update: true +project: + upload: + #上传映射地址 + proxy-url: http://183.234.29.228:6021/ + #物理存储地址 + logical-path: D:\\WebMapPath\\ diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 00000000..44864f83 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,69 @@ +spring: + servlet: + multipart: + max-file-size: 6MB + max-request-size: 12MB + profiles: + include: dev + main: + #easypoi启用覆盖 + allow-bean-definition-overriding: true +#项目配置 +project: + ignore-url: + tenants: #忽略租户拦截 + - /portal/** + - /api/dev/** #测试接口 + - /bpm/appr/getById/** + - /callback + - /favicon.ico + - /error + permits: #忽略登录 + - /common/upload #支持API上传调整 + - /common/validToken #验证token + - /api/** + - /bpm/appr/getById/** + - /portal/** + - /favicon.ico + - /error + - /callback + +#mybatis plus +mybatis-plus: + mapper-locations: classpath:mapper/*/*.xml + type-aliases-package: com.qs.serve.modules.*.entity.* + configuration: + map-underscore-to-camel-case: true + global-config: + banner: false + db-config: + logic-delete-value: 1 + logic-not-delete-value: 0 + select-strategy: not_empty + logic-delete-field: delFlag +# 日志配置 +logging: + level: + ROOT: info + com.qs.serve.modules: debug + org.xnio.nio: info + org.springframework: info + com.baomidou: info + org.mybatis: info + org.hibernate.validator: info + druid.sql.ResultSet: info + druid.sql.Connection: info + com.zaxxer.hikari.pool: info + com.zaxxer.hikari.HikariConfig: info + java.io: warn + io.netty: info + io.undertow: info + io.lettuce.core: info + config: classpath:log4j2.xml +# PageHelper分页插件 +pagehelper: + reasonable: false + autoRuntimeDialect: true + supportMethodsArguments: true + params: count=countSql + diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 00000000..1b302049 --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,4 @@ +${AnsiBackground.BLACK} +-- ---------------------------- +-- 问卷系统 by.柒胜 +-- ---------------------------- diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 00000000..e340b909 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/qms/QmsGroupMapper.xml b/src/main/resources/mapper/qms/QmsGroupMapper.xml new file mode 100644 index 00000000..c4072306 --- /dev/null +++ b/src/main/resources/mapper/qms/QmsGroupMapper.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + qms_group.`id`, + qms_group.`name`, + qms_group.`descr`, + qms_group.`form_id`, + qms_group.`form_context`, + qms_group.`publish_state`, + qms_group.`version`, + qms_group.`remark`, + qms_group.`create_time`, + qms_group.`create_by`, + qms_group.`update_time`, + qms_group.`update_by`, + qms_group.`tenant_id`, + qms_group.`del_flag` + + + + + + diff --git a/src/main/resources/mapper/sys/SysDeptMapper.xml b/src/main/resources/mapper/sys/SysDeptMapper.xml new file mode 100644 index 00000000..1d5e94de --- /dev/null +++ b/src/main/resources/mapper/sys/SysDeptMapper.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + sys_dept.`id`, + sys_dept.`name`, + sys_dept.`code`, + sys_dept.`parent_id`, + sys_dept.`mgr_user_id`, + sys_dept.`level_path`, + sys_dept.`create_time`, + sys_dept.`create_by`, + sys_dept.`update_time`, + sys_dept.`update_by` + + + + + + diff --git a/src/main/resources/mapper/sys/SysMenuMapper.xml b/src/main/resources/mapper/sys/SysMenuMapper.xml new file mode 100644 index 00000000..02c79942 --- /dev/null +++ b/src/main/resources/mapper/sys/SysMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + sys_menu.`id`, + sys_menu.`name`, + sys_menu.`sort`, + sys_menu.`pid`, + sys_menu.`type`, + sys_menu.`client_type`, + sys_menu.`hide_flag`, + sys_menu.`del_flag` + + + + + diff --git a/src/main/resources/mapper/sys/SysNoticeUsermapper.xml b/src/main/resources/mapper/sys/SysNoticeUsermapper.xml new file mode 100644 index 00000000..2742afff --- /dev/null +++ b/src/main/resources/mapper/sys/SysNoticeUsermapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + `sys_notice_user`.`id`, + `sys_notice_user`.`notice_id`, + `sys_notice_user`.`user_id`, + `sys_notice_user`.`read_flag`, + `sys_notice_user`.`read_time`, + `sys_notice_user`.`read_count`, + `sys_notice_user`.`create_time`, + `sys_notice_user`.`create_by`, + `sys_notice_user`.`update_time`, + `sys_notice_user`.`update_by`, + `sys_notice_user`.`tenant_id`, + `sys_notice_user`.`del_flag` + + + + + + diff --git a/src/main/resources/mapper/sys/SysOperationLogMapper.xml b/src/main/resources/mapper/sys/SysOperationLogMapper.xml new file mode 100644 index 00000000..5149574a --- /dev/null +++ b/src/main/resources/mapper/sys/SysOperationLogMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `sys_operation_log`.`id`, + `sys_operation_log`.`title`, + `sys_operation_log`.`biz_type`, + `sys_operation_log`.`inter_type`, + `sys_operation_log`.`code_method`, + `sys_operation_log`.`req_method`, + `sys_operation_log`.`req_url`, + `sys_operation_log`.`req_param`, + `sys_operation_log`.`req_ip`, + `sys_operation_log`.`user_type`, + `sys_operation_log`.`user_id`, + `sys_operation_log`.`err_msg`, + `sys_operation_log`.`json_result`, + `sys_operation_log`.`elapsed_time`, + `sys_operation_log`.`user_agent`, + `sys_operation_log`.`create_time`, + `sys_operation_log`.`create_by`, + `sys_operation_log`.`update_time`, + `sys_operation_log`.`update_by` + + + + INSERT INTO `sys_operation_log` + (`title`, `biz_type`, `inter_type`, `code_method`, `req_method`, `req_url`, `req_param`, `req_ip`, `user_type`, `user_id`, + `err_msg`, `json_result`, `elapsed_time`, `user_agent`, `create_time`, `create_by`, `tenant_id`,creator_name) + VALUES + ( #{title}, #{bizType}, #{interType}, #{codeMethod}, #{reqMethod}, #{reqUrl}, #{reqParam}, #{reqIp}, #{userType}, #{userId}, + #{errMsg}, #{jsonResult}, #{elapsedTime}, #{userAgent}, now(), #{userId}, #{tenantId},#{creatorName}); + + + + + + diff --git a/src/main/resources/mapper/sys/SysUserMapper.xml b/src/main/resources/mapper/sys/SysUserMapper.xml new file mode 100644 index 00000000..aa04e4ca --- /dev/null +++ b/src/main/resources/mapper/sys/SysUserMapper.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sys_user.`id`, + sys_user.`mobile`, + sys_user.`account`, + sys_user.`name`, + sys_user.`code`, + sys_user.`password`, + sys_user.`icon`, + sys_user.`dept_id`, + sys_user.`position_id`, + sys_user.`super_flag`, + sys_user.`login_enable`, + sys_user.`serving_state`, + sys_user.`identity_no`, + sys_user.`enter_date`, + sys_user.`formal_date`, + sys_user.`formal_status`, + sys_user.`remark`, + sys_user.`emer_name`, + sys_user.`emer_relate`, + sys_user.`emer_mobile`, + sys_user.`emer_worksapce`, + sys_user.`emer_address`, + sys_user.`local_type`, + sys_user.`house_type`, + sys_user.`nation`, + sys_user.`national`, + sys_user.`native_place`, + sys_user.`native_address`, + sys_user.`curr_address`, + sys_user.`politics_status`, + sys_user.`married_flag`, + sys_user.`gender`, + sys_user.`birthday`, + sys_user.`edu_school`, + sys_user.`edu_level`, + sys_user.`edu_profession`, + sys_user.`app_client`, + sys_user.`app_token`, + sys_user.`create_time`, + sys_user.`create_by`, + sys_user.`update_time`, + sys_user.`update_by`, + sys_user.`del_flag`, + sys_user.`tenant_id` + + + +