From 9dd127479a40f532085bac98e1a7b71371546b3a Mon Sep 17 00:00:00 2001 From: xuyuxiang Date: Tue, 13 May 2025 01:33:37 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8D=87=E7=BA=A7=E3=80=91v3.5.0?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=9B=B4=E6=96=B0=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=A7=81=E6=8E=A8=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 54 +- snowy-common/pom.xml | 6 + .../common/cache/CommonCacheOperator.java | 18 +- .../xiaonuo/common/consts/CacheConstant.java | 3 +- .../common/enums/CommonSortOrderEnum.java | 4 - .../handler/CommonSm4CbcTypeHandler.java | 6 +- .../listener/CommonDataChangeEventCenter.java | 9 +- .../common/page/CommonPageRequest.java | 2 - .../vip/xiaonuo/common/pojo/CommonResult.java | 26 +- .../xiaonuo/common/prop/CommonProperties.java | 3 - .../common/util/CommonCryptogramUtil.java | 2 +- .../xiaonuo/common/util/CommonEmailUtil.java | 6 +- .../common/util/CommonIpAddressUtil.java | 2 +- .../common/util/CommonTimeFormatUtil.java | 32 +- .../snowy-plugin-auth-api/pom.xml | 2 +- .../xiaonuo/auth/api/SaBaseLoginUserApi.java | 56 + snowy-plugin-api/snowy-plugin-dev-api/pom.xml | 20 +- .../java/vip/xiaonuo/dev/api/DevEmailApi.java | 22 + .../java/vip/xiaonuo/dev/api/DevFileApi.java | 9 + .../java/vip/xiaonuo/dev/api/DevPushApi.java | 109 ++ .../java/vip/xiaonuo/dev/api/DevSmsApi.java | 30 +- .../xiaonuo/dev/api/DevWeakPasswordApi.java | 32 + .../vip/xiaonuo/mobile/api/MobileApi.java | 22 + .../xiaonuo/mobile/api/MobileButtonApi.java | 2 +- .../vip/xiaonuo/mobile/api/MobileMenuApi.java | 8 + .../main/java/vip/xiaonuo/sys/api/SysApi.java | 30 + .../vip/xiaonuo/sys/api/SysModuleApi.java | 1 + .../vip/xiaonuo/sys/api/SysPositionApi.java | 2 +- .../java/vip/xiaonuo/sys/api/SysRoleApi.java | 16 + .../auth/core/config/AuthConfigure.java | 11 +- .../auth/core/util/AuthEmailFormatUtl.java | 48 + .../auth/core/util/AuthExceptionUtil.java | 6 + .../controller/AuthClientController.java | 27 +- .../login/controller/AuthController.java | 60 +- .../login/enums/AuthDeviceTypeEnum.java | 12 +- .../login/enums/AuthExceptionEnum.java | 46 +- .../login/enums/AuthPhoneOrEmailTypeEnum.java | 45 + .../login/enums/AuthSmsEngineTypeEnum.java | 40 + ...trategyWhenNoUserWithPhoneOrEmailEnum.java | 45 + .../param/AuthEmailValidCodeLoginParam.java | 48 + .../param/AuthGetEmailValidCodeParam.java | 44 + .../login/param/AuthRegisterParam.java | 47 + .../modular/login/service/AuthService.java | 30 +- .../login/service/impl/AuthServiceImpl.java | 603 ++++++++-- .../controller/AuthSessionController.java | 16 +- .../sso/controller/AuthSsoController.java | 58 + .../sso/param/AuthSsoTicketLoginParam.java | 38 + .../modular/sso/service/AuthSsoService.java | 32 + .../sso/service/impl/AuthSsoServiceImpl.java | 37 + .../third/controller/AuthThirdController.java | 9 +- .../modular/third/entity/AuthThirdUser.java | 8 +- snowy-plugin/snowy-plugin-biz/pom.xml | 2 +- .../biz/core/enums/BizBuildInEnum.java | 4 +- .../dict/controller/BizDictController.java | 9 +- .../biz/modular/dict/entity/BizDict.java | 2 +- .../modular/dict/param/BizDictEditParam.java | 6 +- .../group/controller/BizGroupController.java | 12 +- .../biz/modular/group/entity/BizGroup.java | 3 +- .../group/mapper/mapping/BizGroupMapper.xml | 2 +- .../modular/group/param/BizGroupAddParam.java | 4 +- .../group/param/BizGroupEditParam.java | 4 +- .../modular/group/param/BizGroupIdParam.java | 3 +- .../service/impl/BizGroupServiceImpl.java | 24 +- .../org/controller/BizOrgController.java | 16 +- .../biz/modular/org/entity/BizOrg.java | 4 +- .../biz/modular/org/entity/BizOrgExt.java | 46 + .../org/enums/BizOrgSourceFromTypeEnum.java | 37 + .../modular/org/mapper/BizOrgExtMapper.java | 25 + .../org/mapper/mapping/BizOrgExtMapper.xml | 5 + .../biz/modular/org/param/BizOrgAddParam.java | 8 +- .../modular/org/param/BizOrgEditParam.java | 10 +- .../biz/modular/org/param/BizOrgIdParam.java | 2 +- .../org/provider/BizOrgApiProvider.java | 1 + .../modular/org/service/BizOrgExtService.java | 33 + .../modular/org/service/BizOrgService.java | 2 +- .../service/impl/BizOrgExtServiceImpl.java | 37 + .../org/service/impl/BizOrgServiceImpl.java | 71 +- .../controller/BizPositionController.java | 12 +- .../modular/position/entity/BizPosition.java | 2 +- .../position/param/BizPositionAddParam.java | 8 +- .../position/param/BizPositionEditParam.java | 10 +- .../position/param/BizPositionIdParam.java | 2 +- .../service/impl/BizPositionServiceImpl.java | 21 +- .../user/controller/BizUserController.java | 25 +- .../biz/modular/user/entity/BizUser.java | 64 +- .../biz/modular/user/entity/BizUserExt.java | 52 + .../user/enums/BizUserSourceFromTypeEnum.java | 40 + .../modular/user/mapper/BizUserExtMapper.java | 25 + .../user/mapper/mapping/BizUserExtMapper.xml | 5 + .../user/mapper/mapping/BizUserMapper.xml | 2 +- .../modular/user/param/BizUserAddParam.java | 8 +- .../modular/user/param/BizUserEditParam.java | 10 +- .../user/param/BizUserGrantRoleParam.java | 4 +- .../modular/user/param/BizUserIdParam.java | 2 +- .../user/service/BizUserExtService.java | 41 + .../modular/user/service/BizUserService.java | 4 +- .../service/impl/BizUserExtServiceImpl.java | 55 + .../user/service/impl/BizUserServiceImpl.java | 81 +- .../enums/ClientPasswordComplexityEnum.java | 64 + ...rPasswordExpiredNoticeTimerTaskRunner.java | 39 + .../core/util/ClientEmailFormatUtl.java | 48 + .../client/core/util/ClientPasswordUtl.java | 405 +++++++ .../impl/ClientRelationServiceImpl.java | 8 + .../ClientUserCenterController.java | 363 ++++++ .../user/controller/ClientUserController.java | 41 +- .../modular/user/entity/ClientUser.java | 52 +- .../modular/user/entity/ClientUserExt.java | 52 + .../user/entity/ClientUserPassword.java | 46 + .../ClientUpdatePasswordValidTypeEnum.java | 40 + .../enums/ClientUserSourceFromTypeEnum.java | 40 + .../user/mapper/ClientUserExtMapper.java | 25 + .../user/mapper/ClientUserPasswordMapper.java | 25 + .../mapper/mapping/ClientUserExtMapper.xml | 5 + .../mapping/ClientUserPasswordMapper.xml | 5 + .../user/param/ClientUserAddParam.java | 6 +- .../user/param/ClientUserBindEmailParam.java | 49 + .../user/param/ClientUserBindPhoneParam.java | 44 + .../user/param/ClientUserEditParam.java | 2 +- .../param/ClientUserFindPwdByEmailParam.java | 49 + .../param/ClientUserFindPwdByPhoneParam.java | 49 + .../ClientUserGetEmailValidCodeParam.java | 44 + .../ClientUserGetPhoneValidCodeParam.java | 44 + .../modular/user/param/ClientUserIdParam.java | 2 +- .../user/param/ClientUserPageParam.java | 2 +- .../user/param/ClientUserSignatureParam.java | 34 + .../user/param/ClientUserUpdateInfoParam.java | 51 + .../ClientUserUpdatePwdByEmailParam.java | 49 + .../param/ClientUserUpdatePwdByOldParam.java | 39 + .../ClientUserUpdatePwdByPhoneParam.java | 49 + .../provider/ClientLoginUserApiProvider.java | 41 +- .../result/ClientUserPicValidCodeResult.java | 36 + .../user/service/ClientUserExtService.java | 41 + .../service/ClientUserPasswordService.java | 43 + .../user/service/ClientUserService.java | 253 +++- .../impl/ClientUserExtServiceImpl.java | 57 + .../impl/ClientUserPasswordServiceImpl.java | 50 + .../service/impl/ClientUserServiceImpl.java | 938 ++++++++++++++- snowy-plugin/snowy-plugin-dev/pom.xml | 3 +- .../dev/core/listener/DevJobListener.java | 6 +- .../controller/DevConfigController.java | 78 +- .../dev/modular/config/entity/DevConfig.java | 2 +- .../config/enums/DevConfigCategoryEnum.java | 11 +- .../config/mapper/mapping/DevConfigMapper.xml | 1 - .../config/param/DevConfigAddParam.java | 6 +- .../config/param/DevConfigBatchParam.java | 4 +- .../config/param/DevConfigEditParam.java | 8 +- .../config/param/DevConfigIdParam.java | 2 +- .../param/DevConfigSelectorOrgListParam.java | 44 + .../param/DevConfigSelectorPositionParam.java | 44 + .../param/DevConfigSelectorRoleParam.java | 48 + .../service/impl/DevConfigServiceImpl.java | 7 +- .../dict/controller/DevDictController.java | 12 +- .../dev/modular/dict/entity/DevDict.java | 6 +- .../dict/mapper/mapping/DevDictMapper.xml | 1 - .../modular/dict/param/DevDictIdParam.java | 2 +- .../dict/service/impl/DevDictServiceImpl.java | 14 +- .../email/controller/DevEmailController.java | 48 +- .../dev/modular/email/entity/DevEmail.java | 2 +- .../modular/email/param/DevEmailIdParam.java | 2 +- .../param/DevEmailSendAliyunHtmlParam.java | 8 +- .../param/DevEmailSendAliyunTmpParam.java | 6 +- .../param/DevEmailSendAliyunTxtParam.java | 8 +- .../param/DevEmailSendDynamicHtmlParam.java | 44 + .../param/DevEmailSendDynamicTxtParam.java | 44 + .../param/DevEmailSendLocalHtmlParam.java | 6 +- .../param/DevEmailSendLocalTxtParam.java | 6 +- .../param/DevEmailSendTencentHtmlParam.java | 8 +- .../param/DevEmailSendTencentTmpParam.java | 8 +- .../param/DevEmailSendTencentTxtParam.java | 8 +- .../email/provider/DevEmailApiProvider.java | 18 + .../email/service/DevEmailService.java | 40 + .../service/impl/DevEmailServiceImpl.java | 87 ++ .../email/util/DevEmailAliyunUtil.java | 38 +- .../modular/email/util/DevEmailLocalUtil.java | 1 + .../email/util/DevEmailTencentUtil.java | 44 +- .../file/controller/DevFileController.java | 35 +- .../dev/modular/file/entity/DevFile.java | 2 +- .../modular/file/param/DevFileIdParam.java | 2 +- .../file/provider/DevFileApiProvider.java | 9 +- .../file/service/impl/DevFileServiceImpl.java | 15 +- .../modular/file/util/DevFileAliyunUtil.java | 4 +- .../modular/file/util/DevFileLocalUtil.java | 17 +- .../modular/file/util/DevFileMinIoUtil.java | 23 +- .../modular/file/util/DevFileTencentUtil.java | 4 +- .../job/controller/DevJobController.java | 17 +- .../dev/modular/job/entity/DevJob.java | 2 +- .../dev/modular/job/param/DevJobAddParam.java | 10 +- .../modular/job/param/DevJobEditParam.java | 12 +- .../dev/modular/job/param/DevJobIdParam.java | 2 +- .../job/service/impl/DevJobServiceImpl.java | 13 +- .../job/task/DevJobTimerTaskRunner.java | 2 +- .../log/controller/DevLogController.java | 12 +- .../dev/modular/log/entity/DevLog.java | 2 +- .../modular/log/param/DevLogDeleteParam.java | 2 +- .../dev/modular/log/param/DevLogIdParam.java | 2 +- .../log/service/impl/DevLogServiceImpl.java | 2 +- .../dev/modular/log/util/DevLogUtil.java | 12 - .../controller/DevMessageController.java | 11 +- .../modular/message/entity/DevMessage.java | 2 +- .../message/param/DevMessageIdParam.java | 2 +- .../message/param/DevMessageSendParam.java | 4 +- .../message/result/DevMessageResult.java | 2 +- .../service/impl/DevMessageServiceImpl.java | 8 +- .../controller/DevMonitorController.java | 5 + .../controller/DevWeakPasswordController.java | 125 ++ .../password/entity/DevWeakPassword.java | 42 + .../mapper/DevWeakPasswordMapper.java | 25 + .../mapper/mapping/DevWeakPasswordMapper.xml | 5 + .../param/DevWeakPasswordAddParam.java | 34 + .../param/DevWeakPasswordEditParam.java | 39 + .../param/DevWeakPasswordIdParam.java | 34 + .../param/DevWeakPasswordPageParam.java | 48 + .../provider/DevWeakPasswordApiProvider.java | 40 + .../service/DevWeakPasswordService.java | 81 ++ .../impl/DevWeakPasswordServiceImpl.java | 108 ++ .../push/controller/DevPushController.java | 212 ++++ .../dev/modular/push/entity/DevPush.java | 59 + .../push/enums/DevPushEngineTypeEnum.java | 40 + .../push/enums/DevPushMessageTypeEnum.java | 43 + .../push/enums/DevPushNoticeTypeEnum.java | 40 + .../modular/push/mapper/DevPushMapper.java | 25 + .../push/mapper/mapping/DevPushMapper.xml | 5 + .../push/param/DevPushDingTalkLinkParam.java | 50 + .../param/DevPushDingTalkMarkdownParam.java | 44 + .../push/param/DevPushDingTalkTextParam.java | 43 + .../push/param/DevPushDynamicTextParam.java | 40 + .../push/param/DevPushFeiShuTextParam.java | 39 + .../modular/push/param/DevPushIdParam.java | 34 + .../modular/push/param/DevPushPageParam.java | 52 + .../param/DevPushWorkWechatMarkdownParam.java | 39 + .../param/DevPushWorkWechatNewsParam.java | 49 + .../param/DevPushWorkWechatTextParam.java | 43 + .../push/provider/DevPushApiProvider.java | 127 ++ .../modular/push/service/DevPushService.java | 137 +++ .../push/service/impl/DevPushServiceImpl.java | 271 +++++ .../push/util/DevPushDingTalkUtil.java | 170 +++ .../modular/push/util/DevPushFeiShuUtil.java | 97 ++ .../push/util/DevPushWorkWechatUtil.java | 161 +++ .../service/impl/DevRelationServiceImpl.java | 8 + .../service/impl/DevSlideshowServiceImpl.java | 2 +- .../sms/controller/DevSmsController.java | 30 +- .../dev/modular/sms/entity/DevSms.java | 2 +- .../dev/modular/sms/param/DevSmsIdParam.java | 2 +- .../sms/param/DevSmsSendAliyunParam.java | 4 +- .../sms/param/DevSmsSendDynamicParam.java | 43 + .../sms/param/DevSmsSendTencentParam.java | 8 +- .../sms/param/DevSmsSendXiaonuoParam.java | 11 + .../sms/provider/DevSmsApiProvider.java | 15 +- .../modular/sms/service/DevSmsService.java | 21 + .../sms/service/impl/DevSmsServiceImpl.java | 67 +- .../modular/sms/util/DevSmsAliyunUtil.java | 95 +- .../modular/sms/util/DevSmsTencentUtil.java | 127 +- .../modular/sms/util/DevSmsXiaonuoUtil.java | 47 +- .../controller/DevSseEmitterController.java | 7 + .../dev/modular/sse/util/DevSseCacheUtil.java | 60 +- .../gen/modular/basic/entity/GenBasic.java | 2 +- .../modular/mobile/MobileApiProvider.java | 27 + .../controller/MobileButtonController.java | 10 +- .../controller/MobileMenuController.java | 13 +- .../controller/MobileModuleController.java | 12 +- .../modular/resource/entity/MobileButton.java | 2 +- .../modular/resource/entity/MobileMenu.java | 2 +- .../modular/resource/entity/MobileModule.java | 2 +- .../provider/MobileButtonApiProvider.java | 2 +- .../provider/MobileMenuApiProvider.java | 7 + .../resource/service/MobileMenuService.java | 8 + .../service/impl/MobileButtonServiceImpl.java | 2 + .../service/impl/MobileMenuServiceImpl.java | 44 +- .../service/impl/MobileModuleServiceImpl.java | 5 + .../resources/static/mobile/flw/COMPLETED.png | Bin 0 -> 15194 bytes .../main/resources/static/mobile/flw/END.png | Bin 0 -> 15606 bytes .../resources/static/mobile/flw/REJECT.png | Bin 0 -> 14969 bytes .../resources/static/mobile/flw/REVOKE.png | Bin 0 -> 15096 bytes .../resources/static/mobile/flw/SUSPENDED.png | Bin 0 -> 15117 bytes .../sys/core/enums/SysBuildInEnum.java | 13 +- .../core/enums/SysPasswordComplexityEnum.java | 64 + .../core/listener/SysDataChangeListener.java | 34 +- ...rPasswordExpiredNoticeTimerTaskRunner.java | 39 + .../sys/core/util/SysEmailFormatUtl.java | 48 + .../xiaonuo/sys/core/util/SysPasswordUtl.java | 460 +++++++ .../group/controller/SysGroupController.java | 8 +- .../sys/modular/group/entity/SysGroup.java | 3 +- .../group/mapper/mapping/SysGroupMapper.xml | 2 +- .../modular/group/param/SysGroupAddParam.java | 4 +- .../group/param/SysGroupEditParam.java | 4 +- .../modular/group/param/SysGroupIdParam.java | 2 +- .../group/provider/SysGroupApiProvider.java | 1 + .../service/impl/SysGroupServiceImpl.java | 25 +- .../index/controller/SysIndexController.java | 15 +- .../index/param/SysIndexMessageIdParam.java | 2 +- .../index/param/SysIndexScheduleAddParam.java | 6 +- .../index/param/SysIndexScheduleIdParam.java | 2 +- .../param/SysIndexScheduleListParam.java | 2 +- .../result/SysIndexMessageDetailResult.java | 2 +- .../result/SysIndexMessageListResult.java | 2 +- .../index/result/SysIndexOpLogListResult.java | 2 +- .../result/SysIndexScheduleListResult.java | 2 +- .../result/SysIndexVisLogListResult.java | 2 +- .../org/controller/SysOrgController.java | 16 +- .../sys/modular/org/entity/SysOrg.java | 4 +- .../sys/modular/org/entity/SysOrgExt.java | 46 + .../org/enums/SysOrgSourceFromTypeEnum.java | 37 + .../modular/org/mapper/SysOrgExtMapper.java | 25 + .../sys/modular/org/mapper/SysOrgMapper.java | 12 - .../org/mapper/mapping/SysOrgExtMapper.xml | 5 + .../org/mapper/mapping/SysOrgMapper.xml | 3 - .../sys/modular/org/param/SysOrgAddParam.java | 8 +- .../modular/org/param/SysOrgEditParam.java | 10 +- .../sys/modular/org/param/SysOrgIdParam.java | 2 +- .../modular/org/service/SysOrgExtService.java | 33 + .../modular/org/service/SysOrgService.java | 2 +- .../service/impl/SysOrgExtServiceImpl.java | 37 + .../org/service/impl/SysOrgServiceImpl.java | 79 +- .../controller/SysPositionController.java | 12 +- .../modular/position/entity/SysPosition.java | 2 +- .../enums/SysPositionCategoryEnum.java | 8 - .../position/mapper/SysPositionMapper.java | 12 - .../mapper/mapping/SysPositionMapper.xml | 3 - .../position/param/SysPositionAddParam.java | 8 +- .../position/param/SysPositionEditParam.java | 10 +- .../position/param/SysPositionIdParam.java | 2 +- .../provider/SysPositionApiProvider.java | 2 +- .../service/impl/SysPositionServiceImpl.java | 16 +- .../modular/relation/entity/SysRelation.java | 2 +- .../mapper/mapping/SysRelationMapper.xml | 1 - .../service/impl/SysRelationServiceImpl.java | 8 + .../controller/SysButtonController.java | 10 +- .../controller/SysMenuController.java | 14 +- .../controller/SysModuleController.java | 12 +- .../modular/resource/entity/SysButton.java | 2 +- .../sys/modular/resource/entity/SysMenu.java | 8 +- .../modular/resource/entity/SysModule.java | 2 +- .../resource/mapper/SysButtonMapper.java | 12 - .../resource/mapper/SysMenuMapper.java | 12 - .../resource/mapper/SysModuleMapper.java | 13 - .../mapper/mapping/SysButtonMapper.xml | 3 - .../resource/mapper/mapping/SysMenuMapper.xml | 3 - .../mapper/mapping/SysModuleMapper.xml | 3 - .../param/button/SysButtonAddParam.java | 8 +- .../param/button/SysButtonEditParam.java | 10 +- .../param/button/SysButtonIdParam.java | 2 +- .../resource/param/menu/SysMenuAddParam.java | 12 +- .../param/menu/SysMenuChangeModuleParam.java | 4 +- .../resource/param/menu/SysMenuEditParam.java | 14 +- .../resource/param/menu/SysMenuIdParam.java | 2 +- .../param/module/SysModuleAddParam.java | 8 +- .../param/module/SysModuleEditParam.java | 10 +- .../param/module/SysModuleIdParam.java | 2 +- .../service/impl/SysButtonServiceImpl.java | 4 + .../service/impl/SysMenuServiceImpl.java | 21 +- .../service/impl/SysModuleServiceImpl.java | 2 +- .../role/controller/SysRoleController.java | 26 +- .../sys/modular/role/entity/SysRole.java | 4 +- .../modular/role/mapper/SysRoleMapper.java | 12 - .../role/mapper/mapping/SysRoleMapper.xml | 3 - .../modular/role/param/SysRoleAddParam.java | 11 +- .../modular/role/param/SysRoleEditParam.java | 13 +- .../param/SysRoleGrantMobileMenuParam.java | 6 +- .../param/SysRoleGrantPermissionParam.java | 6 +- .../role/param/SysRoleGrantResourceParam.java | 6 +- .../role/param/SysRoleGrantUserParam.java | 4 +- .../modular/role/param/SysRoleIdParam.java | 2 +- .../role/provider/SysRoleApiProvider.java | 10 + .../SysRoleGrantResourceTreeResult.java | 14 +- .../modular/role/service/SysRoleService.java | 20 +- .../role/service/impl/SysRoleServiceImpl.java | 140 ++- .../sys/modular/sys/SysApiProvider.java | 20 + .../controller/SysUserCenterController.java | 351 ++++-- .../user/controller/SysUserController.java | 37 +- .../sys/modular/user/entity/SysUser.java | 68 +- .../sys/modular/user/entity/SysUserExt.java | 52 + .../modular/user/entity/SysUserPassword.java | 46 + .../user/enums/SysEmailEngineTypeEnum.java | 40 + .../user/enums/SysSmsEngineTypeEnum.java | 40 + .../enums/SysUpdatePasswordValidTypeEnum.java | 40 + .../user/enums/SysUserSourceFromTypeEnum.java | 40 + .../modular/user/mapper/SysUserExtMapper.java | 25 + .../modular/user/mapper/SysUserMapper.java | 11 - .../user/mapper/SysUserPasswordMapper.java | 25 + .../user/mapper/mapping/SysUserExtMapper.xml | 5 + .../user/mapper/mapping/SysUserMapper.xml | 6 +- .../mapper/mapping/SysUserPasswordMapper.xml | 5 + .../modular/user/param/SysUserAddParam.java | 12 +- .../user/param/SysUserBindEmailParam.java | 49 + .../user/param/SysUserBindPhoneParam.java | 44 + .../modular/user/param/SysUserEditParam.java | 10 +- .../param/SysUserFindPwdByEmailParam.java | 10 +- .../param/SysUserFindPwdByPhoneParam.java | 10 +- .../param/SysUserGetEmailValidCodeParam.java | 6 +- .../param/SysUserGetPhoneValidCodeParam.java | 6 +- .../param/SysUserGrantPermissionParam.java | 6 +- .../user/param/SysUserGrantResourceParam.java | 6 +- .../user/param/SysUserGrantRoleParam.java | 4 +- .../user/param/SysUserIdListParam.java | 2 +- .../modular/user/param/SysUserIdParam.java | 2 +- .../user/param/SysUserMessageIdParam.java | 2 +- .../user/param/SysUserSignatureParam.java | 4 +- .../user/param/SysUserUpdateInfoParam.java | 14 +- .../param/SysUserUpdatePwdByEmailParam.java | 49 + .../param/SysUserUpdatePwdByOldParam.java | 39 + .../param/SysUserUpdatePwdByPhoneParam.java | 49 + .../param/SysUserUpdateWorkbenchParam.java | 2 +- .../provider/SysLoginUserApiProvider.java | 41 +- .../result/SysUserMessageDetailResult.java | 2 +- .../user/result/SysUserMessageResult.java | 2 +- .../user/service/SysUserExtService.java | 41 + .../user/service/SysUserPasswordService.java | 43 + .../modular/user/service/SysUserService.java | 174 ++- .../service/impl/SysUserExtServiceImpl.java | 55 + .../impl/SysUserPasswordServiceImpl.java | 50 + .../user/service/impl/SysUserServiceImpl.java | 1066 +++++++++++++++-- snowy-web-app/pom.xml | 11 +- .../xiaonuo/core/config/GlobalConfigure.java | 32 +- .../handler/GlobalErrorAttributesHandler.java | 3 +- .../handler/GlobalErrorViewController.java | 5 +- .../core/handler/GlobalErrorViewHandler.java | 3 +- .../core/handler/GlobalExceptionUtil.java | 6 +- .../src/main/resources/_sql/snowy_mysql.sql | 766 ++++++++---- .../src/main/resources/_sql/数据库说明.md | 6 - .../src/main/resources/application.properties | 209 ++++ .../src/main/resources/application.yaml | 163 --- snowy-web-app/src/main/resources/favicon.ico | Bin 0 -> 4286 bytes 422 files changed, 13368 insertions(+), 2033 deletions(-) create mode 100644 snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevPushApi.java create mode 100644 snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevWeakPasswordApi.java create mode 100644 snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileApi.java create mode 100644 snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysApi.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthEmailFormatUtl.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthPhoneOrEmailTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthSmsEngineTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthStrategyWhenNoUserWithPhoneOrEmailEnum.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthEmailValidCodeLoginParam.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthGetEmailValidCodeParam.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthRegisterParam.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/controller/AuthSsoController.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/param/AuthSsoTicketLoginParam.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/AuthSsoService.java create mode 100644 snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/impl/AuthSsoServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrgExt.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/enums/BizOrgSourceFromTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/BizOrgExtMapper.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/mapping/BizOrgExtMapper.xml create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgExtService.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgExtServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUserExt.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/enums/BizUserSourceFromTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/BizUserExtMapper.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserExtMapper.xml create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserExtService.java create mode 100644 snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserExtServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/enums/ClientPasswordComplexityEnum.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/timer/ClientUserPasswordExpiredNoticeTimerTaskRunner.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientEmailFormatUtl.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientPasswordUtl.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserCenterController.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserExt.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserPassword.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUpdatePasswordValidTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUserSourceFromTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserExtMapper.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserPasswordMapper.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserExtMapper.xml create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserPasswordMapper.xml create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindEmailParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindPhoneParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByEmailParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByPhoneParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetEmailValidCodeParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetPhoneValidCodeParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserSignatureParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdateInfoParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByEmailParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByOldParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByPhoneParam.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/result/ClientUserPicValidCodeResult.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserExtService.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserPasswordService.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserExtServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserPasswordServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorOrgListParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorPositionParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorRoleParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicHtmlParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicTxtParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/controller/DevWeakPasswordController.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/entity/DevWeakPassword.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/DevWeakPasswordMapper.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/mapping/DevWeakPasswordMapper.xml create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordAddParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordEditParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordIdParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordPageParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/provider/DevWeakPasswordApiProvider.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/DevWeakPasswordService.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/impl/DevWeakPasswordServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/controller/DevPushController.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/entity/DevPush.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushEngineTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushMessageTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushNoticeTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/DevPushMapper.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/mapping/DevPushMapper.xml create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkLinkParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkMarkdownParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkTextParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDynamicTextParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushFeiShuTextParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushIdParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushPageParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatMarkdownParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatNewsParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatTextParam.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/provider/DevPushApiProvider.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/DevPushService.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/impl/DevPushServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushDingTalkUtil.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushFeiShuUtil.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushWorkWechatUtil.java create mode 100644 snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendDynamicParam.java create mode 100644 snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/mobile/MobileApiProvider.java create mode 100644 snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/COMPLETED.png create mode 100644 snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/END.png create mode 100644 snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/REJECT.png create mode 100644 snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/REVOKE.png create mode 100644 snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/SUSPENDED.png create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysPasswordComplexityEnum.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/timer/SysUserPasswordExpiredNoticeTimerTaskRunner.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysEmailFormatUtl.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysPasswordUtl.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrgExt.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/enums/SysOrgSourceFromTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgExtMapper.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgExtMapper.xml create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgExtService.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgExtServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/sys/SysApiProvider.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserExt.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserPassword.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysEmailEngineTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysSmsEngineTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUpdatePasswordValidTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUserSourceFromTypeEnum.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserExtMapper.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserPasswordMapper.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserExtMapper.xml create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserPasswordMapper.xml create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindPhoneParam.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByEmailParam.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByOldParam.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByPhoneParam.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserExtService.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserPasswordService.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserExtServiceImpl.java create mode 100644 snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserPasswordServiceImpl.java delete mode 100644 snowy-web-app/src/main/resources/_sql/数据库说明.md create mode 100644 snowy-web-app/src/main/resources/application.properties delete mode 100644 snowy-web-app/src/main/resources/application.yaml create mode 100644 snowy-web-app/src/main/resources/favicon.ico diff --git a/pom.xml b/pom.xml index 58acc2f9..4f087cf5 100644 --- a/pom.xml +++ b/pom.xml @@ -245,21 +245,28 @@ 3.3.3 - + + + com.github.wnameless.json + json-flattener + 0.16.4 + + + cn.dev33 sa-token-core 1.37.0 - + cn.dev33 sa-token-spring-boot3-starter 1.37.0 - + cn.dev33 sa-token-redis-jackson @@ -343,25 +350,18 @@ 3.1.944 - - - com.aliyun - dysmsapi20170525 - 2.0.24 - - - - - com.tencentcloudapi - tencentcloud-sdk-java-sms - 3.1.893 - - org.dromara.sms4j sms4j-javase-plugin - 3.1.1 + 3.3.4 + + + + + org.dromara.sms4j + sms4j-oa-core + 3.3.4 @@ -371,6 +371,14 @@ 6.4.11 + + + org.junit.jupiter + junit-jupiter-api + 5.10.1 + test + + com.baomidou @@ -432,7 +440,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.12.1 + 3.7.0 -parameters @@ -461,11 +469,19 @@ src/main/resources + + _sql/* + *.md + src/main/java **/*.xml + **/*.ttf + **/*.ttc + **/*.TTF + **/*.TTC diff --git a/snowy-common/pom.xml b/snowy-common/pom.xml index 6c0d25d5..963cf0ac 100644 --- a/snowy-common/pom.xml +++ b/snowy-common/pom.xml @@ -129,5 +129,11 @@ com.alibaba easyexcel + + + + com.github.wnameless.json + json-flattener + diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/cache/CommonCacheOperator.java b/snowy-common/src/main/java/vip/xiaonuo/common/cache/CommonCacheOperator.java index 0c3e784a..600b4011 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/cache/CommonCacheOperator.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/cache/CommonCacheOperator.java @@ -58,21 +58,13 @@ public class CommonCacheOperator { public Collection getAllKeys() { Set keys = redisTemplate.keys(CACHE_KEY_PREFIX + "*"); - if (keys != null) { - // 去掉缓存key的common prefix前缀 - return keys.stream().map(key -> StrUtil.removePrefix(key, CACHE_KEY_PREFIX)).collect(Collectors.toSet()); - } else { - return CollectionUtil.newHashSet(); - } + // 去掉缓存key的common prefix前缀 + return keys.stream().map(key -> StrUtil.removePrefix(key, CACHE_KEY_PREFIX)).collect(Collectors.toSet()); } public Collection getAllValues() { Set keys = redisTemplate.keys(CACHE_KEY_PREFIX + "*"); - if (keys != null) { - return redisTemplate.opsForValue().multiGet(keys); - } else { - return CollectionUtil.newArrayList(); - } + return redisTemplate.opsForValue().multiGet(keys); } public Map getAllKeyValues() { @@ -86,8 +78,6 @@ public class CommonCacheOperator { public void removeBatch(String pattern) { Set keys = redisTemplate.keys(CACHE_KEY_PREFIX + pattern); - if (keys != null) { - redisTemplate.delete(keys); - } + redisTemplate.delete(keys); } } diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/consts/CacheConstant.java b/snowy-common/src/main/java/vip/xiaonuo/common/consts/CacheConstant.java index 44cdf430..ffcde459 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/consts/CacheConstant.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/consts/CacheConstant.java @@ -13,7 +13,8 @@ package vip.xiaonuo.common.consts; /** - * @description 缓存静态常量 + * 缓存静态常量 + * * @author dongxiayu * @date 2023/1/30 0:44 **/ diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonSortOrderEnum.java b/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonSortOrderEnum.java index 30d7cd53..74f04ea7 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonSortOrderEnum.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/enums/CommonSortOrderEnum.java @@ -42,8 +42,4 @@ public enum CommonSortOrderEnum { throw new CommonException("不支持该排序方式:{}", value); } } - - public String getValue() { - return value.toLowerCase(); - } } diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/handler/CommonSm4CbcTypeHandler.java b/snowy-common/src/main/java/vip/xiaonuo/common/handler/CommonSm4CbcTypeHandler.java index 0b70a808..22b51a15 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/handler/CommonSm4CbcTypeHandler.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/handler/CommonSm4CbcTypeHandler.java @@ -42,20 +42,20 @@ public class CommonSm4CbcTypeHandler extends BaseTypeHandler { public T getNullableResult(ResultSet rs, String columnName) throws SQLException { String columnValue = rs.getString(columnName); //有一些可能是空字符 - return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)CommonCryptogramUtil.doSm4CbcDecrypt(columnValue); + return StringUtils.isBlank(columnValue) ? (T)columnValue : (T) CommonCryptogramUtil.doSm4CbcDecrypt(columnValue); } @SuppressWarnings("ALL") @Override public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String columnValue = rs.getString(columnIndex); - return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)CommonCryptogramUtil.doSm4CbcDecrypt(columnValue); + return StringUtils.isBlank(columnValue) ? (T)columnValue : (T) CommonCryptogramUtil.doSm4CbcDecrypt(columnValue); } @SuppressWarnings("ALL") @Override public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String columnValue = cs.getString(columnIndex); - return StringUtils.isBlank(columnValue) ? (T)columnValue : (T)CommonCryptogramUtil.doSm4CbcDecrypt(columnValue); + return StringUtils.isBlank(columnValue) ? (T)columnValue : (T) CommonCryptogramUtil.doSm4CbcDecrypt(columnValue); } } diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java b/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java index 531b93fd..ef29901d 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/listener/CommonDataChangeEventCenter.java @@ -15,6 +15,7 @@ package vip.xiaonuo.common.listener; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import lombok.Getter; import vip.xiaonuo.common.exception.CommonException; import java.util.ArrayList; @@ -31,15 +32,11 @@ public class CommonDataChangeEventCenter { // --------- 注册侦听器 - private static List listenerList = new ArrayList<>(); - /** * 获取已注册的所有侦听器 - * @return / */ - public static List getListenerList() { - return listenerList; - } + @Getter + private static List listenerList = new ArrayList<>(); /** * 重置侦听器集合 diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/page/CommonPageRequest.java b/snowy-common/src/main/java/vip/xiaonuo/common/page/CommonPageRequest.java index d3728782..cff1c304 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/page/CommonPageRequest.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/page/CommonPageRequest.java @@ -56,7 +56,6 @@ public class CommonPageRequest { } } catch (Exception e) { log.error(">>> 分页条数转换异常:", e); - size = 20; } } @@ -67,7 +66,6 @@ public class CommonPageRequest { page = Convert.toInt(pageString); } catch (Exception e) { log.error(">>> 分页页数转换异常:", e); - page = 1; } } Page objectPage = new Page<>(page, size); diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/pojo/CommonResult.java b/snowy-common/src/main/java/vip/xiaonuo/common/pojo/CommonResult.java index ffa97398..1061a6c3 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/pojo/CommonResult.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/pojo/CommonResult.java @@ -13,7 +13,9 @@ package vip.xiaonuo.common.pojo; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import java.io.Serial; import java.io.Serializable; /** @@ -23,6 +25,7 @@ import java.io.Serializable; * @date 2022/8/15 16:08 **/ public class CommonResult implements Serializable{ + @Serial private static final long serialVersionUID = 1L; public static final int CODE_SUCCESS = 200; public static final int CODE_ERROR = 500; @@ -30,9 +33,17 @@ public class CommonResult implements Serializable{ @Schema(description = "状态码") private int code; + /** + * 获取msg + */ + @Getter @Schema(description = "提示语") private String msg; + /** + * 获取data + */ + @Getter @Schema(description = "返回数据") private T data; @@ -53,21 +64,6 @@ public class CommonResult implements Serializable{ return this.code; } - /** - * 获取msg - * @return msg - */ - public String getMsg() { - return this.msg; - } - /** - * 获取data - * @return data - */ - public T getData() { - return this.data; - } - /** * 给code赋值,连缀风格 * @param code code diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/prop/CommonProperties.java b/snowy-common/src/main/java/vip/xiaonuo/common/prop/CommonProperties.java index a54b2b29..a5b845e1 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/prop/CommonProperties.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/prop/CommonProperties.java @@ -29,9 +29,6 @@ import org.springframework.stereotype.Component; @ConfigurationProperties(prefix = "snowy.config.common") public class CommonProperties { - /** 前端地址 */ - private String frontUrl; - /** 后端地址 */ private String backendUrl; } diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java index 53c9bf80..2a2560f0 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java @@ -19,7 +19,7 @@ import com.antherd.smcrypto.sm4.Sm4Options; import lombok.extern.slf4j.Slf4j; /** - * 加密工具类,本框架目前使用 https://github.com/antherd/sm-crypto 项目中一些加解密方式 + * 加密工具类,本框架目前使用 sm-crypto 项目中一些加解密方式 * 使用小伙伴需要过等保密评相关,请在此处更改为自己的加密方法,或加密机,使用加密机同时需要替换公钥,私钥在内部无法导出,提供加密的方法 * 如果不涉及到加密机方面的内容,请更改公私要为自己重新生成的,生成方式请看集成的sm-crypto主页 * diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonEmailUtil.java b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonEmailUtil.java index c087c585..a3effdfb 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonEmailUtil.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonEmailUtil.java @@ -30,8 +30,8 @@ public class CommonEmailUtil { * @author xuyuxiang * @date 2022/8/15 13:32 **/ - public static boolean isEmail(String email) { - return Validator.isEmail(email); + public static boolean isNotEmail(String email) { + return !Validator.isEmail(email); } /** @@ -42,7 +42,7 @@ public class CommonEmailUtil { **/ public static void validEmail(String emails) { StrUtil.split(emails, StrUtil.COMMA).forEach(email -> { - if(!isEmail(email)) { + if(isNotEmail(email)) { throw new CommonException("邮件地址:{}格式错误", email); } }); diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonIpAddressUtil.java b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonIpAddressUtil.java index 159e5c80..2d82fded 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonIpAddressUtil.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonIpAddressUtil.java @@ -26,7 +26,7 @@ import java.io.InputStream; /** * 根据ip地址定位工具类,离线方式 - * 参考地址:https://gitee.com/lionsoul/ip2region/tree/master/binding/java + * 参考地址:ip2region * * @author xuyuxiang * @date 2020/3/16 11:25 diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonTimeFormatUtil.java b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonTimeFormatUtil.java index c3f0f294..d2abf21e 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonTimeFormatUtil.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonTimeFormatUtil.java @@ -77,29 +77,15 @@ public class CommonTimeFormatUtil { String weekday; //获取是本周的第几天 int dayOfWeek = DateUtil.dayOfWeek(date) - 1; - switch (dayOfWeek) { - case 1: - weekday = "周一"; - break; - case 2: - weekday = "周二"; - break; - case 3: - weekday = "周三"; - break; - case 4: - weekday = "周四"; - break; - case 5: - weekday = "周五"; - break; - case 6: - weekday = "周六"; - break; - default: - weekday = "周日"; - break; - } + weekday = switch (dayOfWeek) { + case 1 -> "周一"; + case 2 -> "周二"; + case 3 -> "周三"; + case 4 -> "周四"; + case 5 -> "周五"; + case 6 -> "周六"; + default -> "周日"; + }; //显示本周时分 return weekday + " " + DateUtil.format(date, "HH:mm"); } else { diff --git a/snowy-plugin-api/snowy-plugin-auth-api/pom.xml b/snowy-plugin-api/snowy-plugin-auth-api/pom.xml index 649c8cd4..d5aceb36 100644 --- a/snowy-plugin-api/snowy-plugin-auth-api/pom.xml +++ b/snowy-plugin-api/snowy-plugin-auth-api/pom.xml @@ -27,4 +27,4 @@ sa-token-core - \ No newline at end of file + diff --git a/snowy-plugin-api/snowy-plugin-auth-api/src/main/java/vip/xiaonuo/auth/api/SaBaseLoginUserApi.java b/snowy-plugin-api/snowy-plugin-auth-api/src/main/java/vip/xiaonuo/auth/api/SaBaseLoginUserApi.java index 151f384f..fb2f1174 100644 --- a/snowy-plugin-api/snowy-plugin-auth-api/src/main/java/vip/xiaonuo/auth/api/SaBaseLoginUserApi.java +++ b/snowy-plugin-api/snowy-plugin-auth-api/src/main/java/vip/xiaonuo/auth/api/SaBaseLoginUserApi.java @@ -66,6 +66,14 @@ public interface SaBaseLoginUserApi { **/ SaBaseLoginUser getUserByPhone(String phone); + /** + * 根据邮箱获取B端用户信息,查不到则返回null + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + SaBaseLoginUser getUserByEmail(String email); + /** * 根据手机号获取C端用户信息,查不到则返回null * @@ -74,6 +82,14 @@ public interface SaBaseLoginUserApi { **/ SaBaseClientLoginUser getClientUserByPhone(String phone); + /** + * 根据邮箱获取C端用户信息,查不到则返回null + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + SaBaseClientLoginUser getClientUserByEmail(String email); + /** * 根据用户id获取用户集合 * @@ -121,4 +137,44 @@ public interface SaBaseLoginUserApi { * @date 2022/4/27 22:57 */ void updateUserLoginInfo(String userId, String device); + + /** + * 使用手机号创建B端用户 + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + SaBaseLoginUser createUserWithPhone(String phone); + + /** + * 使用手机号创建C端用户 + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + SaBaseClientLoginUser createClientUserWithPhone(String phone); + + /** + * 使用邮箱创建B端用户 + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + SaBaseLoginUser createUserWithEmail(String email); + + /** + * 使用邮箱创建C端用户 + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + SaBaseClientLoginUser createClientUserWithEmail(String email); + + /** + * 执行注册 + * + * @author xuyuxiang + * @date 2022/3/10 16:14 + **/ + void doRegister(String account, String password); } diff --git a/snowy-plugin-api/snowy-plugin-dev-api/pom.xml b/snowy-plugin-api/snowy-plugin-dev-api/pom.xml index c8155fed..bd10263b 100644 --- a/snowy-plugin-api/snowy-plugin-dev-api/pom.xml +++ b/snowy-plugin-api/snowy-plugin-dev-api/pom.xml @@ -63,28 +63,22 @@ tencentcloud-sdk-java-ses - - - com.aliyun - dysmsapi20170525 - - - - - com.tencentcloudapi - tencentcloud-sdk-java-sms - - org.dromara.sms4j sms4j-javase-plugin + + + org.dromara.sms4j + sms4j-oa-core + + com.github.oshi oshi-core - \ No newline at end of file + diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevEmailApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevEmailApi.java index 0704bb7d..9d5a7359 100644 --- a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevEmailApi.java +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevEmailApi.java @@ -27,6 +27,28 @@ import java.util.Map; **/ public interface DevEmailApi { + /** + * 动态发送TXT邮件(使用系统配置的默认邮件引擎) + * + * @param tos 收件人邮箱,逗号拼接 + * @param subject 邮件主题 + * @param content 邮件内容 + * @author xuyuxiang + * @date 2022/2/7 22:29 + */ + void sendDynamicTxtEmail(String tos, String subject, String content); + + /** + * 动态发送HTML邮件(使用系统配置的默认邮件引擎) + * + * @param tos 收件人邮箱,逗号拼接 + * @param subject 邮件主题 + * @param content 邮件内容 + * @author xuyuxiang + * @date 2022/2/7 22:29 + */ + void sendDynamicHtmlEmail(String tos, String subject, String content); + /* =========本地邮件========= */ /** diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java index e0a20d28..21ae3487 100644 --- a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java @@ -31,6 +31,14 @@ public interface DevFileApi { **/ String uploadDynamicReturnId(MultipartFile file); + /** + * 动态上传文件返回url(使用系统配置的默认文件引擎) + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + String uploadDynamicReturnUrl(MultipartFile file); + /* =========本地文件========= */ /** @@ -119,6 +127,7 @@ public interface DevFileApi { */ JSONObject getFileInfoById(String id); + /** * 根据文件id物理删除文件 * diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevPushApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevPushApi.java new file mode 100644 index 00000000..d0bb90d3 --- /dev/null +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevPushApi.java @@ -0,0 +1,109 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.api; + +/** + * 邮件API接口 + * + * @author xuyuxiang + * @date 2022/6/22 15:21 + **/ +public interface DevPushApi { + + /** + * 动态推送消息(使用系统配置的默认消息推送引擎) + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushDynamicText(String content, boolean noticeAll); + + /** + * 推送消息——飞书TXT + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushFeiShuText(String content, boolean noticeAll); + + /** + * 推送消息——钉钉TXT + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @param phones 通知的用户手机号,英文逗号分割 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushDingTalkText(String content, boolean noticeAll, String phones); + + /** + * 推送消息——钉钉MARKDOWN + * + * @param title 标题 + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushDingTalkMarkdown(String title, String content, boolean noticeAll); + + /** + * 推送消息——钉钉LINK + * + * @param title 标题 + * @param content 内容 + * @param picUrl 封面图片地址 + * @param messageUrl 消息链接地址 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushDingTalkLink(String title, String content, String picUrl,String messageUrl); + + /** + * 推送消息——企业微信TXT + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @param phones 通知的用户手机号,英文逗号分割 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushWorkWechatText(String content, boolean noticeAll, String phones); + + /** + * 推送消息——企业微信MARKDOWN + * + * @param title 标题 + * @param content 内容 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushWorkWechatMarkdown(String title, String content); + + /** + * 推送消息——企业微信NEWS + * + * @param title 标题 + * @param content 内容 + * @param picUrl 封面图片地址 + * @param messageUrl 消息链接地址 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + void pushWorkWechatNews(String title, String content, String picUrl,String messageUrl); +} diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevSmsApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevSmsApi.java index 5d1523d4..7db035c9 100644 --- a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevSmsApi.java +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevSmsApi.java @@ -12,6 +12,8 @@ */ package vip.xiaonuo.dev.api; +import cn.hutool.json.JSONObject; + /** * 短信API * @@ -20,6 +22,17 @@ package vip.xiaonuo.dev.api; **/ public interface DevSmsApi { + /** + * 动态发送短信(使用系统配置的默认短信引擎) + * + * @param phoneNumbers 手机号 + * @param templateCodeOrId 模板id或编码 + * @param paramMap 发送参数 + * @author xuyuxiang + * @date 2022/2/7 22:29 + */ + void sendDynamicSms(String phoneNumbers, String templateCodeOrId, JSONObject paramMap); + /* =========阿里云短信========= */ /** @@ -27,7 +40,7 @@ public interface DevSmsApi { * * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 * 上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。 - * @param signName 短信服务控制台配置且审核通过的短信签名,为空则使用默认签名 + * @param signName 短信服务控制台配置且审核通过的短信签名 * @param templateCode 短信服务控制台配置且审核通过的模板编码 * @param templateParam 短信模板变量对应的实际值,JSON格式。支持传入多个参数,示例:{"name":"张三","number":"15038****76"} * @author xuyuxiang @@ -40,17 +53,15 @@ public interface DevSmsApi { /** * 发送短信 * - * @param sdkAppId 短信 SdkAppId,在 短信控制台 添加应用后生成的实际 SdkAppId,示例如1400006666。 - * 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看 * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 * 上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。 - * @param signName 短信服务控制台配置且审核通过的短信签名,为空则使用默认签名 + * @param signName 短信服务控制台配置且审核通过的短信签名 * @param templateCode 短信服务控制台配置且审核通过的模板编码 * @param templateParam 短信模板变量对应的顺序。支持传入多个参数,逗号拼接,示例:"张三,15038****76,进行中"} * @author xuyuxiang * @date 2022/2/24 13:42 **/ - void sendSmsTencent(String sdkAppId, String phoneNumbers, String signName, String templateCode, String templateParam); + void sendSmsTencent(String phoneNumbers, String signName, String templateCode, String templateParam); /* =========小诺短信========= */ @@ -58,10 +69,11 @@ public interface DevSmsApi { * 发送短信 * * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 - * @param signName 短信签名,为空则使用默认签名 - * @param message 短信内容 - * @author xuyuxiang - * @date 2022/2/24 13:42 + * 上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。 + * @param signName 短信服务控制台配置且审核通过的短信签名 + * @param message 短信内容,发送时编写好的整条短信内容,不带签名【】 + * @author yubaoshan + * @date 2024/5/20 12:00 **/ void sendSmsXiaonuo(String phoneNumbers, String signName, String message); } diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevWeakPasswordApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevWeakPasswordApi.java new file mode 100644 index 00000000..f87155f8 --- /dev/null +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevWeakPasswordApi.java @@ -0,0 +1,32 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.api; + +import java.util.List; + +/** + * 弱密码库APi接口 + * + * @author xuyuxiang + * @date 2022/6/17 10:37 + **/ +public interface DevWeakPasswordApi { + + /** + * 获取弱密码库列表 + * + * @author xuyuxiang + * @date 2022/6/17 11:11 + **/ + List weakPasswordList(); +} diff --git a/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileApi.java b/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileApi.java new file mode 100644 index 00000000..7634d4bb --- /dev/null +++ b/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileApi.java @@ -0,0 +1,22 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.mobile.api; + +/** + * 移动端综合API + * + * @author xuyuxiang + * @date 2022/9/26 14:24 + **/ +public interface MobileApi { +} diff --git a/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileButtonApi.java b/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileButtonApi.java index 49e184df..7d71ed88 100644 --- a/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileButtonApi.java +++ b/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileButtonApi.java @@ -28,5 +28,5 @@ public interface MobileButtonApi { * @author 每天一点 * @date 2023/2/5 13:26 **/ - List listByIds(List idList); + List listButtonCodeListByIdList(List idList); } diff --git a/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileMenuApi.java b/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileMenuApi.java index 1636a883..54392b71 100644 --- a/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileMenuApi.java +++ b/snowy-plugin-api/snowy-plugin-mobile-api/src/main/java/vip/xiaonuo/mobile/api/MobileMenuApi.java @@ -33,6 +33,14 @@ public interface MobileMenuApi { **/ List mobileMenuTreeSelector(); + /** + * 获取移动端菜单授权树 + * + * @author xuyuxiang + * @date 2023/1/31 10:10 + **/ + List mobileMenuTreeSelector(List originDataList); + /** * 获取移动端登录菜单树 * diff --git a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysApi.java b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysApi.java new file mode 100644 index 00000000..d5034865 --- /dev/null +++ b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysApi.java @@ -0,0 +1,30 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.api; + +/** + * 系统模块综合API + * + * @author xuyuxiang + * @date 2022/9/26 14:24 + **/ +public interface SysApi { + + /** + * 获取系统默认密码 + * + * @author xuyuxiang + * @date 2022/9/26 14:25 + **/ + String getDefaultPassword(); +} diff --git a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysModuleApi.java b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysModuleApi.java index b53c0580..a760400a 100644 --- a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysModuleApi.java +++ b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysModuleApi.java @@ -13,6 +13,7 @@ package vip.xiaonuo.sys.api; import cn.hutool.json.JSONObject; + import java.util.List; /** diff --git a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysPositionApi.java b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysPositionApi.java index e4fea209..7cd782a6 100644 --- a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysPositionApi.java +++ b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysPositionApi.java @@ -37,5 +37,5 @@ public interface SysPositionApi { * @author xuyuxiang * @date 2022/7/22 14:47 **/ - Page positionSelector(String orgId, String searchKey); + Page positionSelector(String orgId, String searchKey, Integer current, Integer size); } diff --git a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysRoleApi.java b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysRoleApi.java index d39c4ffc..f691df51 100644 --- a/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysRoleApi.java +++ b/snowy-plugin-api/snowy-plugin-sys-api/src/main/java/vip/xiaonuo/sys/api/SysRoleApi.java @@ -48,4 +48,20 @@ public interface SysRoleApi { * @date 2022/11/1 15:58 **/ void grantForGenMenuAndButton(String menuId); + + /** + * 获取资源授权树 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + List resourceTreeSelector(); + + /** + * 获取权限授权树 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + List permissionTreeSelector(); } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/config/AuthConfigure.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/config/AuthConfigure.java index 3d88eadb..957b4362 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/config/AuthConfigure.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/config/AuthConfigure.java @@ -17,7 +17,8 @@ import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.stp.StpInterface; import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.strategy.SaStrategy; -import cn.hutool.json.JSONUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -71,6 +72,7 @@ public class AuthConfigure implements WebMvcConfigurer { @Bean("stpClientLogic") public StpLogic getStpClientLogic(SaTokenConfig saTokenConfig) { + // 重写Sa-Token的StpLogic,默认客户端类型为C return new StpLogic(SaClientTypeEnum.C.getValue()).setConfig(saTokenConfig); } @@ -105,7 +107,12 @@ public class AuthConfigure implements WebMvcConfigurer { } else { permissionListObject = commonCacheOperator.get(CacheConstant.AUTH_C_PERMISSION_LIST_CACHE_KEY + loginId); } - return JSONUtil.parseArray(permissionListObject).toList(String.class); + // 转为字符串 + String permissionListString = permissionListObject.toString(); + // 去除首尾的方括号 + String trimmedStr = StrUtil.sub(permissionListString, 1, -1); + // 使用逗号和空格分割字符串,并转换为列表 + return CollectionUtil.newArrayList(StrUtil.split(trimmedStr, ", ")); } /** diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthEmailFormatUtl.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthEmailFormatUtl.java new file mode 100644 index 00000000..ced77820 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthEmailFormatUtl.java @@ -0,0 +1,48 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.core.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import vip.xiaonuo.dev.api.DevConfigApi; + +/** + * 认证相关邮件格式化工具类 + * + * @author xuyuxiang + * @date 2025/3/21 19:07 + **/ +public class AuthEmailFormatUtl { + + /** 系统名称 */ + private static final String SNOWY_SYS_NAME_KEY = "SNOWY_SYS_NAME"; + + /** + * 格式化邮件内容 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static String format(String content, JSONObject paramMap) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取系统名称 + String sysName = devConfigApi.getValueByKey(SNOWY_SYS_NAME_KEY); + // 系统名称 + paramMap.set("sysName", sysName); + // 当前时间 + paramMap.set("sysNowTime", DateUtil.now()); + return StrUtil.format(content, paramMap); + } +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthExceptionUtil.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthExceptionUtil.java index 54d76038..9bf33693 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthExceptionUtil.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/core/util/AuthExceptionUtil.java @@ -18,6 +18,12 @@ import lombok.extern.slf4j.Slf4j; import vip.xiaonuo.common.pojo.CommonResult; import vip.xiaonuo.common.util.CommonServletUtil; +/** + * 认证相关异常处理工具类 + * + * @author xuyuxiang + * @date 2021/10/9 14:24 + **/ @Slf4j public class AuthExceptionUtil { diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java index de4ea207..5b20dbc5 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthClientController.java @@ -12,10 +12,11 @@ */ package vip.xiaonuo.auth.modular.login.controller; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -28,10 +29,13 @@ import vip.xiaonuo.auth.core.util.StpClientUtil; import vip.xiaonuo.auth.modular.login.param.AuthAccountPasswordLoginParam; import vip.xiaonuo.auth.modular.login.param.AuthGetPhoneValidCodeParam; import vip.xiaonuo.auth.modular.login.param.AuthPhoneValidCodeLoginParam; +import vip.xiaonuo.auth.modular.login.param.AuthRegisterParam; import vip.xiaonuo.auth.modular.login.result.AuthPicValidCodeResult; import vip.xiaonuo.auth.modular.login.service.AuthService; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; + /** * C端登录控制器 * @@ -39,6 +43,7 @@ import vip.xiaonuo.common.pojo.CommonResult; * @date 2021/12/23 21:50 */ @Tag(name = "C端登录控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 1) @RestController @Validated public class AuthClientController { @@ -52,6 +57,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2022/7/8 9:26 **/ + @ApiOperationSupport(order = 1) @Operation(summary = "C端获取图片验证码") @GetMapping("/auth/c/getPicCaptcha") public CommonResult getPicCaptcha() { @@ -64,6 +70,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2022/7/8 9:26 **/ + @ApiOperationSupport(order = 2) @Operation(summary = "C端获取手机验证码") @GetMapping("/auth/c/getPhoneValidCode") public CommonResult getPhoneValidCode(@Valid AuthGetPhoneValidCodeParam authGetPhoneValidCodeParam) { @@ -76,6 +83,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 3) @Operation(summary = "C端账号密码登录") @PostMapping("/auth/c/doLogin") public CommonResult doLogin(@RequestBody @Valid AuthAccountPasswordLoginParam authAccountPasswordLoginParam) { @@ -88,6 +96,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 4) @Operation(summary = "C端手机验证码登录") @PostMapping("/auth/c/doLoginByPhone") public CommonResult doLoginByPhone(@RequestBody @Valid AuthPhoneValidCodeLoginParam authPhoneValidCodeLoginParam) { @@ -100,6 +109,7 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 5) @Operation(summary = "C端退出") @SaClientCheckLogin @GetMapping("/auth/c/doLogout") @@ -114,10 +124,25 @@ public class AuthClientController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 6) @Operation(summary = "C端获取用户信息") @SaClientCheckLogin @GetMapping("/auth/c/getLoginUser") public CommonResult getLoginUser() { return CommonResult.data(authService.getClientLoginUser()); } + + /** + * C端注册 + * + * @author xuyuxiang + * @date 2021/10/15 13:12 + **/ + @ApiOperationSupport(order = 7) + @Operation(summary = "C端注册") + @PostMapping("/auth/c/register") + public CommonResult register(@RequestBody @Valid AuthRegisterParam authRegisterParam) { + authService.register(authRegisterParam, SaClientTypeEnum.C.getValue()); + return CommonResult.ok(); + } } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthController.java index 9802812b..9a8287fe 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthController.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/controller/AuthController.java @@ -14,10 +14,11 @@ package vip.xiaonuo.auth.modular.login.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.stp.StpUtil; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -25,13 +26,13 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import vip.xiaonuo.auth.core.enums.SaClientTypeEnum; import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; -import vip.xiaonuo.auth.modular.login.param.AuthAccountPasswordLoginParam; -import vip.xiaonuo.auth.modular.login.param.AuthGetPhoneValidCodeParam; -import vip.xiaonuo.auth.modular.login.param.AuthPhoneValidCodeLoginParam; +import vip.xiaonuo.auth.modular.login.param.*; import vip.xiaonuo.auth.modular.login.result.AuthPicValidCodeResult; import vip.xiaonuo.auth.modular.login.service.AuthService; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; + /** * B端登录控制器 * @@ -39,6 +40,7 @@ import vip.xiaonuo.common.pojo.CommonResult; * @date 2021/12/23 21:50 */ @Tag(name = "B端登录控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 2) @RestController @Validated public class AuthController { @@ -52,6 +54,7 @@ public class AuthController { * @author xuyuxiang * @date 2022/7/8 9:26 **/ + @ApiOperationSupport(order = 1) @Operation(summary = "B端获取图片验证码") @GetMapping("/auth/b/getPicCaptcha") public CommonResult getPicCaptcha() { @@ -59,23 +62,38 @@ public class AuthController { } /** - * B端获取手机验证码 + * B端获取手机登录验证码 * * @author xuyuxiang * @date 2022/7/8 9:26 **/ - @Operation(summary = "B端获取手机验证码") + @ApiOperationSupport(order = 2) + @Operation(summary = "B端获取手机登录验证码") @GetMapping("/auth/b/getPhoneValidCode") public CommonResult getPhoneValidCode(@Valid AuthGetPhoneValidCodeParam authGetPhoneValidCodeParam) { return CommonResult.data(authService.getPhoneValidCode(authGetPhoneValidCodeParam, SaClientTypeEnum.B.getValue())); } + /** + * B端获取邮箱登录验证码 + * + * @author xuyuxiang + * @date 2022/7/8 9:26 + **/ + @ApiOperationSupport(order = 3) + @Operation(summary = "B端获取邮箱登录验证码") + @GetMapping("/auth/b/getEmailValidCode") + public CommonResult getEmailValidCode(@Valid AuthGetEmailValidCodeParam authGetEmailValidCodeParam) { + return CommonResult.data(authService.getEmailValidCode(authGetEmailValidCodeParam, SaClientTypeEnum.B.getValue())); + } + /** * B端账号密码登录 * * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 4) @Operation(summary = "B端账号密码登录") @PostMapping("/auth/b/doLogin") public CommonResult doLogin(@RequestBody @Valid AuthAccountPasswordLoginParam authAccountPasswordLoginParam) { @@ -88,18 +106,33 @@ public class AuthController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 5) @Operation(summary = "B端手机验证码登录") @PostMapping("/auth/b/doLoginByPhone") public CommonResult doLoginByPhone(@RequestBody @Valid AuthPhoneValidCodeLoginParam authPhoneValidCodeLoginParam) { return CommonResult.data(authService.doLoginByPhone(authPhoneValidCodeLoginParam, SaClientTypeEnum.B.getValue())); } + /** + * B端邮箱验证码登录 + * + * @author xuyuxiang + * @date 2021/10/15 13:12 + **/ + @ApiOperationSupport(order = 6) + @Operation(summary = "B端邮箱验证码登录") + @PostMapping("/auth/b/doLoginByEmail") + public CommonResult doLoginByEmail(@RequestBody @Valid AuthEmailValidCodeLoginParam authEmailValidCodeLoginParam) { + return CommonResult.data(authService.doLoginByEmail(authEmailValidCodeLoginParam, SaClientTypeEnum.B.getValue())); + } + /** * B端退出 * * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 7) @Operation(summary = "B端退出") @SaCheckLogin @GetMapping("/auth/b/doLogout") @@ -114,10 +147,25 @@ public class AuthController { * @author xuyuxiang * @date 2021/10/15 13:12 **/ + @ApiOperationSupport(order = 8) @Operation(summary = "B端获取用户信息") @SaCheckLogin @GetMapping("/auth/b/getLoginUser") public CommonResult getLoginUser() { return CommonResult.data(authService.getLoginUser()); } + + /** + * B端注册 + * + * @author xuyuxiang + * @date 2021/10/15 13:12 + **/ + @ApiOperationSupport(order = 9) + @Operation(summary = "B端注册") + @PostMapping("/auth/b/register") + public CommonResult register(@RequestBody @Valid AuthRegisterParam authRegisterParam) { + authService.register(authRegisterParam, SaClientTypeEnum.B.getValue()); + return CommonResult.ok(); + } } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthDeviceTypeEnum.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthDeviceTypeEnum.java index 0815ff2a..95065da8 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthDeviceTypeEnum.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthDeviceTypeEnum.java @@ -24,19 +24,13 @@ import vip.xiaonuo.common.exception.CommonException; @Getter public enum AuthDeviceTypeEnum { - /** - * PC端 - */ + /** PC端 */ PC("PC"), - /** - * 移动端 - */ + /** 移动端 */ APP("APP"), - /** - * 小程序端 - */ + /** 小程序端 */ MINI("MINI"); private final String value; diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthExceptionEnum.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthExceptionEnum.java index dfbfc913..7753b20f 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthExceptionEnum.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthExceptionEnum.java @@ -23,59 +23,37 @@ import lombok.Getter; @Getter public enum AuthExceptionEnum { - /** - * 验证码不能为空 - */ + /** 验证码不能为空 */ VALID_CODE_EMPTY("验证码不能为空"), - /** - * 验证码请求号不能为空 - */ + /** 验证码请求号不能为空 */ VALID_CODE_REQ_NO_EMPTY("验证码请求号不能为空"), - /** - * 验证码错误 - */ + /** 验证码错误 */ VALID_CODE_ERROR("验证码错误"), - /** - * 账号错误 - */ + /** 账号错误 */ ACCOUNT_ERROR("账号错误"), - /** - * 账号已停用 - */ + /** 账号已停用 */ ACCOUNT_DISABLED("账号已停用"), - /** - * 密码错误 - */ + /** 密码错误 */ PWD_ERROR("密码错误"), - /** - * 手机号格式错误 - */ + /** 手机号格式错误 */ PHONE_FORMAT_ERROR("手机号格式错误"), - /** - * 手机号不存在 - */ - PHONE_ERROR("手机号不存在"), + /** 邮箱格式错误 */ + EMAIL_FORMAT_ERROR("邮箱格式错误"), - /** - * 客户端类型不能为空 - */ + /** 客户端类型不能为空 */ CLIENT_TYPE_EMPTY("客户端类型不能为空"), - /** - * 客户端类型错误 - */ + /** 客户端类型错误 */ CLIENT_TYPE_ERROR("客户端类型错误"), - /** - * 密码解密失败,请检查前端公钥 - */ + /** 密码解密失败,请检查前端公钥 */ PWD_DECRYPT_ERROR("密码解密失败,请检查前端公钥"); private final String value; diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthPhoneOrEmailTypeEnum.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthPhoneOrEmailTypeEnum.java new file mode 100644 index 00000000..9030fd83 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthPhoneOrEmailTypeEnum.java @@ -0,0 +1,45 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.login.enums; + +import lombok.Getter; +import vip.xiaonuo.common.exception.CommonException; + +/** + * 手机号邮箱类型枚举 + * + * @author xuyuxiang + * @date 2021/10/11 14:02 + **/ +@Getter +public enum AuthPhoneOrEmailTypeEnum { + + /** 手机号 */ + PHONE("PHONE"), + + /** 邮箱 */ + EMAIL("EMAIL"); + + private final String value; + + AuthPhoneOrEmailTypeEnum(String value) { + this.value = value; + } + + public static void validate(String value) { + boolean flag = PHONE.getValue().equals(value) || EMAIL.getValue().equals(value); + if(!flag) { + throw new CommonException("不支持的手机号邮箱类型:{}", value); + } + } +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthSmsEngineTypeEnum.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthSmsEngineTypeEnum.java new file mode 100644 index 00000000..493e6fb6 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthSmsEngineTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.login.enums; + +import lombok.Getter; + +/** + * 短信发送引擎类型枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum AuthSmsEngineTypeEnum { + + /** 阿里云 */ + ALIYUN("ALIYUN"), + + /** 腾讯云 */ + TENCENT("TENCENT"), + + /** 小诺短信 */ + XIAONUO("XIAONUO"); + + private final String value; + + AuthSmsEngineTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthStrategyWhenNoUserWithPhoneOrEmailEnum.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthStrategyWhenNoUserWithPhoneOrEmailEnum.java new file mode 100644 index 00000000..d42e70a6 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/enums/AuthStrategyWhenNoUserWithPhoneOrEmailEnum.java @@ -0,0 +1,45 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.login.enums; + +import lombok.Getter; +import vip.xiaonuo.common.exception.CommonException; + +/** + * 手机号或邮箱无对应用户时策略 + * + * @author xuyuxiang + * @date 2021/10/11 14:02 + **/ +@Getter +public enum AuthStrategyWhenNoUserWithPhoneOrEmailEnum { + + /** 不允许登录 */ + NOT_ALLOW_LOGIN("NOT_ALLOW_LOGIN"), + + /** 自动创建用户 */ + AUTO_CREATE_USER("AUTO_CREATE_USER"); + + private final String value; + + AuthStrategyWhenNoUserWithPhoneOrEmailEnum(String value) { + this.value = value; + } + + public static void validate(String value) { + boolean flag = NOT_ALLOW_LOGIN.getValue().equals(value) || AUTO_CREATE_USER.getValue().equals(value); + if(!flag) { + throw new CommonException("不支持的手机号或邮箱无对应用户时策略型:{}", value); + } + } +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthEmailValidCodeLoginParam.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthEmailValidCodeLoginParam.java new file mode 100644 index 00000000..57017cfe --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthEmailValidCodeLoginParam.java @@ -0,0 +1,48 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.login.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 邮箱验证码登录参数 + * + * @author xuyuxiang + * @date 2022/7/7 16:46 + **/ +@Getter +@Setter +public class AuthEmailValidCodeLoginParam { + + /** 邮箱 */ + @Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "邮箱不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "验证码不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "验证码请求号不能为空") + private String validCodeReqNo; + + /** 设备 */ + @Schema(description = "设备") + private String device; +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthGetEmailValidCodeParam.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthGetEmailValidCodeParam.java new file mode 100644 index 00000000..201838f6 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthGetEmailValidCodeParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.login.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 获取邮箱验证码参数 + * + * @author xuyuxiang + * @date 2022/8/25 13:45 + **/ +@Getter +@Setter +public class AuthGetEmailValidCodeParam { + + /** 邮箱 */ + @Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "邮箱不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "验证码不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "验证码请求号不能为空") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthRegisterParam.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthRegisterParam.java new file mode 100644 index 00000000..cf059a9d --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/param/AuthRegisterParam.java @@ -0,0 +1,47 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.login.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 注册参数 + * + * @author xuyuxiang + * @date 2022/7/7 16:46 + **/ +@Getter +@Setter +public class AuthRegisterParam { + + /** 账号 */ + @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "账号不能为空") + private String account; + + /** 密码 */ + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "密码不能为空") + private String password; + + /** 验证码 */ + @Schema(description = "验证码") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/AuthService.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/AuthService.java index 4a6d7ac6..4bc69a6f 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/AuthService.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/AuthService.java @@ -14,9 +14,7 @@ package vip.xiaonuo.auth.modular.login.service; import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser; import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; -import vip.xiaonuo.auth.modular.login.param.AuthAccountPasswordLoginParam; -import vip.xiaonuo.auth.modular.login.param.AuthGetPhoneValidCodeParam; -import vip.xiaonuo.auth.modular.login.param.AuthPhoneValidCodeLoginParam; +import vip.xiaonuo.auth.modular.login.param.*; import vip.xiaonuo.auth.modular.login.result.AuthPicValidCodeResult; /** @@ -36,13 +34,21 @@ public interface AuthService { AuthPicValidCodeResult getPicCaptcha(String type); /** - * 获取手机验证码 + * 获取手机登录验证码 * * @author xuyuxiang * @date 2021/12/28 14:46 **/ String getPhoneValidCode(AuthGetPhoneValidCodeParam authGetPhoneValidCodeParam, String type); + /** + * 获取邮箱登录验证码 + * + * @author xuyuxiang + * @date 2021/12/28 14:46 + **/ + String getEmailValidCode(AuthGetEmailValidCodeParam authGetEmailValidCodeParam, String type); + /** * 账号密码登录 * @@ -59,6 +65,14 @@ public interface AuthService { **/ String doLoginByPhone(AuthPhoneValidCodeLoginParam authPhoneValidCodeLoginParam, String type); + /** + * 邮箱验证码登录 + * + * @author xuyuxiang + * @date 2021/12/28 14:46 + **/ + String doLoginByEmail(AuthEmailValidCodeLoginParam authEmailValidCodeLoginParam, String type); + /** * 获取B端登录用户信息 * @@ -82,4 +96,12 @@ public interface AuthService { * @date 2022/7/9 14:44 */ String doLoginById(String userId, String device, String type); + + /** + * C端注册 + * + * @author xuyuxiang + * @date 2022/7/9 14:44 + */ + void register(AuthRegisterParam authRegisterParam, String type); } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java index 94da6e48..877d1982 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java @@ -23,6 +23,7 @@ import cn.hutool.core.util.PhoneUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -30,14 +31,15 @@ import vip.xiaonuo.auth.api.SaBaseLoginUserApi; import vip.xiaonuo.auth.core.enums.SaClientTypeEnum; import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser; import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; +import vip.xiaonuo.auth.core.util.AuthEmailFormatUtl; import vip.xiaonuo.auth.core.util.StpClientLoginUserUtil; import vip.xiaonuo.auth.core.util.StpClientUtil; import vip.xiaonuo.auth.core.util.StpLoginUserUtil; import vip.xiaonuo.auth.modular.login.enums.AuthDeviceTypeEnum; import vip.xiaonuo.auth.modular.login.enums.AuthExceptionEnum; -import vip.xiaonuo.auth.modular.login.param.AuthAccountPasswordLoginParam; -import vip.xiaonuo.auth.modular.login.param.AuthGetPhoneValidCodeParam; -import vip.xiaonuo.auth.modular.login.param.AuthPhoneValidCodeLoginParam; +import vip.xiaonuo.auth.modular.login.enums.AuthPhoneOrEmailTypeEnum; +import vip.xiaonuo.auth.modular.login.enums.AuthStrategyWhenNoUserWithPhoneOrEmailEnum; +import vip.xiaonuo.auth.modular.login.param.*; import vip.xiaonuo.auth.modular.login.result.AuthPicValidCodeResult; import vip.xiaonuo.auth.modular.login.service.AuthService; import vip.xiaonuo.common.cache.CommonCacheOperator; @@ -45,7 +47,9 @@ import vip.xiaonuo.common.consts.CacheConstant; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.util.CommonCryptogramUtil; import vip.xiaonuo.common.util.CommonEmailUtil; +import vip.xiaonuo.common.util.CommonTimeFormatUtil; import vip.xiaonuo.dev.api.DevConfigApi; +import vip.xiaonuo.dev.api.DevEmailApi; import vip.xiaonuo.dev.api.DevSmsApi; import java.util.List; @@ -60,10 +64,82 @@ import java.util.stream.Collectors; @Service public class AuthServiceImpl implements AuthService { - private static final String SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_OPEN"; + /** B端验证码是否开启(适用图片验证码) */ + private static final String SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_B"; + /** C端验证码是否开启(适用图片验证码) */ + private static final String SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_C"; + + /** B端验证码失效时间(适用图片验证码和短信验证码,单位:分钟,默认5分钟有效) */ + private static final String SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B"; + + /** C端验证码失效时间(适用图片验证码和短信验证码,单位:分钟,默认5分钟有效) */ + private static final String SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C"; + + /** B端登录验证码短信消息模板编码 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_B"; + + /** C端登录验证码短信消息模板编码 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_C"; + + /** B端登录验证码邮件消息模板内容 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_B"; + + /** C端登录验证码邮件消息模板内容 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_C"; + + /** B端连续登录失败持续时间(即N分钟内连续登录失败,单位:分钟) */ + private static final String SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_B_KEY = "SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_B"; + + /** C端连续登录失败持续时间(即N分钟内连续登录失败,单位:分钟) */ + private static final String SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_C_KEY = "SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_C"; + + /** B端连续登录失败次数(即指定分钟内连续登录失败N次) */ + private static final String SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_B_KEY = "SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_B"; + + /** C端连续登录失败次数(即指定分钟内连续登录失败N次) */ + private static final String SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_C_KEY = "SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_C"; + + /** B端连续登录失败锁定时间(即指定分钟内连续登录失败指定次数,锁定N分钟,单位:分钟) */ + private static final String SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_B_KEY = "SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_B"; + + /** C端连续登录失败锁定时间(即指定分钟内连续登录失败指定次数,锁定N分钟,单位:分钟) */ + private static final String SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_C_KEY = "SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_C"; + + /** B端手机号登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B"; + + /** C端手机号登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C"; + + /** B端邮箱登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B"; + + /** C端邮箱登录是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C"; + + /** B端手机号无对应用户时策略 */ + private static final String SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_B_KEY = "SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_B"; + + /** C端手机号无对应用户时策略 */ + private static final String SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_C_KEY = "SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_C"; + + /** B端邮箱无对应用户时策略 */ + private static final String SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_B_KEY = "SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_B"; + + /** C端邮箱无对应用户时策略 */ + private static final String SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_C_KEY = "SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_C"; + + /** B端注册是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B"; + + /** C端注册是否开启 */ + private static final String SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C"; + + /** 验证码缓存前缀 */ private static final String AUTH_VALID_CODE_CACHE_KEY = "auth-validCode:"; + /** 失败次数缓存前缀 */ private static final String LOGIN_ERROR_TIMES_KEY_PREFIX = "login-error-times:"; @Resource(name = "loginUserApi") @@ -78,6 +154,9 @@ public class AuthServiceImpl implements AuthService { @Resource private DevSmsApi devSmsApi; + @Resource + private DevEmailApi devEmailApi; + @Resource private CommonCacheOperator commonCacheOperator; @@ -97,13 +176,17 @@ public class AuthServiceImpl implements AuthService { authPicValidCodeResult.setValidCodeBase64(validCodeBase64); // 将请求号返回前端 authPicValidCodeResult.setValidCodeReqNo(validCodeReqNo); - // 将请求号作为key,验证码的值作为value放到redis,用于校验,5分钟有效 - commonCacheOperator.put(AUTH_VALID_CODE_CACHE_KEY + validCodeReqNo, validCode, 5 * 60); + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(type); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(AUTH_VALID_CODE_CACHE_KEY + validCodeReqNo, validCode, validCodeExpiredDuration); return authPicValidCodeResult; } @Override public String getPhoneValidCode(AuthGetPhoneValidCodeParam authGetPhoneValidCodeParam, String type) { + // 校验是否允许手机号登录 + this.checkAllowPhoneLoginFlag(type); // 手机号 String phone = authGetPhoneValidCodeParam.getPhone(); // 验证码 @@ -111,26 +194,123 @@ public class AuthServiceImpl implements AuthService { // 验证码请求号 String validCodeReqNo = authGetPhoneValidCodeParam.getValidCodeReqNo(); // 校验参数 - validPhoneValidCodeParam(null, validCode, validCodeReqNo, type); + validPhoneOrEmailValidCodeParam(null, AuthPhoneOrEmailTypeEnum.PHONE.getValue(), validCode, validCodeReqNo, type); // 生成手机验证码的值,随机6为数字 String phoneValidCode = RandomUtil.randomNumbers(6); // 生成手机验证码的请求号 String phoneValidCodeReqNo = IdWorker.getIdStr(); - - // TODO 使用阿里云执行发送验证码,将验证码作为短信内容的参数变量放入, - // TODO 签名不传则使用系统默认配置的签名,支持传入多个参数,示例:{"name":"张三","number":"15038****76"} - //devSmsApi.sendSmsAliyun(phone, null, "验证码模板号", JSONUtil.toJsonStr(JSONUtil.createObj().set("validCode", phoneValidCode))); - - // TODO 使用腾讯云执行发送验证码,将验证码作为短信内容的参数变量放入, - // TODO sdkAppId和签名不传则使用系统默认配置的sdkAppId和签名,支持传入多个参数,逗号拼接,示例:"张三,15038****76,进行中" - devSmsApi.sendSmsTencent("sdkAppId", phone, "签名", "模板编码", phoneValidCode); - - // 将请求号作为key,验证码的值作为value放到redis,用于校验,5分钟有效 - commonCacheOperator.put(AUTH_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, 5 * 60); + // 登录验证码短信消息模板编码 + String smsTemplateCode; + if(SaClientTypeEnum.B.getValue().equals(type)) { + smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_B_KEY); + } else { + smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_C_KEY); + } + if(ObjectUtil.isEmpty(smsTemplateCode)){ + throw new CommonException("请联系管理员配置{}端登录验证码短信消息模板编码", type); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(type); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("validCode", phoneValidCode).set("validTime", validCodeExpiredDuration/60); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(AUTH_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, validCodeExpiredDuration); // 返回请求号 return phoneValidCodeReqNo; } + /** + * 校验是否允许手机号登录 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private void checkAllowPhoneLoginFlag(String type) { + // 是否允许手机号登录 + String allowPhoneLoginFlag; + if(SaClientTypeEnum.B.getValue().equals(type)) { + allowPhoneLoginFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B_KEY); + } else { + allowPhoneLoginFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C_KEY); + } + if(ObjectUtil.isNotEmpty(allowPhoneLoginFlag)) { + if(!Convert.toBool(allowPhoneLoginFlag)) { + throw new CommonException("管理员未开启手机号登录"); + } + } + } + + @Override + public String getEmailValidCode(AuthGetEmailValidCodeParam authGetEmailValidCodeParam, String type) { + // 校验是否允许邮箱登录 + this.checkAllowEmailLoginFlag(type); + // 邮箱 */ + String email = authGetEmailValidCodeParam.getEmail(); + // 验证码 + String validCode = authGetEmailValidCodeParam.getValidCode(); + // 验证码请求号 + String validCodeReqNo = authGetEmailValidCodeParam.getValidCodeReqNo(); + // 校验参数 + validPhoneOrEmailValidCodeParam(null, AuthPhoneOrEmailTypeEnum.EMAIL.getValue(), validCode, validCodeReqNo, type); + // 生成邮箱验证码的值,随机6为数字 + String emailValidCode = RandomUtil.randomNumbers(6); + // 生成邮箱验证码的请求号 + String emailValidCodeReqNo = IdWorker.getIdStr(); + // 登录验证码邮件消息模板内容 + String emailTemplateContent; + if(SaClientTypeEnum.B.getValue().equals(type)) { + emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_B_KEY); + } else { + emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_C_KEY); + } + if(ObjectUtil.isEmpty(emailTemplateContent)){ + throw new CommonException("请联系管理员配置{}端登录验证码邮件消息模板内容", type); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(type); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("validCode", emailValidCode).set("validTime", validCodeExpiredDuration/60); + // 获取格式化后的主题 + String subject = AuthEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = AuthEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(AUTH_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, validCodeExpiredDuration); + // 返回请求号 + return emailValidCodeReqNo; + } + + /** + * 校验是否允许邮箱登录 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private void checkAllowEmailLoginFlag(String type) { + // 是否允许邮箱登录 + String allowEmailLoginFlag; + if(SaClientTypeEnum.B.getValue().equals(type)) { + allowEmailLoginFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B_KEY); + } else { + allowEmailLoginFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C_KEY); + } + if(ObjectUtil.isNotEmpty(allowEmailLoginFlag)) { + if(!Convert.toBool(allowEmailLoginFlag)) { + throw new CommonException("管理员未开启邮箱登录"); + } + } + } + /** * 校验验证码方法 * @@ -141,8 +321,10 @@ public class AuthServiceImpl implements AuthService { // 依据请求号,取出缓存中的验证码进行校验 Object existValidCode; if(ObjectUtil.isEmpty(phoneOrEmail)) { + // 图形验证码 existValidCode = commonCacheOperator.get(AUTH_VALID_CODE_CACHE_KEY + validCodeReqNo); } else { + // 手机或者邮箱验证码 existValidCode = commonCacheOperator.get(AUTH_VALID_CODE_CACHE_KEY + phoneOrEmail + StrUtil.UNDERLINE + validCodeReqNo); } // 为空则直接验证码错误 @@ -151,8 +333,10 @@ public class AuthServiceImpl implements AuthService { } // 移除该验证码 if(ObjectUtil.isEmpty(phoneOrEmail)) { + // 图形验证码 commonCacheOperator.remove(AUTH_VALID_CODE_CACHE_KEY + validCodeReqNo); } else { + // 手机或者邮箱验证码 commonCacheOperator.remove(AUTH_VALID_CODE_CACHE_KEY + phoneOrEmail + StrUtil.UNDERLINE + validCodeReqNo); } // 不一致则直接验证码错误 @@ -167,28 +351,59 @@ public class AuthServiceImpl implements AuthService { * @author xuyuxiang * @date 2022/8/25 14:29 **/ - private void validPhoneValidCodeParam(String phoneOrEmail, String validCode, String validCodeReqNo, String type) { + private String validPhoneOrEmailValidCodeParam(String phoneOrEmail, String phoneOrEmailType, String validCode, + String validCodeReqNo, String type) { // 验证码正确则校验手机号格式 if(ObjectUtil.isEmpty(phoneOrEmail)) { - // 执行校验验证码 - validValidCode(null, validCode, validCodeReqNo); - } else { - if(!PhoneUtil.isMobile(phoneOrEmail) && !CommonEmailUtil.isEmail(phoneOrEmail)) { - throw new CommonException(AuthExceptionEnum.PHONE_FORMAT_ERROR.getValue()); - } - // 执行校验验证码 - validValidCode(phoneOrEmail, validCode, validCodeReqNo); - - // 根据手机号获取用户信息,判断用户是否存在,根据B端或C端判断 + // 根据手机号或者邮箱获取用户信息,判断用户是否存在,根据B端或C端判断 if(SaClientTypeEnum.B.getValue().equals(type)) { - if(ObjectUtil.isEmpty(loginUserApi.getUserByPhone(phoneOrEmail))) { - throw new CommonException(AuthExceptionEnum.PHONE_ERROR.getValue()); + if(phoneOrEmailType.equals(AuthPhoneOrEmailTypeEnum.PHONE.getValue())) { + SaBaseLoginUser saBaseLoginUser = loginUserApi.getUserByPhone(phoneOrEmail); + if(ObjectUtil.isEmpty(saBaseLoginUser)) { + // B端手机号无对应用户时策略 + return devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_B_KEY); + } + } else { + SaBaseLoginUser saBaseLoginUser = loginUserApi.getUserByEmail(phoneOrEmail); + if(ObjectUtil.isEmpty(saBaseLoginUser)) { + // B端邮箱无对应用户时策略 + return devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_B_KEY); + } } } else { - if(ObjectUtil.isEmpty(clientLoginUserApi.getClientUserByPhone(phoneOrEmail))) { - throw new CommonException(AuthExceptionEnum.PHONE_ERROR.getValue()); + if(phoneOrEmailType.equals(AuthPhoneOrEmailTypeEnum.PHONE.getValue())) { + SaBaseClientLoginUser saBaseClientLoginUser = clientLoginUserApi.getClientUserByPhone(phoneOrEmail); + if(ObjectUtil.isEmpty(saBaseClientLoginUser)) { + // C端手机号无对应用户时策略 + return devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_C_KEY); + } + } else { + SaBaseClientLoginUser saBaseClientLoginUser = clientLoginUserApi.getClientUserByEmail(phoneOrEmail); + if(ObjectUtil.isEmpty(saBaseClientLoginUser)) { + // BC端邮箱无对应用户时策略 + return devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_C_KEY); + } } } + // 执行校验图形验证码 + validValidCode(null, validCode, validCodeReqNo); + // 返回空值 + return null; + } else { + AuthPhoneOrEmailTypeEnum.validate(phoneOrEmailType); + if(phoneOrEmailType.equals(AuthPhoneOrEmailTypeEnum.PHONE.getValue())) { + if(!PhoneUtil.isMobile(phoneOrEmail)) { + throw new CommonException(AuthExceptionEnum.PHONE_FORMAT_ERROR.getValue()); + } + } else { + if(CommonEmailUtil.isNotEmail(phoneOrEmail)) { + throw new CommonException(AuthExceptionEnum.PHONE_FORMAT_ERROR.getValue()); + } + } + // 执行校验手机或者邮箱验证码 + validValidCode(phoneOrEmail, validCode, validCodeReqNo); + // 返回空值 + return null; } } @@ -209,7 +424,12 @@ public class AuthServiceImpl implements AuthService { AuthDeviceTypeEnum.validate(device); } // 校验验证码 - String defaultCaptchaOpen = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_KEY); + String defaultCaptchaOpen; + if(SaClientTypeEnum.B.getValue().equals(type)) { + defaultCaptchaOpen = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_B_KEY); + } else { + defaultCaptchaOpen = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_C_KEY); + } if(ObjectUtil.isNotEmpty(defaultCaptchaOpen)) { if(Convert.toBool(defaultCaptchaOpen)) { // 获取验证码 @@ -224,7 +444,7 @@ public class AuthServiceImpl implements AuthService { if(ObjectUtil.isEmpty(validCodeReqNo)) { throw new CommonException(AuthExceptionEnum.VALID_CODE_REQ_NO_EMPTY.getValue()); } - // 执行校验验证码 + // 执行校验图形验证码 validValidCode(null, validCode, validCodeReqNo); } } @@ -240,24 +460,24 @@ public class AuthServiceImpl implements AuthService { if(SaClientTypeEnum.B.getValue().equals(type)) { SaBaseLoginUser saBaseLoginUser = loginUserApi.getUserByAccount(account); if(ObjectUtil.isEmpty(saBaseLoginUser)) { + // 提示账号错误 throw new CommonException(AuthExceptionEnum.ACCOUNT_ERROR.getValue()); } if (!saBaseLoginUser.getPassword().equals(passwordHash)) { - // 记录登录次数 和 过期时间 - saveLoginTimes(account); - throw new CommonException(AuthExceptionEnum.PWD_ERROR.getValue()); + // 密码错误,处理剩余次数提示信息 + handleRemainingTimes(account, AuthExceptionEnum.PWD_ERROR.getValue(), type); } - // 删除redis 中的key - clearLoginErrorTimes(account); // 执行B端登录 return execLoginB(saBaseLoginUser, device); } else { SaBaseClientLoginUser saBaseClientLoginUser = clientLoginUserApi.getClientUserByAccount(account); if(ObjectUtil.isEmpty(saBaseClientLoginUser)) { + // 提示账号错误 throw new CommonException(AuthExceptionEnum.ACCOUNT_ERROR.getValue()); } if (!saBaseClientLoginUser.getPassword().equals(passwordHash)) { - throw new CommonException(AuthExceptionEnum.PWD_ERROR.getValue()); + // 密码错误,处理剩余次数提示信息 + handleRemainingTimes(account, AuthExceptionEnum.PWD_ERROR.getValue(), type); } // 执行C端登录 return execLoginC(saBaseClientLoginUser, device); @@ -266,10 +486,14 @@ public class AuthServiceImpl implements AuthService { @Override public String doLoginByPhone(AuthPhoneValidCodeLoginParam authPhoneValidCodeLoginParam, String type) { + // 校验是否允许手机号登录 + this.checkAllowPhoneLoginFlag(type); // 手机号 String phone = authPhoneValidCodeLoginParam.getPhone(); - // 校验参数 - validPhoneValidCodeParam(phone, authPhoneValidCodeLoginParam.getValidCode(), authPhoneValidCodeLoginParam.getValidCodeReqNo(), type); + // 校验参数,返回手机号无对应用户时的策略 + String strategyWhenNoUserWithPhoneOrEmail = validPhoneOrEmailValidCodeParam(phone, + AuthPhoneOrEmailTypeEnum.PHONE.getValue(), authPhoneValidCodeLoginParam.getValidCode(), + authPhoneValidCodeLoginParam.getValidCodeReqNo(), type); // 设备 String device = authPhoneValidCodeLoginParam.getDevice(); // 默认指定为PC,如在小程序跟移动端的情况下,自行指定即可 @@ -282,20 +506,115 @@ public class AuthServiceImpl implements AuthService { if(SaClientTypeEnum.B.getValue().equals(type)) { SaBaseLoginUser saBaseLoginUser = loginUserApi.getUserByPhone(phone); if(ObjectUtil.isEmpty(saBaseLoginUser)) { - throw new CommonException(AuthExceptionEnum.ACCOUNT_ERROR.getValue()); + // 判断手机号无对应用户时的策略,如果为空则直接抛出异常 + if(ObjectUtil.isEmpty(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("手机号码:{}不存在对应用户", phone); + } else { + // 如果不允许登录,则抛出异常 + if(AuthStrategyWhenNoUserWithPhoneOrEmailEnum.NOT_ALLOW_LOGIN.getValue().equals(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("手机号码:{}不存在对应用户", phone); + } else { + // 根据手机号自动创建B端用户 + saBaseLoginUser = loginUserApi.createUserWithPhone(phone); + } + } } // 执行B端登录 return execLoginB(saBaseLoginUser, device); } else { SaBaseClientLoginUser saBaseClientLoginUser = clientLoginUserApi.getClientUserByPhone(phone); if(ObjectUtil.isEmpty(saBaseClientLoginUser)) { - throw new CommonException(AuthExceptionEnum.ACCOUNT_ERROR.getValue()); + // 判断手机号无对应用户时的策略,如果为空则直接抛出异常 + if(ObjectUtil.isEmpty(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("手机号码:{}不存在对应用户", phone); + } else { + // 如果不允许登录,则抛出异常 + if(AuthStrategyWhenNoUserWithPhoneOrEmailEnum.NOT_ALLOW_LOGIN.getValue().equals(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("手机号码:{}不存在对应用户", phone); + } else { + // 根据手机号自动创建C端用户 + saBaseClientLoginUser = clientLoginUserApi.createClientUserWithPhone(phone); + } + } } // 执行C端登录 return execLoginC(saBaseClientLoginUser, device); } } + @Override + public String doLoginByEmail(AuthEmailValidCodeLoginParam authEmailValidCodeLoginParam, String type) { + // 校验是否允许邮箱登录 + this.checkAllowEmailLoginFlag(type); + // 邮箱 + String email = authEmailValidCodeLoginParam.getEmail(); + // 校验参数,返回邮箱无对应用户时的策略 + String strategyWhenNoUserWithPhoneOrEmail = validPhoneOrEmailValidCodeParam(email, + AuthPhoneOrEmailTypeEnum.EMAIL.getValue(), authEmailValidCodeLoginParam.getValidCode(), + authEmailValidCodeLoginParam.getValidCodeReqNo(), type); + // 设备 + String device = authEmailValidCodeLoginParam.getDevice(); + // 默认指定为PC,如在小程序跟移动端的情况下,自行指定即可 + if(ObjectUtil.isEmpty(device)) { + device = AuthDeviceTypeEnum.PC.getValue(); + } else { + AuthDeviceTypeEnum.validate(device); + } + // 根据邮箱获取用户信息,根据B端或C端判断 + if(SaClientTypeEnum.B.getValue().equals(type)) { + SaBaseLoginUser saBaseLoginUser = loginUserApi.getUserByEmail(email); + if(ObjectUtil.isEmpty(saBaseLoginUser)) { + // 判断邮箱无对应用户时的策略,如果为空则直接抛出异常 + if(ObjectUtil.isEmpty(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("邮箱:{}不存在对应用户", email); + } else { + // 如果不允许登录,则抛出异常 + if(AuthStrategyWhenNoUserWithPhoneOrEmailEnum.NOT_ALLOW_LOGIN.getValue().equals(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("邮箱:{}不存在对应用户", email); + } else { + // 根据邮箱自动创建B端用户 + saBaseLoginUser = loginUserApi.createUserWithEmail(email); + } + } + } + // 执行B端登录 + return execLoginB(saBaseLoginUser, device); + } else { + SaBaseClientLoginUser saBaseClientLoginUser = clientLoginUserApi.getClientUserByEmail(email); + if(ObjectUtil.isEmpty(saBaseClientLoginUser)) { + // 判断邮箱无对应用户时的策略,如果为空则直接抛出异常 + if(ObjectUtil.isEmpty(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("邮箱:{}不存在对应用户", email); + } else { + // 如果不允许登录,则抛出异常 + if(AuthStrategyWhenNoUserWithPhoneOrEmailEnum.NOT_ALLOW_LOGIN.getValue().equals(strategyWhenNoUserWithPhoneOrEmail)) { + throw new CommonException("邮箱:{}不存在对应用户", email); + } else { + // 根据邮箱自动创建C端用户 + saBaseClientLoginUser = clientLoginUserApi.createClientUserWithEmail(email); + } + } + } + // 执行C端登录 + return execLoginC(saBaseClientLoginUser, device); + } + } + + /** + * 处理剩余次数提示信息 + */ + private void handleRemainingTimes(String account, String errorMessage, String type) { + // 记录登录次数 和 过期时间 + int remainingTimes = saveLoginTimes(account, type); + if(remainingTimes == 0) { + // 此时已封禁,返回提示语 + isDisableTime(account); + } else { + // 提示错误 + throw new CommonException(errorMessage + ",您还可以尝试【" + remainingTimes + "】次"); + } + } + /** * 是否封禁状态 * 如果被封禁了,执行以下逻辑,返回前端还需等待的时间 @@ -304,33 +623,81 @@ public class AuthServiceImpl implements AuthService { // disableTime = -2表示未被封禁 long disableTime = StpUtil.getDisableTime(userAccount); if (disableTime > 0) { - if (disableTime > 60) { - throw new CommonException(userAccount + "账号已被封禁, 请再"+ disableTime/60+ "分钟后重新尝试登录!!"); - } - throw new CommonException(userAccount + "账号已被封禁, 请再"+ disableTime+ "秒后重新尝试登录!!"); + String formatTime = CommonTimeFormatUtil.formatSeconds(disableTime); + throw new CommonException("账号" + userAccount + "已被封禁, 请在"+ formatTime+ "后重新尝试登录!"); } } - // redis中保存登录错误次数 - private void saveLoginTimes(String userAccount){ - String loginErrorKey = LOGIN_ERROR_TIMES_KEY_PREFIX + userAccount; + /** + * redis中保存登录错误次数 + */ + private int saveLoginTimes(String userAccount, String type){ + // 获取连续登录失败持续时间 + String configContinuousLoginFailDuration; + // 获取连续登录失败次数 + String configContinuousLoginFailTimes; + // 获取连续登录失败锁定时间 + String configContinuousLoginFailLockDuration; + if(SaClientTypeEnum.B.getValue().equals(type)) { + configContinuousLoginFailDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_B_KEY); + configContinuousLoginFailTimes = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_B_KEY); + configContinuousLoginFailLockDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_B_KEY); + } else { + configContinuousLoginFailDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_C_KEY); + configContinuousLoginFailTimes = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_C_KEY); + configContinuousLoginFailLockDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_C_KEY); + } + // 连续登录失败持续时间默认5分钟 + long continuousLoginFailDuration = 5 * 60; + if(ObjectUtil.isNotEmpty(configContinuousLoginFailDuration)){ + // 配置了则使用配置的失效时间 + continuousLoginFailDuration = Convert.toLong(configContinuousLoginFailDuration) * 60; + } + + // 连续登录失败次数默认5次 + int continuousLoginFailTimes = 5; + if(ObjectUtil.isNotEmpty(configContinuousLoginFailTimes)){ + // 配置了则使用配置的失效时间 + continuousLoginFailTimes = Convert.toInt(configContinuousLoginFailTimes); + } + + // 连续登录失败锁定时间默认5分钟 + long continuousLoginFailLockDuration = 5 * 60; + if(ObjectUtil.isNotEmpty(configContinuousLoginFailLockDuration)){ + // 配置了则使用配置的失效时间 + continuousLoginFailLockDuration = Convert.toLong(configContinuousLoginFailLockDuration) * 60; + } + // 获取登录失败次数缓存键 + String loginErrorKey = LOGIN_ERROR_TIMES_KEY_PREFIX + ":" + userAccount; + // 获取登录失败次数缓存值 Integer number = (Integer) commonCacheOperator.get(loginErrorKey); if (number == null) { - // 如果redis中没有保存,代表失败第一次 - number = 2; - commonCacheOperator.put(loginErrorKey, number,5 * 60); - return; + // 如果redis中没有保存,代表失败第一次,如果配置的值为1次 + if(continuousLoginFailTimes == 1) { + // 直接进入isDisableTime方法,返回用户还需等待时间 + StpUtil.disable(userAccount, continuousLoginFailLockDuration); + // 删除redis 中的key + clearLoginErrorTimes(userAccount); + return 0; + } else { + // 否则失败次数为2 + number = 2; + commonCacheOperator.put(loginErrorKey, number, continuousLoginFailDuration); + return continuousLoginFailTimes - number + 1; + } + } else { + if (number < continuousLoginFailTimes) { + number++; + commonCacheOperator.put(loginErrorKey, number, continuousLoginFailDuration); + return continuousLoginFailTimes - number + 1; + } else { + // 第N次封禁账号,第N+1次进入isDisableTime方法,返回用户还需等待时间 + StpUtil.disable(userAccount, continuousLoginFailLockDuration); + // 删除redis 中的key + clearLoginErrorTimes(userAccount); + return 0; + } } - if (number < 5) { - number++; - commonCacheOperator.put(loginErrorKey, number,5 * 60); - return; - } - // 第五次封禁账号,第六次进入isDisableTime方法,返回用户还需等待时间 - StpUtil.disable(userAccount, 5 * 60); - // 删除redis 中的key - clearLoginErrorTimes(userAccount); - } /** @@ -338,7 +705,8 @@ public class AuthServiceImpl implements AuthService { * @param userAccount 账号 */ private void clearLoginErrorTimes(String userAccount) { - String loginErrorKey = LOGIN_ERROR_TIMES_KEY_PREFIX + userAccount; + // 获取登录失败次数缓存键 + String loginErrorKey = LOGIN_ERROR_TIMES_KEY_PREFIX + ":" + userAccount; // 删除redis中的key commonCacheOperator.remove(loginErrorKey); } @@ -466,11 +834,11 @@ public class AuthServiceImpl implements AuthService { // 填充B端用户信息并更新缓存 fillSaBaseLoginUserAndUpdateCache(saBaseLoginUser); // 去掉密码 - saBaseLoginUser.setPassword(null); + saBaseLoginUser.setPassword("******"); // 去掉权限码 - saBaseLoginUser.setPermissionCodeList(null); + saBaseLoginUser.setPermissionCodeList(CollectionUtil.newArrayList()); // 去掉数据范围 - saBaseLoginUser.setDataScopeList(null); + saBaseLoginUser.setDataScopeList(CollectionUtil.newArrayList()); // 返回 return saBaseLoginUser; } @@ -490,11 +858,11 @@ public class AuthServiceImpl implements AuthService { // 填充C端用户信息并更新缓存 fillSaBaseClientLoginUserAndUpdateCache(saBaseClientLoginUser); // 去掉密码 - saBaseClientLoginUser.setPassword(null); + saBaseClientLoginUser.setPassword("******"); // 去掉权限码 - saBaseClientLoginUser.setPermissionCodeList(null); + saBaseClientLoginUser.setPermissionCodeList(CollectionUtil.newArrayList()); // 去掉数据范围 - saBaseClientLoginUser.setDataScopeList(null); + saBaseClientLoginUser.setDataScopeList(CollectionUtil.newArrayList()); // 返回 return saBaseClientLoginUser; } @@ -518,4 +886,93 @@ public class AuthServiceImpl implements AuthService { return execLoginC(saBaseClientLoginUser, device); } } + + @Override + public void register(AuthRegisterParam authRegisterParam, String type) { + // 校验是否允许注册 + this.checkAllowRegisterFlag(type); + // 获取账号 + String account = authRegisterParam.getAccount(); + // 获取密码 + String password = authRegisterParam.getPassword(); + // 校验验证码 + String defaultCaptchaOpen; + if(SaClientTypeEnum.B.getValue().equals(type)) { + defaultCaptchaOpen = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_B_KEY); + } else { + defaultCaptchaOpen = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_C_KEY); + } + if(ObjectUtil.isNotEmpty(defaultCaptchaOpen)) { + if(Convert.toBool(defaultCaptchaOpen)) { + // 获取验证码 + String validCode = authRegisterParam.getValidCode(); + // 获取验证码请求号 + String validCodeReqNo = authRegisterParam.getValidCodeReqNo(); + // 开启验证码则必须传入验证码 + if(ObjectUtil.isEmpty(validCode)) { + throw new CommonException(AuthExceptionEnum.VALID_CODE_EMPTY.getValue()); + } + // 开启验证码则必须传入验证码请求号 + if(ObjectUtil.isEmpty(validCodeReqNo)) { + throw new CommonException(AuthExceptionEnum.VALID_CODE_REQ_NO_EMPTY.getValue()); + } + // 执行校验图形验证码 + validValidCode(null, validCode, validCodeReqNo); + } + } + // SM2解密前端传来的密码 + String passwordDecrypt = CommonCryptogramUtil.doSm2Decrypt(password); + // 根据账号获取用户信息,根据B端或C端判断 + if(SaClientTypeEnum.B.getValue().equals(type)) { + clientLoginUserApi.doRegister(account, passwordDecrypt); + } else { + loginUserApi.doRegister(account, passwordDecrypt); + } + } + + /** + * 校验是否开启注册 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private void checkAllowRegisterFlag(String type) { + // 是否允许注册 + String allowRegisterFlag; + if(SaClientTypeEnum.B.getValue().equals(type)) { + allowRegisterFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B_KEY); + } else { + allowRegisterFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C_KEY); + } + if(ObjectUtil.isNotEmpty(allowRegisterFlag)) { + if(!Convert.toBool(allowRegisterFlag)) { + throw new CommonException("管理员未开启注册"); + } + } + } + + /** + * 获取验证码失效时间(单位:秒) + * + * @author xuyuxiang + * @date 2025/3/21 20:25 + **/ + private long getValidCodeExpiredDuration(String type) { + // 默认5分钟 + int defaultExpiredTime = 5; + // 获取配置验证码失效时间(单位:分钟) + String configCaptchaExpiredDuration; + if(SaClientTypeEnum.B.getValue().equals(type)) { + configCaptchaExpiredDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B_KEY); + } else { + configCaptchaExpiredDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C_KEY); + } + // 判断是否为空 + if(ObjectUtil.isNotEmpty(configCaptchaExpiredDuration)){ + // 配置了则使用配置的失效时间 + defaultExpiredTime = Convert.toInt(configCaptchaExpiredDuration); + } + // 转为秒 + return defaultExpiredTime * 60L; + } } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/monitor/controller/AuthSessionController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/monitor/controller/AuthSessionController.java index 8374e3d1..fc189930 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/monitor/controller/AuthSessionController.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/monitor/controller/AuthSessionController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.auth.modular.monitor.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.auth.modular.monitor.service.AuthSessionService; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/6/24 15:20 **/ @Tag(name = "会话治理控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 3) @RestController @Validated public class AuthSessionController { @@ -54,6 +57,7 @@ public class AuthSessionController { * @author xuyuxiang * @date 2022/6/24 22:28 */ + @ApiOperationSupport(order = 1) @Operation(summary = "会话统计") @GetMapping("/auth/session/analysis") public CommonResult analysis() { @@ -66,6 +70,7 @@ public class AuthSessionController { * @author xuyuxiang * @date 2022/6/24 22:28 */ + @ApiOperationSupport(order = 2) @Operation(summary = "查询B端会话") @GetMapping("/auth/session/b/page") public CommonResult> pageForB(AuthSessionPageParam authSessionPageParam) { @@ -78,6 +83,7 @@ public class AuthSessionController { * @author xuyuxiang * @date 2022/6/24 22:28 */ + @ApiOperationSupport(order = 3) @Operation(summary = "查询C端会话") @GetMapping("/auth/session/c/page") public CommonResult> pageForC(AuthSessionPageParam authSessionPageParam) { @@ -90,11 +96,12 @@ public class AuthSessionController { * @author xuyuxiang * @date 2021/10/12 10:25 **/ + @ApiOperationSupport(order = 4) @Operation(summary = "强退B端会话") @CommonLog("强退B端会话") @PostMapping("/auth/session/b/exit") public CommonResult exitSessionForB(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List authExitSessionParamList) { + List authExitSessionParamList) { authSessionService.exitSessionForB(authExitSessionParamList); return CommonResult.ok(); } @@ -105,11 +112,12 @@ public class AuthSessionController { * @author xuyuxiang * @date 2021/10/12 10:25 **/ + @ApiOperationSupport(order = 5) @Operation(summary = "强退C端会话") @CommonLog("强退C端会话") @PostMapping("/auth/session/c/exit") public CommonResult exitSessionForC(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List authExitSessionParamList) { + List authExitSessionParamList) { authSessionService.exitSessionForC(authExitSessionParamList); return CommonResult.ok(); } @@ -120,6 +128,7 @@ public class AuthSessionController { * @author xuyuxiang * @date 2021/10/12 10:25 **/ + @ApiOperationSupport(order = 6) @Operation(summary = "强退B端token") @CommonLog("强退B端token") @PostMapping("/auth/token/b/exit") @@ -135,6 +144,7 @@ public class AuthSessionController { * @author xuyuxiang * @date 2021/10/12 10:25 **/ + @ApiOperationSupport(order = 7) @Operation(summary = "强退C端token") @CommonLog("强退C端token") @PostMapping("/auth/token/c/exit") diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/controller/AuthSsoController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/controller/AuthSsoController.java new file mode 100644 index 00000000..b5e1e5e7 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/controller/AuthSsoController.java @@ -0,0 +1,58 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.sso.controller; + +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import vip.xiaonuo.auth.core.enums.SaClientTypeEnum; +import vip.xiaonuo.auth.modular.sso.param.AuthSsoTicketLoginParam; +import vip.xiaonuo.auth.modular.sso.service.AuthSsoService; +import vip.xiaonuo.common.pojo.CommonResult; + +import javax.validation.Valid; + +/** + * 单点登录控制器 + * + * @author xuyuxiang + * @date 2022/8/30 9:20 + **/ +@Tag(name = "单点登录控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 4) +@RestController +@Validated +public class AuthSsoController { + + @Resource + private AuthSsoService authSsoService; + + /** + * 根据ticket执行单点登录 + * + * @author xuyuxiang + * @date 2021/10/15 13:12 + **/ + @ApiOperationSupport(order = 1) + @Operation(summary = "根据ticket执行单点登录") + @PostMapping("/auth/sso/doLogin") + public CommonResult doLogin(@RequestBody @Valid AuthSsoTicketLoginParam authAccountPasswordLoginParam) { + return CommonResult.data(authSsoService.doLogin(authAccountPasswordLoginParam, SaClientTypeEnum.B.getValue())); + } +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/param/AuthSsoTicketLoginParam.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/param/AuthSsoTicketLoginParam.java new file mode 100644 index 00000000..3b652bd4 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/param/AuthSsoTicketLoginParam.java @@ -0,0 +1,38 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.sso.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * ticket单点登录登录参数 + * + * @author xuyuxiang + * @date 2022/7/7 16:46 + **/ +@Getter +@Setter +public class AuthSsoTicketLoginParam { + + /** ticket */ + @Schema(description = "ticket", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "ticket不能为空") + private String ticket; + + /** 设备 */ + @Schema(description = "设备") + private String device; +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/AuthSsoService.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/AuthSsoService.java new file mode 100644 index 00000000..96bbfb58 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/AuthSsoService.java @@ -0,0 +1,32 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.sso.service; + +import vip.xiaonuo.auth.modular.sso.param.AuthSsoTicketLoginParam; + +/** + * 单点登录Service接口 + * + * @author xuyuxiang + * @date 2022/8/30 9:20 + **/ +public interface AuthSsoService { + + /** + * 根据ticket执行单点登录 + * + * @author xuyuxiang + * @date 2022/8/30 9:36 + **/ + String doLogin(AuthSsoTicketLoginParam authAccountPasswordLoginParam, String value); +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/impl/AuthSsoServiceImpl.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/impl/AuthSsoServiceImpl.java new file mode 100644 index 00000000..bc8bf964 --- /dev/null +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/sso/service/impl/AuthSsoServiceImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.auth.modular.sso.service.impl; + +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import vip.xiaonuo.auth.modular.login.service.AuthService; +import vip.xiaonuo.auth.modular.sso.param.AuthSsoTicketLoginParam; +import vip.xiaonuo.auth.modular.sso.service.AuthSsoService; + +/** + * 单点登录Service接口实现类 + * + * @author xuyuxiang + * @date 2022/8/30 9:21 + **/ +@Service +public class AuthSsoServiceImpl implements AuthSsoService { + + @Resource + private AuthService authService; + + @Override + public String doLogin(AuthSsoTicketLoginParam authAccountPasswordLoginParam, String device) { + return null; + } +} diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/controller/AuthThirdController.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/controller/AuthThirdController.java index 35dae66d..1a20569c 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/controller/AuthThirdController.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/controller/AuthThirdController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.auth.modular.third.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import me.zhyd.oauth.model.AuthCallback; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -29,6 +30,8 @@ import vip.xiaonuo.auth.modular.third.result.AuthThirdRenderResult; import vip.xiaonuo.auth.modular.third.service.AuthThirdService; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; + /** * 第三方登录控制器 * @@ -36,6 +39,7 @@ import vip.xiaonuo.common.pojo.CommonResult; * @date 2022/7/8 16:18 **/ @Tag(name = "三方登录控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 5) @RestController @Validated public class AuthThirdController { @@ -49,6 +53,7 @@ public class AuthThirdController { * @author xuyuxiang * @date 2022/7/8 16:19 **/ + @ApiOperationSupport(order = 1) @Operation(summary = "第三方登录页面渲染") @GetMapping("/auth/third/render") public CommonResult render(@Valid AuthThirdRenderParam authThirdRenderParam) { @@ -61,6 +66,7 @@ public class AuthThirdController { * @author xuyuxiang * @date 2022/7/8 16:42 **/ + @ApiOperationSupport(order = 2) @Operation(summary = "第三方登录授权回调") @GetMapping("/auth/third/callback") public CommonResult callback(@Valid AuthThirdCallbackParam authThirdCallbackParam, AuthCallback authCallback) { @@ -73,6 +79,7 @@ public class AuthThirdController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 3) @Operation(summary = "获取三方用户分页") @GetMapping("/auth/third/page") public CommonResult> page(AuthThirdUserPageParam authThirdUserPageParam) { diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/entity/AuthThirdUser.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/entity/AuthThirdUser.java index 6c997937..ae045266 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/entity/AuthThirdUser.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/third/entity/AuthThirdUser.java @@ -45,7 +45,7 @@ public class AuthThirdUser extends CommonEntity { /** 头像 */ @Schema(description = "头像") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String avatar; /** 姓名 */ @@ -54,12 +54,12 @@ public class AuthThirdUser extends CommonEntity { /** 昵称 */ @Schema(description = "昵称") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nickname; /** 性别 */ @Schema(description = "性别") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String gender; /** 分类 */ @@ -68,6 +68,6 @@ public class AuthThirdUser extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-biz/pom.xml b/snowy-plugin/snowy-plugin-biz/pom.xml index 1984227b..a3625a67 100644 --- a/snowy-plugin/snowy-plugin-biz/pom.xml +++ b/snowy-plugin/snowy-plugin-biz/pom.xml @@ -39,4 +39,4 @@ snowy-plugin-dev-api - \ No newline at end of file + diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/core/enums/BizBuildInEnum.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/core/enums/BizBuildInEnum.java index 363c1039..513f7af1 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/core/enums/BizBuildInEnum.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/core/enums/BizBuildInEnum.java @@ -23,7 +23,9 @@ import lombok.Getter; @Getter public enum BizBuildInEnum { - /** 超管用户账号 */ + /** + * 超管用户账号 + */ BUILD_IN_USER_ACCOUNT("superAdmin", "超管"); private final String value; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/controller/BizDictController.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/controller/BizDictController.java index 24e77628..8ca6a7de 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/controller/BizDictController.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/controller/BizDictController.java @@ -15,10 +15,11 @@ package vip.xiaonuo.biz.modular.dict.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -31,6 +32,7 @@ import vip.xiaonuo.biz.modular.dict.service.BizDictService; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; import java.util.List; /** @@ -40,6 +42,7 @@ import java.util.List; * @date 2022/6/21 14:58 **/ @Tag(name = "业务字典控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 4) @RestController @Validated public class BizDictController { @@ -53,6 +56,7 @@ public class BizDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取业务字典分页") @SaCheckPermission("/biz/dict/page") @GetMapping("/biz/dict/page") @@ -66,6 +70,7 @@ public class BizDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取业务字典树") @SaCheckPermission("/biz/dict/tree") @GetMapping("/biz/dict/tree") @@ -79,6 +84,7 @@ public class BizDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 3) @Operation(summary = "获取所有字典树") @GetMapping("/biz/dict/treeAll") public CommonResult>> treeAll() { @@ -91,6 +97,7 @@ public class BizDictController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "编辑业务字典") @CommonLog("编辑业务字典") @SaCheckPermission("/biz/dict/edit") diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/entity/BizDict.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/entity/BizDict.java index b4ce95ec..624b4c2e 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/entity/BizDict.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/entity/BizDict.java @@ -57,6 +57,6 @@ public class BizDict extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/param/BizDictEditParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/param/BizDictEditParam.java index 5e7c625d..4ebcc82f 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/param/BizDictEditParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/dict/param/BizDictEditParam.java @@ -29,17 +29,17 @@ import lombok.Setter; public class BizDictEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 字典文字 */ - @Schema(description = "字典文字", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "字典文字") @NotBlank(message = "dictLabel不能为空") private String dictLabel; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/controller/BizGroupController.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/controller/BizGroupController.java index 7ec8b1dd..a02e7584 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/controller/BizGroupController.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/controller/BizGroupController.java @@ -15,23 +15,23 @@ package vip.xiaonuo.biz.modular.group.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import vip.xiaonuo.biz.modular.group.entity.BizGroup; import vip.xiaonuo.biz.modular.group.param.*; +import vip.xiaonuo.biz.modular.group.service.BizGroupService; import vip.xiaonuo.biz.modular.user.entity.BizUser; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; -import vip.xiaonuo.biz.modular.group.entity.BizGroup; -import vip.xiaonuo.biz.modular.group.service.BizGroupService; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; import java.util.List; /** diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/entity/BizGroup.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/entity/BizGroup.java index 6870cdae..db7bc1d6 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/entity/BizGroup.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/entity/BizGroup.java @@ -12,7 +12,8 @@ */ package vip.xiaonuo.biz.modular.group.entity; -import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/mapper/mapping/BizGroupMapper.xml b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/mapper/mapping/BizGroupMapper.xml index 34b35a0a..1aa500dd 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/mapper/mapping/BizGroupMapper.xml +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/mapper/mapping/BizGroupMapper.xml @@ -2,4 +2,4 @@ - \ No newline at end of file + diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupAddParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupAddParam.java index 48093c10..e5dcb445 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupAddParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupAddParam.java @@ -13,10 +13,10 @@ package vip.xiaonuo.biz.modular.group.param; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.Setter; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; /** * 用户组添加参数 diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupEditParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupEditParam.java index 9b14c16b..e812fc45 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupEditParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupEditParam.java @@ -13,10 +13,10 @@ package vip.xiaonuo.biz.modular.group.param; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.Setter; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; /** * 用户组编辑参数 diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupIdParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupIdParam.java index 7df88659..ce18a546 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupIdParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/param/BizGroupIdParam.java @@ -13,11 +13,10 @@ package vip.xiaonuo.biz.modular.group.param; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; import lombok.Setter; -import jakarta.validation.constraints.NotBlank; - /** * 用户组Id参数 * diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/service/impl/BizGroupServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/service/impl/BizGroupServiceImpl.java index a178abe8..499e78c8 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/service/impl/BizGroupServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/group/service/impl/BizGroupServiceImpl.java @@ -21,7 +21,6 @@ import cn.hutool.core.lang.tree.TreeUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -29,17 +28,18 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import vip.xiaonuo.auth.core.util.StpLoginUserUtil; +import vip.xiaonuo.biz.modular.group.entity.BizGroup; +import vip.xiaonuo.biz.modular.group.mapper.BizGroupMapper; import vip.xiaonuo.biz.modular.group.param.*; +import vip.xiaonuo.biz.modular.group.service.BizGroupService; import vip.xiaonuo.biz.modular.org.entity.BizOrg; import vip.xiaonuo.biz.modular.org.service.BizOrgService; import vip.xiaonuo.biz.modular.user.entity.BizUser; +import vip.xiaonuo.biz.modular.user.enums.BizUserStatusEnum; import vip.xiaonuo.biz.modular.user.service.BizUserService; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; -import vip.xiaonuo.biz.modular.group.entity.BizGroup; -import vip.xiaonuo.biz.modular.group.mapper.BizGroupMapper; -import vip.xiaonuo.biz.modular.group.service.BizGroupService; import vip.xiaonuo.sys.api.SysGroupApi; import java.util.List; @@ -143,32 +143,34 @@ public class BizGroupServiceImpl extends ServiceImpl i @Override public Page userSelector(BizGroupSelectorUserParam bizGroupSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + // 只查询状态为正常的 + queryWrapper.lambda().eq(BizUser::getUserStatus, BizUserStatusEnum.ENABLE.getValue()); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizUser::getOrgId, loginUserDataScope); + queryWrapper.lambda().in(BizUser::getOrgId, loginUserDataScope); } else { return new Page<>(); } // 只查询部分字段 - lambdaQueryWrapper.select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount, + queryWrapper.lambda().select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount, BizUser::getName, BizUser::getSortCode, BizUser::getGender, BizUser::getEntryDate); if (ObjectUtil.isNotEmpty(bizGroupSelectorUserParam.getOrgId())) { // 如果机构id不为空,则查询该机构及其子机构下的所有人 List childOrgIdList = CollStreamUtil.toList(bizOrgService.getChildListById(bizOrgService .getAllOrgList(), bizGroupSelectorUserParam.getOrgId(), true), BizOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(BizUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(BizUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if(ObjectUtil.isNotEmpty(bizGroupSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(BizUser::getName, bizGroupSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(BizUser::getName, bizGroupSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizUser::getSortCode); - return bizUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizUser::getSortCode); + return bizUserService.page(CommonPageRequest.defaultPage(), queryWrapper); } @Override diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java index 89cfbfaa..d87b7663 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/controller/BizOrgController.java @@ -15,10 +15,11 @@ package vip.xiaonuo.biz.modular.org.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -26,12 +27,14 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import vip.xiaonuo.biz.modular.org.entity.BizOrg; +import vip.xiaonuo.biz.modular.org.enums.BizOrgSourceFromTypeEnum; import vip.xiaonuo.biz.modular.org.param.*; import vip.xiaonuo.biz.modular.org.service.BizOrgService; import vip.xiaonuo.biz.modular.user.entity.BizUser; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +44,7 @@ import java.util.List; * @date 2022/4/24 19:55 */ @Tag(name = "机构控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 1) @RestController @Validated public class BizOrgController { @@ -54,6 +58,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取机构分页") @SaCheckPermission("/biz/org/page") @GetMapping("/biz/org/page") @@ -67,6 +72,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取机构树") @SaCheckPermission("/biz/org/tree") @GetMapping("/biz/org/tree") @@ -80,12 +86,13 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "添加机构") @CommonLog("添加机构") @SaCheckPermission("/biz/org/add") @PostMapping("/biz/org/add") public CommonResult add(@RequestBody @Valid BizOrgAddParam bizOrgAddParam) { - bizOrgService.add(bizOrgAddParam); + bizOrgService.add(bizOrgAddParam, BizOrgSourceFromTypeEnum.SYSTEM_ADD.getValue()); return CommonResult.ok(); } @@ -95,6 +102,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "编辑机构") @CommonLog("编辑机构") @SaCheckPermission("/biz/org/edit") @@ -110,6 +118,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "删除机构") @CommonLog("删除机构") @SaCheckPermission("/biz/org/delete") @@ -126,6 +135,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取机构详情") @SaCheckPermission("/biz/org/detail") @GetMapping("/biz/org/detail") @@ -141,6 +151,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取机构树选择器") @SaCheckPermission("/biz/org/orgTreeSelector") @GetMapping("/biz/org/orgTreeSelector") @@ -154,6 +165,7 @@ public class BizOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 8) @Operation(summary = "获取人员选择器") @SaCheckPermission("/biz/org/userSelector") @GetMapping("/biz/org/userSelector") diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrg.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrg.java index 727c19e9..1e3a0db7 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrg.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrg.java @@ -44,7 +44,7 @@ public class BizOrg extends CommonEntity { /** 主管id */ @Schema(description = "主管id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.SIMPLE, target = BizUser.class, fields = "name", alias = "director", ref = "directorName") private String directorId; @@ -66,6 +66,6 @@ public class BizOrg extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrgExt.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrgExt.java new file mode 100644 index 00000000..1700e092 --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/entity/BizOrgExt.java @@ -0,0 +1,46 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.org.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +/** + * 机构扩展实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("SYS_ORG_EXT") +public class BizOrgExt extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 机构id */ + @Schema(description = "机构id") + private String orgId; + + /** 来源类别 */ + @Schema(description = "来源类别") + private String sourceFromType; + +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/enums/BizOrgSourceFromTypeEnum.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/enums/BizOrgSourceFromTypeEnum.java new file mode 100644 index 00000000..679e1433 --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/enums/BizOrgSourceFromTypeEnum.java @@ -0,0 +1,37 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.org.enums; + +import lombok.Getter; + +/** + * 机构来源类型枚举 + * + * @author xuyuxiang + * @date 2022/4/21 19:56 + **/ +@Getter +public enum BizOrgSourceFromTypeEnum { + + /** 系统自建 */ + SYSTEM_ADD("SYSTEM_ADD"), + + /** 身份源 */ + ID_SOURCE("ID_SOURCE"); + + private final String value; + + BizOrgSourceFromTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/BizOrgExtMapper.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/BizOrgExtMapper.java new file mode 100644 index 00000000..7c85726b --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/BizOrgExtMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.org.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.biz.modular.org.entity.BizOrgExt; + +/** + * 机构扩展Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface BizOrgExtMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/mapping/BizOrgExtMapper.xml b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/mapping/BizOrgExtMapper.xml new file mode 100644 index 00000000..0289058a --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/mapper/mapping/BizOrgExtMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgAddParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgAddParam.java index 5377b0b1..baa7fbc5 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgAddParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgAddParam.java @@ -29,22 +29,22 @@ import lombok.Setter; public class BizOrgAddParam { /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgEditParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgEditParam.java index f967579c..bbce6e03 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgEditParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgEditParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class BizOrgEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgIdParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgIdParam.java index e6b68989..9c95cb61 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgIdParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class BizOrgIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/provider/BizOrgApiProvider.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/provider/BizOrgApiProvider.java index 2d4330db..58e89954 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/provider/BizOrgApiProvider.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/provider/BizOrgApiProvider.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Service; import vip.xiaonuo.biz.api.BizOrgApi; import vip.xiaonuo.biz.modular.org.param.BizOrgSelectorOrgListParam; import vip.xiaonuo.biz.modular.org.service.BizOrgService; + import java.util.List; /** diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgExtService.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgExtService.java new file mode 100644 index 00000000..ecc67ecd --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgExtService.java @@ -0,0 +1,33 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.org.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.biz.modular.org.entity.BizOrgExt; + +/** + * 机构扩展Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface BizOrgExtService extends IService { + + /** + * 插入扩展信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void createExtInfo(String orgId, String sourceFromType); +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgService.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgService.java index 0f0209d4..69f621ab 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgService.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/BizOrgService.java @@ -51,7 +51,7 @@ public interface BizOrgService extends IService { * @author xuyuxiang * @date 2022/4/24 20:48 */ - void add(BizOrgAddParam bizOrgAddParam); + void add(BizOrgAddParam bizOrgAddParam, String sourceFromType); /** * 编辑机构 diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgExtServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgExtServiceImpl.java new file mode 100644 index 00000000..d5478b72 --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgExtServiceImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.org.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.biz.modular.org.entity.BizOrgExt; +import vip.xiaonuo.biz.modular.org.mapper.BizOrgExtMapper; +import vip.xiaonuo.biz.modular.org.service.BizOrgExtService; + +/** + * 机构扩展Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class BizOrgExtServiceImpl extends ServiceImpl implements BizOrgExtService { + + @Override + public void createExtInfo(String orgId, String sourceFromType) { + BizOrgExt bizOrgExt = new BizOrgExt(); + bizOrgExt.setOrgId(orgId); + bizOrgExt.setSourceFromType(sourceFromType); + this.save(bizOrgExt); + } +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java index b0d67242..b31c8826 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java @@ -36,18 +36,19 @@ import vip.xiaonuo.biz.modular.org.entity.BizOrg; import vip.xiaonuo.biz.modular.org.enums.BizOrgCategoryEnum; import vip.xiaonuo.biz.modular.org.mapper.BizOrgMapper; import vip.xiaonuo.biz.modular.org.param.*; +import vip.xiaonuo.biz.modular.org.service.BizOrgExtService; import vip.xiaonuo.biz.modular.org.service.BizOrgService; import vip.xiaonuo.biz.modular.position.entity.BizPosition; import vip.xiaonuo.biz.modular.position.service.BizPositionService; import vip.xiaonuo.biz.modular.user.entity.BizUser; import vip.xiaonuo.biz.modular.user.service.BizUserService; -import vip.xiaonuo.common.cache.CommonCacheOperator; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.listener.CommonDataChangeEventCenter; import vip.xiaonuo.common.page.CommonPageRequest; import vip.xiaonuo.sys.api.SysRoleApi; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -62,14 +63,12 @@ import java.util.stream.Collectors; @Service public class BizOrgServiceImpl extends ServiceImpl implements BizOrgService { - public static final String ORG_CACHE_ALL_KEY = "sys-org:all"; - - @Resource - private CommonCacheOperator commonCacheOperator; - @Resource private SysRoleApi sysRoleApi; + @Resource + private BizOrgExtService bizOrgExtService; + @Resource private BizPositionService bizPositionService; @@ -127,7 +126,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme @Transactional(rollbackFor = Exception.class) @Override - public void add(BizOrgAddParam bizOrgAddParam) { + public void add(BizOrgAddParam bizOrgAddParam, String sourceFromType) { BizOrgCategoryEnum.validate(bizOrgAddParam.getCategory()); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); @@ -147,8 +146,10 @@ public class BizOrgServiceImpl extends ServiceImpl impleme throw new CommonException("存在重复的同级机构,名称为:{}", bizOrg.getName()); } bizOrg.setCode(RandomUtil.randomString(10)); + // 保存机构 this.save(bizOrg); - + // 插入扩展信息 + bizOrgExtService.createExtInfo(bizOrg.getId(), sourceFromType); // 发布增加事件 CommonDataChangeEventCenter.doAddWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(bizOrg)); } @@ -182,8 +183,8 @@ public class BizOrgServiceImpl extends ServiceImpl impleme if(errorLevel) { throw new CommonException("不可选择上级机构:{}", this.getById(originDataList, bizOrg.getParentId()).getName()); } + // 更新机构 this.updateById(bizOrg); - // 发布更新事件 CommonDataChangeEventCenter.doUpdateWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(bizOrg)); } @@ -196,7 +197,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - if(!loginUserDataScope.containsAll(orgIdList)) { + if(!new HashSet<>(loginUserDataScope).containsAll(orgIdList)) { throw new CommonException("您没有权限删除这些机构,机构id:{}", orgIdList); } } else { @@ -219,7 +220,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme List positionOrgIdList = CollectionUtil.newArrayList(); positionJsonList.forEach(positionJson -> JSONUtil.toList(JSONUtil.parseArray(positionJson), JSONObject.class) .forEach(jsonObject -> positionOrgIdList.add(jsonObject.getStr("orgId")))); - boolean hasPositionUser = CollectionUtil.intersectionDistinct(toDeleteOrgIdList, CollectionUtil.removeNull(positionOrgIdList)).size() > 0; + boolean hasPositionUser = !CollectionUtil.intersectionDistinct(toDeleteOrgIdList, CollectionUtil.removeNull(positionOrgIdList)).isEmpty(); if(hasPositionUser) { throw new CommonException("请先删除机构下的人员"); } @@ -263,28 +264,28 @@ public class BizOrgServiceImpl extends ServiceImpl impleme @Override public String getOrgIdByOrgFullNameWithCreate(String orgFullName) { - List cachedAllOrgList = this.getAllOrgList(); - List> treeList = TreeUtil.build(cachedAllOrgList.stream().map(bizOrg -> + List allOrgList = this.getAllOrgList(); + List> treeList = TreeUtil.build(allOrgList.stream().map(bizOrg -> new TreeNode<>(bizOrg.getId(), bizOrg.getParentId(), bizOrg.getName(), bizOrg.getSortCode())) .collect(Collectors.toList()), "0"); - return findOrgIdByOrgName("0", StrUtil.split(orgFullName, StrUtil.DASHED).iterator(), cachedAllOrgList, treeList); + return findOrgIdByOrgName("0", StrUtil.split(orgFullName, StrUtil.DASHED).iterator(), allOrgList, treeList); } - public String findOrgIdByOrgName(String parentId, Iterator iterator, List cachedAllOrgList, List> treeList) { + public String findOrgIdByOrgName(String parentId, Iterator iterator, List allOrgList, List> treeList) { String orgName = iterator.next(); if(ObjectUtil.isNotEmpty(treeList)) { List> findList = treeList.stream().filter(tree -> tree.getName().equals(orgName)).collect(Collectors.toList()); if(ObjectUtil.isNotEmpty(findList)) { if(iterator.hasNext()) { - return findOrgIdByOrgName(findList.get(0).getId(), iterator, cachedAllOrgList, findList.get(0).getChildren()); + return findOrgIdByOrgName(findList.get(0).getId(), iterator, allOrgList, findList.get(0).getChildren()); } else { return findList.get(0).getId(); } } } - String orgId = this.doCreateOrg(parentId, orgName, cachedAllOrgList); + String orgId = this.doCreateOrg(parentId, orgName, allOrgList); if(iterator.hasNext()) { - return findOrgIdByOrgName(orgId, iterator, cachedAllOrgList, CollectionUtil.newArrayList()); + return findOrgIdByOrgName(orgId, iterator, allOrgList, CollectionUtil.newArrayList()); } else { return orgId; } @@ -296,7 +297,7 @@ public class BizOrgServiceImpl extends ServiceImpl impleme * @author xuyuxiang * @date 2023/3/8 9:38 **/ - public String doCreateOrg(String parentId, String orgName, List cachedAllOrgList) { + public String doCreateOrg(String parentId, String orgName, List allOrgList) { //创建该机构 BizOrg bizOrg = new BizOrg(); bizOrg.setName(orgName); @@ -307,10 +308,6 @@ public class BizOrgServiceImpl extends ServiceImpl impleme this.save(bizOrg); // 发布增加事件 CommonDataChangeEventCenter.doAddWithData(BizDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(bizOrg)); - // 将该机构加入缓存 - cachedAllOrgList.add(bizOrg); - // 更新缓存 - commonCacheOperator.put(ORG_CACHE_ALL_KEY, cachedAllOrgList); return bizOrg.getId(); } @@ -342,55 +339,55 @@ public class BizOrgServiceImpl extends ServiceImpl impleme @Override public List orgListSelector(BizOrgSelectorOrgListParam bizOrgSelectorOrgListParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizOrg::getId, loginUserDataScope); + queryWrapper.lambda().in(BizOrg::getId, loginUserDataScope); } else { return CollectionUtil.newArrayList(); } // 查询部分字段 - lambdaQueryWrapper.select(BizOrg::getId, BizOrg::getParentId, BizOrg::getName, + queryWrapper.lambda().select(BizOrg::getId, BizOrg::getParentId, BizOrg::getName, BizOrg::getCategory, BizOrg::getSortCode); if(ObjectUtil.isNotEmpty(bizOrgSelectorOrgListParam.getParentId())) { - lambdaQueryWrapper.eq(BizOrg::getParentId, bizOrgSelectorOrgListParam.getParentId()); + queryWrapper.lambda().eq(BizOrg::getParentId, bizOrgSelectorOrgListParam.getParentId()); } if(ObjectUtil.isNotEmpty(bizOrgSelectorOrgListParam.getSearchKey())) { - lambdaQueryWrapper.like(BizOrg::getName, bizOrgSelectorOrgListParam.getSearchKey()); + queryWrapper.lambda().like(BizOrg::getName, bizOrgSelectorOrgListParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizOrg::getSortCode); - return this.list(lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizOrg::getSortCode); + return this.list(queryWrapper.lambda()); } @Override public Page userSelector(BizOrgSelectorUserParam bizOrgSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizUser::getOrgId, loginUserDataScope); + queryWrapper.lambda().in(BizUser::getOrgId, loginUserDataScope); } else { return new Page<>(); } // 只查询部分字段 - lambdaQueryWrapper.select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount, + queryWrapper.lambda().select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount, BizUser::getName, BizUser::getSortCode, BizUser::getGender, BizUser::getEntryDate); if (ObjectUtil.isNotEmpty(bizOrgSelectorUserParam.getOrgId())) { // 如果机构id不为空,则查询该机构及其子机构下的所有人 List childOrgIdList = CollStreamUtil.toList(this.getChildListById(this .getAllOrgList(), bizOrgSelectorUserParam.getOrgId(), true), BizOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(BizUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(BizUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if(ObjectUtil.isNotEmpty(bizOrgSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(BizUser::getName, bizOrgSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(BizUser::getName, bizOrgSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizUser::getSortCode); - return bizUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizUser::getSortCode); + return bizUserService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } /* ====以下为各种递归方法==== */ diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/controller/BizPositionController.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/controller/BizPositionController.java index 6986cffa..4d7193f7 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/controller/BizPositionController.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/controller/BizPositionController.java @@ -15,10 +15,11 @@ package vip.xiaonuo.biz.modular.position.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -31,6 +32,7 @@ import vip.xiaonuo.biz.modular.position.service.BizPositionService; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; import java.util.List; /** @@ -40,6 +42,7 @@ import java.util.List; * @date 2022/4/25 20:40 */ @Tag(name = "岗位控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 2) @RestController @Validated public class BizPositionController { @@ -53,6 +56,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取岗位分页") @SaCheckPermission("/biz/position/page") @GetMapping("/biz/position/page") @@ -66,6 +70,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加岗位") @CommonLog("添加岗位") @SaCheckPermission("/biz/position/add") @@ -81,6 +86,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑岗位") @CommonLog("编辑岗位") @SaCheckPermission("/biz/position/edit") @@ -96,6 +102,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除岗位") @CommonLog("删除岗位") @SaCheckPermission("/biz/position/delete") @@ -112,6 +119,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取岗位详情") @SaCheckPermission("/biz/position/detail") @GetMapping("/biz/position/detail") @@ -127,6 +135,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取组织树选择器") @SaCheckPermission("/biz/position/orgTreeSelector") @GetMapping("/biz/position/orgTreeSelector") @@ -140,6 +149,7 @@ public class BizPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取岗位选择器") @SaCheckPermission("/biz/position/positionSelector") @GetMapping("/biz/position/positionSelector") diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/entity/BizPosition.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/entity/BizPosition.java index 8dad4e8a..7a4fb169 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/entity/BizPosition.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/entity/BizPosition.java @@ -57,6 +57,6 @@ public class BizPosition extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionAddParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionAddParam.java index 0ae96260..7bdb2515 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionAddParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionAddParam.java @@ -29,22 +29,22 @@ import lombok.Setter; public class BizPositionAddParam { /** 机构id */ - @Schema(description = "机构id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "机构id") @NotBlank(message = "orgId不能为空") private String orgId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionEditParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionEditParam.java index df5fb980..f3c24300 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionEditParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionEditParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class BizPositionEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 机构id */ - @Schema(description = "机构id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "机构id") @NotBlank(message = "orgId不能为空") private String orgId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionIdParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionIdParam.java index 5b7510ba..38e1dc20 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionIdParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/param/BizPositionIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class BizPositionIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java index 2517bdc2..a1967ee8 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/position/service/impl/BizPositionServiceImpl.java @@ -47,6 +47,7 @@ import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.listener.CommonDataChangeEventCenter; import vip.xiaonuo.common.page.CommonPageRequest; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -71,7 +72,7 @@ public class BizPositionServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 queryWrapper.lambda().select(BizPosition::getId, BizPosition::getOrgId, BizPosition::getName, - BizPosition::getCategory, BizPosition::getSortCode); + BizPosition::getCategory, BizPosition::getSortCode, BizPosition::getExtJson); if(ObjectUtil.isNotEmpty(bizPositionPageParam.getOrgId())) { queryWrapper.lambda().eq(BizPosition::getOrgId, bizPositionPageParam.getOrgId()); } @@ -162,7 +163,7 @@ public class BizPositionServiceImpl extends ServiceImpl loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - if(!loginUserDataScope.containsAll(positionOrgIdList)) { + if(!new HashSet<>(loginUserDataScope).containsAll(positionOrgIdList)) { throw new CommonException("您没有权限删除这些机构下的岗位,机构id:{}", positionOrgIdList); } } else { @@ -180,7 +181,7 @@ public class BizPositionServiceImpl extends ServiceImpl extPositionIdList = CollectionUtil.newArrayList(); positionJsonList.forEach(positionJson -> JSONUtil.toList(JSONUtil.parseArray(positionJson), JSONObject.class) .forEach(jsonObject -> extPositionIdList.add(jsonObject.getStr("positionId")))); - boolean hasPositionUser = CollectionUtil.intersectionDistinct(positionIdList, CollectionUtil.removeNull(extPositionIdList)).size() > 0; + boolean hasPositionUser = !CollectionUtil.intersectionDistinct(positionIdList, CollectionUtil.removeNull(extPositionIdList)).isEmpty(); if(hasPositionUser) { throw new CommonException("请先删除岗位下的用户"); } @@ -240,24 +241,24 @@ public class BizPositionServiceImpl extends ServiceImpl positionSelector(BizPositionSelectorPositionParam bizPositionSelectorPositionParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper(); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizPosition::getOrgId, loginUserDataScope); + queryWrapper.lambda().in(BizPosition::getOrgId, loginUserDataScope); } else { return new Page<>(); } // 查询部分字段 - lambdaQueryWrapper.select(BizPosition::getId, BizPosition::getOrgId, BizPosition::getName, + queryWrapper.lambda().select(BizPosition::getId, BizPosition::getOrgId, BizPosition::getName, BizPosition::getCategory, BizPosition::getSortCode); if(ObjectUtil.isNotEmpty(bizPositionSelectorPositionParam.getOrgId())) { - lambdaQueryWrapper.eq(BizPosition::getOrgId, bizPositionSelectorPositionParam.getOrgId()); + queryWrapper.lambda().eq(BizPosition::getOrgId, bizPositionSelectorPositionParam.getOrgId()); } if(ObjectUtil.isNotEmpty(bizPositionSelectorPositionParam.getSearchKey())) { - lambdaQueryWrapper.like(BizPosition::getName, bizPositionSelectorPositionParam.getSearchKey()); + queryWrapper.lambda().like(BizPosition::getName, bizPositionSelectorPositionParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizPosition::getSortCode); - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizPosition::getSortCode); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/controller/BizUserController.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/controller/BizUserController.java index b0304a91..964b3142 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/controller/BizUserController.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/controller/BizUserController.java @@ -15,11 +15,12 @@ package vip.xiaonuo.biz.modular.user.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; @@ -30,12 +31,14 @@ import org.springframework.web.bind.annotation.RestController; import vip.xiaonuo.biz.modular.org.entity.BizOrg; import vip.xiaonuo.biz.modular.position.entity.BizPosition; import vip.xiaonuo.biz.modular.user.entity.BizUser; +import vip.xiaonuo.biz.modular.user.enums.BizUserSourceFromTypeEnum; import vip.xiaonuo.biz.modular.user.param.*; import vip.xiaonuo.biz.modular.user.result.BizUserRoleResult; import vip.xiaonuo.biz.modular.user.service.BizUserService; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; import java.io.IOException; import java.util.List; @@ -46,6 +49,7 @@ import java.util.List; * @date 2022/4/22 9:34 **/ @Tag(name = "人员控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 9) @RestController @Validated public class BizUserController { @@ -59,6 +63,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取人员分页") @SaCheckPermission("/biz/user/page") @GetMapping("/biz/user/page") @@ -72,12 +77,13 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加人员") @CommonLog("添加人员") @SaCheckPermission("/biz/user/add") @PostMapping("/biz/user/add") public CommonResult add(@RequestBody @Valid BizUserAddParam bizUserAddParam) { - bizUserService.add(bizUserAddParam); + bizUserService.add(bizUserAddParam, BizUserSourceFromTypeEnum.SYSTEM_ADD.getValue()); return CommonResult.ok(); } @@ -87,6 +93,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑人员") @CommonLog("编辑人员") @SaCheckPermission("/biz/user/edit") @@ -102,6 +109,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除人员") @CommonLog("删除人员") @SaCheckPermission("/biz/user/delete") @@ -118,6 +126,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取人员详情") @SaCheckPermission("/biz/user/detail") @GetMapping("/biz/user/detail") @@ -131,6 +140,7 @@ public class BizUserController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 6) @Operation(summary = "禁用人员") @CommonLog("禁用人员") @SaCheckPermission("/biz/user/disableUser") @@ -146,6 +156,7 @@ public class BizUserController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 7) @Operation(summary = "启用人员") @CommonLog("启用人员") @SaCheckPermission("/biz/user/enableUser") @@ -161,6 +172,7 @@ public class BizUserController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 8) @Operation(summary = "重置人员密码") @CommonLog("重置人员密码") @SaCheckPermission("/biz/user/resetPassword") @@ -176,6 +188,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 9) @Operation(summary = "获取人员拥有角色") @SaCheckPermission("/biz/user/ownRole") @GetMapping("/biz/user/ownRole") @@ -189,6 +202,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 10) @Operation(summary = "给人员授权角色") @CommonLog("给人员授权角色") @SaCheckPermission("/biz/user/grantRole") @@ -204,6 +218,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 11) @Operation(summary = "人员导出") @CommonLog("人员导出") @SaCheckPermission("/biz/user/export") @@ -218,6 +233,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 12) @Operation(summary = "导出人员个人信息") @CommonLog("导出人员个人信息") @SaCheckPermission("/biz/user/exportUserInfo") @@ -234,6 +250,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 13) @Operation(summary = "获取机构树选择器") @SaCheckPermission("/biz/user/orgTreeSelector") @GetMapping("/biz/user/orgTreeSelector") @@ -247,6 +264,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 14) @Operation(summary = "获取机构列表选择器") @SaCheckPermission("/biz/user/orgListSelector") @GetMapping("/biz/user/orgListSelector") @@ -260,6 +278,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 15) @Operation(summary = "获取岗位选择器") @SaCheckPermission("/biz/user/positionSelector") @GetMapping("/biz/user/positionSelector") @@ -273,6 +292,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 16) @Operation(summary = "获取角色选择器") @SaCheckPermission("/biz/user/roleSelector") @GetMapping("/biz/user/roleSelector") @@ -286,6 +306,7 @@ public class BizUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 17) @Operation(summary = "获取人员选择器") @SaCheckPermission("/biz/user/userSelector") @GetMapping("/biz/user/userSelector") diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUser.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUser.java index af95768a..f8b3e20c 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUser.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUser.java @@ -47,12 +47,12 @@ public class BizUser extends CommonEntity { /** 头像 */ @Schema(description = "头像") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String avatar; /** 签名 */ @Schema(description = "签名") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String signature; /** 账号 */ @@ -70,156 +70,154 @@ public class BizUser extends CommonEntity { /** 昵称 */ @Schema(description = "昵称") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nickname; /** 性别 */ @Schema(description = "性别") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.DICTIONARY, key = "GENDER") private String gender; /** 年龄 */ @Schema(description = "年龄") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String age; /** 出生日期 */ @Schema(description = "出生日期") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String birthday; /** 民族 */ @Schema(description = "民族") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nation; /** 籍贯 */ @Schema(description = "籍贯") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nativePlace; /** 家庭住址 */ @Schema(description = "家庭住址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String homeAddress; /** 通信地址 */ @Schema(description = "通信地址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String mailingAddress; /** 证件类型 */ @Schema(description = "证件类型") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String idCardType; /** 证件号码 */ @Schema(description = "证件号码") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String idCardNumber; /** 文化程度 */ @Schema(description = "文化程度") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String cultureLevel; /** 政治面貌 */ @Schema(description = "政治面貌") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String politicalOutlook; /** 毕业院校 */ @Schema(description = "毕业院校") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String college; /** 学历 */ @Schema(description = "学历") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String education; /** 学制 */ @Schema(description = "学制") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String eduLength; /** 学位 */ @Schema(description = "学位") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String degree; /** 手机 */ @Schema(description = "手机") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String phone; /** 邮箱 */ @Schema(description = "邮箱") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String email; /** 家庭电话 */ @Schema(description = "家庭电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String homeTel; /** 办公电话 */ @Schema(description = "办公电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String officeTel; /** 紧急联系人 */ @Schema(description = "紧急联系人") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String emergencyContact; /** 紧急联系人电话 */ @Schema(description = "紧急联系人电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String emergencyPhone; /** 紧急联系人地址 */ @Schema(description = "紧急联系人地址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String emergencyAddress; /** 员工编号 */ @Schema(description = "员工编号") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String empNo; /** 入职日期 */ @Schema(description = "入职日期") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String entryDate; /** 机构id */ @Schema(description = "机构id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) @Trans(type = TransType.SIMPLE, target = BizOrg.class, fields = "name", alias = "org", ref = "orgName") private String orgId; /** 岗位id */ @Schema(description = "岗位id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) @Trans(type = TransType.SIMPLE, target = BizPosition.class, fields = "name", alias = "position", ref = "positionName") private String positionId; /** 职级 */ @Schema(description = "职级") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String positionLevel; /** 主管id */ @Schema(description = "主管id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.SIMPLE, target = BizUser.class, fields = "name", alias = "director", ref = "directorName") private String directorId; /** 兼任信息 */ @Schema(description = "兼任信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String positionJson; /** 上次登录ip */ @@ -264,7 +262,7 @@ public class BizUser extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; @Schema(description = "机构名称") diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUserExt.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUserExt.java new file mode 100644 index 00000000..042d6915 --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/entity/BizUserExt.java @@ -0,0 +1,52 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.user.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +import java.util.Date; + +/** + * 用户扩展实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("SYS_USER_EXT") +public class BizUserExt extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 用户id */ + @Schema(description = "用户id") + private String userId; + + /** 来源类别 */ + @Schema(description = "来源类别") + private String sourceFromType; + + /** 密码修改日期 */ + @Schema(description = "密码修改日期") + private Date passwordUpdateTime; + +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/enums/BizUserSourceFromTypeEnum.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/enums/BizUserSourceFromTypeEnum.java new file mode 100644 index 00000000..8c124b58 --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/enums/BizUserSourceFromTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.user.enums; + +import lombok.Getter; + +/** + * 用户来源类型枚举 + * + * @author xuyuxiang + * @date 2022/4/21 19:56 + **/ +@Getter +public enum BizUserSourceFromTypeEnum { + + /** 系统自建 */ + SYSTEM_ADD("SYSTEM_ADD"), + + /** 用户注册 */ + SYSTEM_REGISTER("SYSTEM_REGISTER"), + + /** 身份源 */ + ID_SOURCE("ID_SOURCE"); + + private final String value; + + BizUserSourceFromTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/BizUserExtMapper.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/BizUserExtMapper.java new file mode 100644 index 00000000..85865b0c --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/BizUserExtMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.biz.modular.user.entity.BizUserExt; + +/** + * 用户扩展Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface BizUserExtMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserExtMapper.xml b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserExtMapper.xml new file mode 100644 index 00000000..cac6a04c --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserExtMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserMapper.xml b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserMapper.xml index 80c82584..6e97622f 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserMapper.xml +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/mapper/mapping/BizUserMapper.xml @@ -2,4 +2,4 @@ - \ No newline at end of file + diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserAddParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserAddParam.java index 1604bb61..ad0a732e 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserAddParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserAddParam.java @@ -28,22 +28,22 @@ import lombok.Setter; public class BizUserAddParam { /** 账号 */ - @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "账号") @NotBlank(message = "account不能为空") private String account; /** 姓名 */ - @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "姓名") @NotBlank(message = "name不能为空") private String name; /** 机构id */ - @Schema(description = "机构id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "机构id") @NotBlank(message = "orgId不能为空") private String orgId; /** 岗位id */ - @Schema(description = "岗位id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "岗位id") @NotBlank(message = "positionId不能为空") private String positionId; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserEditParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserEditParam.java index ee0e7c1a..ad4d938d 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserEditParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserEditParam.java @@ -28,27 +28,27 @@ import lombok.Setter; public class BizUserEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 账号 */ - @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "账号") @NotBlank(message = "account不能为空") private String account; /** 姓名 */ - @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "姓名") @NotBlank(message = "name不能为空") private String name; /** 机构id */ - @Schema(description = "机构id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "机构id") @NotBlank(message = "orgId不能为空") private String orgId; /** 岗位id */ - @Schema(description = "岗位id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "岗位id") @NotBlank(message = "positionId不能为空") private String positionId; diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserGrantRoleParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserGrantRoleParam.java index f7809015..d057dc6b 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserGrantRoleParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserGrantRoleParam.java @@ -31,12 +31,12 @@ import java.util.List; public class BizUserGrantRoleParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 角色id集合 */ - @Schema(description = "角色id集合", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色id集合") @NotNull(message = "roleIdList不能为空") private List roleIdList; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserIdParam.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserIdParam.java index 21d7e643..4e7229ca 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserIdParam.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/param/BizUserIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class BizUserIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserExtService.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserExtService.java new file mode 100644 index 00000000..d5f2603d --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserExtService.java @@ -0,0 +1,41 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.biz.modular.user.entity.BizUserExt; + +/** + * 用户扩展Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface BizUserExtService extends IService { + + /** + * 更新用户最新修改密码时间 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void updatePasswordLastTime(String userId); + + /** + * 插入扩展信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void createExtInfo(String userId, String sourceFromType); +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserService.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserService.java index 1532f8c7..7c3906fc 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserService.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/BizUserService.java @@ -47,7 +47,7 @@ public interface BizUserService extends IService { * @author xuyuxiang * @date 2022/4/24 20:48 */ - void add(BizUserAddParam bizUserAddParam); + void add(BizUserAddParam bizUserAddParam, String sourceFromType); /** * 编辑人员 @@ -83,7 +83,7 @@ public interface BizUserService extends IService { /** * 禁用人员 - * + * * @author xuyuxiang * @date 2022/7/5 18:20 **/ diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserExtServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserExtServiceImpl.java new file mode 100644 index 00000000..e5dd949e --- /dev/null +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserExtServiceImpl.java @@ -0,0 +1,55 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.biz.modular.user.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.biz.modular.user.entity.BizUserExt; +import vip.xiaonuo.biz.modular.user.mapper.BizUserExtMapper; +import vip.xiaonuo.biz.modular.user.service.BizUserExtService; + +/** + * 用户扩展Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class BizUserExtServiceImpl extends ServiceImpl implements BizUserExtService { + + @Override + public void updatePasswordLastTime(String userId) { + BizUserExt bizUserExt = this.getOne(new LambdaQueryWrapper().eq(BizUserExt::getUserId, userId)); + if(ObjectUtil.isEmpty(bizUserExt)){ + bizUserExt = new BizUserExt(); + bizUserExt.setUserId(userId); + bizUserExt.setPasswordUpdateTime(DateTime.now()); + this.save(bizUserExt); + } else { + bizUserExt.setPasswordUpdateTime(DateTime.now()); + this.updateById(bizUserExt); + } + } + + @Override + public void createExtInfo(String userId, String sourceFromType) { + BizUserExt bizUserExt = new BizUserExt(); + bizUserExt.setUserId(userId); + bizUserExt.setSourceFromType(sourceFromType); + bizUserExt.setPasswordUpdateTime(DateTime.now()); + this.save(bizUserExt); + } +} diff --git a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserServiceImpl.java b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserServiceImpl.java index 2ed9ff9b..16a8aa4f 100644 --- a/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserServiceImpl.java +++ b/snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/user/service/impl/BizUserServiceImpl.java @@ -61,12 +61,14 @@ import vip.xiaonuo.biz.modular.org.service.BizOrgService; import vip.xiaonuo.biz.modular.position.entity.BizPosition; import vip.xiaonuo.biz.modular.position.service.BizPositionService; import vip.xiaonuo.biz.modular.user.entity.BizUser; +import vip.xiaonuo.biz.modular.user.entity.BizUserExt; import vip.xiaonuo.biz.modular.user.enums.BizRoleCategoryEnum; import vip.xiaonuo.biz.modular.user.enums.BizUserStatusEnum; import vip.xiaonuo.biz.modular.user.mapper.BizUserMapper; import vip.xiaonuo.biz.modular.user.param.*; import vip.xiaonuo.biz.modular.user.result.BizUserExportResult; import vip.xiaonuo.biz.modular.user.result.BizUserRoleResult; +import vip.xiaonuo.biz.modular.user.service.BizUserExtService; import vip.xiaonuo.biz.modular.user.service.BizUserService; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.excel.CommonExcelCustomMergeStrategy; @@ -74,7 +76,7 @@ import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.listener.CommonDataChangeEventCenter; import vip.xiaonuo.common.page.CommonPageRequest; import vip.xiaonuo.common.util.*; -import vip.xiaonuo.dev.api.DevConfigApi; +import vip.xiaonuo.sys.api.SysApi; import vip.xiaonuo.sys.api.SysRoleApi; import vip.xiaonuo.sys.api.SysUserApi; @@ -82,10 +84,7 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -97,13 +96,11 @@ import java.util.stream.Collectors; @Service public class BizUserServiceImpl extends ServiceImpl implements BizUserService { - private static final String SNOWY_SYS_DEFAULT_PASSWORD_KEY = "SNOWY_SYS_DEFAULT_PASSWORD"; - @Resource private TransService transService; @Resource - private DevConfigApi devConfigApi; + private SysApi sysApi; @Resource private SysUserApi sysUserApi; @@ -111,6 +108,9 @@ public class BizUserServiceImpl extends ServiceImpl impl @Resource private SysRoleApi sysRoleApi; + @Resource + private BizUserExtService bizUserExtService; + @Resource private BizOrgService bizOrgService; @@ -151,7 +151,7 @@ public class BizUserServiceImpl extends ServiceImpl impl @Transactional(rollbackFor = Exception.class) @Override - public void add(BizUserAddParam bizUserAddParam) { + public void add(BizUserAddParam bizUserAddParam, String sourceFromType) { checkParam(bizUserAddParam); BizUser bizUser = BeanUtil.toBean(bizUserAddParam, BizUser.class); if(ObjectUtil.isEmpty(bizUser.getAvatar())) { @@ -159,11 +159,13 @@ public class BizUserServiceImpl extends ServiceImpl impl bizUser.setAvatar(CommonAvatarUtil.generateImg(bizUser.getName())); } // 设置密码 - bizUser.setPassword(CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_KEY))); + bizUser.setPassword(CommonCryptogramUtil.doHashValue(sysApi.getDefaultPassword())); // 设置状态 bizUser.setUserStatus(BizUserStatusEnum.ENABLE.getValue()); + // 保存用户 this.save(bizUser); - + // 插入扩展信息 + bizUserExtService.createExtInfo(bizUser.getId(), sourceFromType); // 发布增加事件 CommonDataChangeEventCenter.doAddWithData(BizDataTypeEnum.USER.getValue(), JSONUtil.createArray().put(bizUser)); } @@ -192,7 +194,7 @@ public class BizUserServiceImpl extends ServiceImpl impl } } if(ObjectUtil.isNotEmpty(bizUserAddParam.getEmail())) { - if(!CommonEmailUtil.isEmail(bizUserAddParam.getEmail())) { + if(CommonEmailUtil.isNotEmail(bizUserAddParam.getEmail())) { throw new CommonException("邮箱:{}格式错误", bizUserAddParam.getEmail()); } if (this.count(new LambdaQueryWrapper() @@ -213,8 +215,8 @@ public class BizUserServiceImpl extends ServiceImpl impl throw new CommonException("不可修改系统内置超管人员账号"); } BeanUtil.copyProperties(bizUserEditParam, bizUser); + // 更新用户 this.updateById(bizUser); - // 发布更新事件 CommonDataChangeEventCenter.doUpdateWithData(BizDataTypeEnum.USER.getValue(), JSONUtil.createArray().put(bizUser)); } @@ -247,7 +249,7 @@ public class BizUserServiceImpl extends ServiceImpl impl } } if(ObjectUtil.isNotEmpty(bizUserEditParam.getEmail())) { - if(!CommonEmailUtil.isEmail(bizUserEditParam.getEmail())) { + if(CommonEmailUtil.isNotEmail(bizUserEditParam.getEmail())) { throw new CommonException("邮箱:{}格式错误", bizUserEditParam.getEmail()); } if (this.count(new LambdaQueryWrapper() @@ -273,7 +275,7 @@ public class BizUserServiceImpl extends ServiceImpl impl // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - if(!loginUserDataScope.containsAll(userOrgIdList)) { + if(!new HashSet<>(loginUserDataScope).containsAll(userOrgIdList)) { throw new CommonException("您没有权限删除这些机构下的人员,机构id:{}", CollectionUtil.subtract(userOrgIdList, loginUserDataScope)); } @@ -304,6 +306,9 @@ public class BizUserServiceImpl extends ServiceImpl impl // 执行删除 this.removeByIds(bizUserIdList); + // 删除扩展信息 + bizUserExtService.remove(new LambdaQueryWrapper().in(BizUserExt::getUserId, bizUserIdList)); + // 发布删除事件 CommonDataChangeEventCenter.doDeleteWithDataId(BizDataTypeEnum.USER.getValue(), bizUserIdList); } @@ -369,7 +374,7 @@ public class BizUserServiceImpl extends ServiceImpl impl } this.update(new LambdaUpdateWrapper().eq(BizUser::getId, bizUserIdParam.getId()).set(BizUser::getPassword, - CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_KEY)))); + CommonCryptogramUtil.doHashValue(sysApi.getDefaultPassword()))); } @Override @@ -563,7 +568,7 @@ public class BizUserServiceImpl extends ServiceImpl impl if(ObjectUtil.isNotEmpty(bizUser.getBirthday())) { try { // 年龄 - long age = cn.hutool.core.date.DateUtil.betweenYear(cn.hutool.core.date.DateUtil.parseDate(bizUser.getBirthday()), DateTime.now(), true); + long age = DateUtil.betweenYear(DateUtil.parseDate(bizUser.getBirthday()), DateTime.now(), true); if(age != 0) { map.put("age", age + "岁"); } @@ -633,48 +638,48 @@ public class BizUserServiceImpl extends ServiceImpl impl @Override public Page orgListSelector(BizUserSelectorOrgListParam bizUserSelectorOrgListParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizOrg::getId, loginUserDataScope); + queryWrapper.lambda().in(BizOrg::getId, loginUserDataScope); } else { return new Page<>(); } // 查询部分字段 - lambdaQueryWrapper.select(BizOrg::getId, BizOrg::getParentId, BizOrg::getName, + queryWrapper.lambda().select(BizOrg::getId, BizOrg::getParentId, BizOrg::getName, BizOrg::getCategory, BizOrg::getSortCode); if(ObjectUtil.isNotEmpty(bizUserSelectorOrgListParam.getParentId())) { - lambdaQueryWrapper.eq(BizOrg::getParentId, bizUserSelectorOrgListParam.getParentId()); + queryWrapper.lambda().eq(BizOrg::getParentId, bizUserSelectorOrgListParam.getParentId()); } if(ObjectUtil.isNotEmpty(bizUserSelectorOrgListParam.getSearchKey())) { - lambdaQueryWrapper.like(BizOrg::getName, bizUserSelectorOrgListParam.getSearchKey()); + queryWrapper.lambda().like(BizOrg::getName, bizUserSelectorOrgListParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizOrg::getSortCode); - return bizOrgService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizOrg::getSortCode); + return bizOrgService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @Override public Page positionSelector(BizUserSelectorPositionParam bizUserSelectorPositionParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizPosition::getOrgId, loginUserDataScope); + queryWrapper.lambda().in(BizPosition::getOrgId, loginUserDataScope); } else { return new Page<>(); } // 查询部分字段 - lambdaQueryWrapper.select(BizPosition::getId, BizPosition::getOrgId, BizPosition::getName, + queryWrapper.lambda().select(BizPosition::getId, BizPosition::getOrgId, BizPosition::getName, BizPosition::getCategory, BizPosition::getSortCode); if(ObjectUtil.isNotEmpty(bizUserSelectorPositionParam.getOrgId())) { - lambdaQueryWrapper.eq(BizPosition::getOrgId, bizUserSelectorPositionParam.getOrgId()); + queryWrapper.lambda().eq(BizPosition::getOrgId, bizUserSelectorPositionParam.getOrgId()); } if(ObjectUtil.isNotEmpty(bizUserSelectorPositionParam.getSearchKey())) { - lambdaQueryWrapper.like(BizPosition::getName, bizUserSelectorPositionParam.getSearchKey()); + queryWrapper.lambda().like(BizPosition::getName, bizUserSelectorPositionParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizPosition::getSortCode); - return bizPositionService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizPosition::getSortCode); + return bizPositionService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @SuppressWarnings("ALL") @@ -707,31 +712,31 @@ public class BizUserServiceImpl extends ServiceImpl impl @Override public Page userSelector(BizUserSelectorUserParam bizUserSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 校验数据范围 List loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope(); if(ObjectUtil.isNotEmpty(loginUserDataScope)) { - lambdaQueryWrapper.in(BizUser::getOrgId, loginUserDataScope); + queryWrapper.lambda().in(BizUser::getOrgId, loginUserDataScope); } else { return new Page<>(); } // 只查询部分字段 - lambdaQueryWrapper.select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount, + queryWrapper.lambda().select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount, BizUser::getName, BizUser::getSortCode, BizUser::getGender, BizUser::getEntryDate); if (ObjectUtil.isNotEmpty(bizUserSelectorUserParam.getOrgId())) { // 如果机构id不为空,则查询该机构及其子机构下的所有人 List childOrgIdList = CollStreamUtil.toList(bizOrgService.getChildListById(bizOrgService .getAllOrgList(), bizUserSelectorUserParam.getOrgId(), true), BizOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(BizUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(BizUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if(ObjectUtil.isNotEmpty(bizUserSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(BizUser::getName, bizUserSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(BizUser::getName, bizUserSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(BizUser::getSortCode); - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(BizUser::getSortCode); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/enums/ClientPasswordComplexityEnum.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/enums/ClientPasswordComplexityEnum.java new file mode 100644 index 00000000..f7aca7e3 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/enums/ClientPasswordComplexityEnum.java @@ -0,0 +1,64 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.core.enums; + +import lombok.Getter; + +/** + * 密码复杂度类型枚举 + * + * @author xuyuxiang + * @date 2023/3/3 10:40 + **/ +@Getter +public enum ClientPasswordComplexityEnum { + + /** + * 无限制 + */ + REG0("REG0", "无限制"), + + /** + * 必须包含数字和字母 + */ + REG1("REG1", "必须包含数字和字母"), + + /** + * 必须包含数字和大写字母 + */ + REG2("REG2", "必须包含数字和大写字母"), + + /** + * 必须包含数字、大写字母、小写字母和特殊字符 + */ + REG3("REG3", "必须包含数字、大写字母、小写字母和特殊字符"), + + /** + * 至少包含数字、字母和特殊字符中的两种 + */ + REG4("REG4", "至少包含数字、字母和特殊字符中的两种"), + + /** + * 至少包含数字、大写字母、小写字母和特殊字符的三种 + */ + REG5("REG5", "至少包含数字、大写字母、小写字母和特殊字符的三种"); + + private final String value; + + private final String message; + + ClientPasswordComplexityEnum(String value, String message) { + this.value = value; + this.message = message; + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/timer/ClientUserPasswordExpiredNoticeTimerTaskRunner.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/timer/ClientUserPasswordExpiredNoticeTimerTaskRunner.java new file mode 100644 index 00000000..b8e3ca63 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/timer/ClientUserPasswordExpiredNoticeTimerTaskRunner.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.core.timer; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import vip.xiaonuo.client.modular.user.service.ClientUserService; +import vip.xiaonuo.common.timer.CommonTimerTaskRunner; + +/** + * 通知用户密码即将到期定时类 + * + * @author xuyuxiang + * @date 2022/8/5 15:52 + **/ +@Slf4j +@Component +public class ClientUserPasswordExpiredNoticeTimerTaskRunner implements CommonTimerTaskRunner { + + @Resource + private ClientUserService clientUserService; + + @Override + public void action(String extJson) { + // 通知用户密码即将到期 + clientUserService.noticeUserPasswordAboutToExpired(); + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientEmailFormatUtl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientEmailFormatUtl.java new file mode 100644 index 00000000..5d641df8 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientEmailFormatUtl.java @@ -0,0 +1,48 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.core.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import vip.xiaonuo.dev.api.DevConfigApi; + +/** + * 系统相关邮件格式化工具类 + * + * @author xuyuxiang + * @date 2025/3/21 19:07 + **/ +public class ClientEmailFormatUtl { + + /** 系统名称 */ + private static final String SNOWY_SYS_NAME_KEY = "SNOWY_SYS_NAME"; + + /** + * 格式化邮件内容 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static String format(String content, JSONObject paramMap) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取系统名称 + String sysName = devConfigApi.getValueByKey(SNOWY_SYS_NAME_KEY); + // 系统名称 + paramMap.set("sysName", sysName); + // 当前时间 + paramMap.set("sysNowTime", DateUtil.now()); + return StrUtil.format(content, paramMap); + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientPasswordUtl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientPasswordUtl.java new file mode 100644 index 00000000..d8ccf707 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/core/util/ClientPasswordUtl.java @@ -0,0 +1,405 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.core.util; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.pinyin.PinyinUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import vip.xiaonuo.client.core.enums.ClientPasswordComplexityEnum; +import vip.xiaonuo.client.modular.user.entity.ClientUser; +import vip.xiaonuo.client.modular.user.entity.ClientUserExt; +import vip.xiaonuo.client.modular.user.result.ClientLoginUser; +import vip.xiaonuo.client.modular.user.service.ClientUserExtService; +import vip.xiaonuo.client.modular.user.service.ClientUserPasswordService; +import vip.xiaonuo.client.modular.user.service.ClientUserService; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.common.util.CommonCryptogramUtil; +import vip.xiaonuo.dev.api.DevConfigApi; +import vip.xiaonuo.dev.api.DevWeakPasswordApi; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统密码工具类 + * + * @author xuyuxiang + * @date 2025/3/21 19:07 + **/ +public class ClientPasswordUtl { + + /** C端系统默认密码 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_FOR_C"; + + /** C端系统密码修改验证方式 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_C"; + + /** C端密码最小长度 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_C"; + + /** C端密码最大长度 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_C"; + + /** C端密码复杂度 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_C"; + + /** C端密码不能连续存在相同字符个数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_C_KEY= "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_C"; + + /** C端密码不能包含用户信息开关(开启后,密码中将不能包含账号、手机号、邮箱前缀和姓名拼音) */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_C"; + + /** C端密码不能使用历史密码开关 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_C"; + + /** C端密码不能使用历史密码范围个数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_C"; + + /** C端密码不能使用弱密码库中密码开关 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_C"; + + /** C端密码自定义额外弱密码库 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_C"; + + /** C端密码有效期天数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_C"; + + /** C端密码过期前提醒天数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_C_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_C"; + + /** + * 获取系统默认密码 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static String getDefaultPassword() { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + String defaultPassword = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_FOR_C_KEY); + if(ObjectUtil.isEmpty(defaultPassword)){ + throw new CommonException("请联系管理员配置系统默认密码"); + } + return defaultPassword; + } + + /** + * 校验修改密码验证方式 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validUpdatePasswordValidType(String type) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + String passwordUpdateValidType = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_C_KEY); + if(ObjectUtil.isEmpty(passwordUpdateValidType)){ + throw new CommonException("请联系管理员配置系统密码修改验证方式"); + } + if(!passwordUpdateValidType.equals(type)){ + throw new CommonException("系统配置不支持此方式修改密码"); + } + } + + /** + * 校验新密码 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(ClientLoginUser clientLoginUser, String newPassword) { + String userId = clientLoginUser.getId(); + String account = clientLoginUser.getAccount(); + String name = clientLoginUser.getName(); + String phone = clientLoginUser.getPhone(); + String email = clientLoginUser.getEmail(); + validNewPassword(userId, account, name, phone, email, newPassword); + } + + /** + * 校验新密码 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(ClientUser clientUser, String newPassword) { + String userId = clientUser.getId(); + String account = clientUser.getAccount(); + String name = clientUser.getName(); + String phone = clientUser.getPhone(); + String email = clientUser.getEmail(); + validNewPassword(userId, account, name, phone, email, newPassword); + } + + /** + * 校验新密码(基本要求) + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(String newPassword) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 密码最小长度 + String passwordMinLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordMinLength)){ + Integer minLengthInt = Convert.toInt(passwordMinLength); + if(newPassword.length() < minLengthInt){ + throw new CommonException("密码最小长度应为:{}", minLengthInt); + } + } + // 密码最大长度 + String passwordMaxLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordMaxLength)){ + Integer maxLengthInt = Convert.toInt(passwordMaxLength); + if(newPassword.length() > maxLengthInt){ + throw new CommonException("密码最大长度应为:{}", maxLengthInt); + } + } + // 密码复杂度 + String passwordComplexity = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordComplexity)){ + // 据复杂度配置判断 + boolean notLimit = ClientPasswordComplexityEnum.REG0.getValue().equals(passwordComplexity); + if(!notLimit){ + if(ClientPasswordComplexityEnum.REG1.getValue().equals(passwordComplexity)) { + String reg = "^(?=.*[0-9])(?=.*[a-zA-Z]).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", ClientPasswordComplexityEnum.REG1.getMessage()); + } + } + if(ClientPasswordComplexityEnum.REG2.getValue().equals(passwordComplexity)) { + String reg = "^(?=.*[0-9])(?=.*[A-Z]).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", ClientPasswordComplexityEnum.REG2.getMessage()); + } + } + if(ClientPasswordComplexityEnum.REG3.getValue().equals(passwordComplexity)) { + String reg = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9]).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", ClientPasswordComplexityEnum.REG3.getMessage()); + } + } + if(ClientPasswordComplexityEnum.REG4.getValue().equals(passwordComplexity)) { + String reg = "^(?:(?=.*[0-9])(?=.*[a-zA-Z])|(?=.*[0-9])(?=.*[^a-zA-Z0-9])|(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9])).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", ClientPasswordComplexityEnum.REG4.getMessage()); + } + } + if(ClientPasswordComplexityEnum.REG5.getValue().equals(passwordComplexity)) { + String reg = "^(?:(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])|(?=.*[0-9])(?=.*[a-z])(?=.*[^a-zA-Z0-9])|(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9])).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", ClientPasswordComplexityEnum.REG5.getMessage()); + } + } + } + } + // 密码不能连续存在相同字符个数 + String passwordNotAllowContinuousSameCharacterLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowContinuousSameCharacterLength)){ + // 密码不能连续存在相同字符个数 + Integer passwordNotAllowContinuousSameCharacterLengthInt = Convert.toInt(passwordNotAllowContinuousSameCharacterLength); + boolean hasConsecutiveChars = hasConsecutiveChars(newPassword, passwordNotAllowContinuousSameCharacterLengthInt); + if(hasConsecutiveChars){ + throw new CommonException("密码不可存在" + passwordNotAllowContinuousSameCharacterLengthInt + "个连续相同的字符"); + } + } + + // 密码不能使用弱密码库中密码开关 + String passwordNotAllowUseWeakFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowUseWeakFlag)){ + if(Convert.toBool(passwordNotAllowUseWeakFlag)){ + // 不能包含内置弱密码和自定义额外弱密码库中密码 + DevWeakPasswordApi devWeakPasswordApi = SpringUtil.getBean(DevWeakPasswordApi.class); + List weakPasswordList = devWeakPasswordApi.weakPasswordList(); + // 获取自定义额外弱密码库 + String passwordDefineWeakDatabase = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordDefineWeakDatabase)){ + weakPasswordList.addAll(StrUtil.split(passwordDefineWeakDatabase, StrUtil.COMMA)); + } + if(weakPasswordList.contains(newPassword)){ + throw new CommonException("密码不可使用弱密码"); + } + } + } + } + + /** + * 校验新密码(含用户信息等) + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(String userId, String account, String name, String phone, String email, String newPassword) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 密码不能包含用户信息开关 + String passwordNotAllowContainsUserInfoFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowContainsUserInfoFlag)){ + if(Convert.toBool(passwordNotAllowContainsUserInfoFlag)){ + // 账号,不能包含 + if(ObjectUtil.isNotEmpty(account) && newPassword.contains(account)){ + throw new CommonException("密码不可包含账号"); + } + // 姓名,不能包含拼音 + if(ObjectUtil.isNotEmpty(name) && newPassword.contains(PinyinUtil.getPinyin(name, ""))){ + throw new CommonException("密码不可包含姓名拼音"); + } + // 手机号,不能包含 + if(ObjectUtil.isNotEmpty(phone) && newPassword.contains(phone)){ + throw new CommonException("密码不可包含手机号"); + } + // 邮箱,不能包含前缀,即@字符之前内容 + if(ObjectUtil.isNotEmpty(email) && newPassword.contains(StrUtil.split(email, StrUtil.AT).get(0))){ + throw new CommonException("密码不可包含邮箱前缀"); + } + } + } + // 密码不能使用历史密码开关 + String passwordNotAllowUseHistoryFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowUseHistoryFlag)){ + if(Convert.toBool(passwordNotAllowUseHistoryFlag)){ + // 密码不能使用历史密码范围个数 + String passwordNotAllowContainsHistoryCount = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowContainsHistoryCount)){ + Integer passwordNotAllowContainsHistoryCountInt = Convert.toInt(passwordNotAllowContainsHistoryCount); + // 取前N次密码,进行判断 + ClientUserPasswordService clientUserPasswordService = SpringUtil.getBean(ClientUserPasswordService.class); + List userPasswordHistoryLimit = clientUserPasswordService.getUserPasswordHistoryLimit(userId, passwordNotAllowContainsHistoryCountInt); + if(ObjectUtil.isNotEmpty(userPasswordHistoryLimit)){ + if(userPasswordHistoryLimit.contains(CommonCryptogramUtil.doHashValue(newPassword))) { + throw new CommonException("密码不可包含历史密码"); + } + } + } + } + } + } + + /** + * 判断当前用户密码是否过期 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static boolean isUserPasswordExpired(String userId) { + // 先判断是否系统默认密码 + ClientUserService clientUserService = SpringUtil.getBean(ClientUserService.class); + ClientUser clientUser = clientUserService.queryEntity(userId); + String defaultPassword = getDefaultPassword(); + // 若是,则认为已过期,需要修改 + if(CommonCryptogramUtil.doHashValue(defaultPassword).equals(clientUser.getPassword())){ + return true; + } + ClientUserExtService clientUserExtService = SpringUtil.getBean(ClientUserExtService.class); + // 获取用户扩展信息 + ClientUserExt clientUserExt = clientUserExtService.getOne(new LambdaQueryWrapper().eq(ClientUserExt::getUserId, userId)); + if(ObjectUtil.isEmpty(clientUserExt)){ + // 无扩展信息的,直接认定为密码过期 + return true; + } else { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取密码有效期天数 + String passwordExpiredDays = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_C_KEY); + if(ObjectUtil.isEmpty(passwordExpiredDays)){ + throw new CommonException("请联系管理员配置密码有效期天数"); + } else { + // 判断上次密码修改时间距今天的天数 + long betweenDays = DateUtil.between(clientUserExt.getPasswordUpdateTime(), DateTime.now(), DateUnit.DAY, false); + // 如果距离今天已经超过了系统配置的有效期,则认为已过期 + return betweenDays >= Convert.toInt(passwordExpiredDays); + } + } + } + + /** + * 获取今日需要提醒密码到期的用户集合 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static List thisDayPasswordExpiredNeedNoticeUserIdList() { + List resultUserList = new ArrayList<>(); + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取密码有效期天数 + String passwordExpiredDays = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_C_KEY); + // 密码有效期配置如果不为空 + if(ObjectUtil.isNotEmpty(passwordExpiredDays)){ + // 获取密码过期前提醒天数 + String passwordExpiredNoticeDays = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_C_KEY); + // 密码过期前提醒天数如果不为空 + if(ObjectUtil.isNotEmpty(passwordExpiredDays)){ + // 获取密码修改日期距离提醒日的天数N + int noticeOffsetDays = Convert.toInt(passwordExpiredDays) - Convert.toInt(passwordExpiredNoticeDays); + // 提前提醒天数必须大于过期天数 + if(noticeOffsetDays > 0) { + // 今日需要提醒的,即密码修改日期为N天前的 + DateTime passWordUpdateTime = DateUtil.offsetDay(DateTime.now(), -noticeOffsetDays); + // 获取当天的开始时间 + DateTime beginDay = DateUtil.beginOfDay(passWordUpdateTime); + // 获取当天的结束时间 + DateTime endDay = DateUtil.endOfDay(passWordUpdateTime); + // 获取ClientUserExtService + ClientUserExtService clientUserExtService = SpringUtil.getBean(ClientUserExtService.class); + // 查询密码修改日期在该范围内的(无修改密码历史(即扩展信息为空)的无需提醒,会强制修改密码) + List userIdList = clientUserExtService.list(new LambdaQueryWrapper() + .between(ClientUserExt::getPasswordUpdateTime,beginDay, endDay)).stream() + .map(ClientUserExt::getUserId).collect(Collectors.toList()); + if(ObjectUtil.isNotEmpty(userIdList)){ + // 获取ClientUserService + ClientUserService clientUserService = SpringUtil.getBean(ClientUserService.class); + resultUserList = clientUserService.listByIds(userIdList); + } + } + } + } + return resultUserList; + } + + /** + * 判断字符串是否存在N个连续相同的字符 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + private static boolean hasConsecutiveChars(String str, int n) { + // 处理无效输入:字符串为空、n非正、或字符串长度不足 + if (str == null || n <= 0 || str.length() < n) { + return false; + } + // 特殊情况:n=1时只要字符串非空即存在连续1个字符 + if (n == 1) { + return true; + } + + int maxStartIndex = str.length() - n; + for (int i = 0; i <= maxStartIndex; i++) { + char currentChar = str.charAt(i); + boolean isConsecutive = true; + // 检查后续n-1个字符是否相同 + for (int j = 1; j < n; j++) { + if (str.charAt(i + j) != currentChar) { + isConsecutive = false; + break; + } + } + if (isConsecutive) { + return true; + } + } + return false; + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/relation/service/impl/ClientRelationServiceImpl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/relation/service/impl/ClientRelationServiceImpl.java index 70c57341..fd62bddd 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/relation/service/impl/ClientRelationServiceImpl.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/relation/service/impl/ClientRelationServiceImpl.java @@ -72,41 +72,49 @@ public class ClientRelationServiceImpl extends ServiceImpl targetIdList, String category) { this.saveRelationBatch(objectId, targetIdList, category, null, false); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithAppend(String objectId, List targetIdList, String category, List extJsonList) { this.saveRelationBatch(objectId, targetIdList, category, extJsonList, false); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationWithClear(String objectId, String targetId, String category) { this.saveRelation(objectId, targetId, category, null, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationWithClear(String objectId, String targetId, String category, String extJson) { this.saveRelation(objectId, targetId, category, extJson, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithClear(String objectId, List targetIdList, String category) { this.saveRelationBatch(objectId, targetIdList, category, null, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithClear(String objectId, List targetIdList, String category, List extJsonList) { this.saveRelationBatch(objectId, targetIdList, category, extJsonList, true); diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserCenterController.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserCenterController.java new file mode 100644 index 00000000..e589c18a --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserCenterController.java @@ -0,0 +1,363 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.controller; + +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import vip.xiaonuo.client.modular.user.param.*; +import vip.xiaonuo.client.modular.user.result.ClientUserPicValidCodeResult; +import vip.xiaonuo.client.modular.user.service.ClientUserService; +import vip.xiaonuo.common.annotation.CommonLog; +import vip.xiaonuo.common.pojo.CommonResult; + +import javax.validation.Valid; + +/** + * C端用户个人控制器 + * + * @author xuyuxiang + * @date 2022/4/22 9:34 + **/ +@Tag(name = "C端用户个人控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 2) +@RestController +@Validated +public class ClientUserCenterController { + + @Resource + private ClientUserService clientUserService; + + /** + * 获取图片验证码 + * + * @author xuyuxiang + * @date 2022/7/8 9:26 + **/ + @ApiOperationSupport(order = 1) + @Operation(summary = "获取图片验证码") + @GetMapping("/client/userCenter/getPicCaptcha") + public CommonResult getPicCaptcha() { + return CommonResult.data(clientUserService.getPicCaptcha()); + } + + /** + * 找回密码获取手机验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 2) + @Operation(summary = "找回密码获取手机验证码") + @GetMapping("/client/userCenter/findPasswordGetPhoneValidCode") + public CommonResult findPasswordGetPhoneValidCode(@Valid ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + return CommonResult.data(clientUserService.findPasswordGetPhoneValidCode(clientUserGetPhoneValidCodeParam)); + } + + /** + * 找回密码获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 3) + @Operation(summary = "找回密码获取邮箱验证码") + @GetMapping("/client/userCenter/findPasswordGetEmailValidCode") + public CommonResult findPasswordGetEmailValidCode(@Valid ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + return CommonResult.data(clientUserService.findPasswordGetEmailValidCode(clientUserGetEmailValidCodeParam)); + } + + /** + * 通过手机号找回用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 4) + @Operation(summary = "通过手机号找回用户密码") + @CommonLog("通过手机号找回用户密码") + @PostMapping("/client/userCenter/findPasswordByPhone") + public CommonResult findPasswordByPhone(@RequestBody @Valid ClientUserFindPwdByPhoneParam clientUserFindPwdByPhoneParam) { + clientUserService.findPasswordByPhone(clientUserFindPwdByPhoneParam); + return CommonResult.ok(); + } + + /** + * 通过邮箱找回用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 5) + @Operation(summary = "通过邮箱找回用户密码") + @CommonLog("通过邮箱找回用户密码") + @PostMapping("/client/userCenter/findPasswordByEmail") + public CommonResult findPasswordByEmail(@RequestBody @Valid ClientUserFindPwdByEmailParam clientUserFindPwdByEmailParam) { + clientUserService.findPasswordByEmail(clientUserFindPwdByEmailParam); + return CommonResult.ok(); + } + + /** + * 修改密码获取手机验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 6) + @Operation(summary = "修改密码获取手机验证码") + @GetMapping("/client/userCenter/updatePasswordGetPhoneValidCode") + public CommonResult updatePasswordGetPhoneValidCode(@Valid ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + return CommonResult.data(clientUserService.updatePasswordGetPhoneValidCode(clientUserGetPhoneValidCodeParam)); + } + + /** + * 修改密码获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 7) + @Operation(summary = "修改密码获取邮箱验证码") + @GetMapping("/client/userCenter/updatePasswordGetEmailValidCode") + public CommonResult updatePasswordGetEmailValidCode(@Valid ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + return CommonResult.data(clientUserService.updatePasswordGetEmailValidCode(clientUserGetEmailValidCodeParam)); + } + + /** + * 通过验证旧密码修改用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 8) + @Operation(summary = "通过验证旧密码修改用户密码") + @CommonLog("通过验证旧密码修改用户密码") + @PostMapping("/client/userCenter/updatePasswordByOld") + public CommonResult updatePasswordByOld(@RequestBody @Valid ClientUserUpdatePwdByOldParam clientUserUpdatePwdByOldParam) { + clientUserService.updatePasswordByOld(clientUserUpdatePwdByOldParam); + return CommonResult.ok(); + } + + /** + * 通过验证手机号修改用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 9) + @Operation(summary = "通过验证手机号修改用户密码") + @CommonLog("通过验证手机号修改用户密码") + @PostMapping("/client/userCenter/updatePasswordByPhone") + public CommonResult updatePasswordByPhone(@RequestBody @Valid ClientUserUpdatePwdByPhoneParam clientUserUpdatePwdByPhoneParam) { + clientUserService.updatePasswordByPhone(clientUserUpdatePwdByPhoneParam); + return CommonResult.ok(); + } + + /** + * 通过验证邮箱修改用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 10) + @Operation(summary = "通过验证邮箱修改用户密码") + @CommonLog("通过验证邮箱修改用户密码") + @PostMapping("/client/userCenter/updatePasswordByEmail") + public CommonResult updatePasswordByEmail(@RequestBody @Valid ClientUserUpdatePwdByEmailParam clientUserUpdatePwdByEmailParam) { + clientUserService.updatePasswordByEmail(clientUserUpdatePwdByEmailParam); + return CommonResult.ok(); + } + + /** + * 绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 11) + @Operation(summary = "绑定手机号获取手机验证码") + @GetMapping("/client/userCenter/bindPhoneGetPhoneValidCode") + public CommonResult bindPhoneGetPhoneValidCode(@Valid ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + return CommonResult.data(clientUserService.bindPhoneGetPhoneValidCode(clientUserGetPhoneValidCodeParam)); + } + + /** + * 修改绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 12) + @Operation(summary = "修改绑定手机号获取手机验证码") + @GetMapping("/client/userCenter/updateBindPhoneGetPhoneValidCode") + public CommonResult updateBindPhoneGetPhoneValidCode(@Valid ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + return CommonResult.data(clientUserService.updateBindPhoneGetPhoneValidCode(clientUserGetPhoneValidCodeParam)); + } + + /** + * 绑定手机号 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 13) + @Operation(summary = "绑定手机号") + @CommonLog("绑定手机号") + @PostMapping("/client/userCenter/bindPhone") + public CommonResult bindPhone(@RequestBody @Valid ClientUserBindPhoneParam clientUserBindPhoneParam) { + clientUserService.bindPhone(clientUserBindPhoneParam); + return CommonResult.ok(); + } + + /** + * 绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 14) + @Operation(summary = "绑定邮箱获取邮箱验证码") + @GetMapping("/client/userCenter/bindEmailGetEmailValidCode") + public CommonResult bindEmailGetEmailValidCode(@Valid ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + return CommonResult.data(clientUserService.bindEmailGetEmailValidCode(clientUserGetEmailValidCodeParam)); + } + + /** + * 修改绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 15) + @Operation(summary = "修改绑定邮箱获取邮箱验证码") + @GetMapping("/client/userCenter/updateBindEmailGetEmailValidCode") + public CommonResult updateBindEmailGetEmailValidCode(@Valid ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + return CommonResult.data(clientUserService.updateBindEmailGetEmailValidCode(clientUserGetEmailValidCodeParam)); + } + + /** + * 绑定邮箱 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 16) + @Operation(summary = "绑定邮箱") + @CommonLog("绑定邮箱") + @PostMapping("/client/userCenter/bindEmail") + public CommonResult bindEmail(@RequestBody @Valid ClientUserBindEmailParam clientUserBindEmailParam) { + clientUserService.bindEmail(clientUserBindEmailParam); + return CommonResult.ok(); + } + + /** + * 修改用户头像 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 17) + @Operation(summary = "修改用户头像") + @CommonLog("修改用户头像") + @PostMapping("/client/userCenter/updateAvatar") + public CommonResult updateAvatar(@RequestPart("file") MultipartFile file) { + return CommonResult.data(clientUserService.updateAvatar(file)); + } + + /** + * 修改用户签名图片 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 18) + @Operation(summary = "修改用户签名图片") + @CommonLog("修改用户签名图片") + @PostMapping("/client/userCenter/updateSignature") + public CommonResult updateSignature(@RequestBody @Valid ClientUserSignatureParam clientUserSignatureParam) { + clientUserService.updateSignature(clientUserSignatureParam); + return CommonResult.ok(); + } + + /** + * 编辑个人信息 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 19) + @Operation(summary = "编辑个人信息") + @CommonLog("编辑个人信息") + @PostMapping("/client/userCenter/updateUserInfo") + public CommonResult updateUserInfo(@RequestBody @Valid ClientUserUpdateInfoParam clientUserUpdateInfoParam) { + clientUserService.updateUserInfo(clientUserUpdateInfoParam); + return CommonResult.ok(); + } + + /** + * 根据id获取头像 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 20) + @Operation(summary = "根据id获取头像") + @GetMapping("/client/userCenter/getAvatarById") + public CommonResult getAvatarById(@Valid ClientUserIdParam clientUserIdParam) { + return CommonResult.data(clientUserService.getAvatarById(clientUserIdParam)); + } + + /** + * 判断当前用户是否需要绑定手机号 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 21) + @Operation(summary = "判断当前用户是否需要绑定手机号") + @GetMapping("/client/userCenter/isUserNeedBindPhone") + public CommonResult isUserNeedBindPhone() { + return CommonResult.data(clientUserService.isUserNeedBindPhone()); + } + + /** + * 判断当前用户是否需要绑定邮箱 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 22) + @Operation(summary = "判断当前用户是否需要绑定邮箱") + @GetMapping("/client/userCenter/isUserNeedBindEmail") + public CommonResult isUserNeedBindEmail() { + return CommonResult.data(clientUserService.isUserNeedBindEmail()); + } + + /** + * 判断当前用户密码是否过期 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 21) + @Operation(summary = "判断当前用户密码是否过期") + @GetMapping("/client/userCenter/isUserPasswordExpired") + public CommonResult isUserPasswordExpired() { + return CommonResult.data(clientUserService.isUserPasswordExpired()); + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserController.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserController.java index d471048a..b36c8268 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserController.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/controller/ClientUserController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.client.modular.user.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import vip.xiaonuo.client.modular.user.entity.ClientUser; +import vip.xiaonuo.client.modular.user.enums.ClientUserSourceFromTypeEnum; import vip.xiaonuo.client.modular.user.param.ClientUserAddParam; import vip.xiaonuo.client.modular.user.param.ClientUserEditParam; import vip.xiaonuo.client.modular.user.param.ClientUserIdParam; @@ -32,6 +34,7 @@ import vip.xiaonuo.client.modular.user.service.ClientUserService; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +44,7 @@ import java.util.List; * @date 2022/4/22 9:34 **/ @Tag(name = "C端用户控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 1) @RestController @Validated public class ClientUserController { @@ -49,39 +53,42 @@ public class ClientUserController { private ClientUserService clientUserService; /** - * 获取C端用户分页 + * 获取用户分页 * * @author xuyuxiang * @date 2022/4/24 20:00 */ - @Operation(summary = "获取C端用户分页") + @ApiOperationSupport(order = 1) + @Operation(summary = "获取用户分页") @GetMapping("/client/user/page") public CommonResult> page(ClientUserPageParam clientUserPageParam) { return CommonResult.data(clientUserService.page(clientUserPageParam)); } /** - * 添加C端用户 + * 添加用户 * * @author xuyuxiang * @date 2022/4/24 20:47 */ - @Operation(summary = "添加C端用户") - @CommonLog("添加C端用户") + @ApiOperationSupport(order = 2) + @Operation(summary = "添加用户") + @CommonLog("添加用户") @PostMapping("/client/user/add") public CommonResult add(@RequestBody @Valid ClientUserAddParam clientUserAddParam) { - clientUserService.add(clientUserAddParam); + clientUserService.add(clientUserAddParam, ClientUserSourceFromTypeEnum.SYSTEM_ADD.getValue()); return CommonResult.ok(); } /** - * 编辑C端用户 + * 编辑用户 * * @author xuyuxiang * @date 2022/4/24 20:47 */ - @Operation(summary = "编辑C端用户") - @CommonLog("编辑C端用户") + @ApiOperationSupport(order = 3) + @Operation(summary = "编辑用户") + @CommonLog("编辑用户") @PostMapping("/client/user/edit") public CommonResult edit(@RequestBody @Valid ClientUserEditParam clientUserEditParam) { clientUserService.edit(clientUserEditParam); @@ -89,27 +96,29 @@ public class ClientUserController { } /** - * 删除C端用户 + * 删除用户 * * @author xuyuxiang * @date 2022/4/24 20:00 */ - @Operation(summary = "删除C端用户") - @CommonLog("删除C端用户") + @ApiOperationSupport(order = 4) + @Operation(summary = "删除用户") + @CommonLog("删除用户") @PostMapping("/client/user/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List clientUserIdParamList) { + List clientUserIdParamList) { clientUserService.delete(clientUserIdParamList); return CommonResult.ok(); } /** - * 获取C端用户详情 + * 获取用户详情 * * @author xuyuxiang * @date 2022/4/24 20:00 */ - @Operation(summary = "获取C端用户详情") + @ApiOperationSupport(order = 5) + @Operation(summary = "获取用户详情") @GetMapping("/client/user/detail") public CommonResult detail(@Valid ClientUserIdParam clientUserIdParam) { return CommonResult.data(clientUserService.detail(clientUserIdParam)); diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUser.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUser.java index 36c9ef0d..4e8f3031 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUser.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUser.java @@ -43,12 +43,12 @@ public class ClientUser extends CommonEntity { /** 头像 */ @Schema(description = "头像,图片base64") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String avatar; /** 签名 */ @Schema(description = "签名,图片base64") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String signature; /** 账号 */ @@ -66,118 +66,118 @@ public class ClientUser extends CommonEntity { /** 昵称 */ @Schema(description = "昵称") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nickname; /** 性别 */ @Schema(description = "性别") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.DICTIONARY, key = "GENDER") private String gender; /** 年龄 */ @Schema(description = "年龄") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String age; /** 出生日期 */ @Schema(description = "出生日期") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String birthday; /** 民族 */ @Schema(description = "民族") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nation; /** 籍贯 */ @Schema(description = "籍贯") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nativePlace; /** 家庭住址 */ @Schema(description = "家庭住址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String homeAddress; /** 通信地址 */ @Schema(description = "通信地址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String mailingAddress; /** 证件类型 */ @Schema(description = "证件类型") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String idCardType; /** 证件号码 */ @Schema(description = "证件号码") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String idCardNumber; /** 文化程度 */ @Schema(description = "文化程度") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String cultureLevel; /** 政治面貌 */ @Schema(description = "政治面貌") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String politicalOutlook; /** 毕业院校 */ @Schema(description = "毕业院校") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String college; /** 学历 */ @Schema(description = "学历") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String education; /** 学制 */ @Schema(description = "学制") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String eduLength; /** 学位 */ @Schema(description = "学位") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String degree; /** 手机 */ @Schema(description = "手机") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String phone; /** 邮箱 */ @Schema(description = "邮箱") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String email; /** 家庭电话 */ @Schema(description = "家庭电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String homeTel; /** 办公电话 */ @Schema(description = "办公电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String officeTel; /** 紧急联系人 */ @Schema(description = "紧急联系人") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String emergencyContact; /** 紧急联系人电话 */ @Schema(description = "紧急联系人电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String emergencyPhone; /** 紧急联系人地址 */ @Schema(description = "紧急联系人地址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String emergencyAddress; /** 上次登录ip */ @@ -222,6 +222,6 @@ public class ClientUser extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserExt.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserExt.java new file mode 100644 index 00000000..4778facd --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserExt.java @@ -0,0 +1,52 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +import java.util.Date; + +/** + * C端用户扩展实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("CLIENT_USER_EXT") +public class ClientUserExt extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 用户id */ + @Schema(description = "用户id") + private String userId; + + /** 来源类别 */ + @Schema(description = "来源类别") + private String sourceFromType; + + /** 密码修改日期 */ + @Schema(description = "密码修改日期") + private Date passwordUpdateTime; + +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserPassword.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserPassword.java new file mode 100644 index 00000000..550d2a54 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/entity/ClientUserPassword.java @@ -0,0 +1,46 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +/** + * C端用户密码实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("CLIENT_USER_PASSWORD") +public class ClientUserPassword extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 用户id */ + @Schema(description = "用户id") + private String userId; + + /** 密码 */ + @Schema(description = "密码") + private String password; + +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUpdatePasswordValidTypeEnum.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUpdatePasswordValidTypeEnum.java new file mode 100644 index 00000000..af468a1c --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUpdatePasswordValidTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.enums; + +import lombok.Getter; + +/** + * 系统修改密码验证方式枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum ClientUpdatePasswordValidTypeEnum { + + /** 旧密码 */ + OLD("OLD"), + + /** 手机号 */ + PHONE("PHONE"), + + /** 邮箱 */ + EMAIL("EMAIL"); + + private final String value; + + ClientUpdatePasswordValidTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUserSourceFromTypeEnum.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUserSourceFromTypeEnum.java new file mode 100644 index 00000000..5f07de5d --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/enums/ClientUserSourceFromTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.enums; + +import lombok.Getter; + +/** + * 用户来源类型枚举 + * + * @author xuyuxiang + * @date 2022/4/21 19:56 + **/ +@Getter +public enum ClientUserSourceFromTypeEnum { + + /** 系统自建 */ + SYSTEM_ADD("SYSTEM_ADD"), + + /** 用户注册 */ + SYSTEM_REGISTER("SYSTEM_REGISTER"), + + /** 身份源 */ + ID_SOURCE("ID_SOURCE"); + + private final String value; + + ClientUserSourceFromTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserExtMapper.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserExtMapper.java new file mode 100644 index 00000000..46cd9371 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserExtMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.client.modular.user.entity.ClientUserExt; + +/** + * C端用户扩展Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface ClientUserExtMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserPasswordMapper.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserPasswordMapper.java new file mode 100644 index 00000000..78862c8d --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/ClientUserPasswordMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.client.modular.user.entity.ClientUserPassword; + +/** + * C端用户密码Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface ClientUserPasswordMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserExtMapper.xml b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserExtMapper.xml new file mode 100644 index 00000000..d5550ce0 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserExtMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserPasswordMapper.xml b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserPasswordMapper.xml new file mode 100644 index 00000000..1171b472 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/mapper/mapping/ClientUserPasswordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserAddParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserAddParam.java index 5291c09f..99bfe877 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserAddParam.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserAddParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * C端用户添加参数 + * 用户添加参数 * * @author xuyuxiang * @date 2022/4/21 16:13 @@ -37,6 +37,10 @@ public class ClientUserAddParam { @NotBlank(message = "name不能为空") private String name; + /** 密码 */ + @Schema(description = "密码") + private String password; + /** 头像 */ @Schema(description = "头像,图片base64") private String avatar; diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindEmailParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindEmailParam.java new file mode 100644 index 00000000..d950194d --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindEmailParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 绑定邮箱参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserBindEmailParam { + + /** 邮箱 */ + @Schema(description = "邮箱") + @NotBlank(message = "email不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindPhoneParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindPhoneParam.java new file mode 100644 index 00000000..4b3cd4ea --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserBindPhoneParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 绑定手机号参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserBindPhoneParam { + + /** 手机号 */ + @Schema(description = "手机号") + @NotBlank(message = "phone不能为空") + private String phone; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserEditParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserEditParam.java index d6ca910b..38a4dad7 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserEditParam.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserEditParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * C端用户参数 + * 用户编辑参数 * * @author xuyuxiang * @date 2022/4/21 16:13 diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByEmailParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByEmailParam.java new file mode 100644 index 00000000..7ccbc7c7 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByEmailParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户找回密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserFindPwdByEmailParam { + + /** 邮箱 */ + @Schema(description = "邮箱") + @NotBlank(message = "email不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByPhoneParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByPhoneParam.java new file mode 100644 index 00000000..64a6495c --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserFindPwdByPhoneParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户找回密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserFindPwdByPhoneParam { + + /** 手机号 */ + @Schema(description = "手机号") + @NotBlank(message = "phone不能为空") + private String phone; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetEmailValidCodeParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetEmailValidCodeParam.java new file mode 100644 index 00000000..0e7db7e7 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetEmailValidCodeParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 获取邮箱验证码参数 + * + * @author xuyuxiang + * @date 2022/8/25 13:45 + **/ +@Getter +@Setter +public class ClientUserGetEmailValidCodeParam { + + /** 邮箱 */ + @Schema(description = "邮箱") + @NotBlank(message = "邮箱不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "验证码不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "验证码请求号不能为空") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetPhoneValidCodeParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetPhoneValidCodeParam.java new file mode 100644 index 00000000..f291fab5 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserGetPhoneValidCodeParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 获取手机验证码参数 + * + * @author xuyuxiang + * @date 2022/8/25 13:45 + **/ +@Getter +@Setter +public class ClientUserGetPhoneValidCodeParam { + + /** 手机号 */ + @Schema(description = "手机号") + @NotBlank(message = "手机号不能为空") + private String phone; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "验证码不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "验证码请求号不能为空") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserIdParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserIdParam.java index e98c7a89..fb28ad46 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserIdParam.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserIdParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * C端用户Id参数 + * 用户Id参数 * * @author xuyuxiang * @date 2022/4/21 16:13 diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserPageParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserPageParam.java index 39bf173f..e04571c7 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserPageParam.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserPageParam.java @@ -17,7 +17,7 @@ import lombok.Getter; import lombok.Setter; /** - * C端用户参数 + * 用户查询参数 * * @author xuyuxiang * @date 2022/4/21 16:13 diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserSignatureParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserSignatureParam.java new file mode 100644 index 00000000..ff1d7f96 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserSignatureParam.java @@ -0,0 +1,34 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户修改签名图片参数 + * + * @author yubaoshan + * @date 2022/9/7 23:12 + **/ +@Getter +@Setter +public class ClientUserSignatureParam { + + /** 签名图片base64编码 */ + @Schema(description = "signature") + @NotBlank(message = "signature签名图片不能为空") + private String signature; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdateInfoParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdateInfoParam.java new file mode 100644 index 00000000..7b1b52bf --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdateInfoParam.java @@ -0,0 +1,51 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户编辑个人信息参数 + * + * @author xuyuxiang + * @date 2022/7/27 17:08 + **/ +@Getter +@Setter +public class ClientUserUpdateInfoParam { + + /** id */ + @Schema(description = "id") + @NotBlank(message = "id不能为空") + private String id; + + /** 姓名 */ + @Schema(description = "姓名") + @NotBlank(message = "name不能为空") + private String name; + + /** 昵称 */ + @Schema(description = "昵称") + private String nickname; + + /** 性别 */ + @Schema(description = "性别") + private String gender; + + /** 出生日期 */ + @Schema(description = "出生日期") + private String birthday; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByEmailParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByEmailParam.java new file mode 100644 index 00000000..adb206fe --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByEmailParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户通过验证邮箱修改密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserUpdatePwdByEmailParam { + + /** 邮箱 */ + @Schema(description = "邮箱") + @NotBlank(message = "email不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByOldParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByOldParam.java new file mode 100644 index 00000000..2965efac --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByOldParam.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户通过验证旧密码修改密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserUpdatePwdByOldParam { + + /** 旧密码 */ + @Schema(description = "旧密码") + @NotBlank(message = "password不能为空") + private String password; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByPhoneParam.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByPhoneParam.java new file mode 100644 index 00000000..75321853 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/param/ClientUserUpdatePwdByPhoneParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户通过验证手机号修改密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class ClientUserUpdatePwdByPhoneParam { + + /** 手机号 */ + @Schema(description = "手机号") + @NotBlank(message = "phone不能为空") + private String phone; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/provider/ClientLoginUserApiProvider.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/provider/ClientLoginUserApiProvider.java index a71e838a..4b99f058 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/provider/ClientLoginUserApiProvider.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/provider/ClientLoginUserApiProvider.java @@ -12,6 +12,7 @@ */ package vip.xiaonuo.client.modular.user.provider; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; @@ -20,6 +21,7 @@ import org.springframework.stereotype.Service; import vip.xiaonuo.auth.api.SaBaseLoginUserApi; import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser; import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; +import vip.xiaonuo.client.modular.user.entity.ClientUser; import vip.xiaonuo.client.modular.user.result.ClientLoginUser; import vip.xiaonuo.client.modular.user.service.ClientUserService; @@ -93,6 +95,11 @@ public class ClientLoginUserApiProvider implements SaBaseLoginUserApi { return null; } + @Override + public SaBaseLoginUser getUserByEmail(String email) { + return null; + } + /** * 根据手机号获取C端用户信息,查不到则返回null * @@ -104,6 +111,11 @@ public class ClientLoginUserApiProvider implements SaBaseLoginUserApi { return clientUserService.getUserByPhone(phone); } + @Override + public SaBaseClientLoginUser getClientUserByEmail(String email) { + return clientUserService.getUserByEmail(email); + } + /** * 根据用户id获取用户集合 * @@ -173,4 +185,31 @@ public class ClientLoginUserApiProvider implements SaBaseLoginUserApi { public void updateUserLoginInfo(String userId, String device) { clientUserService.updateUserLoginInfo(userId, device); } -} \ No newline at end of file + + @Override + public SaBaseLoginUser createUserWithPhone(String phone) { + return null; + } + + @Override + public SaBaseClientLoginUser createClientUserWithPhone(String phone) { + ClientUser clientUser = clientUserService.createUserWithPhone(phone); + return BeanUtil.copyProperties(clientUser, SaBaseClientLoginUser.class); + } + + @Override + public SaBaseLoginUser createUserWithEmail(String email) { + return null; + } + + @Override + public SaBaseClientLoginUser createClientUserWithEmail(String email) { + ClientUser clientUser = clientUserService.createUserWithEmail(email); + return BeanUtil.copyProperties(clientUser, SaBaseClientLoginUser.class); + } + + @Override + public void doRegister(String account, String password) { + clientUserService.doRegister(account, password); + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/result/ClientUserPicValidCodeResult.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/result/ClientUserPicValidCodeResult.java new file mode 100644 index 00000000..0bcacc7f --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/result/ClientUserPicValidCodeResult.java @@ -0,0 +1,36 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.result; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * 图片验证码结果 + * + * @author xuyuxiang + * @date 2022/7/8 9:28 + **/ +@Getter +@Setter +public class ClientUserPicValidCodeResult { + + /** 验证码图片,Base64 */ + @Schema(description = "验证码图片,Base64") + private String validCodeBase64; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserExtService.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserExtService.java new file mode 100644 index 00000000..044f5c34 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserExtService.java @@ -0,0 +1,41 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.client.modular.user.entity.ClientUserExt; + +/** + * C端用户扩展Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface ClientUserExtService extends IService { + + /** + * 更新用户最新修改密码时间 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void updatePasswordLastTime(String userId); + + /** + * 插入扩展信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void createExtInfo(String userId, String sourceFromType); +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserPasswordService.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserPasswordService.java new file mode 100644 index 00000000..82eb1ccb --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserPasswordService.java @@ -0,0 +1,43 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.client.modular.user.entity.ClientUserPassword; + +import java.util.List; + +/** + * C端用户密码Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface ClientUserPasswordService extends IService { + + /** + * 追加用户历史密码信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void insertUserPasswordHistory(String userId, String newPassword); + + /** + * 获取用户前N个历史密码 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + List getUserPasswordHistoryLimit(String userId, int limitValue); +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserService.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserService.java index 6bd00084..66022b3d 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserService.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/ClientUserService.java @@ -14,17 +14,16 @@ package vip.xiaonuo.client.modular.user.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.client.modular.user.entity.ClientUser; -import vip.xiaonuo.client.modular.user.param.ClientUserAddParam; -import vip.xiaonuo.client.modular.user.param.ClientUserEditParam; -import vip.xiaonuo.client.modular.user.param.ClientUserIdParam; -import vip.xiaonuo.client.modular.user.param.ClientUserPageParam; +import vip.xiaonuo.client.modular.user.param.*; import vip.xiaonuo.client.modular.user.result.ClientLoginUser; +import vip.xiaonuo.client.modular.user.result.ClientUserPicValidCodeResult; import java.util.List; /** - * C端用户Service接口 + * 用户Service接口 * * @author xuyuxiang * @date 2022/4/21 18:35 @@ -64,7 +63,7 @@ public interface ClientUserService extends IService { ClientLoginUser getUserByEmail(String email); /** - * 获取C端用户分页 + * 获取用户分页 * * @author xuyuxiang * @date 2022/4/24 20:08 @@ -72,15 +71,15 @@ public interface ClientUserService extends IService { Page page(ClientUserPageParam clientUserPageParam); /** - * 添加C端用户 + * 添加用户 * * @author xuyuxiang * @date 2022/4/24 20:48 */ - void add(ClientUserAddParam clientUserAddParam); + void add(ClientUserAddParam clientUserAddParam, String sourceFromType); /** - * 编辑C端用户 + * 编辑用户 * * @author xuyuxiang * @date 2022/4/24 21:13 @@ -88,7 +87,7 @@ public interface ClientUserService extends IService { void edit(ClientUserEditParam clientUserEditParam); /** - * 删除C端用户 + * 删除用户 * * @author xuyuxiang * @date 2022/4/24 21:18 @@ -96,7 +95,7 @@ public interface ClientUserService extends IService { void delete(List clientUserIdParamList); /** - * 获取C端用户详情 + * 获取用户详情 * * @author xuyuxiang * @date 2022/4/24 21:18 @@ -104,7 +103,159 @@ public interface ClientUserService extends IService { ClientUser detail(ClientUserIdParam clientUserIdParam); /** - * 更新C端用户的登录时间和登录ip等信息 + * 获取用户详情 + * + * @author xuyuxiang + * @date 2022/4/24 21:18 + */ + ClientUser queryEntity(String id); + + /** + * 获取图片验证码 + * + * @author xuyuxiang + * @date 2021/12/28 14:46 + **/ + ClientUserPicValidCodeResult getPicCaptcha(); + + /** + * 找回密码获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String findPasswordGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam); + + /** + * 找回密码获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String findPasswordGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam); + + /** + * 通过手机号找回用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void findPasswordByPhone(ClientUserFindPwdByPhoneParam clientUserFindPwdByPhoneParam); + + /** + * 通过邮箱找回用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void findPasswordByEmail(ClientUserFindPwdByEmailParam clientUserFindPwdByEmailParam); + + /** + * 修改密码获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updatePasswordGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam); + + /** + * 修改密码获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updatePasswordGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam); + + /** + * 通过验证旧密码修改用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void updatePasswordByOld(ClientUserUpdatePwdByOldParam clientUserUpdatePwdByOldParam); + + /** + * 通过验证手机号修改用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void updatePasswordByPhone(ClientUserUpdatePwdByPhoneParam clientUserUpdatePwdByPhoneParam); + + /** + * 通过验证邮箱修改用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void updatePasswordByEmail(ClientUserUpdatePwdByEmailParam clientUserUpdatePwdByEmailParam); + + /** + * 绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String bindPhoneGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam); + + /** + * 修改绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updateBindPhoneGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam); + + /** + * 绑定手机号 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void bindPhone(ClientUserBindPhoneParam clientUserBindPhoneParam); + + /** + * 绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String bindEmailGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam); + + /** + * 修改绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updateBindEmailGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam); + + /** + * 绑定邮箱 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void bindEmail(ClientUserBindEmailParam clientUserBindEmailParam); + + /** + * 修改用户头像返回base64 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + String updateAvatar(MultipartFile file); + + /** + * 修改用户签名图片返回base64 + * + * @author xuyuxiang yubaoshan + * @date 2022/4/22 15:53 + **/ + void updateSignature(ClientUserSignatureParam clientUserSignatureParam); + + /** + * 更新用户的登录时间和登录ip等信息 * * @author xuyuxiang * @date 2022/4/27 22:58 @@ -112,10 +263,82 @@ public interface ClientUserService extends IService { void updateUserLoginInfo(String userId, String device); /** - * 获取C端用户详情 + * 编辑个人信息 * * @author xuyuxiang - * @date 2022/4/24 21:18 + * @date 2022/4/24 20:47 */ - ClientUser queryEntity(String id); + void updateUserInfo(ClientUserUpdateInfoParam clientUserUpdateInfoParam); + + /** + * 根据id获取头像 + * + * @author xuyuxiang + * @date 2023/8/28 10:10 + **/ + String getAvatarById(ClientUserIdParam clientUserIdParam); + + /** + * 根据手机号创建用户 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + ClientUser createUserWithPhone(String phone); + + /** + * 根据邮箱创建用户 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + ClientUser createUserWithEmail(String email); + + /** + * 根据账号密码创建用户 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + ClientUser createUserWithAccount(String account, String password); + + /** + * 判断当前用户密码是否过期 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + Boolean isUserPasswordExpired(); + + /** + * 判断当前用户是否需要绑定手机号 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + Boolean isUserNeedBindPhone(); + + /** + * 判断当前用户是否需要绑定邮箱 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + Boolean isUserNeedBindEmail(); + + /** + * 通知用户密码即将到期 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void noticeUserPasswordAboutToExpired(); + + /** + * 执行注册 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void doRegister(String account, String password); } diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserExtServiceImpl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserExtServiceImpl.java new file mode 100644 index 00000000..16745d30 --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserExtServiceImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.client.modular.user.entity.ClientUserExt; +import vip.xiaonuo.client.modular.user.enums.ClientUserSourceFromTypeEnum; +import vip.xiaonuo.client.modular.user.mapper.ClientUserExtMapper; +import vip.xiaonuo.client.modular.user.service.ClientUserExtService; + +/** + * C端用户扩展Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class ClientUserExtServiceImpl extends ServiceImpl implements ClientUserExtService { + + @Override + public void updatePasswordLastTime(String userId) { + ClientUserExt clientUserExt = this.getOne(new LambdaQueryWrapper().eq(ClientUserExt::getUserId, userId)); + if(ObjectUtil.isEmpty(clientUserExt)){ + clientUserExt = new ClientUserExt(); + clientUserExt.setUserId(userId); + clientUserExt.setSourceFromType(ClientUserSourceFromTypeEnum.SYSTEM_ADD.getValue()); + clientUserExt.setPasswordUpdateTime(DateTime.now()); + this.save(clientUserExt); + } else { + clientUserExt.setPasswordUpdateTime(DateTime.now()); + this.updateById(clientUserExt); + } + } + + @Override + public void createExtInfo(String userId, String sourceFromType) { + ClientUserExt clientUserExt = new ClientUserExt(); + clientUserExt.setUserId(userId); + clientUserExt.setSourceFromType(sourceFromType); + clientUserExt.setPasswordUpdateTime(DateTime.now()); + this.save(clientUserExt); + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserPasswordServiceImpl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserPasswordServiceImpl.java new file mode 100644 index 00000000..c45377ee --- /dev/null +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserPasswordServiceImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.client.modular.user.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.client.modular.user.entity.ClientUserPassword; +import vip.xiaonuo.client.modular.user.mapper.ClientUserPasswordMapper; +import vip.xiaonuo.client.modular.user.service.ClientUserPasswordService; +import vip.xiaonuo.common.util.CommonCryptogramUtil; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * C端用户密码Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class ClientUserPasswordServiceImpl extends ServiceImpl implements ClientUserPasswordService { + + @Override + public void insertUserPasswordHistory(String userId, String newPassword) { + ClientUserPassword clientUserPassword = new ClientUserPassword(); + clientUserPassword.setUserId(userId); + clientUserPassword.setPassword(CommonCryptogramUtil.doHashValue(newPassword)); + this.save(clientUserPassword); + } + + @Override + public List getUserPasswordHistoryLimit(String userId, int limitValue) { + return this.page(new Page<>(1, limitValue), new LambdaQueryWrapper() + .eq(ClientUserPassword::getUserId, userId).orderByDesc(ClientUserPassword::getCreateTime)) + .getRecords().stream().map(ClientUserPassword::getPassword).collect(Collectors.toList()); + } +} diff --git a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java index a93ab1f1..72c44791 100644 --- a/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java +++ b/snowy-plugin/snowy-plugin-client/src/main/java/vip/xiaonuo/client/modular/user/service/impl/ClientUserServiceImpl.java @@ -12,37 +12,60 @@ */ package vip.xiaonuo.client.modular.user.service.impl; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.CircleCaptcha; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateTime; +import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.PhoneUtil; +import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fhs.trans.service.impl.TransService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import vip.xiaonuo.client.modular.relation.service.ClientRelationService; +import org.springframework.web.multipart.MultipartFile; +import vip.xiaonuo.auth.core.util.StpClientUtil; +import vip.xiaonuo.auth.core.util.StpLoginUserUtil; +import vip.xiaonuo.client.core.util.ClientEmailFormatUtl; +import vip.xiaonuo.client.core.util.ClientPasswordUtl; import vip.xiaonuo.client.modular.user.entity.ClientUser; +import vip.xiaonuo.client.modular.user.entity.ClientUserExt; +import vip.xiaonuo.client.modular.user.enums.ClientUpdatePasswordValidTypeEnum; +import vip.xiaonuo.client.modular.user.enums.ClientUserSourceFromTypeEnum; import vip.xiaonuo.client.modular.user.enums.ClientUserStatusEnum; import vip.xiaonuo.client.modular.user.mapper.ClientUserMapper; -import vip.xiaonuo.client.modular.user.param.ClientUserAddParam; -import vip.xiaonuo.client.modular.user.param.ClientUserEditParam; -import vip.xiaonuo.client.modular.user.param.ClientUserIdParam; -import vip.xiaonuo.client.modular.user.param.ClientUserPageParam; +import vip.xiaonuo.client.modular.user.param.*; import vip.xiaonuo.client.modular.user.result.ClientLoginUser; +import vip.xiaonuo.client.modular.user.result.ClientUserPicValidCodeResult; +import vip.xiaonuo.client.modular.user.service.ClientUserExtService; +import vip.xiaonuo.client.modular.user.service.ClientUserPasswordService; import vip.xiaonuo.client.modular.user.service.ClientUserService; +import vip.xiaonuo.common.cache.CommonCacheOperator; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; import vip.xiaonuo.common.util.*; import vip.xiaonuo.dev.api.DevConfigApi; +import vip.xiaonuo.dev.api.DevEmailApi; +import vip.xiaonuo.dev.api.DevSmsApi; +import java.awt.image.BufferedImage; +import java.io.IOException; import java.util.List; +import java.util.Objects; /** * C端用户Service接口实现类 @@ -53,16 +76,80 @@ import java.util.List; @Service public class ClientUserServiceImpl extends ServiceImpl implements ClientUserService { - private static final String SNOWY_SYS_DEFAULT_PASSWORD_KEY = "SNOWY_SYS_DEFAULT_PASSWORD"; + /** C端验证码失效时间(适用图片验证码和短信验证码,单位:分钟,默认5分钟有效) */ + private static final String SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C"; + + /** C端重置密码验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_C"; + + /** C端重置密码验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_C"; + + /** C端修改密码验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C"; + + /** C端修改密码验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C"; + + /** C端重置密码成功短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C"; + + /** C端重置密码成功邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C"; + + /** C端密码即将到期短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C"; + + /** C端密码即将到期邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C"; + + /** C端绑定手机验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_C"; + + /** C端绑定邮箱验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_C"; + + /** C端修改绑定手机验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_C"; + + /** C端修改绑定邮箱验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_C"; + + /** C端注册账号成功短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C_KEY = "SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C"; + + /** C端注册账号成功邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C_KEY = "SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C"; + + /** C端注册后是否需要绑定手机号 */ + private static final String SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_C_KEY = "SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_C"; + + /** C端注册后是否需要绑定邮箱 */ + private static final String SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_C_KEY = "SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_C"; + + /** 验证码缓存前缀 */ + private static final String USER_VALID_CODE_CACHE_KEY = "user-validCode:"; @Resource - private DevConfigApi devConfigApi; + private CommonCacheOperator commonCacheOperator; + + @Resource + private DevSmsApi devSmsApi; @Resource private TransService transService; @Resource - private ClientRelationService clientRelationService; + private DevEmailApi devEmailApi; + + @Resource + private DevConfigApi devConfigApi; + + @Resource + private ClientUserExtService clientUserExtService; + + @Resource + private ClientUserPasswordService clientUserPasswordService; @Override public ClientLoginUser getUserById(String id) { @@ -123,18 +210,26 @@ public class ClientUserServiceImpl extends ServiceImpl() @@ -187,7 +282,7 @@ public class ClientUserServiceImpl extends ServiceImpl() @@ -224,6 +319,35 @@ public class ClientUserServiceImpl extends ServiceImpl lambdaUpdateWrapper = new LambdaUpdateWrapper().eq(ClientUser::getId, clientUser.getId()); + if(ObjectUtil.isNotEmpty(clientUserUpdateInfoParam.getName())) { + lambdaUpdateWrapper.set(ClientUser::getName, clientUserUpdateInfoParam.getName()); + } + if(ObjectUtil.isNotEmpty(clientUserUpdateInfoParam.getNickname())) { + lambdaUpdateWrapper.set(ClientUser::getNickname, clientUserUpdateInfoParam.getNickname()); + } + if(ObjectUtil.isNotEmpty(clientUserUpdateInfoParam.getGender())) { + lambdaUpdateWrapper.set(ClientUser::getGender, clientUserUpdateInfoParam.getGender()); + } + if(ObjectUtil.isNotEmpty(clientUserUpdateInfoParam.getBirthday())) { + lambdaUpdateWrapper.set(ClientUser::getBirthday, clientUserUpdateInfoParam.getBirthday()); + } + // 更新指定字段 + this.update(lambdaUpdateWrapper); + } + + @Override + public String getAvatarById(ClientUserIdParam clientUserIdParam) { + return this.detail(clientUserIdParam).getAvatar(); + } + @Override public ClientUser queryEntity(String id) { ClientUser clientUser = this.getById(id); @@ -232,4 +356,792 @@ public class ClientUserServiceImpl extends ServiceImpl().eq(ClientUser::getPhone, + CommonCryptogramUtil.doSm4CbcEncrypt(phone)).set(ClientUser::getPassword, + CommonCryptogramUtil.doHashValue(newPassword))); + // 更新用户最新修改密码时间 + clientUserExtService.updatePasswordLastTime(clientLoginUser.getId()); + // 追加用户历史密码信息 + clientUserPasswordService.insertUserPasswordHistory(clientLoginUser.getId(), newPassword); + // 重置密码成功短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("userNewPassword", newPassword); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } + } + + @Override + public void findPasswordByEmail(ClientUserFindPwdByEmailParam clientUserFindPwdByEmailParam) { + // 再次校验邮箱是否合法 + String email = clientUserFindPwdByEmailParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 根据邮箱获取用户信息,判断用户是否存在 + ClientLoginUser clientLoginUser = this.getUserByEmail(email); + if (ObjectUtil.isEmpty(clientLoginUser)) { + throw new CommonException("邮箱:{}不存在对应用户", email); + } + // 执行校验验证码 + validValidCode(email, clientUserFindPwdByEmailParam.getValidCode(), clientUserFindPwdByEmailParam.getValidCodeReqNo()); + // 获取新密码 + String newPassword = CommonCryptogramUtil.doSm2Decrypt(clientUserFindPwdByEmailParam.getNewPassword()).trim(); + // 校验新密码 + ClientPasswordUtl.validNewPassword(clientLoginUser, newPassword); + // 修改密码 + this.update(new LambdaUpdateWrapper().eq(ClientUser::getEmail, email).set(ClientUser::getPassword, + CommonCryptogramUtil.doHashValue(newPassword))); + // 更新用户最新修改密码时间 + clientUserExtService.updatePasswordLastTime(clientLoginUser.getId()); + // 追加用户历史密码信息 + clientUserPasswordService.insertUserPasswordHistory(clientLoginUser.getId(), newPassword); + // 重置密码成功邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", clientUserFindPwdByEmailParam.getEmail()).set("userNewPassword", newPassword); + // 获取格式化后的主题 + String subject = ClientEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = ClientEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } + } + + @Override + public String updatePasswordGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + // 判断密码验证方式 + ClientPasswordUtl.validUpdatePasswordValidType(ClientUpdatePasswordValidTypeEnum.PHONE.getValue()); + return this.getPhoneValidCode(clientUserGetPhoneValidCodeParam, "修改密码验证码短信消息模板编码", SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C_KEY); + } + + @Override + public String updatePasswordGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + // 判断密码验证方式 + ClientPasswordUtl.validUpdatePasswordValidType(ClientUpdatePasswordValidTypeEnum.EMAIL.getValue()); + return this.getEmailValidCode(clientUserGetEmailValidCodeParam, "修改密码验证码邮件消息模板内容", SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C_KEY); + } + + @Override + public void updatePasswordByOld(ClientUserUpdatePwdByOldParam clientUserUpdatePwdByOldParam) { + // 判断密码验证方式 + ClientPasswordUtl.validUpdatePasswordValidType(ClientUpdatePasswordValidTypeEnum.OLD.getValue()); + ClientUser clientUser = this.queryEntity(StpClientUtil.getLoginIdAsString()); + String password = CommonCryptogramUtil.doSm2Decrypt(clientUserUpdatePwdByOldParam.getPassword()).trim(); + String newPassword = CommonCryptogramUtil.doSm2Decrypt(clientUserUpdatePwdByOldParam.getNewPassword()).trim(); + if (!CommonCryptogramUtil.doHashValue(password).equals(clientUser.getPassword())) { + throw new CommonException("原密码错误"); + } + // 校验新密码 + ClientPasswordUtl.validNewPassword(clientUser, newPassword); + // 修改密码 + this.update(new LambdaUpdateWrapper().eq(ClientUser::getId, + clientUser.getId()).set(ClientUser::getPassword, + CommonCryptogramUtil.doHashValue(newPassword))); + // 更新用户最新修改密码时间 + clientUserExtService.updatePasswordLastTime(clientUser.getId()); + // 追加用户历史密码信息 + clientUserPasswordService.insertUserPasswordHistory(clientUser.getId(), newPassword); + // 获取手机号 + String phone = clientUser.getPhone(); + // 手机号不为空则发送密码重置成功短信 + if(ObjectUtil.isNotEmpty(phone)){ + // 重置密码成功短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("userNewPassword", newPassword); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 编码不为空 + if(ObjectUtil.isNotEmpty(codeValue)){ + try { + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } catch (Exception e) { + log.error(">>> 短信发送失败", e); + } + } + } + } + // 获取手机号 + String email = clientUser.getEmail(); + // 密码不为空则发送密码重置成功邮件 + if(ObjectUtil.isNotEmpty(email)){ + // 重置密码成功邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("userNewPassword", newPassword); + // 获取格式化后的主题 + String subject = ClientEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = ClientEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + try { + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } catch (Exception e) { + log.error(">>> 邮件发送失败", e); + } + } + } + } + + @Override + public void updatePasswordByPhone(ClientUserUpdatePwdByPhoneParam clientUserUpdatePwdByPhoneParam) { + // 判断密码验证方式 + ClientPasswordUtl.validUpdatePasswordValidType(ClientUpdatePasswordValidTypeEnum.PHONE.getValue()); + ClientUserFindPwdByPhoneParam clientUserFindPwdByPhoneParam = new ClientUserFindPwdByPhoneParam(); + BeanUtil.copyProperties(clientUserUpdatePwdByPhoneParam, clientUserFindPwdByPhoneParam); + this.findPasswordByPhone(clientUserFindPwdByPhoneParam); + } + + @Override + public void updatePasswordByEmail(ClientUserUpdatePwdByEmailParam clientUserUpdatePwdByEmailParam) { + // 判断密码验证方式 + ClientPasswordUtl.validUpdatePasswordValidType(ClientUpdatePasswordValidTypeEnum.EMAIL.getValue()); + ClientUserFindPwdByEmailParam clientUserFindPwdByEmailParam = new ClientUserFindPwdByEmailParam(); + BeanUtil.copyProperties(clientUserUpdatePwdByEmailParam, clientUserFindPwdByEmailParam); + this.findPasswordByEmail(clientUserFindPwdByEmailParam); + } + + @Override + public String bindPhoneGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + // 手机号 + String phone = clientUserGetPhoneValidCodeParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 执行校验验证码 + validValidCode(null, clientUserGetPhoneValidCodeParam.getValidCode(), clientUserGetPhoneValidCodeParam.getValidCodeReqNo()); + // 根据手机号获取用户信息,判断用户是否存在,如果存在则不能绑定该手机号 + if (ObjectUtil.isNotEmpty(this.getUserByPhone(phone))) { + throw new CommonException("手机号码:{}已存在对应用户", phone); + } + // 生成手机验证码的值,随机6为数字 + String phoneValidCode = RandomUtil.randomNumbers(6); + // 生成手机验证码的请求号 + String phoneValidCodeReqNo = IdWorker.getIdStr(); + // 绑定手机验证码短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_C_KEY); + if(ObjectUtil.isEmpty(smsTemplateCode)){ + throw new CommonException("请联系管理员配置绑定手机验证码短信消息模板编码"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("validCode", phoneValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, validCodeExpiredDuration); + // 返回请求号 + return phoneValidCodeReqNo; + } + + @Override + public String updateBindPhoneGetPhoneValidCode(ClientUserGetPhoneValidCodeParam clientUserGetPhoneValidCodeParam) { + // 手机号 + String phone = clientUserGetPhoneValidCodeParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 执行校验验证码 + validValidCode(null, clientUserGetPhoneValidCodeParam.getValidCode(), clientUserGetPhoneValidCodeParam.getValidCodeReqNo()); + // 根据手机号获取用户信息,判断用户是否存在,如果存在则不能绑定该手机号 + if (ObjectUtil.isNotEmpty(this.getUserByPhone(phone))) { + throw new CommonException("手机号码:{}已存在对应用户", phone); + } + // 生成手机验证码的值,随机6为数字 + String phoneValidCode = RandomUtil.randomNumbers(6); + // 生成手机验证码的请求号 + String phoneValidCodeReqNo = IdWorker.getIdStr(); + // 修改绑定手机验证码短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_C_KEY); + if(ObjectUtil.isEmpty(smsTemplateCode)){ + throw new CommonException("请联系管理员配置修改绑定手机验证码短信消息模板编码"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("validCode", phoneValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, validCodeExpiredDuration); + // 返回请求号 + return phoneValidCodeReqNo; + } + + @Override + public void bindPhone(ClientUserBindPhoneParam clientUserBindPhoneParam) { + // 再次校验手机号是否合法 + String phone = clientUserBindPhoneParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 根据手机号获取用户信息,判断用户是否存在,如果存在则不能绑定该手机号 + if (ObjectUtil.isNotEmpty(this.getUserByPhone(phone))) { + throw new CommonException("手机号码:{}已存在对应用户", phone); + } + // 执行校验验证码 + validValidCode(phone, clientUserBindPhoneParam.getValidCode(), clientUserBindPhoneParam.getValidCodeReqNo()); + // 修改手机号 + this.update(new LambdaUpdateWrapper().eq(ClientUser::getId, StpClientUtil.getLoginIdAsString()) + .set(ClientUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(phone))); + } + + @Override + public String bindEmailGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + // 邮箱 + String email = clientUserGetEmailValidCodeParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 执行校验验证码 + validValidCode(null, clientUserGetEmailValidCodeParam.getValidCode(), clientUserGetEmailValidCodeParam.getValidCodeReqNo()); + // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 + if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + throw new CommonException("邮箱:{}已存在对应用户", email); + } + // 生成邮箱验证码的值,随机6为数字 + String emailValidCode = RandomUtil.randomNumbers(6); + // 生成邮箱验证码的请求号 + String emailValidCodeReqNo = IdWorker.getIdStr(); + // 绑定邮箱验证码邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_C_KEY); + if(ObjectUtil.isEmpty(emailTemplateContent)){ + throw new CommonException("请联系管理员配置绑定邮箱验证码邮件消息模板内容"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("validCode", emailValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取格式化后的主题 + String subject = ClientEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = ClientEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, validCodeExpiredDuration); + // 返回请求号 + return emailValidCodeReqNo; + } + + @Override + public String updateBindEmailGetEmailValidCode(ClientUserGetEmailValidCodeParam clientUserGetEmailValidCodeParam) { + // 邮箱 + String email = clientUserGetEmailValidCodeParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 执行校验验证码 + validValidCode(null, clientUserGetEmailValidCodeParam.getValidCode(), clientUserGetEmailValidCodeParam.getValidCodeReqNo()); + // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 + if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + throw new CommonException("邮箱:{}已存在对应用户", email); + } + // 生成邮箱验证码的值,随机6为数字 + String emailValidCode = RandomUtil.randomNumbers(6); + // 生成邮箱验证码的请求号 + String emailValidCodeReqNo = IdWorker.getIdStr(); + // 修改绑定邮箱验证码邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_C_KEY); + if(ObjectUtil.isEmpty(emailTemplateContent)){ + throw new CommonException("请联系管理员配置修改绑定邮箱验证码邮件消息模板内容"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("validCode", emailValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取格式化后的主题 + String subject = ClientEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = ClientEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, validCodeExpiredDuration); + // 返回请求号 + return emailValidCodeReqNo; + } + + @Override + public void bindEmail(ClientUserBindEmailParam clientUserBindEmailParam) { + // 再次校验邮箱是否合法 + String email = clientUserBindEmailParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 + if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + throw new CommonException("邮箱:{}已存在对应用户", email); + } + // 执行校验验证码 + validValidCode(email, clientUserBindEmailParam.getValidCode(), clientUserBindEmailParam.getValidCodeReqNo()); + // 修改邮箱 + this.update(new LambdaUpdateWrapper().eq(ClientUser::getId, StpClientUtil.getLoginIdAsString()) + .set(ClientUser::getEmail, email)); + } + + @Override + public String updateAvatar(MultipartFile file) { + ClientUser clientUser = this.queryEntity(StpClientUtil.getLoginIdAsString()); + try { + String suffix = Objects.requireNonNull(FileUtil.getSuffix(file.getOriginalFilename())).toLowerCase(); + BufferedImage image = ImgUtil.toImage(file.getBytes()); + String base64; + if(image.getWidth() <= 200 && image.getHeight() <= 200) { + base64 = ImgUtil.toBase64DataUri(image, suffix); + } else { + base64 = ImgUtil.toBase64DataUri(ImgUtil.scale(image, 200, 200, null), suffix); + } + this.update(new LambdaUpdateWrapper().eq(ClientUser::getId, + clientUser.getId()).set(ClientUser::getAvatar, base64)); + return base64; + } catch (IOException e) { + log.error(">>> 头像修改失败:", e); + throw new CommonException("头像修改失败,用户id值为:{}", clientUser.getId()); + } + } + + @Override + public void updateSignature(ClientUserSignatureParam clientUserSignatureParam) { + ClientUser clientUser = this.queryEntity(StpClientUtil.getLoginIdAsString()); + String clientUserSignatureStr = clientUserSignatureParam.getSignature(); + if(clientUserSignatureParam.getSignature().contains(StrUtil.COMMA)) { + clientUserSignatureStr = StrUtil.split(clientUserSignatureStr, StrUtil.COMMA).get(1); + } + String base64 = ImgUtil.toBase64DataUri(ImgUtil.scale(ImgUtil.toImage(clientUserSignatureStr), + 100, 50, null), ImgUtil.IMAGE_TYPE_PNG); + // 更新指定字段 + this.update(new LambdaUpdateWrapper().eq(ClientUser::getId, clientUser.getId()) + .set(ClientUser::getSignature, base64)); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ClientUser createUserWithPhone(String phone) { + ClientUserAddParam clientUserAddParam = new ClientUserAddParam(); + clientUserAddParam.setAccount(phone); + clientUserAddParam.setName(phone); + clientUserAddParam.setPhone(phone); + // 保存用户 + this.add(clientUserAddParam, ClientUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); + // 获取用户信息 + ClientUser clientUser = this.getOne(new LambdaQueryWrapper().eq(ClientUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(phone))); + // 发送注册成功短信 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } + // 返回用户 + return clientUser; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ClientUser createUserWithEmail(String email) { + ClientUserAddParam clientUserAddParam = new ClientUserAddParam(); + clientUserAddParam.setAccount(email); + clientUserAddParam.setName(email); + clientUserAddParam.setEmail(email); + // 保存用户 + this.add(clientUserAddParam, ClientUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); + // 获取用户信息 + ClientUser clientUser = this.getOne(new LambdaQueryWrapper().eq(ClientUser::getEmail, email)); + // 发送注册成功邮件 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)) { + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email); + // 获取格式化后的主题 + String subject = ClientEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap); + // 获取格式化后的内容 + String content = ClientEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap); + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } + // 返回用户 + return clientUser; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ClientUser createUserWithAccount(String account, String password) { + ClientUserAddParam clientUserAddParam = new ClientUserAddParam(); + clientUserAddParam.setAccount(account); + clientUserAddParam.setName(account); + clientUserAddParam.setPassword(password); + // 保存用户 + this.add(clientUserAddParam, ClientUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); + // 返回用户 + return this.getOne(new LambdaQueryWrapper().eq(ClientUser::getAccount, account)); + } + + @Override + public Boolean isUserPasswordExpired() { + return ClientPasswordUtl.isUserPasswordExpired(StpClientUtil.getLoginIdAsString()); + } + + @Override + public Boolean isUserNeedBindPhone() { + // 获取当前用户 + ClientUser clientUser = this.queryEntity(StpClientUtil.getLoginIdAsString()); + // 查询当前用户是否注册的 + ClientUserExt clientUserExt = clientUserExtService.getOne(new LambdaQueryWrapper().eq(ClientUserExt::getUserId, StpClientUtil.getLoginIdAsString()) + .eq(ClientUserExt::getSourceFromType, ClientUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue())); + // 不为空,则判断手机号是否为空 + if(ObjectUtil.isNotEmpty(clientUserExt)){ + // 手机号为空,判断系统注册后是否需要绑定手机号 + if(ObjectUtil.isEmpty(clientUser.getPhone())) { + String registerNeedBindPhone = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(registerNeedBindPhone)){ + return Convert.toBool(registerNeedBindPhone); + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + @Override + public Boolean isUserNeedBindEmail() { + // 获取当前用户 + ClientUser clientUser = this.queryEntity(StpClientUtil.getLoginIdAsString()); + // 查询当前用户是否注册的 + ClientUserExt clientUserExt = clientUserExtService.getOne(new LambdaQueryWrapper().eq(ClientUserExt::getUserId, StpClientUtil.getLoginIdAsString()) + .eq(ClientUserExt::getSourceFromType, ClientUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue())); + // 不为空,则判断邮箱是否为空 + if(ObjectUtil.isNotEmpty(clientUserExt)){ + // 邮箱为空,判断系统注册后是否需要绑定邮箱 + if(ObjectUtil.isEmpty(clientUser.getEmail())) { + String registerNeedBindEmail = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_C_KEY); + if(ObjectUtil.isNotEmpty(registerNeedBindEmail)){ + return Convert.toBool(registerNeedBindEmail); + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + @Override + public void noticeUserPasswordAboutToExpired() { + // 密码即将到期短信消息模板 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C_KEY); + // 密码即将到期邮件消息模板 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C_KEY); + // 获取今日需要提醒密码到期的用户集合 + ClientPasswordUtl.thisDayPasswordExpiredNeedNoticeUserIdList().forEach(clientUser -> { + // 获取手机号 + String phone = clientUser.getPhone(); + // 不为空才发送 + if(ObjectUtil.isAllNotEmpty(phone, smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 编码不为空 + if(ObjectUtil.isNotEmpty(codeValue)){ + try { + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } catch (Exception e) { + log.error(">>> 短信发送失败", e); + } + } + } + // 获取邮箱 + String email = clientUser.getEmail(); + // 不为空才发送 + if(ObjectUtil.isAllNotEmpty(email, emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email); + // 获取格式化后的主题 + String subject = ClientEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = ClientEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + try { + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } catch (Exception e) { + log.error(">>> 邮件发送失败", e); + } + } + }); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void doRegister(String account, String password) { + // 校验账号 + ClientLoginUser clientLoginUser = this.getUserByAccount(account); + if(ObjectUtil.isNotEmpty(clientLoginUser)) { + throw new CommonException("账号已存在"); + } + // 校验密码 + ClientPasswordUtl.validNewPassword(password); + // 根据账号密码创建用户 + this.createUserWithAccount(account, password); + } + + /** + * 获取验证码失效时间(单位:秒) + * + * @author xuyuxiang + * @date 2025/3/21 20:25 + **/ + private long getValidCodeExpiredDuration() { + // 默认5分钟 + int defaultExpiredTime = 5; + // 获取配置验证码失效时间 + String configCaptchaExpiredDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C_KEY); + // 判断是否为空 + if(ObjectUtil.isNotEmpty(configCaptchaExpiredDuration)){ + // 配置了则使用配置的失效时间 + defaultExpiredTime = Convert.toInt(configCaptchaExpiredDuration); + } + // 转为秒 + return defaultExpiredTime * 60L; + } } diff --git a/snowy-plugin/snowy-plugin-dev/pom.xml b/snowy-plugin/snowy-plugin-dev/pom.xml index 68f51eba..fc35ce48 100644 --- a/snowy-plugin/snowy-plugin-dev/pom.xml +++ b/snowy-plugin/snowy-plugin-dev/pom.xml @@ -15,6 +15,7 @@ 开发工具插件 + vip.xiaonuo @@ -33,4 +34,4 @@ snowy-plugin-sys-api - \ No newline at end of file + diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/core/listener/DevJobListener.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/core/listener/DevJobListener.java index dbf0ddac..36dbd0d8 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/core/listener/DevJobListener.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/core/listener/DevJobListener.java @@ -15,6 +15,7 @@ package vip.xiaonuo.dev.core.listener; import cn.hutool.cron.CronUtil; import cn.hutool.extra.spring.SpringUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.ApplicationListener; @@ -36,9 +37,8 @@ import vip.xiaonuo.dev.modular.job.service.DevJobService; @Configuration public class DevJobListener implements ApplicationListener, Ordered { - @SuppressWarnings("ALL") @Override - public void onApplicationEvent( ApplicationStartedEvent applicationStartedEvent) { + public void onApplicationEvent(@NonNull ApplicationStartedEvent applicationStartedEvent) { SpringUtil.getBean(DevJobService.class).list(new LambdaQueryWrapper() .eq(DevJob::getJobStatus, DevJobStatusEnum.RUNNING.getValue()).orderByAsc(DevJob::getSortCode)) .forEach(devJob -> CronUtil.schedule(devJob.getId(), devJob.getCronExpression(), () -> { @@ -52,7 +52,7 @@ public class DevJobListener implements ApplicationListener> page(DevConfigPageParam devConfigPageParam) { @@ -63,6 +81,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取系统基础配置") @GetMapping("/dev/config/sysBaseList") public CommonResult> sysBaseList() { @@ -75,6 +94,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取配置列表") @GetMapping("/dev/config/list") public CommonResult> list(DevConfigListParam devConfigListParam) { @@ -87,6 +107,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "添加配置") @CommonLog("添加配置") @PostMapping("/dev/config/add") @@ -101,6 +122,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "编辑配置") @CommonLog("编辑配置") @PostMapping("/dev/config/edit") @@ -115,6 +137,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "删除配置") @CommonLog("删除配置") @PostMapping("/dev/config/delete") @@ -130,6 +153,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取配置详情") @GetMapping("/dev/config/detail") public CommonResult detail(@Valid DevConfigIdParam devConfigIdParam) { @@ -142,6 +166,7 @@ public class DevConfigController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "配置批量更新") @CommonLog("配置批量更新") @PostMapping("/dev/config/editBatch") @@ -150,4 +175,55 @@ public class DevConfigController { devConfigService.editBatch(devConfigBatchParamList); return CommonResult.ok(); } + + /** + * 获取机构选树 + * + * @author yubaoshan + * @date 2025/4/23 20:00 + */ + @Operation(summary = "获取机构选树") + @GetMapping("/dev/config/orgTree") + public CommonResult>> orgTree() { + return CommonResult.data(sysOrgApi.orgTreeSelector()); + } + + /** + * 获取角色选择器 + * + * @author yubaoshan + * @date 2025/4/23 20:00 + */ + @Operation(summary = "获取角色选择器") + @GetMapping("/dev/config/roleSelector") + public CommonResult> roleSelector(DevConfigSelectorRoleParam devConfigSelectorRoleParam) { + return CommonResult.data(sysRoleApi.roleSelector(devConfigSelectorRoleParam.getOrgId(), devConfigSelectorRoleParam.getCategory(), + devConfigSelectorRoleParam.getSearchKey(), null , false)); + } + + /** + * 获取机构选择器 + * + * @author yubaoshan + * @date 2025/4/23 20:00 + */ + @Operation(summary = "获取机构选择器") + @GetMapping("/dev/config/orgSelector") + public CommonResult> orgSelector(DevConfigSelectorOrgListParam devConfigSelectorOrgListParam) { + return CommonResult.data(sysOrgApi.orgListSelector(devConfigSelectorOrgListParam.getParentId())); + } + + /** + * 获取职位选择器 + * + * @author yubaoshan + * @date 2025/4/23 20:00 + */ + @Operation(summary = "获取职位选择器") + @GetMapping("/dev/config/positionSelector") + public CommonResult> positionSelector(@Valid DevConfigSelectorPositionParam devConfigSelectorPositionParam) { + return CommonResult.data(sysPositionApi.positionSelector(devConfigSelectorPositionParam.getOrgId(), devConfigSelectorPositionParam.getSearchKey(), + devConfigSelectorPositionParam.getCurrent(), devConfigSelectorPositionParam.getSize())); + } + } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/entity/DevConfig.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/entity/DevConfig.java index 10d04717..fd907409 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/entity/DevConfig.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/entity/DevConfig.java @@ -57,6 +57,6 @@ public class DevConfig extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/enums/DevConfigCategoryEnum.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/enums/DevConfigCategoryEnum.java index 712d4336..05849d08 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/enums/DevConfigCategoryEnum.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/enums/DevConfigCategoryEnum.java @@ -90,9 +90,14 @@ public enum DevConfigCategoryEnum { SMS_ALIYUN("SMS_ALIYUN"), /** - * 短信-小诺短信 + * 支付-支付宝 */ - SMS_XIAONUO("SMS_XIAONUO"); + PAY_ALI("PAY_ALI"), + + /** + * 支付-微信 + */ + PAY_WX("PAY_WX"); private final String value; @@ -107,7 +112,7 @@ public enum DevConfigCategoryEnum { FILE_ALIYUN.getValue().equals(value) || FILE_MINIO.getValue().equals(value) || EMAIL_TENCENT.getValue().equals(value) || EMAIL_ALIYUN.getValue().equals(value) || SMS_TENCENT.getValue().equals(value) || SMS_ALIYUN.getValue().equals(value) || - SMS_XIAONUO.getValue().equals(value); + PAY_ALI.getValue().equals(value) || PAY_WX.getValue().equals(value); if(!flag) { throw new CommonException("不支持的配置分类:{}", value); } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/mapper/mapping/DevConfigMapper.xml b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/mapper/mapping/DevConfigMapper.xml index ba9a3918..7abd6474 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/mapper/mapping/DevConfigMapper.xml +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/mapper/mapping/DevConfigMapper.xml @@ -2,5 +2,4 @@ - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigAddParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigAddParam.java index 7f32f8a1..544c93c5 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigAddParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigAddParam.java @@ -29,12 +29,12 @@ import lombok.Setter; public class DevConfigAddParam { /** 配置键 */ - @Schema(description = "配置键", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "配置键") @NotBlank(message = "configKey不能为空") private String configKey; /** 配置值 */ - @Schema(description = "配置值", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "配置值") @NotBlank(message = "configValue不能为空") private String configValue; @@ -43,7 +43,7 @@ public class DevConfigAddParam { private String remark; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigBatchParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigBatchParam.java index 4c5c2252..2286d307 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigBatchParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigBatchParam.java @@ -28,12 +28,12 @@ import lombok.Setter; public class DevConfigBatchParam { /** 配置键 */ - @Schema(description = "配置键", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "配置键") @NotBlank(message = "configKey不能为空") private String configKey; /** 配置值 */ - @Schema(description = "配置值", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "配置值") @NotBlank(message = "configValue不能为空") private String configValue; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigEditParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigEditParam.java index f1009608..c66c8be5 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigEditParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigEditParam.java @@ -29,17 +29,17 @@ import lombok.Setter; public class DevConfigEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 配置键 */ - @Schema(description = "配置键", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "配置键") @NotBlank(message = "configKey不能为空") private String configKey; /** 配置值 */ - @Schema(description = "配置值", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "配置值") @NotBlank(message = "configValue不能为空") private String configValue; @@ -48,7 +48,7 @@ public class DevConfigEditParam { private String remark; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigIdParam.java index 228d6a28..64ec8716 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevConfigIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorOrgListParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorOrgListParam.java new file mode 100644 index 00000000..e18dbcac --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorOrgListParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.config.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * 组织列表选择器参数 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +public class DevConfigSelectorOrgListParam { + + /** 当前页 */ + @Schema(description = "当前页码") + private Integer current; + + /** 每页条数 */ + @Schema(description = "每页条数") + private Integer size; + + /** 父id */ + @Schema(description = "父id") + private String parentId; + + /** 名称关键词 */ + @Schema(description = "名称关键词") + private String searchKey; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorPositionParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorPositionParam.java new file mode 100644 index 00000000..79879f3f --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorPositionParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.config.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * 职位选择器参数 + * + * @author xuyuxiang + * @date 2022/7/26 15:58 + **/ +@Getter +@Setter +public class DevConfigSelectorPositionParam { + + /** 当前页 */ + @Schema(description = "当前页码") + private Integer current; + + /** 每页条数 */ + @Schema(description = "每页条数") + private Integer size; + + /** 组织id */ + @Schema(description = "组织id") + private String orgId; + + /** 名称关键词 */ + @Schema(description = "名称关键词") + private String searchKey; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorRoleParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorRoleParam.java new file mode 100644 index 00000000..6d7af091 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/param/DevConfigSelectorRoleParam.java @@ -0,0 +1,48 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.config.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * 角色选择器参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:02 + **/ +@Getter +@Setter +public class DevConfigSelectorRoleParam { + + /** 当前页 */ + @Schema(description = "当前页码") + private Integer current; + + /** 每页条数 */ + @Schema(description = "每页条数") + private Integer size; + + /** 组织id */ + @Schema(description = "组织id") + private String orgId; + + /** 角色分类 */ + @Schema(description = "角色分类") + private String category; + + /** 名称关键词 */ + @Schema(description = "名称关键词") + private String searchKey; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/service/impl/DevConfigServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/service/impl/DevConfigServiceImpl.java index c5a256e8..9832d019 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/service/impl/DevConfigServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/config/service/impl/DevConfigServiceImpl.java @@ -50,8 +50,6 @@ public class DevConfigServiceImpl extends ServiceImpl sysBaseList() { DevConfigListParam devConfigListParam = new DevConfigListParam(); devConfigListParam.setCategory(DevConfigCategoryEnum.SYS_BASE.getValue()); - return this.list(devConfigListParam).stream().filter(devConfig -> !devConfig.getConfigKey() - .equals(SNOWY_SYS_DEFAULT_PASSWORD_KEY)).collect(Collectors.toList()); + return this.list(devConfigListParam); } @Override @@ -104,7 +101,7 @@ public class DevConfigServiceImpl extends ServiceImpl lambdaQueryWrapper = new LambdaQueryWrapper<>(); // 查询部分字段 lambdaQueryWrapper.select(DevConfig::getId, DevConfig::getConfigKey, DevConfig::getConfigValue, - DevConfig::getCategory, DevConfig::getSortCode); + DevConfig::getCategory, DevConfig::getSortCode, DevConfig::getRemark); if(ObjectUtil.isNotEmpty(devConfigListParam.getCategory())) { lambdaQueryWrapper.eq(DevConfig::getCategory, devConfigListParam.getCategory()); } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/controller/DevDictController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/controller/DevDictController.java index 6b7b990f..5ba8bac7 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/controller/DevDictController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/controller/DevDictController.java @@ -14,10 +14,11 @@ package vip.xiaonuo.dev.modular.dict.controller; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +31,7 @@ import vip.xiaonuo.dev.modular.dict.entity.DevDict; import vip.xiaonuo.dev.modular.dict.param.*; import vip.xiaonuo.dev.modular.dict.service.DevDictService; +import javax.validation.Valid; import java.util.List; /** @@ -39,6 +41,7 @@ import java.util.List; * @date 2022/6/21 14:58 **/ @Tag(name = "字典控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 2) @RestController @Validated public class DevDictController { @@ -52,6 +55,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取字典分页") @GetMapping("/dev/dict/page") public CommonResult> page(DevDictPageParam devDictPageParam) { @@ -64,6 +68,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取字典列表") @GetMapping("/dev/dict/list") public CommonResult> list(DevDictListParam devDictListParam) { @@ -76,6 +81,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 3) @Operation(summary = "获取字典树") @GetMapping("/dev/dict/tree") public CommonResult>> tree(DevDictTreeParam devDictTreeParam) { @@ -88,6 +94,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "添加字典") @CommonLog("添加字典") @PostMapping("/dev/dict/add") @@ -102,6 +109,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 5) @Operation(summary = "编辑字典") @CommonLog("编辑字典") @PostMapping("/dev/dict/edit") @@ -116,6 +124,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "删除字典") @CommonLog("删除字典") @PostMapping("/dev/dict/delete") @@ -131,6 +140,7 @@ public class DevDictController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取字典详情") @GetMapping("/dev/dict/detail") public CommonResult detail(@Valid DevDictIdParam devDictIdParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/entity/DevDict.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/entity/DevDict.java index ff44cda1..6b795abf 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/entity/DevDict.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/entity/DevDict.java @@ -47,6 +47,10 @@ public class DevDict extends CommonEntity { @Schema(description = "字典值") private String dictValue; + /** 编码 */ + @Schema(description = "编码") + private String code; + /** 分类 */ @Schema(description = "分类") private String category; @@ -57,6 +61,6 @@ public class DevDict extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/mapper/mapping/DevDictMapper.xml b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/mapper/mapping/DevDictMapper.xml index 732eb08b..4e23125c 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/mapper/mapping/DevDictMapper.xml +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/mapper/mapping/DevDictMapper.xml @@ -2,5 +2,4 @@ - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/param/DevDictIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/param/DevDictIdParam.java index 5d420c2d..a8270d24 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/param/DevDictIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/param/DevDictIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevDictIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java index 403a0682..50a773fb 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/dict/service/impl/DevDictServiceImpl.java @@ -20,6 +20,7 @@ import cn.hutool.core.lang.tree.TreeNodeConfig; import cn.hutool.core.lang.tree.TreeUtil; import cn.hutool.core.lang.tree.parser.DefaultNodeParser; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -30,6 +31,7 @@ import com.fhs.trans.service.impl.DictionaryTransService; import jakarta.annotation.Resource; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; @@ -108,8 +110,8 @@ public class DevDictServiceImpl extends ServiceImpl impl } List devDictList = this.list(lambdaQueryWrapper); List> treeNodeList = devDictList.stream().map(devDict -> - new TreeNode<>(devDict.getId(), devDict.getParentId(), - devDict.getDictLabel(), devDict.getSortCode()).setExtra(JSONUtil.parseObj(devDict))) + new TreeNode<>(devDict.getId(), devDict.getParentId(), + devDict.getDictLabel(), devDict.getSortCode()).setExtra(JSONUtil.parseObj(devDict))) .collect(Collectors.toList()); // 精简冗余字段(sortCode、weight字段合并) TreeNodeConfig treeNodeConfig = new TreeNodeConfig(); @@ -121,6 +123,7 @@ public class DevDictServiceImpl extends ServiceImpl impl public void add(DevDictAddParam devDictAddParam) { checkParam(devDictAddParam); DevDict devDict = BeanUtil.toBean(devDictAddParam, DevDict.class); + devDict.setCode(RandomUtil.randomString(10)); this.save(devDict); refreshTransCache(); } @@ -172,6 +175,7 @@ public class DevDictServiceImpl extends ServiceImpl impl } } + @Transactional(rollbackFor = Exception.class) @Override public void delete(List devDictIdParamList) { List devDictIdList = CollStreamUtil.toList(devDictIdParamList, DevDictIdParam::getId); @@ -205,6 +209,12 @@ public class DevDictServiceImpl extends ServiceImpl impl refreshTransCache(); } + /** + * 刷新字典缓存 + * + * @author xuyuxiang + * @date 2022/9/26 15:33 + **/ private void refreshTransCache() { // 异步不阻塞主线程,不会 增加启动用时 CompletableFuture.supplyAsync(() -> { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/controller/DevEmailController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/controller/DevEmailController.java index 78a24eca..f12a618b 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/controller/DevEmailController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/controller/DevEmailController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.dev.modular.email.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -29,6 +30,7 @@ import vip.xiaonuo.dev.modular.email.entity.DevEmail; import vip.xiaonuo.dev.modular.email.param.*; import vip.xiaonuo.dev.modular.email.service.DevEmailService; +import javax.validation.Valid; import java.util.List; /** @@ -38,6 +40,7 @@ import java.util.List; * @date 2022/2/23 18:26 **/ @Tag(name = "邮件控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 3) @RestController @Validated public class DevEmailController { @@ -45,12 +48,43 @@ public class DevEmailController { @Resource private DevEmailService devEmailService; + /** + * 动态发送TXT邮件 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 1) + @Operation(summary = "动态发送TXT邮件") + @CommonLog("动态发送TXT邮件") + @PostMapping("/dev/email/sendDynamicTxt") + public CommonResult sendDynamic(@RequestBody @Valid DevEmailSendDynamicTxtParam devEmailSendDynamicTxtParam) { + devEmailService.sendDynamicTxt(devEmailSendDynamicTxtParam); + return CommonResult.ok(); + } + + /** + * 动态发送HTML邮件 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 2) + @Operation(summary = "动态发送HTML邮件") + @CommonLog("动态发送HTML邮件") + @PostMapping("/dev/email/sendDynamicHtml") + public CommonResult sendDynamic(@RequestBody @Valid DevEmailSendDynamicHtmlParam devEmailSendDynamicHtmlParam) { + devEmailService.sendDynamicHtml(devEmailSendDynamicHtmlParam); + return CommonResult.ok(); + } + /** * 发送邮件——本地TXT * * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "发送本地文本邮件") @CommonLog("发送本地文本邮件") @PostMapping("/dev/email/sendLocalTxt") @@ -65,6 +99,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "发送本地HTML邮件") @CommonLog("发送本地HTML邮件") @PostMapping("/dev/email/sendLocalHtml") @@ -79,6 +114,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 5) @Operation(summary = "发送阿里云文本邮件") @CommonLog("发送阿里云文本邮件") @PostMapping("/dev/email/sendAliyunTxt") @@ -93,6 +129,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 6) @Operation(summary = "发送阿里云HTML邮件") @CommonLog("发送阿里云HTML邮件") @PostMapping("/dev/email/sendAliyunHtml") @@ -107,6 +144,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 7) @Operation(summary = "发送阿里云模板邮件") @CommonLog("发送阿里云模板邮件") @PostMapping("/dev/email/sendAliyunTmp") @@ -121,6 +159,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 8) @Operation(summary = "发送腾讯云文本邮件") @CommonLog("发送腾讯云文本邮件") @PostMapping("/dev/email/sendTencentTxt") @@ -135,6 +174,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 9) @Operation(summary = "发送腾讯云HTML邮件") @CommonLog("发送腾讯云HTML邮件") @PostMapping("/dev/email/sentTencentHtml") @@ -149,6 +189,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 10) @Operation(summary = "发送腾讯云模板邮件") @CommonLog("发送腾讯云模板邮件") @PostMapping("/dev/email/sentTencentTmp") @@ -163,6 +204,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 11) @Operation(summary = "获取邮件分页") @GetMapping("/dev/email/page") public CommonResult> page(DevEmailPageParam devEmailPageParam) { @@ -175,11 +217,12 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 12) @Operation(summary = "删除邮件") @CommonLog("删除邮件") @PostMapping("/dev/email/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List devEmailIdParamList) { + List devEmailIdParamList) { devEmailService.delete(devEmailIdParamList); return CommonResult.ok(); } @@ -190,6 +233,7 @@ public class DevEmailController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 13) @Operation(summary = "获取邮件详情") @GetMapping("/dev/email/detail") public CommonResult detail(@Valid DevEmailIdParam devEmailIdParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/entity/DevEmail.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/entity/DevEmail.java index 00dd7642..16e4fcc7 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/entity/DevEmail.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/entity/DevEmail.java @@ -30,7 +30,7 @@ import vip.xiaonuo.common.pojo.CommonEntity; public class DevEmail extends CommonEntity { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 邮件引擎 */ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailIdParam.java index 46585116..67ba872b 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevEmailIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunHtmlParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunHtmlParam.java index 8ced5a3a..a4ab32fc 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunHtmlParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunHtmlParam.java @@ -28,22 +28,22 @@ import lombok.Setter; public class DevEmailSendAliyunHtmlParam { /** 发件人邮箱 */ - @Schema(description = "发件人邮箱,即管理控制台中配置的发信地址", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "发件人邮箱,即管理控制台中配置的发信地址") @NotBlank(message = "sendAccount不能为空") private String sendAccount; /** 接收人 */ - @Schema(description = "接收人邮箱地址,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人邮箱地址,多个逗号拼接") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; /** 邮件正文 */ - @Schema(description = "邮件正文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件正文") @NotBlank(message = "content不能为空") private String content; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTmpParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTmpParam.java index 5d5b4a5c..47fd9b69 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTmpParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTmpParam.java @@ -28,17 +28,17 @@ import lombok.Setter; public class DevEmailSendAliyunTmpParam { /** 发件人邮箱 */ - @Schema(description = "管理控制台中配置的发信地址", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "管理控制台中配置的发信地址") @NotBlank(message = "sendAccount不能为空") private String sendAccount; /** 接收人 */ - @Schema(description = "预先创建且上传了收件人的收件人列表名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "预先创建且上传了收件人的收件人列表名称") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 模板名 */ - @Schema(description = "预先创建且通过审核的模板名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "预先创建且通过审核的模板名称") @NotBlank(message = "templateName不能为空") private String templateName; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTxtParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTxtParam.java index a6005fcb..91025436 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTxtParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendAliyunTxtParam.java @@ -28,22 +28,22 @@ import lombok.Setter; public class DevEmailSendAliyunTxtParam { /** 发件人邮箱 */ - @Schema(description = "发件人邮箱,即管理控制台中配置的发信地址", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "发件人邮箱,即管理控制台中配置的发信地址") @NotBlank(message = "sendAccount不能为空") private String sendAccount; /** 接收人 */ - @Schema(description = "接收人邮箱地址,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人邮箱地址,多个逗号拼接") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; /** 邮件正文 */ - @Schema(description = "邮件正文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件正文") @NotBlank(message = "content不能为空") private String content; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicHtmlParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicHtmlParam.java new file mode 100644 index 00000000..02136793 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicHtmlParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.email.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 邮件发送——本地HTML参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevEmailSendDynamicHtmlParam { + + /** 接收人 */ + @Schema(description = "接收人邮箱地址,多个逗号拼接") + @NotBlank(message = "receiveAccounts不能为空") + private String receiveAccounts; + + /** 邮件主题 */ + @Schema(description = "邮件主题") + @NotBlank(message = "subject不能为空") + private String subject; + + /** 邮件正文 */ + @Schema(description = "邮件正文") + @NotBlank(message = "content不能为空") + private String content; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicTxtParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicTxtParam.java new file mode 100644 index 00000000..b5aec40f --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendDynamicTxtParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.email.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 邮件发送——本地HTML参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevEmailSendDynamicTxtParam { + + /** 接收人 */ + @Schema(description = "接收人邮箱地址,多个逗号拼接") + @NotBlank(message = "receiveAccounts不能为空") + private String receiveAccounts; + + /** 邮件主题 */ + @Schema(description = "邮件主题") + @NotBlank(message = "subject不能为空") + private String subject; + + /** 邮件正文 */ + @Schema(description = "邮件正文") + @NotBlank(message = "content不能为空") + private String content; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalHtmlParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalHtmlParam.java index 32554513..8db478d0 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalHtmlParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalHtmlParam.java @@ -35,17 +35,17 @@ import java.util.Map; public class DevEmailSendLocalHtmlParam { /** 接收人 */ - @Schema(description = "接收人邮箱地址,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人邮箱地址,多个逗号拼接") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; /** 邮件正文 */ - @Schema(description = "邮件正文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件正文") @NotBlank(message = "content不能为空") private String content; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalTxtParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalTxtParam.java index 145641b4..3947b191 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalTxtParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendLocalTxtParam.java @@ -32,17 +32,17 @@ import java.util.List; public class DevEmailSendLocalTxtParam { /** 接收人 */ - @Schema(description = "接收人邮箱地址,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人邮箱地址,多个逗号拼接") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; /** 邮件正文 */ - @Schema(description = "邮件正文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件正文") @NotBlank(message = "content不能为空") private String content; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentHtmlParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentHtmlParam.java index a5bd06e4..0f7db9d5 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentHtmlParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentHtmlParam.java @@ -32,22 +32,22 @@ import java.util.List; public class DevEmailSendTencentHtmlParam { /** 发件人邮箱 */ - @Schema(description = "管理控制台中配置的发信地址", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "管理控制台中配置的发信地址") @NotBlank(message = "sendAccount不能为空") private String sendAccount; /** 接收人 */ - @Schema(description = "接收人邮箱地址,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人邮箱地址,多个逗号拼接") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; /** 邮件正文 */ - @Schema(description = "邮件正文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件正文") @NotBlank(message = "content不能为空") private String content; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTmpParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTmpParam.java index 1f1d2dae..7e64a9ae 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTmpParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTmpParam.java @@ -32,22 +32,22 @@ import java.util.List; public class DevEmailSendTencentTmpParam { /** 发件人邮箱 */ - @Schema(description = "管理控制台中配置的发信地址", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "管理控制台中配置的发信地址") @NotBlank(message = "sendAccount不能为空") private String sendAccount; /** 接收人 */ - @Schema(description = "预先创建且上传了收件人的收件人列表id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "预先创建且上传了收件人的收件人列表id") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 模板名 */ - @Schema(description = "预先创建且通过审核的模板Id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "预先创建且通过审核的模板Id") @NotBlank(message = "templateName不能为空") private String templateName; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTxtParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTxtParam.java index beeeb2c2..bb8ee72f 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTxtParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/param/DevEmailSendTencentTxtParam.java @@ -32,22 +32,22 @@ import java.util.List; public class DevEmailSendTencentTxtParam { /** 发件人邮箱 */ - @Schema(description = "管理控制台中配置的发信地址", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "管理控制台中配置的发信地址") @NotBlank(message = "sendAccount不能为空") private String sendAccount; /** 接收人 */ - @Schema(description = "接收人邮箱地址,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人邮箱地址,多个逗号拼接") @NotBlank(message = "receiveAccounts不能为空") private String receiveAccounts; /** 邮件主题 */ - @Schema(description = "邮件主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件主题") @NotBlank(message = "subject不能为空") private String subject; /** 邮件正文 */ - @Schema(description = "邮件正文", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮件正文") @NotBlank(message = "content不能为空") private String content; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/provider/DevEmailApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/provider/DevEmailApiProvider.java index a3829fd1..e8790334 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/provider/DevEmailApiProvider.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/provider/DevEmailApiProvider.java @@ -36,6 +36,24 @@ public class DevEmailApiProvider implements DevEmailApi { @Resource private DevEmailService devEmailService; + @Override + public void sendDynamicTxtEmail(String tos, String subject, String content) { + DevEmailSendDynamicTxtParam sendDynamicTxtParam = new DevEmailSendDynamicTxtParam(); + sendDynamicTxtParam.setReceiveAccounts(tos); + sendDynamicTxtParam.setSubject(subject); + sendDynamicTxtParam.setContent(content); + devEmailService.sendDynamicTxt(sendDynamicTxtParam); + } + + @Override + public void sendDynamicHtmlEmail(String tos, String subject, String content) { + DevEmailSendDynamicHtmlParam sendDynamicHtmlParam = new DevEmailSendDynamicHtmlParam(); + sendDynamicHtmlParam.setReceiveAccounts(tos); + sendDynamicHtmlParam.setSubject(subject); + sendDynamicHtmlParam.setContent(content); + devEmailService.sendDynamicHtml(sendDynamicHtmlParam); + } + @Override public void sendTextEmailLocal(String tos, String subject, String content, List files) { DevEmailSendLocalTxtParam devEmailSendLocalTxtParam = new DevEmailSendLocalTxtParam(); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/DevEmailService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/DevEmailService.java index cb03154f..146f6949 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/DevEmailService.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/DevEmailService.java @@ -27,6 +27,46 @@ import java.util.List; **/ public interface DevEmailService extends IService { + /** + * 动态发送TXT邮件 + * + * @param engine 发送引擎 + * @param receiveAccounts 收件人邮箱,逗号拼接 + * @param subject 邮件主题 + * @param content 邮件内容 + * @author xuyuxiang + * @date 2022/2/7 22:29 + */ + void sendDynamicTxt(String engine, String receiveAccounts, String subject, String content); + + /** + * 动态发送HTML邮件 + * + * @param engine 发送引擎 + * @param receiveAccounts 收件人邮箱,逗号拼接 + * @param subject 邮件主题 + * @param content 邮件内容 + * @author xuyuxiang + * @date 2022/2/7 22:29 + */ + void sendDynamicHtml(String engine, String receiveAccounts, String subject, String content); + + /** + * 动态发送TXT邮件 + * + * @author xuyuxiang + * @date 2022/6/21 18:37 + **/ + void sendDynamicTxt(DevEmailSendDynamicTxtParam devEmailSendDynamicTxtParam); + + /** + * 动态发送HTML邮件 + * + * @author xuyuxiang + * @date 2022/6/21 18:37 + **/ + void sendDynamicHtml(DevEmailSendDynamicHtmlParam devEmailSendDynamicHtmlParam); + /** * 发送邮件——本地TXT * diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/impl/DevEmailServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/impl/DevEmailServiceImpl.java index 674e0ecd..71c158cf 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/impl/DevEmailServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/service/impl/DevEmailServiceImpl.java @@ -21,12 +21,14 @@ import cn.hutool.extra.mail.MailAccount; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; import vip.xiaonuo.common.util.CommonEmailUtil; +import vip.xiaonuo.dev.api.DevConfigApi; import vip.xiaonuo.dev.modular.email.entity.DevEmail; import vip.xiaonuo.dev.modular.email.enums.DevEmailEngineTypeEnum; import vip.xiaonuo.dev.modular.email.mapper.DevEmailMapper; @@ -47,6 +49,90 @@ import java.util.List; @Service public class DevEmailServiceImpl extends ServiceImpl implements DevEmailService { + /** 默认邮件引擎 */ + private static final String SNOWY_SYS_DEFAULT_EMAIL_ENGINE_KEY = "SNOWY_SYS_DEFAULT_EMAIL_ENGINE"; + + @Resource + private DevConfigApi devConfigApi; + + @Transactional(rollbackFor = Exception.class) + @Override + public void sendDynamicTxt(String engine, String receiveAccounts, String subject, String content) { + if(engine.equals(DevEmailEngineTypeEnum.LOCAL.getValue())) { + DevEmailSendLocalTxtParam devEmailSendLocalTxtParam = new DevEmailSendLocalTxtParam(); + devEmailSendLocalTxtParam.setReceiveAccounts(receiveAccounts); + devEmailSendLocalTxtParam.setSubject(subject); + devEmailSendLocalTxtParam.setContent(content); + this.sendLocal(devEmailSendLocalTxtParam); + } else if (engine.equals(DevEmailEngineTypeEnum.ALIYUN.getValue())) { + DevEmailSendAliyunTxtParam devEmailSendAliyunTxtParam = new DevEmailSendAliyunTxtParam(); + devEmailSendAliyunTxtParam.setReceiveAccounts(receiveAccounts); + devEmailSendAliyunTxtParam.setSubject(subject); + devEmailSendAliyunTxtParam.setContent(content); + this.sendAliyun(devEmailSendAliyunTxtParam); + } else if (engine.equals(DevEmailEngineTypeEnum.TENCENT.getValue())) { + DevEmailSendTencentTxtParam devEmailSendTencentTxtParam = new DevEmailSendTencentTxtParam(); + devEmailSendTencentTxtParam.setReceiveAccounts(receiveAccounts); + devEmailSendTencentTxtParam.setSubject(subject); + devEmailSendTencentTxtParam.setContent(content); + this.sendTencent(devEmailSendTencentTxtParam); + } else { + throw new CommonException("不支持的邮件引擎:{}", engine); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void sendDynamicHtml(String engine, String receiveAccounts, String subject, String content) { + if(engine.equals(DevEmailEngineTypeEnum.LOCAL.getValue())) { + DevEmailSendLocalHtmlParam devEmailSendLocalHtmlParam = new DevEmailSendLocalHtmlParam(); + devEmailSendLocalHtmlParam.setReceiveAccounts(receiveAccounts); + devEmailSendLocalHtmlParam.setSubject(subject); + devEmailSendLocalHtmlParam.setContent(content); + this.sendLocal(devEmailSendLocalHtmlParam); + } else if (engine.equals(DevEmailEngineTypeEnum.ALIYUN.getValue())) { + DevEmailSendAliyunHtmlParam devEmailSendAliyunHtmlParam = new DevEmailSendAliyunHtmlParam(); + devEmailSendAliyunHtmlParam.setReceiveAccounts(receiveAccounts); + devEmailSendAliyunHtmlParam.setSubject(subject); + devEmailSendAliyunHtmlParam.setContent(content); + this.sendAliyun(devEmailSendAliyunHtmlParam); + } else if (engine.equals(DevEmailEngineTypeEnum.TENCENT.getValue())) { + DevEmailSendTencentHtmlParam devEmailSendTencentHtmlParam = new DevEmailSendTencentHtmlParam(); + devEmailSendTencentHtmlParam.setReceiveAccounts(receiveAccounts); + devEmailSendTencentHtmlParam.setSubject(subject); + devEmailSendTencentHtmlParam.setContent(content); + this.sendTencent(devEmailSendTencentHtmlParam); + } else { + throw new CommonException("不支持的邮件引擎:{}", engine); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void sendDynamicTxt(DevEmailSendDynamicTxtParam devEmailSendDynamicTxtParam) { + String defaultEmailEngine = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_EMAIL_ENGINE_KEY); + if(ObjectUtil.isEmpty(defaultEmailEngine)) { + throw new CommonException("请联系管理员配置默认邮件发送引擎"); + } + String receiveAccounts = devEmailSendDynamicTxtParam.getReceiveAccounts(); + String subject = devEmailSendDynamicTxtParam.getSubject(); + String content = devEmailSendDynamicTxtParam.getContent(); + this.sendDynamicTxt(defaultEmailEngine, receiveAccounts, subject, content); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void sendDynamicHtml(DevEmailSendDynamicHtmlParam devEmailSendDynamicHtmlParam) { + String defaultEmailEngine = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_EMAIL_ENGINE_KEY); + if(ObjectUtil.isEmpty(defaultEmailEngine)) { + throw new CommonException("请联系管理员配置默认邮件发送引擎"); + } + String receiveAccounts = devEmailSendDynamicHtmlParam.getReceiveAccounts(); + String subject = devEmailSendDynamicHtmlParam.getSubject(); + String content = devEmailSendDynamicHtmlParam.getContent(); + this.sendDynamicHtml(defaultEmailEngine, receiveAccounts, subject, content); + } + @Transactional(rollbackFor = Exception.class) @Override public void sendLocal(DevEmailSendLocalTxtParam devEmailSendLocalTxtParam) { @@ -180,6 +266,7 @@ public class DevEmailServiceImpl extends ServiceImpl i return this.page(CommonPageRequest.defaultPage(), queryWrapper); } + @Transactional(rollbackFor = Exception.class) @Override public void delete(List devEmailIdParamList) { this.removeByIds(CollStreamUtil.toList(devEmailIdParamList, DevEmailIdParam::getId)); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailAliyunUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailAliyunUtil.java index 8b2f0090..9c195940 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailAliyunUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailAliyunUtil.java @@ -24,7 +24,7 @@ import vip.xiaonuo.dev.api.DevConfigApi; /** * 阿里云邮件工具类 - * 参考文档:https://help.aliyun.com/document_detail/29459.html + * 参考文档:参考文档 * * @author xuyuxiang * @date 2022/6/17 10:17 @@ -36,7 +36,7 @@ public class DevEmailAliyunUtil { private static final String SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID_KEY = "SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID"; private static final String SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET_KEY = "SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET"; - private static final String SNOWY_EMAIL_ALIYUN_REGION_ID_KEY = "SNOWY_EMAIL_ALIYUN_REGION_ID"; + private static final String SNOWY_EMAIL_ALIYUN_FROM_KEY = "SNOWY_EMAIL_ALIYUN_FROM"; /** * 初始化操作的客户端 @@ -61,16 +61,8 @@ public class DevEmailAliyunUtil { if(ObjectUtil.isEmpty(accessKeySecret)) { throw new CommonException("阿里云邮件操作客户端未正确配置:accessKeySecret为空"); } - - /* regionId */ - String regionId = devConfigApi.getValueByKey(SNOWY_EMAIL_ALIYUN_REGION_ID_KEY); - - if(ObjectUtil.isEmpty(regionId)) { - throw new CommonException("阿里云邮件操作客户端未正确配置:regionId为空"); - } - try { - client = new Client(new Config().setRegionId(regionId).setEndpoint("dm.aliyuncs.com").setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret)); + client = new Client(new Config().setRegionId("cn-hangzhou").setEndpoint("dm.aliyuncs.com").setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret)); } catch (Exception e) { throw new CommonException(e.getMessage()); } @@ -91,6 +83,9 @@ public class DevEmailAliyunUtil { public static String sendTextEmail(String from, String user, String tos, String subject, String content) { try { initClient(); + if(ObjectUtil.isEmpty(from)) { + from = getDefaultFrom(); + } SingleSendMailRequest singleSendMailRequest = createSingleSendRequest(from, user, tos, subject, content, false); return client.singleSendMail(singleSendMailRequest).getBody().getEnvId(); } catch (Exception e) { @@ -113,6 +108,9 @@ public class DevEmailAliyunUtil { public static String sendHtmlEmail(String from, String user, String tos, String subject, String content) { try { initClient(); + if(ObjectUtil.isEmpty(from)) { + from = getDefaultFrom(); + } SingleSendMailRequest singleSendMailRequest = createSingleSendRequest(from, user, tos, subject, content, true); return client.singleSendMail(singleSendMailRequest).getBody().getEnvId(); } catch (Exception e) { @@ -134,6 +132,9 @@ public class DevEmailAliyunUtil { public static String sendEmailWithTemplate(String from, String tagName, String toName, String templateName) { try { initClient(); + if(ObjectUtil.isEmpty(from)) { + from = getDefaultFrom(); + } BatchSendMailRequest batchSendMailRequest = createBatchSendRequest(from, tagName, toName, templateName); return client.batchSendMail(batchSendMailRequest).getBody().getEnvId(); } catch (Exception e) { @@ -211,4 +212,19 @@ public class DevEmailAliyunUtil { return request; } + + /** + * 获取默认发送账号 + * + * @author xuyuxiang + * @date 2024/1/26 16:40 + **/ + public static String getDefaultFrom() { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + String signName = devConfigApi.getValueByKey(SNOWY_EMAIL_ALIYUN_FROM_KEY); + if(ObjectUtil.isEmpty(signName)) { + throw new CommonException("阿里云邮件操作客户端未正确配置:from为空"); + } + return signName; + } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailLocalUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailLocalUtil.java index 897f07aa..fd480c18 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailLocalUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailLocalUtil.java @@ -39,6 +39,7 @@ public class DevEmailLocalUtil { private static MailAccount mailAccount; private static final String SNOWY_EMAIL_LOCAL_FROM_KEY = "SNOWY_EMAIL_LOCAL_FROM"; + private static final String SNOWY_EMAIL_LOCAL_PASSWORD_KEY = "SNOWY_EMAIL_LOCAL_PASSWORD"; private static final String SNOWY_EMAIL_LOCAL_SMTP_HOST_KEY = "SNOWY_EMAIL_LOCAL_SMTP_HOST"; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailTencentUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailTencentUtil.java index 417ac19b..656aeef2 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailTencentUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/email/util/DevEmailTencentUtil.java @@ -31,7 +31,7 @@ import java.util.List; /** * 腾讯云邮件工具类 - * 参考文档:https://cloud.tencent.com/document/api/1288/51034 + * 参考文档:参考文档 * * @author xuyuxiang * @date 2022/6/17 11:26 @@ -43,7 +43,7 @@ public class DevEmailTencentUtil { private static final String SNOWY_EMAIL_TENCENT_SECRET_ID_KEY = "SNOWY_EMAIL_TENCENT_SECRET_ID"; private static final String SNOWY_EMAIL_TENCENT_SECRET_KEY_KEY = "SNOWY_EMAIL_TENCENT_SECRET_KEY"; - private static final String SNOWY_EMAIL_TENCENT_REGION_ID_KEY = "SNOWY_EMAIL_TENCENT_REGION_ID"; + private static final String SNOWY_EMAIL_TENCENT_FROM_KEY = "SNOWY_EMAIL_TENCENT_FROM"; /** * 初始化操作的客户端 @@ -68,15 +68,7 @@ public class DevEmailTencentUtil { if(ObjectUtil.isEmpty(secretKey)) { throw new CommonException("腾讯云邮件操作客户端未正确配置:secretKey为空"); } - - /* regionId */ - String regionId = devConfigApi.getValueByKey(SNOWY_EMAIL_TENCENT_REGION_ID_KEY); - - if(ObjectUtil.isEmpty(regionId)) { - throw new CommonException("腾讯云邮件操作客户端未正确配置:regionId为空"); - } - - client = new SesClient(new Credential(secretId, secretKey), regionId); + client = new SesClient(new Credential(secretId, secretKey), "ap-guangzhou"); } /** @@ -88,7 +80,7 @@ public class DevEmailTencentUtil { * @param subject 邮件主题,必传 * @param content 邮件 txt 正文,必传,注意:腾讯云api目前要求请求包大小不得超过8 MB。 * @param attachmentList 需要发送附件时,填写附件相关参数,格式:[{"FileName": "xxxx", "Content": "xxx"}] - * 支持的格式与说明见:https://cloud.tencent.com/document/api/1288/51053#Attachment + * 支持的格式与说明见:参考文档 * @return 发送成功的回执id * @author xuyuxiang * @date 2022/2/23 14:24 @@ -96,6 +88,9 @@ public class DevEmailTencentUtil { public static String sendTextEmail(String from, String user, String tos, String subject, String content, List attachmentList) { try { initClient(); + if(ObjectUtil.isEmpty(from)) { + from = getDefaultFrom(); + } SendEmailRequest singleSendMailRequest = createSingleSendRequest(from, user, tos, subject, content, false, attachmentList); return client.SendEmail(singleSendMailRequest).getMessageId(); } catch (TencentCloudSDKException e) { @@ -112,7 +107,7 @@ public class DevEmailTencentUtil { * @param subject 邮件主题,必传 * @param content 邮件 txt 正文,必传,注意:腾讯云api目前要求请求包大小不得超过8 MB。 * @param attachmentList 需要发送附件时,填写附件相关参数,格式:[{"FileName": "xxxx", "Content": "xxx"}] - * 支持的格式与说明见:https://cloud.tencent.com/document/api/1288/51053#Attachment + * 支持的格式与说明见:参考文档 * @return 发送成功的回执id * @author xuyuxiang * @date 2022/2/23 14:24 @@ -120,6 +115,9 @@ public class DevEmailTencentUtil { public static String sendHtmlEmail(String from, String user, String tos, String subject, String content, List attachmentList) { try { initClient(); + if(ObjectUtil.isEmpty(from)) { + from = getDefaultFrom(); + } SendEmailRequest singleSendMailRequest = createSingleSendRequest(from, user, tos, subject, content, true, attachmentList); return client.SendEmail(singleSendMailRequest).getMessageId(); } catch (TencentCloudSDKException e) { @@ -137,7 +135,7 @@ public class DevEmailTencentUtil { * @param templateParam 预先创建且通过审核的模板的参数json,格式{"name":"张三"},可不传 * @param subject 邮件主题,必传 * @param attachmentList 需要发送附件时,填写附件相关参数,格式:[{"FileName": "xxxx", "Content": "xxx"}] - * 支持的格式与说明见:https://cloud.tencent.com/document/api/1288/51053#Attachment + * 支持的格式与说明见:参考文档 * @return 发送成功的回执id * @author xuyuxiang * @date 2022/2/23 14:24 @@ -146,6 +144,9 @@ public class DevEmailTencentUtil { String templateParam, String subject, List attachmentList) { try { initClient(); + if(ObjectUtil.isEmpty(from)) { + from = getDefaultFrom(); + } BatchSendEmailRequest batchSendEmailRequest = createBatchSendRequest(from, user, toId, templateId, templateParam, subject, attachmentList); return client.BatchSendEmail(batchSendEmailRequest).getTaskId().toString(); } catch (TencentCloudSDKException e) { @@ -210,4 +211,19 @@ public class DevEmailTencentUtil { } return batchSendEmailRequest; } + + /** + * 获取默认发送账号 + * + * @author xuyuxiang + * @date 2024/1/26 16:40 + **/ + public static String getDefaultFrom() { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + String signName = devConfigApi.getValueByKey(SNOWY_EMAIL_TENCENT_FROM_KEY); + if(ObjectUtil.isEmpty(signName)) { + throw new CommonException("腾讯云邮件操作客户端未正确配置:from为空"); + } + return signName; + } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java index 240c58ea..f4d81e1c 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/controller/DevFileController.java @@ -13,11 +13,12 @@ package vip.xiaonuo.dev.modular.file.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; @@ -34,6 +35,7 @@ import vip.xiaonuo.dev.modular.file.param.DevFilePageParam; import vip.xiaonuo.dev.modular.file.param.DevFileUrlListParam; import vip.xiaonuo.dev.modular.file.service.DevFileService; +import javax.validation.Valid; import java.io.IOException; import java.util.List; @@ -44,6 +46,7 @@ import java.util.List; * @date 2022/2/23 18:26 **/ @Tag(name = "文件控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 4) @RestController @Validated public class DevFileController { @@ -63,6 +66,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 1) @Operation(summary = "动态上传文件返回id") @CommonLog("动态上传文件返回id") @PostMapping("/dev/file/uploadDynamicReturnId") @@ -76,6 +80,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 2) @Operation(summary = "动态上传文件返回url") @CommonLog("动态上传文件返回url") @PostMapping("/dev/file/uploadDynamicReturnUrl") @@ -89,6 +94,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 3) @Operation(summary = "上传本地文件返回id") @CommonLog("上传本地文件返回id") @PostMapping("/dev/file/uploadLocalReturnId") @@ -102,6 +108,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 4) @Operation(summary = "上传本地文件返回url") @CommonLog("上传本地文件返回url") @PostMapping("/dev/file/uploadLocalReturnUrl") @@ -115,6 +122,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 5) @Operation(summary = "上传阿里云文件返回id") @CommonLog("上传阿里云文件返回id") @PostMapping("/dev/file/uploadAliyunReturnId") @@ -128,6 +136,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 6) @Operation(summary = "上传阿里云文件返回url") @CommonLog("上传阿里云文件返回url") @PostMapping("/dev/file/uploadAliyunReturnUrl") @@ -141,6 +150,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 7) @Operation(summary = "上传腾讯云文件返回id") @CommonLog("上传腾讯云文件返回id") @PostMapping("/dev/file/uploadTencentReturnId") @@ -154,6 +164,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 8) @Operation(summary = "上传腾讯云文件返回url") @CommonLog("上传腾讯云文件返回url") @PostMapping("/dev/file/uploadTencentReturnUrl") @@ -167,6 +178,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 9) @Operation(summary = "上传MINIO文件返回id") @CommonLog("上传MINIO文件返回id") @PostMapping("/dev/file/uploadMinioReturnId") @@ -180,6 +192,7 @@ public class DevFileController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 10) @Operation(summary = "上传MINIO文件返回url") @CommonLog("上传MINIO文件返回url") @PostMapping("/dev/file/uploadMinioReturnUrl") @@ -193,6 +206,7 @@ public class DevFileController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 11) @Operation(summary = "获取文件分页列表") @GetMapping("/dev/file/page") public CommonResult> page(DevFilePageParam devFilePageParam) { @@ -205,6 +219,7 @@ public class DevFileController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 12) @Operation(summary = "获取文件列表") @GetMapping("/dev/file/list") public CommonResult> list(DevFileListParam devFileListParam) { @@ -217,6 +232,7 @@ public class DevFileController { * @author xuyuxiang * @date 2022/6/21 15:44 **/ + @ApiOperationSupport(order = 13) @Operation(summary = "下载文件") @CommonLog("下载文件") @GetMapping(value = "/dev/file/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @@ -230,6 +246,7 @@ public class DevFileController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 14) @Operation(summary = "删除文件") @CommonLog("删除文件") @PostMapping(value = "/dev/file/delete") @@ -239,12 +256,27 @@ public class DevFileController { return CommonResult.ok(); } + /** + * 物理删除文件 + * + * @author 每天一点 + * @date 2025/4/06 20:25 + */ + @Operation(summary = "物理删除文件") + @CommonLog("物理删除文件") + @PostMapping(value = "/dev/file/deleteAbsolute") + public CommonResult deleteAbsolute(@RequestBody DevFileIdParam devFileIdParam) { + devFileService.deleteAbsolute(devFileIdParam); + return CommonResult.ok(); + } + /** * 获取文件详情 * * @author xuyuxiang * @date 2022/6/21 15:44 **/ + @ApiOperationSupport(order = 15) @Operation(summary = "获取文件详情") @GetMapping("/dev/file/detail") public CommonResult detail(@Valid DevFileIdParam devFileIdParam) { @@ -257,6 +289,7 @@ public class DevFileController { * @author yubaoshan * @date 2024/6/9 23:52 **/ + @ApiOperationSupport(order = 16) @Operation(summary = "根据文件url集合获取文件集合") @PostMapping("/dev/file/getFileListByUrlList") public CommonResult> getFileListByUrlList(@RequestBody @Valid DevFileUrlListParam devFileUrlListParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java index 1a456d33..0ddc6316 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java @@ -30,7 +30,7 @@ import vip.xiaonuo.common.pojo.CommonEntity; public class DevFile extends CommonEntity { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 存储引擎 */ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/param/DevFileIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/param/DevFileIdParam.java index e2e04c05..b546af26 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/param/DevFileIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/param/DevFileIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevFileIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java index 4b25f3fe..e4927a68 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java @@ -38,16 +38,21 @@ public class DevFileApiProvider implements DevFileApi { private static final String SNOWY_SYS_DEFAULT_FILE_ENGINE_KEY = "SNOWY_SYS_DEFAULT_FILE_ENGINE"; @Resource - private DevFileService devFileService; + private DevConfigApi devConfigApi; @Resource - private DevConfigApi devConfigApi; + private DevFileService devFileService; @Override public String uploadDynamicReturnId(MultipartFile file) { return devFileService.uploadReturnId(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_FILE_ENGINE_KEY), file); } + @Override + public String uploadDynamicReturnUrl(MultipartFile file) { + return devFileService.uploadReturnUrl(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_FILE_ENGINE_KEY), file); + } + @Override public String storageFileWithReturnUrlLocal(MultipartFile file) { return devFileService.uploadReturnUrl(DevFileEngineTypeEnum.LOCAL.getValue(), file); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java index c6360197..5f8ec4c9 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java @@ -124,8 +124,8 @@ public class DevFileServiceImpl extends ServiceImpl impl CommonDownloadUtil.download(devFile.getName(), IoUtil.readBytes(FileUtil.getInputStream(file)), response); } - @Override @Transactional(rollbackFor = Exception.class) + @Override public void delete(List devFileIdParamList) { this.removeByIds(CollStreamUtil.toList(devFileIdParamList, DevFileIdParam::getId)); } @@ -178,6 +178,8 @@ public class DevFileServiceImpl extends ServiceImpl impl // 存储桶名称 String bucketName; + String fileKey = genFileKey(fileId, file); + // 定义存储的url,本地文件返回文件实际路径,其他引擎返回网络地址 String storageUrl; @@ -186,22 +188,22 @@ public class DevFileServiceImpl extends ServiceImpl impl // 使用固定名称defaultBucketName bucketName = "defaultBucketName"; - storageUrl = DevFileLocalUtil.storageFileWithReturnUrl(bucketName, genFileKey(fileId, file), file); + storageUrl = DevFileLocalUtil.storageFileWithReturnUrl(bucketName, fileKey, file); } else if(engine.equals(DevFileEngineTypeEnum.ALIYUN.getValue())) { // 使用阿里云默认配置的bucketName bucketName = DevFileAliyunUtil.getDefaultBucketName(); - storageUrl = DevFileAliyunUtil.storageFileWithReturnUrl(bucketName, genFileKey(fileId, file), file); + storageUrl = DevFileAliyunUtil.storageFileWithReturnUrl(bucketName, fileKey, file); } else if(engine.equals(DevFileEngineTypeEnum.TENCENT.getValue())) { // 使用腾讯云默认配置的bucketName bucketName = DevFileTencentUtil.getDefaultBucketName(); - storageUrl = DevFileTencentUtil.storageFileWithReturnUrl(bucketName, genFileKey(fileId, file), file); + storageUrl = DevFileTencentUtil.storageFileWithReturnUrl(bucketName, fileKey, file); } else if(engine.equals(DevFileEngineTypeEnum.MINIO.getValue())) { // 使用MINIO默认配置的bucketName bucketName = DevFileMinIoUtil.getDefaultBucketName(); - storageUrl = DevFileMinIoUtil.storageFileWithReturnUrl(bucketName, genFileKey(fileId, file), file); + storageUrl = DevFileMinIoUtil.storageFileWithReturnUrl(bucketName, fileKey, file); } else { throw new CommonException("不支持的文件引擎:{}", engine); } @@ -215,12 +217,13 @@ public class DevFileServiceImpl extends ServiceImpl impl // 设置存储引擎类型 devFile.setEngine(engine); devFile.setBucket(bucketName); + devFile.setFileKey(fileKey); devFile.setName(file.getOriginalFilename()); String suffix = ObjectUtil.isNotEmpty(file.getOriginalFilename())?StrUtil.subAfter(file.getOriginalFilename(), StrUtil.DOT, true):null; devFile.setSuffix(suffix); devFile.setSizeKb(Convert.toStr(NumberUtil.div(new BigDecimal(file.getSize()), BigDecimal.valueOf(1024)) - .setScale(0, RoundingMode.HALF_UP))); + .setScale(0, RoundingMode.HALF_UP ))); devFile.setSizeInfo(FileUtil.readableFileSize(file.getSize())); devFile.setObjName(ObjectUtil.isNotEmpty(devFile.getSuffix())?fileId + StrUtil.DOT + devFile.getSuffix():null); // 如果是图片,则压缩生成缩略图 diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileAliyunUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileAliyunUtil.java index 7a304ca0..174490e2 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileAliyunUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileAliyunUtil.java @@ -23,13 +23,13 @@ import com.aliyun.oss.model.CannedAccessControlList; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.OSSObject; import com.aliyun.oss.model.ObjectMetadata; -import jakarta.activation.MimetypesFileTypeMap; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.dev.api.DevConfigApi; import vip.xiaonuo.dev.modular.file.enums.DevFileBucketAuthEnum; +import javax.activation.MimetypesFileTypeMap; import java.io.*; import java.net.URL; import java.util.Date; @@ -37,7 +37,7 @@ import java.util.List; /** * 阿里云文件工具类 - * 参考文档:https://help.aliyun.com/document_detail/32010.html + * 参考文档:参考文档 * * @author xuyuxiang * @date 2022/1/2 18:13 diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileLocalUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileLocalUtil.java index 6bba1924..7dec4e72 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileLocalUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileLocalUtil.java @@ -19,6 +19,7 @@ import cn.hutool.extra.spring.SpringUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.hutool.system.SystemUtil; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.common.exception.CommonException; @@ -39,6 +40,12 @@ import java.io.InputStream; @Slf4j public class DevFileLocalUtil { + /** + * -- GETTER -- + * 获取操作的客户端 + * + */ + @Getter private static JSONObject client; private static final String SNOWY_FILE_LOCAL_FOLDER_FOR_WINDOWS_KEY = "SNOWY_FILE_LOCAL_FOLDER_FOR_WINDOWS"; @@ -92,16 +99,6 @@ public class DevFileLocalUtil { client.clear(); } - /** - * 获取操作的客户端 - * - * @author xuyuxiang - * @date 2022/1/5 23:24 - */ - public static JSONObject getClient() { - return client; - } - /** * 获取上传地址 * diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileMinIoUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileMinIoUtil.java index 0b4054db..91af4d54 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileMinIoUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileMinIoUtil.java @@ -23,18 +23,19 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import io.minio.*; import io.minio.http.Method; -import jakarta.activation.MimetypesFileTypeMap; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.dev.api.DevConfigApi; import vip.xiaonuo.dev.modular.file.enums.DevFileBucketAuthEnum; +import javax.activation.MimetypesFileTypeMap; import java.io.*; /** * MINIO文件工具类 - * 参考文档:http://docs.minio.org.cn/docs/master/java-client-quickstart-guide + * 参考文档:参考文档 * * @author xuyuxiang * @date 2022/1/2 18:13 @@ -42,6 +43,12 @@ import java.io.*; @Slf4j public class DevFileMinIoUtil { + /** + * -- GETTER -- + * 获取操作的客户端 + * + */ + @Getter private static MinioClient client; private static String defaultBucketName; @@ -80,7 +87,7 @@ public class DevFileMinIoUtil { String endpoint = devConfigApi.getValueByKey(SNOWY_FILE_MINIO_END_POINT_KEY); if(ObjectUtil.isEmpty(endpoint)) { - throw new CommonException("MINIO文件操作客户端未正确配置:endpoint为空"); + throw new CommonException("MINIO文件操作客户端未正确配置:secretKey为空"); } /* 默认BucketName */ @@ -114,16 +121,6 @@ public class DevFileMinIoUtil { // 无需 } - /** - * 获取操作的客户端 - * - * @author xuyuxiang - * @date 2022/1/5 23:24 - */ - public static MinioClient getClient() { - return client; - } - /** * 查询存储桶是否存在 * 例如:传入参数examplebucket-1250000000,返回true代表存在此桶 diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileTencentUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileTencentUtil.java index 33f82f6c..cdd050b5 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileTencentUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/util/DevFileTencentUtil.java @@ -27,13 +27,13 @@ import com.qcloud.cos.model.*; import com.qcloud.cos.region.Region; import com.qcloud.cos.transfer.TransferManager; import com.qcloud.cos.transfer.TransferManagerConfiguration; -import jakarta.activation.MimetypesFileTypeMap; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.dev.api.DevConfigApi; import vip.xiaonuo.dev.modular.file.enums.DevFileBucketAuthEnum; +import javax.activation.MimetypesFileTypeMap; import java.io.*; import java.net.URL; import java.util.Date; @@ -42,7 +42,7 @@ import java.util.concurrent.Executors; /** * 腾讯云文件工具类 - * 参考文档:https://cloud.tencent.com/document/product/436/10199 + * 参考文档:参考文档 * * @author xuyuxiang * @date 2022/1/2 18:13 diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/controller/DevJobController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/controller/DevJobController.java index ebd0e9b4..619e267b 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/controller/DevJobController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/controller/DevJobController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.dev.modular.job.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -29,6 +30,7 @@ import vip.xiaonuo.dev.modular.job.entity.DevJob; import vip.xiaonuo.dev.modular.job.param.*; import vip.xiaonuo.dev.modular.job.service.DevJobService; +import javax.validation.Valid; import java.util.List; /** @@ -38,19 +40,21 @@ import java.util.List; * @date 2022/8/5 10:48 **/ @Tag(name = "定时任务控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 7) @RestController @Validated public class DevJobController { @Resource private DevJobService devJobService; - + /** * 获取定时任务分页 * * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取定时任务分页") @GetMapping("/dev/job/page") public CommonResult> page(DevJobPageParam devJobPageParam) { @@ -63,6 +67,7 @@ public class DevJobController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取定时任务列表") @GetMapping("/dev/job/list") public CommonResult> list(DevJobListParam devJobListParam) { @@ -75,6 +80,7 @@ public class DevJobController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "添加定时任务") @CommonLog("添加定时任务") @PostMapping("/dev/job/add") @@ -89,6 +95,7 @@ public class DevJobController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "编辑定时任务") @CommonLog("编辑定时任务") @PostMapping("/dev/job/edit") @@ -103,6 +110,7 @@ public class DevJobController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "删除定时任务") @CommonLog("删除定时任务") @PostMapping("/dev/job/delete") @@ -118,6 +126,7 @@ public class DevJobController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取定时任务详情") @GetMapping("/dev/job/detail") public CommonResult detail(@Valid DevJobIdParam devJobIdParam) { @@ -130,6 +139,7 @@ public class DevJobController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 6) @Operation(summary = "停止定时任务") @CommonLog("停止定时任务") @PostMapping("/dev/job/stopJob") @@ -144,6 +154,7 @@ public class DevJobController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 7) @Operation(summary = "运行定时任务") @CommonLog("运行定时任务") @PostMapping("/dev/job/runJob") @@ -158,6 +169,7 @@ public class DevJobController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 8) @Operation(summary = "立即运行定时任务") @CommonLog("立即运行定时任务") @PostMapping("/dev/job/runJobNow") @@ -172,6 +184,7 @@ public class DevJobController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 9) @Operation(summary = "获取定时任务类") @GetMapping("/dev/job/getActionClass") public CommonResult> getActionClass() { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/entity/DevJob.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/entity/DevJob.java index a927c92f..6328fde4 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/entity/DevJob.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/entity/DevJob.java @@ -65,7 +65,7 @@ public class DevJob extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobAddParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobAddParam.java index 509dc076..69e35833 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobAddParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobAddParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class DevJobAddParam { /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 任务类名 */ - @Schema(description = "任务类名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "任务类名") @NotBlank(message = "actionClass不能为空") private String actionClass; /** cron表达式 */ - @Schema(description = "cron表达式", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "cron表达式") @NotBlank(message = "cronExpression不能为空") private String cronExpression; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobEditParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobEditParam.java index 5a8824df..25e61840 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobEditParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobEditParam.java @@ -29,32 +29,32 @@ import lombok.Setter; public class DevJobEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 任务类名 */ - @Schema(description = "任务类名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "任务类名") @NotBlank(message = "actionClass不能为空") private String actionClass; /** cron表达式 */ - @Schema(description = "cron表达式", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "cron表达式") @NotBlank(message = "cronExpression不能为空") private String cronExpression; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobIdParam.java index f2e7f987..991cdbbd 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/param/DevJobIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevJobIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/service/impl/DevJobServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/service/impl/DevJobServiceImpl.java index 264e3a2f..de84657d 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/service/impl/DevJobServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/service/impl/DevJobServiceImpl.java @@ -82,20 +82,20 @@ public class DevJobServiceImpl extends ServiceImpl impleme @Override public List list(DevJobListParam devJobListParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - lambdaQueryWrapper.select(DevJob::getId, DevJob::getName, DevJob::getCategory, + queryWrapper.lambda().select(DevJob::getId, DevJob::getName, DevJob::getCategory, DevJob::getActionClass, DevJob::getCronExpression, DevJob::getJobStatus, DevJob::getSortCode); if(ObjectUtil.isNotEmpty(devJobListParam.getCategory())) { - lambdaQueryWrapper.eq(DevJob::getCategory, devJobListParam.getCategory()); + queryWrapper.lambda().eq(DevJob::getCategory, devJobListParam.getCategory()); } if(ObjectUtil.isNotEmpty(devJobListParam.getSearchKey())) { - lambdaQueryWrapper.like(DevJob::getName, devJobListParam.getSearchKey()); + queryWrapper.lambda().like(DevJob::getName, devJobListParam.getSearchKey()); } if(ObjectUtil.isNotEmpty(devJobListParam.getJobStatus())) { - lambdaQueryWrapper.like(DevJob::getJobStatus, devJobListParam.getJobStatus()); + queryWrapper.lambda().like(DevJob::getJobStatus, devJobListParam.getJobStatus()); } - return this.list(lambdaQueryWrapper); + return this.list(queryWrapper); } @Override @@ -223,6 +223,7 @@ public class DevJobServiceImpl extends ServiceImpl impleme .set(DevJob::getJobStatus, DevJobStatusEnum.RUNNING.getValue())); } + @Transactional(rollbackFor = Exception.class) @Override public void runJobNow(DevJobIdParam devJobIdParam) { DevJob devJob = this.detail(devJobIdParam); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/task/DevJobTimerTaskRunner.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/task/DevJobTimerTaskRunner.java index 98ddefd1..c97b35b4 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/task/DevJobTimerTaskRunner.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/job/task/DevJobTimerTaskRunner.java @@ -30,7 +30,7 @@ public class DevJobTimerTaskRunner implements CommonTimerTaskRunner { @Override public void action(String extJson) { - log.info("我是一个定时任务,正在在被执行第" + n + "次"); + log.info("我是一个定时任务,正在在被执行第{}次", n); n = n + 1; } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/controller/DevLogController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/controller/DevLogController.java index ee7d7dec..28bdd870 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/controller/DevLogController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/controller/DevLogController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.dev.modular.log.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -34,6 +35,7 @@ import vip.xiaonuo.dev.modular.log.result.DevLogVisLineChartDataResult; import vip.xiaonuo.dev.modular.log.result.DevLogVisPieChartDataResult; import vip.xiaonuo.dev.modular.log.service.DevLogService; +import javax.validation.Valid; import java.util.List; /** @@ -43,6 +45,7 @@ import java.util.List; * @date 2022/9/2 15:15 */ @Tag(name = "日志控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 8) @RestController @Validated public class DevLogController { @@ -56,6 +59,7 @@ public class DevLogController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取日志分页") @GetMapping("/dev/log/page") public CommonResult> page(DevLogPageParam devLogPageParam) { @@ -68,6 +72,7 @@ public class DevLogController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "清空日志") @CommonLog("清空日志") @PostMapping("/dev/log/delete") @@ -82,6 +87,7 @@ public class DevLogController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 3) @Operation(summary = "获取访问日志折线图数据") @GetMapping("/dev/log/vis/lineChartData") public CommonResult> visLogLineChartData() { @@ -94,6 +100,7 @@ public class DevLogController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "获取访问日志饼状图数据") @GetMapping("/dev/log/vis/pieChartData") public CommonResult> visLogPieChartData() { @@ -106,6 +113,7 @@ public class DevLogController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取操作日志柱状图数据") @GetMapping("/dev/log/op/barChartData") public CommonResult> opLogBarChartData() { @@ -118,6 +126,7 @@ public class DevLogController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取操作日志饼状图数据") @GetMapping("/dev/log/op/pieChartData") public CommonResult> opLogPieChartData() { @@ -127,6 +136,7 @@ public class DevLogController { /** * 依据id获取单条日志详情 */ + @ApiOperationSupport(order = 6) @Operation(summary = "依据id获取日志详情") @GetMapping("/dev/log/detail") public CommonResult detail(@Valid DevLogIdParam devLogIdParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/entity/DevLog.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/entity/DevLog.java index 22628439..b2d95bde 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/entity/DevLog.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/entity/DevLog.java @@ -33,7 +33,7 @@ import java.util.Date; public class DevLog { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 日志分类 */ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogDeleteParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogDeleteParam.java index b688e613..438c287f 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogDeleteParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogDeleteParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevLogDeleteParam { /** 日志分类 */ - @Schema(description = "日志分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "日志分类") @NotBlank(message = "category不能为空") private String category; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogIdParam.java index 33858a5c..c00639f2 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/param/DevLogIdParam.java @@ -12,7 +12,7 @@ import lombok.Setter; @Setter public class DevLogIdParam { - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/service/impl/DevLogServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/service/impl/DevLogServiceImpl.java index 41b5c5cf..15f2d431 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/service/impl/DevLogServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/service/impl/DevLogServiceImpl.java @@ -148,7 +148,7 @@ public class DevLogServiceImpl extends ServiceImpl impleme DevLog::getName,DevLog::getOpIp, DevLog::getOpAddress, DevLog::getCategory, DevLog::getClassName, DevLog::getMethodName, DevLog::getOpTime, DevLog::getOpUser) .in(DevLog::getCategory, DevLogCategoryEnum.OPERATE.getValue(), - DevLogCategoryEnum.EXCEPTION.getValue()).between(DevLog::getOpTime, lastWeek, now).orderByAsc(DevLog::getOpTime)) + DevLogCategoryEnum.EXCEPTION.getValue()).between(DevLog::getOpTime, lastWeek, now).orderByAsc(DevLog::getOpTime)) .stream().map(devLog -> JSONUtil.parseObj(devLog).set("date", DateUtil.formatDate(devLog.getOpTime()))) .collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("date"))); long between = DateUtil.between(lastWeek, now, DateUnit.DAY); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/util/DevLogUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/util/DevLogUtil.java index 5525b495..f161d289 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/util/DevLogUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/log/util/DevLogUtil.java @@ -12,11 +12,9 @@ */ package vip.xiaonuo.dev.modular.log.util; -import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.thread.ThreadUtil; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import jakarta.servlet.http.HttpServletRequest; import org.aspectj.lang.JoinPoint; @@ -140,21 +138,11 @@ public class DevLogUtil { private static DevLog genBasOpLog() { HttpServletRequest request = CommonServletUtil.getRequest(); String ip = CommonIpAddressUtil.getIp(request); - String loginId; - try { - loginId = StpUtil.getLoginIdAsString(); - if (ObjectUtil.isEmpty(loginId)) { - loginId = "-1"; - } - } catch (Exception e) { - loginId = "-1"; - } DevLog devLog = new DevLog(); devLog.setOpIp(CommonIpAddressUtil.getIp(request)); devLog.setOpAddress(CommonIpAddressUtil.getCityInfo(ip)); devLog.setOpBrowser(CommonUaUtil.getBrowser(request)); devLog.setOpOs(CommonUaUtil.getOs(request)); - devLog.setCreateUser(loginId); return devLog; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/controller/DevMessageController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/controller/DevMessageController.java index 66a6ae0d..f6462c0e 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/controller/DevMessageController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/controller/DevMessageController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.dev.modular.message.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.dev.modular.message.param.DevMessageSendParam; import vip.xiaonuo.dev.modular.message.result.DevMessageResult; import vip.xiaonuo.dev.modular.message.service.DevMessageService; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/6/21 14:57 **/ @Tag(name = "站内信控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 6) @RestController @Validated public class DevMessageController { @@ -54,6 +57,7 @@ public class DevMessageController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 1) @Operation(summary = "发送站内信") @CommonLog("发送站内信") @PostMapping("/dev/message/send") @@ -68,6 +72,7 @@ public class DevMessageController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取站内信分页") @GetMapping("/dev/message/page") public CommonResult> page(DevMessagePageParam devMessagePageParam) { @@ -80,11 +85,12 @@ public class DevMessageController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 3) @Operation(summary = "删除站内信") @CommonLog("删除站内信") @PostMapping("/dev/message/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List devMessageIdParamList) { + List devMessageIdParamList) { devMessageService.delete(devMessageIdParamList); return CommonResult.ok(); } @@ -95,6 +101,7 @@ public class DevMessageController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "获取站内信详情") @GetMapping("/dev/message/detail") public CommonResult detail(@Valid DevMessageIdParam devMessageIdParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/entity/DevMessage.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/entity/DevMessage.java index 8d3a88b4..3275adcc 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/entity/DevMessage.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/entity/DevMessage.java @@ -30,7 +30,7 @@ import vip.xiaonuo.common.pojo.CommonEntity; public class DevMessage extends CommonEntity { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 分类 */ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageIdParam.java index cd7164e4..aa98ef10 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevMessageIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageSendParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageSendParam.java index d304144c..a5d8e72a 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageSendParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/param/DevMessageSendParam.java @@ -31,12 +31,12 @@ import java.util.List; public class DevMessageSendParam { /** 主题 */ - @Schema(description = "主题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "主题") @NotBlank(message = "subject不能为空") private String subject; /** 接收人id集合 */ - @Schema(description = "接收人id集合", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "接收人id集合") @NotEmpty(message = "receiverIdList不能为空") private List receiverIdList; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/result/DevMessageResult.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/result/DevMessageResult.java index 0f0f636c..48e2076c 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/result/DevMessageResult.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/result/DevMessageResult.java @@ -29,7 +29,7 @@ import java.util.List; public class DevMessageResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 分类 */ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/service/impl/DevMessageServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/service/impl/DevMessageServiceImpl.java index a55c59c1..04407bf4 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/service/impl/DevMessageServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/message/service/impl/DevMessageServiceImpl.java @@ -192,13 +192,7 @@ public class DevMessageServiceImpl extends ServiceImpl receiveInfoList = devRelationService.getRelationListByObjectIdAndCategory(devMessage.getId(), DevRelationCategoryEnum.MSG_TO_USER.getValue()).stream().map(devRelation -> { DevMessageResult.DevReceiveInfo devReceiveInfo = new DevMessageResult.DevReceiveInfo(); - JSONObject userObj = null; - try { - userObj = sysUserApi.getUserByIdWithException(devRelation.getTargetId()); - } - catch (Exception e) { - // 收件人中包含删除用户 在此处做处理 - } + JSONObject userObj = sysUserApi.getUserByIdWithException(devRelation.getTargetId()); String userName = "未知用户"; if(ObjectUtil.isNotEmpty(userObj)) { userName = userObj.getStr("name"); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/monitor/controller/DevMonitorController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/monitor/controller/DevMonitorController.java index 1b6d6eb5..cf7fa4c8 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/monitor/controller/DevMonitorController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/monitor/controller/DevMonitorController.java @@ -12,6 +12,8 @@ */ package vip.xiaonuo.dev.modular.monitor.controller; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -29,6 +31,7 @@ import vip.xiaonuo.dev.modular.monitor.service.DevMonitorService; * @date 2022/6/21 14:57 **/ @Tag(name = "监控控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 9) @RestController @Validated public class DevMonitorController { @@ -42,6 +45,7 @@ public class DevMonitorController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取服务器监控信息") @GetMapping("/dev/monitor/serverInfo") public CommonResult serverInfo() { @@ -54,6 +58,7 @@ public class DevMonitorController { * @author diantu * @date 2023/7/27 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取服务器网络情况") @GetMapping("/dev/monitor/networkInfo") public CommonResult networkInfo() { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/controller/DevWeakPasswordController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/controller/DevWeakPasswordController.java new file mode 100644 index 00000000..41130fc6 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/controller/DevWeakPasswordController.java @@ -0,0 +1,125 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import vip.xiaonuo.common.annotation.CommonLog; +import vip.xiaonuo.common.pojo.CommonResult; +import vip.xiaonuo.dev.modular.password.entity.DevWeakPassword; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordAddParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordEditParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordIdParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordPageParam; +import vip.xiaonuo.dev.modular.password.service.DevWeakPasswordService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 弱密码库控制器 + * + * @author xuyuxiang + * @date 2022/4/25 20:40 + */ +@Tag(name = "弱密码库控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 2) +@RestController +@Validated +public class DevWeakPasswordController { + + @Resource + private DevWeakPasswordService devWeakPasswordService; + + /** + * 获取弱密码库分页 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 1) + @Operation(summary = "获取弱密码库分页") + @GetMapping("/dev/weakPassword/page") + public CommonResult> page(DevWeakPasswordPageParam devWeakPasswordPageParam) { + return CommonResult.data(devWeakPasswordService.page(devWeakPasswordPageParam)); + } + + /** + * 添加弱密码库 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 2) + @Operation(summary = "添加弱密码库") + @CommonLog("添加弱密码库") + @PostMapping("/dev/weakPassword/add") + public CommonResult add(@RequestBody @Valid DevWeakPasswordAddParam devWeakPasswordAddParam) { + devWeakPasswordService.add(devWeakPasswordAddParam); + return CommonResult.ok(); + } + + /** + * 编辑弱密码库 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 3) + @Operation(summary = "编辑弱密码库") + @CommonLog("编辑弱密码库") + @PostMapping("/dev/weakPassword/edit") + public CommonResult edit(@RequestBody @Valid DevWeakPasswordEditParam devWeakPasswordEditParam) { + devWeakPasswordService.edit(devWeakPasswordEditParam); + return CommonResult.ok(); + } + + /** + * 删除弱密码库 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 4) + @Operation(summary = "删除弱密码库") + @CommonLog("删除弱密码库") + @PostMapping("/dev/weakPassword/delete") + public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") + List devWeakPasswordIdParamList) { + devWeakPasswordService.delete(devWeakPasswordIdParamList); + return CommonResult.ok(); + } + + /** + * 获取弱密码库详情 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 5) + @Operation(summary = "获取弱密码库详情") + @GetMapping("/dev/weakPassword/detail") + public CommonResult detail(@Valid DevWeakPasswordIdParam devWeakPasswordIdParam) { + return CommonResult.data(devWeakPasswordService.detail(devWeakPasswordIdParam)); + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/entity/DevWeakPassword.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/entity/DevWeakPassword.java new file mode 100644 index 00000000..23ad936c --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/entity/DevWeakPassword.java @@ -0,0 +1,42 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +/** + * 弱密码库实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("DEV_WEAK_PASSWORD") +public class DevWeakPassword extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 密码 */ + @Schema(description = "密码") + private String password; + +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/DevWeakPasswordMapper.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/DevWeakPasswordMapper.java new file mode 100644 index 00000000..108da3b4 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/DevWeakPasswordMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.dev.modular.password.entity.DevWeakPassword; + +/** + * 弱密码库Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface DevWeakPasswordMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/mapping/DevWeakPasswordMapper.xml b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/mapping/DevWeakPasswordMapper.xml new file mode 100644 index 00000000..261af514 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/mapper/mapping/DevWeakPasswordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordAddParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordAddParam.java new file mode 100644 index 00000000..64aa3e07 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordAddParam.java @@ -0,0 +1,34 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 弱密码库添加参数 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +public class DevWeakPasswordAddParam { + + /** 密码 */ + @Schema(description = "密码") + @NotBlank(message = "password不能为空") + private String password; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordEditParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordEditParam.java new file mode 100644 index 00000000..2a3c67ca --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordEditParam.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 弱密码库编辑参数 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +public class DevWeakPasswordEditParam { + + /** id */ + @Schema(description = "id") + @NotBlank(message = "id不能为空") + private String id; + + /** 密码 */ + @Schema(description = "密码") + @NotBlank(message = "password不能为空") + private String password; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordIdParam.java new file mode 100644 index 00000000..7602c481 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordIdParam.java @@ -0,0 +1,34 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 弱密码库Id参数 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +public class DevWeakPasswordIdParam { + + /** id */ + @Schema(description = "id") + @NotBlank(message = "id不能为空") + private String id; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordPageParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordPageParam.java new file mode 100644 index 00000000..6a00fa43 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/param/DevWeakPasswordPageParam.java @@ -0,0 +1,48 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * 弱密码库查询参数 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +public class DevWeakPasswordPageParam { + + /** 当前页 */ + @Schema(description = "当前页码") + private Integer current; + + /** 每页条数 */ + @Schema(description = "每页条数") + private Integer size; + + /** 排序字段 */ + @Schema(description = "排序字段,字段驼峰名称,如:userName") + private String sortField; + + /** 排序方式 */ + @Schema(description = "排序方式,升序:ASCEND;降序:DESCEND") + private String sortOrder; + + /** 密码关键词 */ + @Schema(description = "密码关键词") + private String searchKey; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/provider/DevWeakPasswordApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/provider/DevWeakPasswordApiProvider.java new file mode 100644 index 00000000..1e50ef02 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/provider/DevWeakPasswordApiProvider.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.provider; + +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import vip.xiaonuo.dev.api.DevWeakPasswordApi; +import vip.xiaonuo.dev.modular.password.entity.DevWeakPassword; +import vip.xiaonuo.dev.modular.password.service.DevWeakPasswordService; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 弱密码库API接口实现类 + * + * @author xuyuxiang + * @date 2022/6/17 14:43 + **/ +@Service +public class DevWeakPasswordApiProvider implements DevWeakPasswordApi { + + @Resource + private DevWeakPasswordService devWeakPasswordService; + + @Override + public List weakPasswordList() { + return devWeakPasswordService.list().stream().map(DevWeakPassword::getPassword).collect(Collectors.toList()); + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/DevWeakPasswordService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/DevWeakPasswordService.java new file mode 100644 index 00000000..cfad0709 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/DevWeakPasswordService.java @@ -0,0 +1,81 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.dev.modular.password.entity.DevWeakPassword; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordAddParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordEditParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordIdParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordPageParam; + +import java.util.List; + +/** + * 弱密码库Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface DevWeakPasswordService extends IService { + + /** + * 获取弱密码库分页 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + Page page(DevWeakPasswordPageParam devWeakPasswordPageParam); + + /** + * 添加弱密码库 + * + * @author xuyuxiang + * @date 2022/4/24 20:48 + */ + void add(DevWeakPasswordAddParam devWeakPasswordAddParam); + + /** + * 编辑弱密码库 + * + * @author xuyuxiang + * @date 2022/4/24 21:13 + */ + void edit(DevWeakPasswordEditParam devWeakPasswordEditParam); + + /** + * 删除弱密码库 + * + * @author xuyuxiang + * @date 2022/4/24 21:18 + */ + void delete(List devWeakPasswordIdParamList); + + /** + * 获取弱密码库详情 + * + * @author xuyuxiang + * @date 2022/4/24 21:18 + */ + DevWeakPassword detail(DevWeakPasswordIdParam devWeakPasswordIdParam); + + /** + * 获取弱密码库详情 + * + * @author xuyuxiang + * @date 2022/7/25 19:42 + **/ + DevWeakPassword queryEntity(String id); + +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/impl/DevWeakPasswordServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/impl/DevWeakPasswordServiceImpl.java new file mode 100644 index 00000000..fef62084 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/password/service/impl/DevWeakPasswordServiceImpl.java @@ -0,0 +1,108 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.password.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import vip.xiaonuo.common.enums.CommonSortOrderEnum; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.common.page.CommonPageRequest; +import vip.xiaonuo.dev.modular.password.entity.DevWeakPassword; +import vip.xiaonuo.dev.modular.password.mapper.DevWeakPasswordMapper; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordAddParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordEditParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordIdParam; +import vip.xiaonuo.dev.modular.password.param.DevWeakPasswordPageParam; +import vip.xiaonuo.dev.modular.password.service.DevWeakPasswordService; + +import java.util.List; + +/** + * 弱密码库Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class DevWeakPasswordServiceImpl extends ServiceImpl implements DevWeakPasswordService { + + @Override + public Page page(DevWeakPasswordPageParam devWeakPasswordPageParam) { + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + if(ObjectUtil.isNotEmpty(devWeakPasswordPageParam.getSearchKey())) { + queryWrapper.lambda().like(DevWeakPassword::getPassword, devWeakPasswordPageParam.getSearchKey()); + } + if(ObjectUtil.isAllNotEmpty(devWeakPasswordPageParam.getSortField(), devWeakPasswordPageParam.getSortOrder())) { + CommonSortOrderEnum.validate(devWeakPasswordPageParam.getSortOrder()); + queryWrapper.orderBy(true, devWeakPasswordPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()), + StrUtil.toUnderlineCase(devWeakPasswordPageParam.getSortField())); + } else { + queryWrapper.lambda().orderByDesc(DevWeakPassword::getCreateTime); + } + return this.page(CommonPageRequest.defaultPage(), queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void add(DevWeakPasswordAddParam devWeakPasswordAddParam) { + DevWeakPassword devWeakPassword = BeanUtil.toBean(devWeakPasswordAddParam, DevWeakPassword.class); + boolean repeatPassword = this.count(new LambdaQueryWrapper().eq(DevWeakPassword::getPassword, devWeakPassword.getPassword())) > 0; + if(repeatPassword) { + throw new CommonException("存在重复的密码,值为:{}", devWeakPassword.getPassword()); + } + this.save(devWeakPassword); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void edit(DevWeakPasswordEditParam devWeakPasswordEditParam) { + DevWeakPassword devWeakPassword = this.queryEntity(devWeakPasswordEditParam.getId()); + BeanUtil.copyProperties(devWeakPasswordEditParam, devWeakPassword); + boolean repeatPassword = this.count(new LambdaQueryWrapper().eq(DevWeakPassword::getPassword, devWeakPassword.getPassword()) + .ne(DevWeakPassword::getId, devWeakPassword.getId())) > 0; + if(repeatPassword) { + throw new CommonException("存在重复的密码,值为:{}", devWeakPassword.getPassword()); + } + this.updateById(devWeakPassword); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(List devWeakPasswordIdParamList) { + List weakPasswordIdList = CollStreamUtil.toList(devWeakPasswordIdParamList, DevWeakPasswordIdParam::getId); + // 执行删除 + this.removeByIds(weakPasswordIdList); + } + + @Override + public DevWeakPassword detail(DevWeakPasswordIdParam devWeakPasswordIdParam) { + return this.queryEntity(devWeakPasswordIdParam.getId()); + } + + @Override + public DevWeakPassword queryEntity(String id) { + DevWeakPassword devWeakPassword = this.getById(id); + if (ObjectUtil.isEmpty(devWeakPassword)) { + throw new CommonException("弱密码数据不存在,id值为:{}", id); + } + return devWeakPassword; + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/controller/DevPushController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/controller/DevPushController.java new file mode 100644 index 00000000..83c70a77 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/controller/DevPushController.java @@ -0,0 +1,212 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.constraints.NotEmpty; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import vip.xiaonuo.common.annotation.CommonLog; +import vip.xiaonuo.common.pojo.CommonResult; +import vip.xiaonuo.dev.modular.push.entity.DevPush; +import vip.xiaonuo.dev.modular.push.param.*; +import vip.xiaonuo.dev.modular.push.service.DevPushService; + +import javax.validation.Valid; +import java.util.List; + +/** + * 消息推送控制器 + * + * @author xuyuxiang + * @date 2022/2/23 18:26 + **/ +@Tag(name = "消息推送控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 11) +@RestController +@Validated +public class DevPushController { + + @Resource + private DevPushService devPushService; + + /** + * 动态推送消息 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 1) + @Operation(summary = "动态推送TEXT消息") + @CommonLog("动态推送TEXT消息") + @PostMapping("/dev/push/pushDynamicText") + public CommonResult pushDynamicText(@RequestBody @Valid DevPushDynamicTextParam devPushDynamicTextParam) { + devPushService.pushDynamicText(devPushDynamicTextParam); + return CommonResult.ok(); + } + + /** + * 推送消息——飞书TXT + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 2) + @Operation(summary = "推送飞书TEXT消息") + @CommonLog("推送飞书TEXT消息") + @PostMapping("/dev/push/pushFeiShuText") + public CommonResult pushFeiShuText(@RequestBody @Valid DevPushFeiShuTextParam devPushFeiShuTextParam) { + devPushService.pushFeiShuText(devPushFeiShuTextParam); + return CommonResult.ok(); + } + + /** + * 推送消息——钉钉TXT + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 3) + @Operation(summary = "推送钉钉TEXT消息") + @CommonLog("推送钉钉TEXT消息") + @PostMapping("/dev/push/pushDingTalkText") + public CommonResult pushDingTalkText(@RequestBody @Valid DevPushDingTalkTextParam devPushDingTalkTextParam) { + devPushService.pushDingTalkText(devPushDingTalkTextParam); + return CommonResult.ok(); + } + + /** + * 推送消息——钉钉MARKDOWN + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 4) + @Operation(summary = "推送钉钉MARKDOWN消息") + @CommonLog("推送钉钉MARKDOWN消息") + @PostMapping("/dev/push/pushDingTalkMarkdown") + public CommonResult pushDingTalkMarkdown(@RequestBody @Valid DevPushDingTalkMarkdownParam devPushDingTalkMarkdownParam) { + devPushService.pushDingTalkMarkdown(devPushDingTalkMarkdownParam); + return CommonResult.ok(); + } + + /** + * 推送消息——钉钉LINK + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 5) + @Operation(summary = "推送钉钉LINK消息") + @CommonLog("推送钉钉LINK消息") + @PostMapping("/dev/push/pushDingTalkLink") + public CommonResult pushDingTalkLink(@RequestBody @Valid DevPushDingTalkLinkParam devPushDingTalkLinkParam) { + devPushService.pushDingTalkLink(devPushDingTalkLinkParam); + return CommonResult.ok(); + } + + /** + * 推送消息——企业微信TXT + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 6) + @Operation(summary = "推送企业微信TEXT消息") + @CommonLog("推送企业微信TEXT消息") + @PostMapping("/dev/push/pushWorkWechatText") + public CommonResult pushWorkWechatText(@RequestBody @Valid DevPushWorkWechatTextParam devPushWorkWechatTextParam) { + devPushService.pushWorkWechatText(devPushWorkWechatTextParam); + return CommonResult.ok(); + } + + /** + * 推送消息——企业微信MARKDOWN + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 7) + @Operation(summary = "推送企业微信MARKDOWN消息") + @CommonLog("推送企业微信MARKDOWN消息") + @PostMapping("/dev/push/pushWorkWechatMarkdown") + public CommonResult pushWorkWechatMarkdown(@RequestBody @Valid DevPushWorkWechatMarkdownParam devPushWorkWechatMarkdownParam) { + devPushService.pushWorkWechatMarkdown(devPushWorkWechatMarkdownParam); + return CommonResult.ok(); + } + + /** + * 推送消息——企业微信NEWS + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + @ApiOperationSupport(order = 8) + @Operation(summary = "推送企业微信NEWS消息") + @CommonLog("推送企业微信NEWS消息") + @PostMapping("/dev/push/pushWorkWechatNews") + public CommonResult pushWorkWechatNews(@RequestBody @Valid DevPushWorkWechatNewsParam devPushWorkWechatNewsParam) { + devPushService.pushWorkWechatNews(devPushWorkWechatNewsParam); + return CommonResult.ok(); + } + + /** + * 获取推送消息分页 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 9) + @Operation(summary = "获取推送消息分页") + @GetMapping("/dev/push/page") + public CommonResult> page(DevPushPageParam devPushPageParam) { + return CommonResult.data(devPushService.page(devPushPageParam)); + } + + /** + * 删除推送消息 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 10) + @Operation(summary = "删除推送消息") + @CommonLog("删除推送消息") + @PostMapping("/dev/push/delete") + public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") + List devPushIdParamList) { + devPushService.delete(devPushIdParamList); + return CommonResult.ok(); + } + + /** + * 获取推送消息详情 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 11) + @Operation(summary = "获取推送消息详情") + @GetMapping("/dev/push/detail") + public CommonResult detail(@Valid DevPushIdParam devPushIdParam) { + return CommonResult.data(devPushService.detail(devPushIdParam)); + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/entity/DevPush.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/entity/DevPush.java new file mode 100644 index 00000000..f24bdf15 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/entity/DevPush.java @@ -0,0 +1,59 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +/** + * 消息推送实体 + * + * @author xuyuxiang + * @date 2022/2/23 18:27 + **/ +@Getter +@Setter +@TableName("DEV_PUSH") +public class DevPush extends CommonEntity { + + /** id */ + @Schema(description = "主键") + private String id; + + /** 消息引擎 */ + @Schema(description = "消息引擎") + private String engine; + + /** 消息类别 */ + @Schema(description = "消息类别") + private String type; + + /** 消息标题 */ + @Schema(description = "消息标题") + private String title; + + /** 消息内容 */ + @Schema(description = "消息内容") + private String content; + + /** 回执信息 */ + @Schema(description = "回执信息") + private String receiptInfo; + + /** 扩展信息 */ + @Schema(description = "扩展信息") + private String extJson; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushEngineTypeEnum.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushEngineTypeEnum.java new file mode 100644 index 00000000..d11971a2 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushEngineTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.enums; + +import lombok.Getter; + +/** + * 消息推送引擎类型枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum DevPushEngineTypeEnum { + + /** 钉钉 */ + DINGTALK("DINGTALK"), + + /** 飞书 */ + FEISHU("FEISHU"), + + /** 企业微信 */ + WORKWECHAT("WORKWECHAT"); + + private final String value; + + DevPushEngineTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushMessageTypeEnum.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushMessageTypeEnum.java new file mode 100644 index 00000000..21d778e7 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushMessageTypeEnum.java @@ -0,0 +1,43 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.enums; + +import lombok.Getter; + +/** + * 消息推送消息类型枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum DevPushMessageTypeEnum { + + /** 文本 */ + TEXT("TEXT"), + + /** 富文本 */ + MARKDOWN("MARKDOWN"), + + /** 链接 */ + LINK("LINK"), + + /** 文章 */ + NEWS("NEWS"); + + private final String value; + + DevPushMessageTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushNoticeTypeEnum.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushNoticeTypeEnum.java new file mode 100644 index 00000000..c70f4b40 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/enums/DevPushNoticeTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.enums; + +import lombok.Getter; + +/** + * 消息推送通知类型枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum DevPushNoticeTypeEnum { + + /** 无通知 */ + NONE("NONE"), + + /** 通知指定手机号 */ + PHONE("PHONE"), + + /** 通知所有人 */ + ALL("ALL"); + + private final String value; + + DevPushNoticeTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/DevPushMapper.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/DevPushMapper.java new file mode 100644 index 00000000..47c5c3a6 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/DevPushMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.dev.modular.push.entity.DevPush; + +/** + * 消息推送Mapper接口 + * + * @author xuyuxiang + * @date 2022/2/23 18:40 + **/ +public interface DevPushMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/mapping/DevPushMapper.xml b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/mapping/DevPushMapper.xml new file mode 100644 index 00000000..573cc7ec --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/mapper/mapping/DevPushMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkLinkParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkLinkParam.java new file mode 100644 index 00000000..d4dfafd4 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkLinkParam.java @@ -0,0 +1,50 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——钉钉LINK参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushDingTalkLinkParam { + + /** 消息标题 */ + @Schema(description = "消息标题") + @NotBlank(message = "title不能为空") + private String title; + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 图片url */ + @Schema(description = "图片url") + @NotBlank(message = "picUrl不能为空") + private String picUrl; + + /** 跳转地址 */ + @Schema(description = "跳转地址") + @NotBlank(message = "messageUrl不能为空") + private String messageUrl; + +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkMarkdownParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkMarkdownParam.java new file mode 100644 index 00000000..7fba299d --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkMarkdownParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——钉钉MARKDOWN参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushDingTalkMarkdownParam { + + /** 消息标题 */ + @Schema(description = "消息标题") + @NotBlank(message = "title不能为空") + private String title; + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 通知类型(无、全部) */ + @Schema(description = "通知类型") + @NotBlank(message = "noticeType不能为空") + private String noticeType; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkTextParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkTextParam.java new file mode 100644 index 00000000..a93f00a1 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDingTalkTextParam.java @@ -0,0 +1,43 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——钉钉TXT参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushDingTalkTextParam { + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 通知类型(无、指定手机、全部) */ + @Schema(description = "通知类型") + @NotBlank(message = "noticeType不能为空") + private String noticeType; + + /** 手机号 */ + @Schema(description = "手机号") + private String phones; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDynamicTextParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDynamicTextParam.java new file mode 100644 index 00000000..15dff49e --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushDynamicTextParam.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +/** + * 动态推送消息参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushDynamicTextParam { + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 是否@所有人 */ + @Schema(description = "是否@所有人") + @NotNull(message = "noticeAll不能为空") + private Boolean noticeAll = false; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushFeiShuTextParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushFeiShuTextParam.java new file mode 100644 index 00000000..4e10ff2f --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushFeiShuTextParam.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——飞书TXT参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushFeiShuTextParam { + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 通知类型(无、全部) */ + @Schema(description = "通知类型") + @NotBlank(message = "noticeType不能为空") + private String noticeType; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushIdParam.java new file mode 100644 index 00000000..3dc16d29 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushIdParam.java @@ -0,0 +1,34 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 消息推送Id参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushIdParam { + + /** id */ + @Schema(description = "id") + @NotBlank(message = "id不能为空") + private String id; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushPageParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushPageParam.java new file mode 100644 index 00000000..e53aaa6c --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushPageParam.java @@ -0,0 +1,52 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * 消息推送查询参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushPageParam { + + /** 当前页 */ + @Schema(description = "当前页码") + private Integer current; + + /** 每页条数 */ + @Schema(description = "每页条数") + private Integer size; + + /** 排序字段 */ + @Schema(description = "排序字段,字段驼峰名称,如:userName") + private String sortField; + + /** 排序方式 */ + @Schema(description = "排序方式,升序:ASCEND;降序:DESCEND") + private String sortOrder; + + /** 消息引擎 */ + @Schema(description = "消息引擎") + private String engine; + + /** 消息标题关键词 */ + @Schema(description = "消息标题关键词") + private String searchKey; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatMarkdownParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatMarkdownParam.java new file mode 100644 index 00000000..cabe5f54 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatMarkdownParam.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——企业微信MARKDOWN参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushWorkWechatMarkdownParam { + + /** 消息标题 */ + @Schema(description = "消息标题") + @NotBlank(message = "title不能为空") + private String title; + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatNewsParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatNewsParam.java new file mode 100644 index 00000000..d7646973 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatNewsParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——企业微信NEWS参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushWorkWechatNewsParam { + + /** 消息标题 */ + @Schema(description = "消息标题") + @NotBlank(message = "title不能为空") + private String title; + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 图片url */ + @Schema(description = "图片url") + @NotBlank(message = "picUrl不能为空") + private String picUrl; + + /** 跳转地址 */ + @Schema(description = "跳转地址") + @NotBlank(message = "messageUrl不能为空") + private String messageUrl; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatTextParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatTextParam.java new file mode 100644 index 00000000..37ea2d1a --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/param/DevPushWorkWechatTextParam.java @@ -0,0 +1,43 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 推送消息——企业微信TXT参数 + * + * @author xuyuxiang + * @date 2022/6/21 15:38 + **/ +@Getter +@Setter +public class DevPushWorkWechatTextParam { + + /** 消息内容 */ + @Schema(description = "消息内容") + @NotBlank(message = "content不能为空") + private String content; + + /** 通知类型(无、指定手机、全部) */ + @Schema(description = "通知类型") + @NotBlank(message = "noticeType不能为空") + private String noticeType; + + /** 手机号 */ + @Schema(description = "手机号") + private String phones; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/provider/DevPushApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/provider/DevPushApiProvider.java new file mode 100644 index 00000000..acf0b97a --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/provider/DevPushApiProvider.java @@ -0,0 +1,127 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.provider; + +import cn.hutool.core.util.ObjectUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import vip.xiaonuo.dev.api.DevPushApi; +import vip.xiaonuo.dev.modular.push.enums.DevPushNoticeTypeEnum; +import vip.xiaonuo.dev.modular.push.param.*; +import vip.xiaonuo.dev.modular.push.service.DevPushService; + +/** + * 消息推送API接口提供者 + * + * @author xuyuxiang + * @date 2022/6/22 15:32 + **/ +@Service +public class DevPushApiProvider implements DevPushApi { + + @Resource + private DevPushService devPushService; + + @Override + public void pushDynamicText(String content, boolean noticeAll) { + DevPushDynamicTextParam dynamicTextParam = new DevPushDynamicTextParam(); + dynamicTextParam.setContent(content); + dynamicTextParam.setNoticeAll(noticeAll); + devPushService.pushDynamicText(dynamicTextParam); + } + + @Override + public void pushFeiShuText(String content, boolean noticeAll) { + DevPushFeiShuTextParam pushFeiShuTextParam = new DevPushFeiShuTextParam(); + pushFeiShuTextParam.setContent(content); + if(noticeAll){ + pushFeiShuTextParam.setNoticeType(DevPushNoticeTypeEnum.ALL.getValue()); + } else { + pushFeiShuTextParam.setNoticeType(DevPushNoticeTypeEnum.NONE.getValue()); + } + devPushService.pushFeiShuText(pushFeiShuTextParam); + } + + @Override + public void pushDingTalkText(String content, boolean noticeAll, String phones) { + DevPushDingTalkTextParam pushDingTalkTextParam = new DevPushDingTalkTextParam(); + pushDingTalkTextParam.setContent(content); + if(noticeAll){ + pushDingTalkTextParam.setNoticeType(DevPushNoticeTypeEnum.ALL.getValue()); + } else { + if(ObjectUtil.isNotEmpty(phones)){ + pushDingTalkTextParam.setNoticeType(DevPushNoticeTypeEnum.PHONE.getValue()); + } else { + pushDingTalkTextParam.setNoticeType(DevPushNoticeTypeEnum.NONE.getValue()); + } + } + devPushService.pushDingTalkText(pushDingTalkTextParam); + } + + @Override + public void pushDingTalkMarkdown(String title, String content, boolean noticeAll) { + DevPushDingTalkMarkdownParam devPushDingTalkMarkdownParam = new DevPushDingTalkMarkdownParam(); + devPushDingTalkMarkdownParam.setTitle(title); + devPushDingTalkMarkdownParam.setContent(content); + if(noticeAll){ + devPushDingTalkMarkdownParam.setNoticeType(DevPushNoticeTypeEnum.ALL.getValue()); + } else { + devPushDingTalkMarkdownParam.setNoticeType(DevPushNoticeTypeEnum.NONE.getValue()); + } + devPushService.pushDingTalkMarkdown(devPushDingTalkMarkdownParam); + } + + @Override + public void pushDingTalkLink(String title, String content, String picUrl, String messageUrl) { + DevPushDingTalkLinkParam devPushDingTalkLinkParam = new DevPushDingTalkLinkParam(); + devPushDingTalkLinkParam.setTitle(title); + devPushDingTalkLinkParam.setContent(content); + devPushDingTalkLinkParam.setPicUrl(picUrl); + devPushDingTalkLinkParam.setMessageUrl(messageUrl); + devPushService.pushDingTalkLink(devPushDingTalkLinkParam); + } + + @Override + public void pushWorkWechatText(String content, boolean noticeAll, String phones) { + DevPushWorkWechatTextParam devPushWorkWechatTextParam = new DevPushWorkWechatTextParam(); + devPushWorkWechatTextParam.setContent(content); + if(noticeAll){ + devPushWorkWechatTextParam.setNoticeType(DevPushNoticeTypeEnum.ALL.getValue()); + } else { + if(ObjectUtil.isNotEmpty(phones)){ + devPushWorkWechatTextParam.setNoticeType(DevPushNoticeTypeEnum.PHONE.getValue()); + } else { + devPushWorkWechatTextParam.setNoticeType(DevPushNoticeTypeEnum.NONE.getValue()); + } + } + devPushService.pushWorkWechatText(devPushWorkWechatTextParam); + } + + @Override + public void pushWorkWechatMarkdown(String title, String content) { + DevPushWorkWechatMarkdownParam devPushWorkWechatMarkdownParam = new DevPushWorkWechatMarkdownParam(); + devPushWorkWechatMarkdownParam.setTitle(title); + devPushWorkWechatMarkdownParam.setContent(content); + devPushService.pushWorkWechatMarkdown(devPushWorkWechatMarkdownParam); + } + + @Override + public void pushWorkWechatNews(String title, String content, String picUrl, String messageUrl) { + DevPushWorkWechatNewsParam devPushWorkWechatNewsParam = new DevPushWorkWechatNewsParam(); + devPushWorkWechatNewsParam.setTitle(title); + devPushWorkWechatNewsParam.setContent(content); + devPushWorkWechatNewsParam.setPicUrl(picUrl); + devPushWorkWechatNewsParam.setMessageUrl(messageUrl); + devPushService.pushWorkWechatNews(devPushWorkWechatNewsParam); + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/DevPushService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/DevPushService.java new file mode 100644 index 00000000..1ab95148 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/DevPushService.java @@ -0,0 +1,137 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.dev.modular.push.entity.DevPush; +import vip.xiaonuo.dev.modular.push.param.*; + +import java.util.List; + +/** + * 消息推送Service接口 + * + * @author xuyuxiang + * @date 2022/2/23 18:27 + **/ +public interface DevPushService extends IService { + + /** + * 动态推送消息 + * + * @param engine 推送引擎 + * @param content 文本内容 + * @param noticeAll 是否@所有人 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushDynamicText(String engine, String content, boolean noticeAll); + + /** + * 动态推送消息 + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushDynamicText(DevPushDynamicTextParam devPushDynamicTextParam); + + /** + * 推送消息——飞书TXT + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushFeiShuText(DevPushFeiShuTextParam devPushFeiShuTextParam); + + /** + * 推送消息——钉钉TXT + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushDingTalkText(DevPushDingTalkTextParam devPushDingTalkTextParam); + + /** + * 推送消息——钉钉MARKDOWN + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushDingTalkMarkdown(DevPushDingTalkMarkdownParam devPushDingTalkMarkdownParam); + + /** + * 推送消息——钉钉LINK + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushDingTalkLink(DevPushDingTalkLinkParam devPushDingTalkLinkParam); + + /** + * 推送消息——企业微信TXT + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushWorkWechatText(DevPushWorkWechatTextParam devPushWorkWechatTextParam); + + /** + * 推送消息——企业微信MARKDOWN + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushWorkWechatMarkdown(DevPushWorkWechatMarkdownParam devPushWorkWechatMarkdownParam); + + /** + * 推送消息——企业微信NEWS + * + * @author xuyuxiang + * @date 2022/4/24 20:47 + */ + void pushWorkWechatNews(DevPushWorkWechatNewsParam devPushWorkWechatNewsParam); + + /** + * 获取推送消息分页 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + Page page(DevPushPageParam devPushPageParam); + + /** + * 删除推送消息 + * + * @author xuyuxiang + * @date 2022/8/4 10:36 + **/ + void delete(List devPushIdParamList); + + /** + * 获取推送消息详情 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + DevPush detail(DevPushIdParam devPushIdParam); + + /** + * 获取推送消息详情 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + DevPush queryEntity(String id); +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/impl/DevPushServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/impl/DevPushServiceImpl.java new file mode 100644 index 00000000..957193a2 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/service/impl/DevPushServiceImpl.java @@ -0,0 +1,271 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.service.impl; + +import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import vip.xiaonuo.common.enums.CommonSortOrderEnum; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.common.page.CommonPageRequest; +import vip.xiaonuo.dev.api.DevConfigApi; +import vip.xiaonuo.dev.modular.push.entity.DevPush; +import vip.xiaonuo.dev.modular.push.enums.DevPushEngineTypeEnum; +import vip.xiaonuo.dev.modular.push.enums.DevPushMessageTypeEnum; +import vip.xiaonuo.dev.modular.push.enums.DevPushNoticeTypeEnum; +import vip.xiaonuo.dev.modular.push.mapper.DevPushMapper; +import vip.xiaonuo.dev.modular.push.param.*; +import vip.xiaonuo.dev.modular.push.service.DevPushService; +import vip.xiaonuo.dev.modular.push.util.DevPushDingTalkUtil; +import vip.xiaonuo.dev.modular.push.util.DevPushFeiShuUtil; +import vip.xiaonuo.dev.modular.push.util.DevPushWorkWechatUtil; + +import java.util.List; + +/** + * 邮件Service接口实现类 + * + * @author xuyuxiang + * @date 2022/2/23 18:43 + **/ +@Service +public class DevPushServiceImpl extends ServiceImpl implements DevPushService { + + /** 默认消息引擎 */ + private static final String SNOWY_SYS_DEFAULT_PUSH_ENGINE_KEY = "SNOWY_SYS_DEFAULT_PUSH_ENGINE"; + + @Resource + private DevConfigApi devConfigApi; + + @Override + public void pushDynamicText(String engine, String content, boolean noticeAll) { + if(engine.equals(DevPushEngineTypeEnum.DINGTALK.getValue())) { + DevPushDingTalkTextParam devPushDingTalkTextParam = new DevPushDingTalkTextParam(); + devPushDingTalkTextParam.setContent(content); + devPushDingTalkTextParam.setNoticeType(noticeAll?DevPushNoticeTypeEnum.ALL.getValue(): + DevPushNoticeTypeEnum.NONE.getValue()); + this.pushDingTalkText(devPushDingTalkTextParam); + } else if (engine.equals(DevPushEngineTypeEnum.FEISHU.getValue())) { + DevPushFeiShuTextParam devPushFeiShuTextParam = new DevPushFeiShuTextParam(); + devPushFeiShuTextParam.setContent(content); + devPushFeiShuTextParam.setNoticeType(noticeAll?DevPushNoticeTypeEnum.ALL.getValue(): + DevPushNoticeTypeEnum.NONE.getValue()); + this.pushFeiShuText(devPushFeiShuTextParam); + } else if (engine.equals(DevPushEngineTypeEnum.WORKWECHAT.getValue())) { + DevPushWorkWechatTextParam devPushWorkWechatTextParam = new DevPushWorkWechatTextParam(); + devPushWorkWechatTextParam.setContent(content); + devPushWorkWechatTextParam.setNoticeType(noticeAll?DevPushNoticeTypeEnum.ALL.getValue(): + DevPushNoticeTypeEnum.NONE.getValue()); + this.pushWorkWechatText(devPushWorkWechatTextParam); + } else { + throw new CommonException("不支持的消息推送引擎:{}", engine); + } + } + + @Override + public void pushDynamicText(DevPushDynamicTextParam devPushDynamicTextParam) { + String defaultEmailEngine = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PUSH_ENGINE_KEY); + if(ObjectUtil.isEmpty(defaultEmailEngine)) { + throw new CommonException("请联系管理员配置默认消息推送引擎"); + } + String content = devPushDynamicTextParam.getContent(); + Boolean noticeAll = devPushDynamicTextParam.getNoticeAll(); + this.pushDynamicText(defaultEmailEngine, content, noticeAll); + } + + @Override + public void pushFeiShuText(DevPushFeiShuTextParam devPushFeiShuTextParam) { + String noticeType = devPushFeiShuTextParam.getNoticeType(); + String receiptInfo; + if(DevPushNoticeTypeEnum.NONE.getValue().equals(noticeType)){ + receiptInfo = DevPushFeiShuUtil.pushFeiShuText(devPushFeiShuTextParam.getContent(), false); + } else if(DevPushNoticeTypeEnum.ALL.getValue().equals(noticeType)) { + receiptInfo = DevPushFeiShuUtil.pushFeiShuText(devPushFeiShuTextParam.getContent(), true); + } else { + throw new CommonException("不支持的通知类型:{}", noticeType); + } + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.FEISHU.getValue()); + devPush.setType(DevPushMessageTypeEnum.TEXT.getValue()); + devPush.setTitle(devPushFeiShuTextParam.getContent()); + devPush.setContent(devPushFeiShuTextParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public void pushDingTalkText(DevPushDingTalkTextParam devPushDingTalkTextParam) { + String noticeType = devPushDingTalkTextParam.getNoticeType(); + String receiptInfo; + if(DevPushNoticeTypeEnum.NONE.getValue().equals(noticeType)){ + receiptInfo = DevPushDingTalkUtil.pushDingTalkText(devPushDingTalkTextParam.getContent(), + false, null); + } else if(DevPushNoticeTypeEnum.ALL.getValue().equals(noticeType)) { + receiptInfo = DevPushDingTalkUtil.pushDingTalkText(devPushDingTalkTextParam.getContent(), + true, null); + } else if(DevPushNoticeTypeEnum.PHONE.getValue().equals(noticeType)) { + if(ObjectUtil.isEmpty(devPushDingTalkTextParam.getPhones())) { + throw new CommonException("手机号不能为空"); + } else { + receiptInfo = DevPushDingTalkUtil.pushDingTalkText(devPushDingTalkTextParam.getContent(), + false, devPushDingTalkTextParam.getPhones()); + } + } else { + throw new CommonException("不支持的通知类型:{}", noticeType); + } + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.DINGTALK.getValue()); + devPush.setType(DevPushMessageTypeEnum.TEXT.getValue()); + devPush.setTitle(devPushDingTalkTextParam.getContent()); + devPush.setContent(devPushDingTalkTextParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public void pushDingTalkMarkdown(DevPushDingTalkMarkdownParam devPushDingTalkMarkdownParam) { + String noticeType = devPushDingTalkMarkdownParam.getNoticeType(); + String receiptInfo; + if(DevPushNoticeTypeEnum.NONE.getValue().equals(noticeType)){ + receiptInfo = DevPushDingTalkUtil.pushDingTalkMarkdown(devPushDingTalkMarkdownParam.getTitle(), + devPushDingTalkMarkdownParam.getContent(), false); + } else if(DevPushNoticeTypeEnum.ALL.getValue().equals(noticeType)) { + receiptInfo = DevPushDingTalkUtil.pushDingTalkMarkdown(devPushDingTalkMarkdownParam.getTitle(), + devPushDingTalkMarkdownParam.getContent(), true); + } else { + throw new CommonException("不支持的通知类型:{}", noticeType); + } + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.DINGTALK.getValue()); + devPush.setType(DevPushMessageTypeEnum.MARKDOWN.getValue()); + devPush.setTitle(devPushDingTalkMarkdownParam.getTitle()); + devPush.setContent(devPushDingTalkMarkdownParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public void pushDingTalkLink(DevPushDingTalkLinkParam devPushDingTalkLinkParam) { + String receiptInfo = DevPushDingTalkUtil.pushDingTalkLink(devPushDingTalkLinkParam.getTitle(), + devPushDingTalkLinkParam.getContent(), + devPushDingTalkLinkParam.getPicUrl(), + devPushDingTalkLinkParam.getMessageUrl()); + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.DINGTALK.getValue()); + devPush.setType(DevPushMessageTypeEnum.LINK.getValue()); + devPush.setTitle(devPushDingTalkLinkParam.getTitle()); + devPush.setContent(devPushDingTalkLinkParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public void pushWorkWechatText(DevPushWorkWechatTextParam devPushWorkWechatTextParam) { + String noticeType = devPushWorkWechatTextParam.getNoticeType(); + String receiptInfo; + if(DevPushNoticeTypeEnum.NONE.getValue().equals(noticeType)){ + receiptInfo = DevPushWorkWechatUtil.pushWorkWechatText(devPushWorkWechatTextParam.getContent(), + false, null); + } else if(DevPushNoticeTypeEnum.ALL.getValue().equals(noticeType)) { + receiptInfo = DevPushWorkWechatUtil.pushWorkWechatText(devPushWorkWechatTextParam.getContent(), + true, null); + } else if(DevPushNoticeTypeEnum.PHONE.getValue().equals(noticeType)) { + if(ObjectUtil.isEmpty(devPushWorkWechatTextParam.getPhones())) { + throw new CommonException("手机号不能为空"); + } else { + receiptInfo = DevPushWorkWechatUtil.pushWorkWechatText(devPushWorkWechatTextParam.getContent(), + false, devPushWorkWechatTextParam.getPhones()); + } + } else { + throw new CommonException("不支持的通知类型:{}", noticeType); + } + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.WORKWECHAT.getValue()); + devPush.setType(DevPushMessageTypeEnum.TEXT.getValue()); + devPush.setTitle(devPushWorkWechatTextParam.getContent()); + devPush.setContent(devPushWorkWechatTextParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public void pushWorkWechatMarkdown(DevPushWorkWechatMarkdownParam devPushWorkWechatMarkdownParam) { + String receiptInfo = DevPushWorkWechatUtil.pushWorkWechatMarkdown(devPushWorkWechatMarkdownParam.getTitle(), + devPushWorkWechatMarkdownParam.getContent()); + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.WORKWECHAT.getValue()); + devPush.setType(DevPushMessageTypeEnum.MARKDOWN.getValue()); + devPush.setTitle(devPushWorkWechatMarkdownParam.getTitle()); + devPush.setContent(devPushWorkWechatMarkdownParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public void pushWorkWechatNews(DevPushWorkWechatNewsParam devPushWorkWechatNewsParam) { + String receiptInfo = DevPushWorkWechatUtil.pushWorkWechatNews(devPushWorkWechatNewsParam.getTitle(), + devPushWorkWechatNewsParam.getContent(), + devPushWorkWechatNewsParam.getPicUrl(), + devPushWorkWechatNewsParam.getMessageUrl()); + DevPush devPush = new DevPush(); + devPush.setEngine(DevPushEngineTypeEnum.WORKWECHAT.getValue()); + devPush.setType(DevPushMessageTypeEnum.NEWS.getValue()); + devPush.setTitle(devPushWorkWechatNewsParam.getTitle()); + devPush.setContent(devPushWorkWechatNewsParam.getContent()); + devPush.setReceiptInfo(receiptInfo); + this.save(devPush); + } + + @Override + public Page page(DevPushPageParam devPushPageParam) { + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + if(ObjectUtil.isNotEmpty(devPushPageParam.getEngine())) { + queryWrapper.lambda().eq(DevPush::getEngine, devPushPageParam.getEngine()); + } + if(ObjectUtil.isNotEmpty(devPushPageParam.getSearchKey())) { + queryWrapper.lambda().like(DevPush::getTitle, devPushPageParam.getSearchKey()); + } + if(ObjectUtil.isAllNotEmpty(devPushPageParam.getSortField(), devPushPageParam.getSortOrder())) { + CommonSortOrderEnum.validate(devPushPageParam.getSortOrder()); + queryWrapper.orderBy(true, devPushPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()), + StrUtil.toUnderlineCase(devPushPageParam.getSortField())); + } + return this.page(CommonPageRequest.defaultPage(), queryWrapper); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(List devPushIdParamList) { + this.removeByIds(CollStreamUtil.toList(devPushIdParamList, DevPushIdParam::getId)); + } + + @Override + public DevPush detail(DevPushIdParam devPushIdParam) { + return this.queryEntity(devPushIdParam.getId()); + } + + @Override + public DevPush queryEntity(String id) { + DevPush devPush = this.getById(id); + if(ObjectUtil.isEmpty(devPush)) { + throw new CommonException("消息推送记录不存在,id值为:{}", id); + } + return devPush; + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushDingTalkUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushDingTalkUtil.java new file mode 100644 index 00000000..a16e52d3 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushDingTalkUtil.java @@ -0,0 +1,170 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.util; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.dromara.oa.api.OaSender; +import org.dromara.oa.comm.entity.Request; +import org.dromara.oa.comm.entity.Response; +import org.dromara.oa.comm.enums.MessageType; +import org.dromara.oa.core.dingTalk.config.DingTalkConfig; +import org.dromara.oa.core.dingTalk.config.DingTalkFactory; +import org.dromara.oa.core.provider.factory.OaFactory; +import org.dromara.oa.core.provider.factory.ProviderFactoryHolder; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.dev.api.DevConfigApi; + +/** + * 钉钉消息推送工具类 + * + * @author xuyuxiang + * @date 2022/1/2 17:05 + */ +@Slf4j +public class DevPushDingTalkUtil { + + private static OaSender oaSender; + + private static final String SNOWY_PUSH_DINGTALK_SIGN_KEY = "SNOWY_PUSH_DINGTALK_SIGN"; + private static final String SNOWY_PUSH_DINGTALK_TOKEN_ID_KEY = "SNOWY_PUSH_DINGTALK_TOKEN_ID"; + + static { + ProviderFactoryHolder.registerFactory(DingTalkFactory.instance()); + } + + /** + * 初始化操作的客户端 + * + * @author xuyuxiang + * @date 2022/1/5 23:24 + */ + private static void initClient() { + + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + + /* sign */ + String sign = devConfigApi.getValueByKey(SNOWY_PUSH_DINGTALK_SIGN_KEY); + + if(ObjectUtil.isEmpty(sign)) { + throw new CommonException("钉钉推送操作客户端未正确配置:sign为空"); + } + + /* tokenId */ + String tokenId = devConfigApi.getValueByKey(SNOWY_PUSH_DINGTALK_TOKEN_ID_KEY); + + if(ObjectUtil.isEmpty(tokenId)) { + throw new CommonException("钉钉推送操作客户端未正确配置:tokenId为空"); + } + + DingTalkConfig dingTalkConfig = new DingTalkConfig(); + dingTalkConfig.setConfigId(tokenId); + dingTalkConfig.setSign(sign); + dingTalkConfig.setTokenId(tokenId); + OaFactory.createAndRegisterOaSender(dingTalkConfig); + oaSender = OaFactory.getSmsOaBlend(tokenId); + } + + /** + * 发送文本消息 + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @param phones 通知的用户手机号,英文逗号分割 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushDingTalkText(String content, boolean noticeAll, String phones) { + try { + initClient(); + Request request = new Request(); + request.setContent(content); + if(noticeAll) { + request.setIsNoticeAll(true); + } else { + if(ObjectUtil.isNotEmpty(phones)) { + request.setPhoneList((StrUtil.split(phones, StrUtil.COMMA))); + } + } + Response response = oaSender.sender(request, MessageType.DING_TALK_TEXT); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } + + /** + * 发送MarkDown消息 + * + * @param title 标题 + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushDingTalkMarkdown(String title, String content, boolean noticeAll) { + try { + initClient(); + Request request = new Request(); + request.setTitle(title); + request.setContent(content); + if(noticeAll) { + request.setIsNoticeAll(true); + } + Response response = oaSender.sender(request, MessageType.DING_TALK_MARKDOWN); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } + + /** + * 发送链接消息 + * + * @param title 标题 + * @param content 内容 + * @param picUrl 封面图片地址 + * @param messageUrl 消息链接地址 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushDingTalkLink(String title, String content, String picUrl,String messageUrl) { + try { + initClient(); + Request request = new Request(); + request.setTitle(title); + request.setContent(content); + request.setPicUrl(picUrl); + request.setMessageUrl(messageUrl); + Response response = oaSender.sender(request, MessageType.DING_TALK_LINK); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushFeiShuUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushFeiShuUtil.java new file mode 100644 index 00000000..f05b56e1 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushFeiShuUtil.java @@ -0,0 +1,97 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.util; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.dromara.oa.api.OaSender; +import org.dromara.oa.comm.entity.Request; +import org.dromara.oa.comm.entity.Response; +import org.dromara.oa.comm.enums.MessageType; +import org.dromara.oa.core.byteTalk.config.ByteTalkConfig; +import org.dromara.oa.core.byteTalk.config.ByteTalkFactory; +import org.dromara.oa.core.provider.factory.OaFactory; +import org.dromara.oa.core.provider.factory.ProviderFactoryHolder; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.dev.api.DevConfigApi; + +/** + * 飞书消息推送工具类 + * + * @author xuyuxiang + * @date 2022/1/2 17:05 + */ +@Slf4j +public class DevPushFeiShuUtil { + + private static OaSender oaSender; + + private static final String SNOWY_PUSH_FEISHU_TOKEN_ID_KEY = "SNOWY_PUSH_FEISHU_TOKEN_ID"; + + static { + ProviderFactoryHolder.registerFactory(ByteTalkFactory.instance()); + } + + /** + * 初始化操作的客户端 + * + * @author xuyuxiang + * @date 2022/1/5 23:24 + */ + private static void initClient() { + + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + + /* tokenId */ + String tokenId = devConfigApi.getValueByKey(SNOWY_PUSH_FEISHU_TOKEN_ID_KEY); + + if(ObjectUtil.isEmpty(tokenId)) { + throw new CommonException("飞书推送操作客户端未正确配置:tokenId为空"); + } + + ByteTalkConfig byteTalkConfig = new ByteTalkConfig(); + byteTalkConfig.setConfigId(tokenId); + byteTalkConfig.setTokenId(tokenId); + OaFactory.createAndRegisterOaSender(byteTalkConfig); + oaSender = OaFactory.getSmsOaBlend(tokenId); + } + + /** + * 发送文本消息 + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushFeiShuText(String content, boolean noticeAll) { + try { + initClient(); + Request request = new Request(); + request.setContent(content); + if(noticeAll) { + request.setIsNoticeAll(true); + } + Response response = oaSender.sender(request, MessageType.BYTE_TALK_TEXT); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushWorkWechatUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushWorkWechatUtil.java new file mode 100644 index 00000000..837c058d --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/push/util/DevPushWorkWechatUtil.java @@ -0,0 +1,161 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.push.util; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.dromara.oa.api.OaSender; +import org.dromara.oa.comm.entity.Request; +import org.dromara.oa.comm.entity.Response; +import org.dromara.oa.comm.entity.WeTalkRequestArticle; +import org.dromara.oa.comm.enums.MessageType; +import org.dromara.oa.core.provider.factory.OaFactory; +import org.dromara.oa.core.provider.factory.ProviderFactoryHolder; +import org.dromara.oa.core.weTalk.config.WeTalkConfig; +import org.dromara.oa.core.weTalk.config.WeTalkFactory; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.dev.api.DevConfigApi; + +/** + * 企业微信消息推送工具类 + * + * @author xuyuxiang + * @date 2022/1/2 17:05 + */ +@Slf4j +public class DevPushWorkWechatUtil { + + private static OaSender oaSender; + + private static final String SNOWY_PUSH_WORKWECHAT_TOKEN_ID_KEY = "SNOWY_PUSH_WORKWECHAT_TOKEN_ID"; + + static { + ProviderFactoryHolder.registerFactory(WeTalkFactory.instance()); + } + + /** + * 初始化操作的客户端 + * + * @author xuyuxiang + * @date 2022/1/5 23:24 + */ + private static void initClient() { + + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + + /* tokenId */ + String tokenId = devConfigApi.getValueByKey(SNOWY_PUSH_WORKWECHAT_TOKEN_ID_KEY); + + if(ObjectUtil.isEmpty(tokenId)) { + throw new CommonException("企业微信推送操作客户端未正确配置:tokenId为空"); + } + + WeTalkConfig weTalkConfig = new WeTalkConfig(); + weTalkConfig.setConfigId(tokenId); + weTalkConfig.setTokenId(tokenId); + OaFactory.createAndRegisterOaSender(weTalkConfig); + oaSender = OaFactory.getSmsOaBlend(tokenId); + } + + /** + * 发送文本消息 + * + * @param content 内容 + * @param noticeAll 是否通知所有人 + * @param phones 通知的用户手机号,英文逗号分割 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushWorkWechatText(String content, boolean noticeAll, String phones) { + try { + initClient(); + Request request = new Request(); + request.setContent(content); + if(noticeAll) { + request.setIsNoticeAll(true); + } else { + if(ObjectUtil.isNotEmpty(phones)) { + request.setPhoneList((StrUtil.split(phones, StrUtil.COMMA))); + } + } + Response response = oaSender.sender(request, MessageType.WE_TALK_TEXT); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } + + /** + * 发送MarkDown消息 + * + * @param title 标题 + * @param content 内容 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushWorkWechatMarkdown(String title, String content) { + try { + initClient(); + Request request = new Request(); + request.setTitle(title); + request.setContent(content); + Response response = oaSender.sender(request, MessageType.WE_TALK_MARKDOWN); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } + + /** + * 发送新闻消息 + * + * @param title 标题 + * @param content 内容 + * @param picUrl 封面图片地址 + * @param messageUrl 消息链接地址 + * @return 发送成功的回执信息 + * @author xuyuxiang + * @date 2022/2/23 14:24 + */ + public static String pushWorkWechatNews(String title, String content, String picUrl,String messageUrl) { + try { + initClient(); + Request request = new Request(); + WeTalkRequestArticle weTalkRequestArticle = new WeTalkRequestArticle(); + weTalkRequestArticle.setTitle(title); + weTalkRequestArticle.setDescription(content); + weTalkRequestArticle.setPicUrl(picUrl); + weTalkRequestArticle.setUrl(messageUrl); + request.setArticleList(CollectionUtil.newArrayList()); + Response response = oaSender.sender(request, MessageType.WE_TALK_NEWS); + if(!response.isSuccess()) { + throw new CommonException("消息推送错误,返回内容:{}", JSONUtil.toJsonStr(response.getData())); + } + return JSONUtil.toJsonStr(response.getData()); + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/relation/service/impl/DevRelationServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/relation/service/impl/DevRelationServiceImpl.java index 709ed653..891c3f14 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/relation/service/impl/DevRelationServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/relation/service/impl/DevRelationServiceImpl.java @@ -72,41 +72,49 @@ public class DevRelationServiceImpl extends ServiceImpl targetIdList, String category) { this.saveRelationBatch(objectId, targetIdList, category, null, false); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithAppend(String objectId, List targetIdList, String category, List extJsonList) { this.saveRelationBatch(objectId, targetIdList, category, extJsonList, false); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationWithClear(String objectId, String targetId, String category) { this.saveRelation(objectId, targetId, category, null, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationWithClear(String objectId, String targetId, String category, String extJson) { this.saveRelation(objectId, targetId, category, extJson, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithClear(String objectId, List targetIdList, String category) { this.saveRelationBatch(objectId, targetIdList, category, null, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithClear(String objectId, List targetIdList, String category, List extJsonList) { this.saveRelationBatch(objectId, targetIdList, category, extJsonList, true); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/slideshow/service/impl/DevSlideshowServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/slideshow/service/impl/DevSlideshowServiceImpl.java index 596ec324..da146648 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/slideshow/service/impl/DevSlideshowServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/slideshow/service/impl/DevSlideshowServiceImpl.java @@ -147,7 +147,7 @@ public class DevSlideshowServiceImpl extends ServiceImpl sendDynamic(@RequestBody @Valid DevSmsSendDynamicParam devSmsSendDynamicParam) { + devSmsService.sendDynamic(devSmsSendDynamicParam); + return CommonResult.ok(); + } + /** * 发送短信——阿里云 * * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "发送阿里云短信") @CommonLog("发送阿里云短信") @PostMapping("/dev/sms/sendAliyun") @@ -65,6 +84,7 @@ public class DevSmsController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "发送腾讯云短信") @CommonLog("发送腾讯云短信") @PostMapping("/dev/sms/sendTencent") @@ -79,6 +99,7 @@ public class DevSmsController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "发送小诺短信") @CommonLog("发送小诺短信") @PostMapping("/dev/sms/sendXiaonuo") @@ -93,7 +114,8 @@ public class DevSmsController { * @author xuyuxiang * @date 2022/4/24 20:00 */ - @Operation(summary = "获取短信分页") + @ApiOperationSupport(order = 5) + @Operation(summary = "获取短信分页") @GetMapping("/dev/sms/page") public CommonResult> page(DevSmsPageParam devSmsPageParam) { return CommonResult.data(devSmsService.page(devSmsPageParam)); @@ -105,11 +127,12 @@ public class DevSmsController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "删除短信") @CommonLog("删除短信") @PostMapping("/dev/sms/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List devSmsIdParamList) { + List devSmsIdParamList) { devSmsService.delete(devSmsIdParamList); return CommonResult.ok(); } @@ -120,6 +143,7 @@ public class DevSmsController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取短信详情") @GetMapping("/dev/sms/detail") public CommonResult detail(@Valid DevSmsIdParam devSmsIdParam) { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/entity/DevSms.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/entity/DevSms.java index 77d25462..62eced7d 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/entity/DevSms.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/entity/DevSms.java @@ -30,7 +30,7 @@ import vip.xiaonuo.common.pojo.CommonEntity; public class DevSms extends CommonEntity { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 短信引擎 */ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsIdParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsIdParam.java index 90cbd521..ee05543f 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsIdParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class DevSmsIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendAliyunParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendAliyunParam.java index 8ddbdcd6..d19e08d2 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendAliyunParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendAliyunParam.java @@ -28,12 +28,12 @@ import lombok.Setter; public class DevSmsSendAliyunParam { /** 手机号 */ - @Schema(description = "手机号,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "手机号,多个逗号拼接") @NotBlank(message = "phoneNumbers不能为空") private String phoneNumbers; /** 模板编码 */ - @Schema(description = "短信服务控制台配置且审核通过的模板编码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "短信服务控制台配置且审核通过的模板编码") @NotBlank(message = "templateCode不能为空") private String templateCode; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendDynamicParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendDynamicParam.java new file mode 100644 index 00000000..36d5fab2 --- /dev/null +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendDynamicParam.java @@ -0,0 +1,43 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.dev.modular.sms.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 短信发送——动态参数 + * + * @author xuyuxiang + * @date 2022/7/31 15:21 + */ +@Getter +@Setter +public class DevSmsSendDynamicParam { + + /** 手机号 */ + @Schema(description = "手机号,多个逗号拼接") + @NotBlank(message = "phoneNumbers不能为空") + private String phoneNumbers; + + /** 模板编码或id */ + @Schema(description = "模板编码或id") + @NotBlank(message = "templateCodeOrId不能为空") + private String templateCodeOrId; + + /** 发送参数 */ + @Schema(description = "短信模板变量对应的实际值,JSON格式") + private String templateParam; +} diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendTencentParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendTencentParam.java index c7f808d7..c59a7ff7 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendTencentParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendTencentParam.java @@ -28,12 +28,12 @@ import lombok.Setter; public class DevSmsSendTencentParam { /** 手机号 */ - @Schema(description = "手机号,多个逗号拼接", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "手机号,多个逗号拼接") @NotBlank(message = "phoneNumbers不能为空") private String phoneNumbers; /** 模板编码 */ - @Schema(description = "短信服务控制台配置且审核通过的模板编码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "短信服务控制台配置且审核通过的模板编码") @NotBlank(message = "templateCode不能为空") private String templateCode; @@ -41,10 +41,6 @@ public class DevSmsSendTencentParam { @Schema(description = "短信模板变量对应的顺序。支持传入多个参数,逗号拼接") private String templateParam; - /** sdkAppId */ - @Schema(description = "在短信控制台添加应用后生成的实际SdkAppId") - private String sdkAppId; - /** 短信签名 */ @Schema(description = "短信服务控制台配置且审核通过的短信签名") private String signName; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendXiaonuoParam.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendXiaonuoParam.java index d14d9870..a089f4b0 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendXiaonuoParam.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/param/DevSmsSendXiaonuoParam.java @@ -32,6 +32,14 @@ public class DevSmsSendXiaonuoParam { @NotBlank(message = "phoneNumbers不能为空") private String phoneNumbers; + /** 模板编码 */ + @Schema(description = "模板编码") + private String templateCode; + + /** 发送参数 */ + @Schema(description = "发送参数") + private String templateParam; + /** 短信内容 */ @Schema(description = "短信内容") private String message; @@ -39,4 +47,7 @@ public class DevSmsSendXiaonuoParam { /** 短信签名 */ @Schema(description = "短信签名") private String signName; + + + } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/provider/DevSmsApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/provider/DevSmsApiProvider.java index c2ca7747..5835ff66 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/provider/DevSmsApiProvider.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/provider/DevSmsApiProvider.java @@ -12,10 +12,13 @@ */ package vip.xiaonuo.dev.modular.sms.provider; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import vip.xiaonuo.dev.api.DevSmsApi; import vip.xiaonuo.dev.modular.sms.param.DevSmsSendAliyunParam; +import vip.xiaonuo.dev.modular.sms.param.DevSmsSendDynamicParam; import vip.xiaonuo.dev.modular.sms.param.DevSmsSendTencentParam; import vip.xiaonuo.dev.modular.sms.param.DevSmsSendXiaonuoParam; import vip.xiaonuo.dev.modular.sms.service.DevSmsService; @@ -32,6 +35,15 @@ public class DevSmsApiProvider implements DevSmsApi { @Resource private DevSmsService devSmsService; + @Override + public void sendDynamicSms(String phoneNumbers, String templateCodeOrId, JSONObject paramMap) { + DevSmsSendDynamicParam dynamicParam = new DevSmsSendDynamicParam(); + dynamicParam.setPhoneNumbers(phoneNumbers); + dynamicParam.setTemplateCodeOrId(templateCodeOrId); + dynamicParam.setTemplateParam(JSONUtil.toJsonStr(paramMap)); + devSmsService.sendDynamic(dynamicParam); + } + @Override public void sendSmsAliyun(String phoneNumbers, String signName, String templateCode, String templateParam) { DevSmsSendAliyunParam devSmsSendAliyunParam = new DevSmsSendAliyunParam(); @@ -43,9 +55,8 @@ public class DevSmsApiProvider implements DevSmsApi { } @Override - public void sendSmsTencent(String sdkAppId, String phoneNumbers, String signName, String templateCode, String templateParam) { + public void sendSmsTencent(String phoneNumbers, String signName, String templateCode, String templateParam) { DevSmsSendTencentParam devSmsSendTencentParam = new DevSmsSendTencentParam(); - devSmsSendTencentParam.setSdkAppId(sdkAppId); devSmsSendTencentParam.setPhoneNumbers(phoneNumbers); devSmsSendTencentParam.setSignName(signName); devSmsSendTencentParam.setTemplateCode(templateCode); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/DevSmsService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/DevSmsService.java index ac334066..2f3bb311 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/DevSmsService.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/DevSmsService.java @@ -12,6 +12,7 @@ */ package vip.xiaonuo.dev.modular.sms.service; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import vip.xiaonuo.dev.modular.sms.entity.DevSms; @@ -27,6 +28,26 @@ import java.util.List; **/ public interface DevSmsService extends IService { + /** + * 动态发送短信 + * + * @param engine 发送引擎 + * @param phoneNumbers 手机号 + * @param templateCodeOrId 模板id或编码 + * @param templateParam 发送参数 + * @author xuyuxiang + * @date 2022/2/7 22:29 + */ + void sendDynamic(String engine, String phoneNumbers, String templateCodeOrId, JSONObject templateParam); + + /** + * 动态发送短信 + * + * @author xuyuxiang + * @date 2022/6/21 18:37 + **/ + void sendDynamic(DevSmsSendDynamicParam devSmsSendDynamicParam); + /** * 发送短信——阿里云 * diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/impl/DevSmsServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/impl/DevSmsServiceImpl.java index 774e9735..88972c48 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/impl/DevSmsServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/service/impl/DevSmsServiceImpl.java @@ -14,17 +14,22 @@ package vip.xiaonuo.dev.modular.sms.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.PhoneUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; +import vip.xiaonuo.dev.api.DevConfigApi; import vip.xiaonuo.dev.modular.sms.entity.DevSms; import vip.xiaonuo.dev.modular.sms.enums.DevSmsEngineTypeEnum; import vip.xiaonuo.dev.modular.sms.mapper.DevSmsMapper; @@ -34,6 +39,7 @@ import vip.xiaonuo.dev.modular.sms.util.DevSmsAliyunUtil; import vip.xiaonuo.dev.modular.sms.util.DevSmsTencentUtil; import vip.xiaonuo.dev.modular.sms.util.DevSmsXiaonuoUtil; +import java.util.LinkedHashMap; import java.util.List; /** @@ -45,6 +51,52 @@ import java.util.List; @Service public class DevSmsServiceImpl extends ServiceImpl implements DevSmsService { + /** 默认短信引擎 */ + private static final String SNOWY_SYS_DEFAULT_SMS_ENGINE_KEY = "SNOWY_SYS_DEFAULT_SMS_ENGINE"; + + @Resource + private DevConfigApi devConfigApi; + + @Transactional(rollbackFor = Exception.class) + @Override + public void sendDynamic(String engine, String phoneNumbers, String templateCodeOrId, JSONObject templateParam) { + if(engine.equals(DevSmsEngineTypeEnum.XIAONUO.getValue())) { + DevSmsSendXiaonuoParam devSmsSendXiaonuoParam = new DevSmsSendXiaonuoParam(); + devSmsSendXiaonuoParam.setPhoneNumbers(phoneNumbers); + devSmsSendXiaonuoParam.setTemplateCode(templateCodeOrId); + devSmsSendXiaonuoParam.setTemplateParam(JSONUtil.toJsonStr(templateParam)); + this.sendXiaonuo(devSmsSendXiaonuoParam); + } else if (engine.equals(DevSmsEngineTypeEnum.ALIYUN.getValue())) { + DevSmsSendAliyunParam devSmsSendAliyunParam = new DevSmsSendAliyunParam(); + devSmsSendAliyunParam.setPhoneNumbers(phoneNumbers); + devSmsSendAliyunParam.setTemplateCode(templateCodeOrId); + devSmsSendAliyunParam.setTemplateParam(JSONUtil.toJsonStr(templateParam)); + this.sendAliyun(devSmsSendAliyunParam); + } else if (engine.equals(DevSmsEngineTypeEnum.TENCENT.getValue())) { + DevSmsSendTencentParam devSmsSendTencentParam = new DevSmsSendTencentParam(); + devSmsSendTencentParam.setPhoneNumbers(phoneNumbers); + devSmsSendTencentParam.setTemplateCode(templateCodeOrId); + devSmsSendTencentParam.setTemplateParam(JSONUtil.toJsonStr(templateParam)); + this.sendTencent(devSmsSendTencentParam); + } else { + throw new CommonException("不支持的短信引擎:{}", engine); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void sendDynamic(DevSmsSendDynamicParam devSmsSendDynamicParam) { + String defaultSmsEngine = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_SMS_ENGINE_KEY); + if(ObjectUtil.isEmpty(defaultSmsEngine)) { + throw new CommonException("请联系管理员配置默认短信发送引擎"); + } + String phoneNumbers = devSmsSendDynamicParam.getPhoneNumbers(); + String templateCodeOrId = devSmsSendDynamicParam.getTemplateCodeOrId(); + String templateParamStr = devSmsSendDynamicParam.getTemplateParam(); + JSONObject templateParam = JSONUtil.parseObj(templateParamStr); + this.sendDynamic(defaultSmsEngine, phoneNumbers, templateCodeOrId, templateParam); + } + @Transactional(rollbackFor = Exception.class) @Override public void sendAliyun(DevSmsSendAliyunParam devSmsSendAliyunParam) { @@ -63,7 +115,7 @@ public class DevSmsServiceImpl extends ServiceImpl impleme @Override public void sendTencent(DevSmsSendTencentParam smsSendTencentParam) { validPhone(smsSendTencentParam.getPhoneNumbers()); - String receiptInfo = DevSmsTencentUtil.sendSms(smsSendTencentParam.getSdkAppId(), smsSendTencentParam.getPhoneNumbers(), + String receiptInfo =DevSmsTencentUtil.sendSms(smsSendTencentParam.getPhoneNumbers(), smsSendTencentParam.getSignName(), smsSendTencentParam.getTemplateCode(), smsSendTencentParam.getTemplateParam()); DevSms devSms = new DevSms(); BeanUtil.copyProperties(smsSendTencentParam, devSms); @@ -76,8 +128,16 @@ public class DevSmsServiceImpl extends ServiceImpl impleme @Override public void sendXiaonuo(DevSmsSendXiaonuoParam devSmsSendXiaonuoParam) { validPhone(devSmsSendXiaonuoParam.getPhoneNumbers()); - String receiptInfo = DevSmsXiaonuoUtil.sendSms(devSmsSendXiaonuoParam.getPhoneNumbers(), devSmsSendXiaonuoParam.getSignName(), - devSmsSendXiaonuoParam.getMessage()); + String receiptInfo; + if(ObjectUtil.isEmpty(devSmsSendXiaonuoParam.getTemplateCode())) { + receiptInfo = DevSmsXiaonuoUtil.sendSms(devSmsSendXiaonuoParam.getPhoneNumbers(), devSmsSendXiaonuoParam.getSignName(), + devSmsSendXiaonuoParam.getMessage()); + } else { + LinkedHashMap paramMap = new LinkedHashMap<>(); + JSONUtil.parseObj(devSmsSendXiaonuoParam.getTemplateParam()).forEach((k, v) -> paramMap.put(k, Convert.toStr(v))); + receiptInfo = DevSmsXiaonuoUtil.sendSms(devSmsSendXiaonuoParam.getPhoneNumbers(), devSmsSendXiaonuoParam.getSignName(), + devSmsSendXiaonuoParam.getTemplateCode(), paramMap); + } DevSms devSms = new DevSms(); BeanUtil.copyProperties(devSmsSendXiaonuoParam, devSms); devSms.setSignName(ObjectUtil.isNotEmpty(devSms.getSignName())?devSms.getSignName():DevSmsXiaonuoUtil.getDefaultSignName()); @@ -103,6 +163,7 @@ public class DevSmsServiceImpl extends ServiceImpl impleme return this.page(CommonPageRequest.defaultPage(), queryWrapper); } + @Transactional(rollbackFor = Exception.class) @Override public void delete(List devSmsIdParamList) { this.removeByIds(CollStreamUtil.toList(devSmsIdParamList, DevSmsIdParam::getId)); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsAliyunUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsAliyunUtil.java index 1a302aad..303ccad6 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsAliyunUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsAliyunUtil.java @@ -12,21 +12,27 @@ */ package vip.xiaonuo.dev.modular.sms.util; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; -import com.aliyun.dysmsapi20170525.Client; -import com.aliyun.dysmsapi20170525.models.SendSmsRequest; -import com.aliyun.dysmsapi20170525.models.SendSmsResponse; -import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody; -import com.aliyun.teaopenapi.models.Config; import lombok.extern.slf4j.Slf4j; +import org.dromara.sms4j.aliyun.config.AlibabaConfig; +import org.dromara.sms4j.api.SmsBlend; +import org.dromara.sms4j.api.entity.SmsResponse; +import org.dromara.sms4j.core.factory.SmsFactory; +import org.dromara.sms4j.javase.config.SEInitializer; +import org.dromara.sms4j.provider.config.SmsConfig; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.dev.api.DevConfigApi; +import java.util.LinkedHashMap; + /** * 阿里云短信工具类 - * 参考文档:https://next.api.aliyun.com/api-tools/sdk/Dysmsapi?version=2017-05-25&language=java-tea * * @author xuyuxiang * @date 2022/1/2 17:05 @@ -34,11 +40,10 @@ import vip.xiaonuo.dev.api.DevConfigApi; @Slf4j public class DevSmsAliyunUtil { - private static Client client; + private static SmsBlend smsBlend; private static final String SNOWY_SMS_ALIYUN_ACCESS_KEY_ID_KEY = "SNOWY_SMS_ALIYUN_ACCESS_KEY_ID"; private static final String SNOWY_SMS_ALIYUN_ACCESS_KEY_SECRET_KEY = "SNOWY_SMS_ALIYUN_ACCESS_KEY_SECRET"; - private static final String SNOWY_SMS_ALIYUN_END_POINT_KEY = "SNOWY_SMS_ALIYUN_END_POINT"; private static final String SNOWY_SMS_ALIYUN_DEFAULT_SIGN_NAME_KEY = "SNOWY_SMS_ALIYUN_DEFAULT_SIGN_NAME"; /** @@ -47,7 +52,7 @@ public class DevSmsAliyunUtil { * @author xuyuxiang * @date 2022/1/5 23:24 */ - private static void initClient() { + private static void initClient(String signName) { DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); @@ -65,50 +70,62 @@ public class DevSmsAliyunUtil { throw new CommonException("阿里云短信操作客户端未正确配置:accessKeySecret为空"); } - /* endpoint */ - String endpoint = devConfigApi.getValueByKey(SNOWY_SMS_ALIYUN_END_POINT_KEY); - - if(ObjectUtil.isEmpty(endpoint)) { - throw new CommonException("阿里云短信操作客户端未正确配置:endpoint为空"); - } - - try { - client = new Client(new Config().setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret).setEndpoint(endpoint)); - } catch (Exception e) { - throw new CommonException(e.getMessage()); - } + AlibabaConfig alibabaConfig = new AlibabaConfig(); + alibabaConfig.setConfigId(accessKeyId); + alibabaConfig.setAccessKeyId(accessKeyId); + alibabaConfig.setAccessKeySecret(accessKeySecret); + alibabaConfig.setSignature(signName); + SEInitializer.initializer().fromConfig(new SmsConfig(), CollectionUtil.newArrayList(alibabaConfig)); + smsBlend = SmsFactory.getSmsBlend(alibabaConfig.getConfigId()); } /** - * 发送短信 + * 发送模板短信 * * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 - * 上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。 - * @param signName 短信服务控制台配置且审核通过的短信签名,为空则使用默认签名 - * @param templateCode 短信服务控制台配置且审核通过的模板编码 + * @param signName 短信签名,为空则使用默认签名 + * @param templateId 模板id * @param templateParam 短信模板变量对应的实际值,JSON格式。支持传入多个参数,示例:{"name":"张三","number":"15038****76"} - * @return 发送的结果信息集合 com.aliyun.dysmsapi20170525.models.SendSmsResponse + * @return 发送的结果信息 * @author xuyuxiang * @date 2022/2/24 13:42 **/ - public static String sendSms(String phoneNumbers, String signName, String templateCode, String templateParam) { + public static String sendSms(String phoneNumbers, String signName, String templateId, String templateParam) { + LinkedHashMap paramMap = new LinkedHashMap<>(); + JSONUtil.parseObj(templateParam).forEach((k, v) -> paramMap.put(k, Convert.toStr(v))); + return sendSms(phoneNumbers, signName, templateId, paramMap); + } + + /** + * 发送模板短信 + * + * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 + * @param signName 短信签名,为空则使用默认签名 + * @param templateId 模板id + * @param paramMap 短信参数,HashMap + * @return 发送的结果信息 + * @author xuyuxiang + * @date 2022/2/24 13:42 + **/ + public static String sendSms(String phoneNumbers, String signName, String templateId, LinkedHashMap paramMap) { try { - initClient(); if(ObjectUtil.isEmpty(signName)) { signName = getDefaultSignName(); } - SendSmsRequest sendSmsRequest = new SendSmsRequest() - .setPhoneNumbers(phoneNumbers) - .setSignName(signName) - .setTemplateCode(templateCode) - .setTemplateParam(templateParam); - SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest); - SendSmsResponseBody body = sendSmsResponse.getBody(); - String code = body.getCode().toLowerCase(); - if("ok".equals(code)) { - return JSONUtil.toJsonStr(body); + // 初始化客户端 + initClient(signName); + // 发送短信 + SmsResponse smsResponse = smsBlend.massTexting(StrUtil.split(phoneNumbers, StrUtil.COMMA), templateId, paramMap); + if(smsResponse.isSuccess()) { + return JSONUtil.toJsonStr(smsResponse.getData()); } else { - throw new CommonException(body.getMessage()); + String data = Convert.toStr(smsResponse.getData()); + if(JSONUtil.isTypeJSON(data)) { + JSONObject responseData = JSONUtil.parseObj(smsResponse.getData()); + throw new CommonException(responseData.getStr("resInfo")); + } else { + throw new CommonException(data); + } } } catch (Exception e) { throw new CommonException(e.getMessage()); diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsTencentUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsTencentUtil.java index b400f072..d5fce517 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsTencentUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsTencentUtil.java @@ -12,22 +12,28 @@ */ package vip.xiaonuo.dev.modular.sms.util; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; -import com.tencentcloudapi.common.Credential; -import com.tencentcloudapi.sms.v20210111.SmsClient; -import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest; -import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; -import com.tencentcloudapi.sms.v20210111.models.SendStatus; import lombok.extern.slf4j.Slf4j; +import org.dromara.sms4j.api.SmsBlend; +import org.dromara.sms4j.api.entity.SmsResponse; +import org.dromara.sms4j.core.factory.SmsFactory; +import org.dromara.sms4j.javase.config.SEInitializer; +import org.dromara.sms4j.provider.config.SmsConfig; +import org.dromara.sms4j.tencent.config.TencentConfig; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.dev.api.DevConfigApi; +import java.util.LinkedHashMap; +import java.util.List; + /** * 腾讯云短信工具类 - * 参考文档:https://cloud.tencent.com/document/product/382/43194 * * @author xuyuxiang * @date 2022/1/2 17:05 @@ -35,11 +41,10 @@ import vip.xiaonuo.dev.api.DevConfigApi; @Slf4j public class DevSmsTencentUtil { - private static SmsClient client; + private static SmsBlend smsBlend; private static final String SNOWY_SMS_TENCENT_SECRET_ID_KEY = "SNOWY_SMS_TENCENT_SECRET_ID"; private static final String SNOWY_SMS_TENCENT_SECRET_KEY_KEY = "SNOWY_SMS_TENCENT_SECRET_KEY"; - private static final String SNOWY_SMS_TENCENT_REGION_ID_KEY = "SNOWY_SMS_TENCENT_REGION_ID"; private static final String SNOWY_SMS_TENCENT_DEFAULT_SDK_APP_ID_KEY = "SNOWY_SMS_TENCENT_DEFAULT_SDK_APP_ID"; private static final String SNOWY_SMS_TENCENT_DEFAULT_SIGN_NAME_KEY = "SNOWY_SMS_TENCENT_DEFAULT_SIGN_NAME"; @@ -49,7 +54,7 @@ public class DevSmsTencentUtil { * @author xuyuxiang * @date 2022/1/5 23:24 */ - private static void initClient() { + private static void initClient(String signName) { DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); @@ -67,52 +72,76 @@ public class DevSmsTencentUtil { throw new CommonException("腾讯云短信操作客户端未正确配置:secretKey为空"); } - /* regionId */ - String regionId = devConfigApi.getValueByKey(SNOWY_SMS_TENCENT_REGION_ID_KEY); - - if(ObjectUtil.isEmpty(regionId)) { - throw new CommonException("腾讯云短信操作客户端未正确配置:regionId为空"); + /* sdkAppId */ + String sdkAppId = devConfigApi.getValueByKey(SNOWY_SMS_TENCENT_DEFAULT_SDK_APP_ID_KEY); + if(ObjectUtil.isEmpty(sdkAppId)) { + throw new CommonException("腾讯云短信操作客户端未正确配置:sdkAppId为空"); } - - client = new SmsClient(new Credential(secretId, secretKey), regionId); + TencentConfig tencentConfig = new TencentConfig(); + tencentConfig.setConfigId(secretId); + tencentConfig.setAccessKeyId(secretId); + tencentConfig.setAccessKeySecret(secretKey); + tencentConfig.setSignature(signName); + tencentConfig.setSdkAppId(sdkAppId); + SEInitializer.initializer().fromConfig(new SmsConfig(), CollectionUtil.newArrayList(tencentConfig)); + smsBlend = SmsFactory.getSmsBlend(tencentConfig.getConfigId()); } /** - * 发送短信 + * 发送模板短信 * - * @param sdkAppId 短信 SdkAppId,在 短信控制台 添加应用后生成的实际 SdkAppId,示例如1400006666。 - * 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看 * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 - * 上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。 - * @param signName 短信服务控制台配置且审核通过的短信签名,为空则使用默认签名 - * @param templateCode 短信服务控制台配置且审核通过的模板编码 - * @param templateParam 短信模板变量对应的顺序。支持传入多个参数,逗号拼接,示例:"张三,15038****76,进行中" - * @return 发送的结果信息集合 com.tencentcloudapi.sms.v20210111.models.SendStatus + * @param signName 短信签名,为空则使用默认签名 + * @param templateId 模板id + * @param templateParam 短信模板变量对应的顺序。支持传入多个参数,逗号拼接,示例:"张三,15038****76,进行中", + * 同时支持JSON格式,示例:{"name":"张三","number":"15038****76"},此时参数的key无效,仅方便统一格式 + * @return 发送的结果信息 * @author xuyuxiang * @date 2022/2/24 13:42 **/ - public static String sendSms(String sdkAppId, String phoneNumbers, String signName, String templateCode, String templateParam) { - try { - initClient(); - if(ObjectUtil.isEmpty(sdkAppId)) { - sdkAppId = getDefaultSdkAppId(); + public static String sendSms(String phoneNumbers, String signName, String templateId, String templateParam) { + LinkedHashMap paramMap = new LinkedHashMap<>(); + if(JSONUtil.isTypeJSON(templateParam)) { + JSONUtil.parseObj(templateParam).forEach((k, v) -> paramMap.put(k, Convert.toStr(v))); + } else { + List templateParamList = StrUtil.split(templateParam, StrUtil.COMMA); + for (int i = 0; i < templateParamList.size(); i++) { + paramMap.put(Convert.toStr(i + 1), templateParamList.get(i)); } + } + return sendSms(phoneNumbers, signName, templateId, paramMap); + } + + /** + * 发送模板短信 + * + * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 + * @param signName 短信签名,为空则使用默认签名 + * @param templateId 模板id + * @param paramMap 短信参数,HashMap + * @return 发送的结果信息 + * @author xuyuxiang + * @date 2022/2/24 13:42 + **/ + public static String sendSms(String phoneNumbers, String signName, String templateId, LinkedHashMap paramMap) { + try { if(ObjectUtil.isEmpty(signName)) { signName = getDefaultSignName(); } - SendSmsRequest sendSmsRequest = new SendSmsRequest(); - sendSmsRequest.setSmsSdkAppId(sdkAppId); - sendSmsRequest.setPhoneNumberSet(StrUtil.splitToArray(phoneNumbers, StrUtil.COMMA)); - sendSmsRequest.setSignName(signName); - sendSmsRequest.setTemplateId(templateCode); - sendSmsRequest.setTemplateParamSet(ObjectUtil.isNotEmpty(templateParam)?StrUtil.splitToArray(templateParam, StrUtil.COMMA):null); - SendSmsResponse sendSmsResponse = client.SendSms(sendSmsRequest); - SendStatus sendStatus = sendSmsResponse.getSendStatusSet()[0]; - String code = sendStatus.getCode().toLowerCase(); - if("ok".equals(code)) { - return JSONUtil.toJsonStr(sendSmsResponse); + // 初始化客户端 + initClient(signName); + // 发送短信 + SmsResponse smsResponse = smsBlend.massTexting(StrUtil.split(phoneNumbers, StrUtil.COMMA), templateId, paramMap); + if(smsResponse.isSuccess()) { + return JSONUtil.toJsonStr(smsResponse.getData()); } else { - throw new CommonException(sendStatus.getMessage()); + String data = Convert.toStr(smsResponse.getData()); + if(JSONUtil.isTypeJSON(data)) { + JSONObject responseData = JSONUtil.parseObj(smsResponse.getData()); + throw new CommonException(responseData.getStr("resInfo")); + } else { + throw new CommonException(data); + } } } catch (Exception e) { throw new CommonException(e.getMessage()); @@ -134,20 +163,4 @@ public class DevSmsTencentUtil { } return signName; } - - /** - * 获取默认sdkAppId - * - * @author xuyuxiang - * @date 2024/1/26 16:40 - **/ - public static String getDefaultSdkAppId() { - // sdkAppId为空,则获取默认sdkAppId - DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); - String sdkAppId = devConfigApi.getValueByKey(SNOWY_SMS_TENCENT_DEFAULT_SDK_APP_ID_KEY); - if(ObjectUtil.isEmpty(sdkAppId)) { - throw new CommonException("腾讯云短信操作客户端未正确配置:sdkAppId为空"); - } - return sdkAppId; - } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsXiaonuoUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsXiaonuoUtil.java index cf238652..c99f859e 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsXiaonuoUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sms/util/DevSmsXiaonuoUtil.java @@ -13,6 +13,7 @@ package vip.xiaonuo.dev.modular.sms.util; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; @@ -28,6 +29,8 @@ import org.dromara.sms4j.provider.config.SmsConfig; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.dev.api.DevConfigApi; +import java.util.LinkedHashMap; + /** * 小诺短信工具类 * @@ -76,21 +79,21 @@ public class DevSmsXiaonuoUtil { } DingZhongConfig dingZhongConfig = new DingZhongConfig(); + dingZhongConfig.setConfigId(accessKeyId); dingZhongConfig.setAccessKeyId(accessKeyId); dingZhongConfig.setAccessKeySecret(accessKeySecret); - dingZhongConfig.setRequestUrl(requestUrl); dingZhongConfig.setSignature(signName); - dingZhongConfig.setConfigId("XIAONUO"); + dingZhongConfig.setRequestUrl(requestUrl); SEInitializer.initializer().fromConfig(new SmsConfig(), CollectionUtil.newArrayList(dingZhongConfig)); smsBlend = SmsFactory.getSmsBlend(dingZhongConfig.getConfigId()); } /** - * 发送短信 + * 发送纯文字短信 * * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 * @param signName 短信签名,为空则使用默认签名 - * @param message 短信内容 + * @param message 短信内容,自定义文字 * @return 发送的结果信息 * @author xuyuxiang * @date 2022/2/24 13:42 @@ -104,6 +107,42 @@ public class DevSmsXiaonuoUtil { initClient(signName); // 发送短信 SmsResponse smsResponse = smsBlend.massTexting(StrUtil.split(phoneNumbers, StrUtil.COMMA), message); + if(smsResponse.isSuccess()) { + return JSONUtil.toJsonStr(smsResponse.getData()); + } else { + String data = Convert.toStr(smsResponse.getData()); + if(JSONUtil.isTypeJSON(data)) { + JSONObject responseData = JSONUtil.parseObj(smsResponse.getData()); + throw new CommonException(responseData.getStr("resInfo")); + } else { + throw new CommonException(data); + } + } + } catch (Exception e) { + throw new CommonException(e.getMessage()); + } + } + + /** + * 发送模板短信 + * + * @param phoneNumbers 手机号码,支持对多个手机号码发送短信,手机号码之间以半角逗号(,)分隔。 + * @param signName 短信签名,为空则使用默认签名 + * @param templateId 模板id + * @param paramMap 短信参数 + * @return 发送的结果信息 + * @author xuyuxiang + * @date 2022/2/24 13:42 + **/ + public static String sendSms(String phoneNumbers, String signName, String templateId, LinkedHashMap paramMap) { + try { + if(ObjectUtil.isEmpty(signName)) { + signName = getDefaultSignName(); + } + // 初始化客户端 + initClient(signName); + // 发送短信 + SmsResponse smsResponse = smsBlend.massTexting(StrUtil.split(phoneNumbers, StrUtil.COMMA), templateId, paramMap); if(smsResponse.isSuccess()) { return JSONUtil.toJsonStr(smsResponse.getData()); } else { diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/controller/DevSseEmitterController.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/controller/DevSseEmitterController.java index 84126148..9bb89bc1 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/controller/DevSseEmitterController.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/controller/DevSseEmitterController.java @@ -12,6 +12,8 @@ */ package vip.xiaonuo.dev.modular.sse.controller; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -30,6 +32,7 @@ import java.util.function.Consumer; * @date 2023/7/3 **/ @Tag(name = "SSE通信控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 10) @RestController @Validated public class DevSseEmitterController { @@ -43,6 +46,7 @@ public class DevSseEmitterController { * @author diantu * @date 2023/7/3 **/ + @ApiOperationSupport(order = 1) @Operation(summary = "创建sse连接") @GetMapping("/dev/sse/createConnect") public SseEmitter createConnect(String clientId, @@ -58,6 +62,7 @@ public class DevSseEmitterController { * @author diantu * @date 2023/7/3 **/ + @ApiOperationSupport(order = 2) @Operation(summary = "关闭sse连接") @GetMapping("/dev/sse/closeSseConnect") public void closeSseConnect(String clientId){ @@ -70,6 +75,7 @@ public class DevSseEmitterController { * @author diantu * @date 2023/7/3 **/ + @ApiOperationSupport(order = 3) @Operation(summary = "推送消息到所有客户端") @PostMapping("/dev/sse/broadcast") public void sendMessageToAllClient(@RequestBody(required = false) String msg){ @@ -82,6 +88,7 @@ public class DevSseEmitterController { * @author diantu * @date 2023/7/3 **/ + @ApiOperationSupport(order = 4) @Operation(summary = "根据clientId发送消息给某一客户端") @PostMapping("/dev/sse/sendMessage") public void sendMessageToOneClient(String clientId,String msg){ diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/util/DevSseCacheUtil.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/util/DevSseCacheUtil.java index 6ef15321..854778b7 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/util/DevSseCacheUtil.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/sse/util/DevSseCacheUtil.java @@ -38,7 +38,7 @@ public class DevSseCacheUtil { /** * 创建一个容器来存储所有的 SseEmitter(使用ConcurrentHashMap是因为它是线程安全的)。 */ - public static Map> sseCache = new ConcurrentHashMap<>(); + public static Map> sseCache = new ConcurrentHashMap<>(); /** @@ -48,7 +48,7 @@ public class DevSseCacheUtil { * @date 2023/7/3 **/ public static SseEmitter getSseEmitterByClientId(String clientId) { - Map map = sseCache.get(clientId); + Map map = sseCache.get(clientId); if (map == null || map.isEmpty()) { return null; } @@ -62,7 +62,7 @@ public class DevSseCacheUtil { * @date 2023/7/18 **/ public static ScheduledFuture getSseFutureByClientId(String clientId) { - Map map = sseCache.get(clientId); + Map map = sseCache.get(clientId); if (map == null || map.isEmpty()) { return null; } @@ -76,7 +76,7 @@ public class DevSseCacheUtil { * @date 2023/7/18 **/ public static ScheduledFuture getLoginIdByClientId(String clientId) { - Map map = sseCache.get(clientId); + Map map = sseCache.get(clientId); if (map == null || map.isEmpty()) { return null; } @@ -89,12 +89,12 @@ public class DevSseCacheUtil { * @author diantu * @date 2023/7/18 **/ - public static String getClientIdByLoginId(String loginId){ - if(existSseCache()){ + public static String getClientIdByLoginId(String loginId) { + if (existSseCache()) { for (Map.Entry> entry : sseCache.entrySet()) { - Map map = sseCache.get(entry.getKey()); + Map map = sseCache.get(entry.getKey()); String lId = (String) map.get(DevSseEmitterParameterEnum.LOGINID.getValue()); - if(loginId.equals(lId)){ + if (loginId.equals(lId)) { return entry.getKey(); } } @@ -109,7 +109,7 @@ public class DevSseCacheUtil { * @date 2023/7/3 **/ public static boolean existSseCache() { - return sseCache.size()>0; + return !sseCache.isEmpty(); } /** @@ -118,8 +118,8 @@ public class DevSseCacheUtil { * @author diantu * @date 2023/7/3 **/ - public static boolean connectionValidity(String clientId,String loginId){ - if(sseCache.get(clientId) == null){ + public static boolean connectionValidity(String clientId, String loginId) { + if (sseCache.get(clientId) == null) { return false; } return Objects.equals(loginId, sseCache.get(clientId).get(DevSseEmitterParameterEnum.LOGINID.getValue())); @@ -131,14 +131,14 @@ public class DevSseCacheUtil { * @author diantu * @date 2023/7/3 **/ - public static void addConnection(String clientId,String loginId, SseEmitter emitter, ScheduledFuture future) { + public static void addConnection(String clientId, String loginId, SseEmitter emitter, ScheduledFuture future) { final SseEmitter oldEmitter = getSseEmitterByClientId(clientId); if (oldEmitter != null) { - throw new CommonException("连接已存在:{}",clientId); + throw new CommonException("连接已存在:{}", clientId); } - Map map = new ConcurrentHashMap<>(); - map.put(DevSseEmitterParameterEnum.EMITTER.getValue(),emitter); - if(future!=null){ + Map map = new ConcurrentHashMap<>(); + map.put(DevSseEmitterParameterEnum.EMITTER.getValue(), emitter); + if (future != null) { map.put(DevSseEmitterParameterEnum.FUTURE.getValue(), future); } map.put(DevSseEmitterParameterEnum.LOGINID.getValue(), loginId); @@ -166,7 +166,7 @@ public class DevSseCacheUtil { * @author diantu * @date 2023/7/3 */ - public static void cancelScheduledFuture(String clientId){ + public static void cancelScheduledFuture(String clientId) { ScheduledFuture future = getSseFutureByClientId(clientId); if (future != null) { future.cancel(true); @@ -194,8 +194,8 @@ public class DevSseCacheUtil { * @author diantu * @date 2023/7/3 **/ - public static Runnable timeoutCallBack(String clientId){ - return ()->{ + public static Runnable timeoutCallBack(String clientId) { + return () -> { log.info("连接超时:{}", clientId); removeConnection(clientId); cancelScheduledFuture(clientId); @@ -227,11 +227,11 @@ public class DevSseCacheUtil { return; } // 判断发送的消息是否为空 - if (StrUtil.isEmpty(msg)){ + if (StrUtil.isEmpty(msg)) { log.info("群发消息为空"); return; } - CommonResult message = new CommonResult<>(CommonResult.CODE_SUCCESS,"",msg); + CommonResult message = new CommonResult<>(CommonResult.CODE_SUCCESS, "", msg); for (Map.Entry> entry : sseCache.entrySet()) { sendMessageToClientByClientId(entry.getKey(), message); } @@ -244,16 +244,16 @@ public class DevSseCacheUtil { * @date 2023/7/3 **/ public static void sendMessageToOneClient(String clientId, String msg) { - if (StrUtil.isEmpty(clientId)){ + if (StrUtil.isEmpty(clientId)) { log.info("客户端ID为空"); return; } - if (StrUtil.isEmpty(msg)){ - log.info("向客户端{}推送消息为空",clientId); + if (StrUtil.isEmpty(msg)) { + log.info("向客户端{}推送消息为空", clientId); return; } - CommonResult message = new CommonResult<>(CommonResult.CODE_SUCCESS,"",msg); - sendMessageToClientByClientId(clientId,message); + CommonResult message = new CommonResult<>(CommonResult.CODE_SUCCESS, "", msg); + sendMessageToClientByClientId(clientId, message); } /** @@ -264,16 +264,16 @@ public class DevSseCacheUtil { **/ public static void sendMessageToClientByClientId(String clientId, CommonResult message) { Map map = sseCache.get(clientId); - if (map==null||map.size()==0) { - log.error("推送消息失败:客户端{}未创建长链接,失败消息:{}",clientId, message.toString()); + if (map == null || map.isEmpty()) { + log.error("推送消息失败:客户端{}未创建长链接,失败消息:{}", clientId, message.toString()); return; } - SseEmitter.SseEventBuilder sendData = SseEmitter.event().data(message,MediaType.APPLICATION_JSON); + SseEmitter.SseEventBuilder sendData = SseEmitter.event().data(message, MediaType.APPLICATION_JSON); SseEmitter sseEmitter = getSseEmitterByClientId(clientId); try { Objects.requireNonNull(sseEmitter).send(sendData); } catch (Exception e) { - log.error("推送消息失败,报错异常:",e); + log.error("推送消息失败,报错异常:", e); removeConnection(clientId); } } diff --git a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/entity/GenBasic.java b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/entity/GenBasic.java index e9cf89be..3094270f 100644 --- a/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/entity/GenBasic.java +++ b/snowy-plugin/snowy-plugin-gen/src/main/java/vip/xiaonuo/gen/modular/basic/entity/GenBasic.java @@ -69,7 +69,7 @@ public class GenBasic extends CommonEntity { /** 移动端所属模块 */ @Schema(description = "移动端所属模块") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String mobileModule; /** 功能名 */ diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/mobile/MobileApiProvider.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/mobile/MobileApiProvider.java new file mode 100644 index 00000000..bf6ee047 --- /dev/null +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/mobile/MobileApiProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.mobile.modular.mobile; + +import org.springframework.stereotype.Service; +import vip.xiaonuo.mobile.api.MobileApi; + +/** + * 移动端综合API接口实现类 + * + * @author xuyuxiang + * @date 2022/9/26 14:24 + **/ +@Service +public class MobileApiProvider implements MobileApi { + +} diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileButtonController.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileButtonController.java index e2b24f77..4c1710a1 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileButtonController.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileButtonController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.mobile.modular.resource.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.mobile.modular.resource.param.button.MobileButtonIdParam; import vip.xiaonuo.mobile.modular.resource.param.button.MobileButtonPageParam; import vip.xiaonuo.mobile.modular.resource.service.MobileButtonService; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/6/27 13:56 **/ @Tag(name = "移动端按钮控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 3) @RestController @Validated public class MobileButtonController { @@ -54,6 +57,7 @@ public class MobileButtonController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取移动端按钮分页") @GetMapping("/mobile/button/page") public CommonResult> page(MobileButtonPageParam mobileButtonPageParam) { @@ -66,6 +70,7 @@ public class MobileButtonController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加移动端按钮") @CommonLog("添加移动端按钮") @PostMapping("/mobile/button/add") @@ -80,6 +85,7 @@ public class MobileButtonController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑移动端按钮") @CommonLog("编辑移动端按钮") @PostMapping("/mobile/button/edit") @@ -94,6 +100,7 @@ public class MobileButtonController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除移动端按钮") @CommonLog("删除移动端按钮") @PostMapping("/mobile/button/delete") @@ -108,6 +115,7 @@ public class MobileButtonController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取移动端按钮详情") @GetMapping("/mobile/button/detail") public CommonResult detail(@Valid MobileButtonIdParam mobileButtonIdParam) { diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileMenuController.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileMenuController.java index 93c8d694..d90f6b6b 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileMenuController.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileMenuController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.mobile.modular.resource.controller; import cn.hutool.core.lang.tree.Tree; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +31,7 @@ import vip.xiaonuo.mobile.modular.resource.entity.MobileModule; import vip.xiaonuo.mobile.modular.resource.param.menu.*; import vip.xiaonuo.mobile.modular.resource.service.MobileMenuService; +import javax.validation.Valid; import java.util.List; /** @@ -39,6 +41,7 @@ import java.util.List; * @date 2023/01/28 22:42 */ @Tag(name = "移动端菜单控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 1) @RestController @Validated public class MobileMenuController { @@ -52,6 +55,7 @@ public class MobileMenuController { * @author yubaoshan * @date 2023/01/28 22:42 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取移动端菜单tree") @GetMapping("/mobile/menu/tree") public CommonResult>> tree(MobileMenuTreeParam mobileMenuTreeParam) { @@ -64,6 +68,7 @@ public class MobileMenuController { * @author yubaoshan * @date 2023/01/28 22:42 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加移动端菜单") @CommonLog("添加移动端菜单") @PostMapping("/mobile/menu/add") @@ -78,6 +83,7 @@ public class MobileMenuController { * @author yubaoshan * @date 2023/01/28 22:42 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑移动端菜单") @CommonLog("编辑移动端菜单") @PostMapping("/mobile/menu/edit") @@ -92,6 +98,7 @@ public class MobileMenuController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 5) @Operation(summary = "更改移动端菜单所属模块") @CommonLog("更改移动端菜单所属模块") @PostMapping("/mobile/menu/changeModule") @@ -106,6 +113,7 @@ public class MobileMenuController { * @author yubaoshan * @date 2023/01/28 22:42 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除移动端菜单") @CommonLog("删除移动端菜单") @PostMapping("/mobile/menu/delete") @@ -121,6 +129,7 @@ public class MobileMenuController { * @author yubaoshan * @date 2023/01/28 22:42 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取移动端菜单详情") @GetMapping("/mobile/menu/detail") public CommonResult detail(@Valid MobileMenuIdParam mobileMenuIdParam) { @@ -135,6 +144,7 @@ public class MobileMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取模块选择器") @GetMapping("/mobile/menu/moduleSelector") public CommonResult> moduleSelector(MobileMenuSelectorModuleParam mobileMenuSelectorModuleParam) { @@ -147,6 +157,7 @@ public class MobileMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取菜单树选择器") @GetMapping("/mobile/menu/menuTreeSelector") public CommonResult>> menuTreeSelector(MobileMenuSelectorMenuParam mobileMenuSelectorMenuParam) { diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileModuleController.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileModuleController.java index a08da7d8..9a41f8f4 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileModuleController.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/controller/MobileModuleController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.mobile.modular.resource.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.mobile.modular.resource.param.module.MobileModuleIdParam; import vip.xiaonuo.mobile.modular.resource.param.module.MobileModulePageParam; import vip.xiaonuo.mobile.modular.resource.service.MobileModuleService; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/6/27 14:12 **/ @Tag(name = "移动端模块控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 6) @RestController @Validated public class MobileModuleController { @@ -54,6 +57,7 @@ public class MobileModuleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取移动端模块分页") @GetMapping("/mobile/module/page") public CommonResult> page(MobileModulePageParam mobileModulePageParam) { @@ -66,6 +70,7 @@ public class MobileModuleController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加移动端模块") @CommonLog("添加移动端模块") @PostMapping("/mobile/module/add") @@ -80,6 +85,7 @@ public class MobileModuleController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑移动端模块") @CommonLog("编辑移动端模块") @PostMapping("/mobile/module/edit") @@ -94,11 +100,12 @@ public class MobileModuleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除移动端模块") @CommonLog("删除移动端模块") @PostMapping("/mobile/module/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List mobileModuleIdParamList) { + List mobileModuleIdParamList) { mobileModuleService.delete(mobileModuleIdParamList); return CommonResult.ok(); } @@ -109,6 +116,7 @@ public class MobileModuleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取移动端模块详情") @GetMapping("/mobile/module/detail") public CommonResult detail(@Valid MobileModuleIdParam mobileModuleIdParam) { diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileButton.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileButton.java index 6f34bb23..25e9a5a2 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileButton.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileButton.java @@ -57,6 +57,6 @@ public class MobileButton extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileMenu.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileMenu.java index 9d4e79c1..f9dd007b 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileMenu.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileMenu.java @@ -87,6 +87,6 @@ public class MobileMenu extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileModule.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileModule.java index 209ed6dd..a774218b 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileModule.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/entity/MobileModule.java @@ -61,6 +61,6 @@ public class MobileModule extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileButtonApiProvider.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileButtonApiProvider.java index c8453a17..9c835219 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileButtonApiProvider.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileButtonApiProvider.java @@ -34,7 +34,7 @@ public class MobileButtonApiProvider implements MobileButtonApi { private MobileButtonService mobileButtonService; @Override - public List listByIds(List buttonIdList) { + public List listButtonCodeListByIdList(List buttonIdList) { return mobileButtonService.listByIds(buttonIdList).stream().map(MobileButton::getCode).collect(Collectors.toList()); } } diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileMenuApiProvider.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileMenuApiProvider.java index bd9a1c3a..47e0ff03 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileMenuApiProvider.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/provider/MobileMenuApiProvider.java @@ -12,11 +12,13 @@ */ package vip.xiaonuo.mobile.modular.resource.provider; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.tree.Tree; import cn.hutool.json.JSONObject; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import vip.xiaonuo.mobile.api.MobileMenuApi; +import vip.xiaonuo.mobile.modular.resource.entity.MobileMenu; import vip.xiaonuo.mobile.modular.resource.service.MobileMenuService; import java.util.List; @@ -38,6 +40,11 @@ public class MobileMenuApiProvider implements MobileMenuApi { return mobileMenuService.mobileMenuTreeSelector(); } + @Override + public List mobileMenuTreeSelector(List originDataList) { + return mobileMenuService.mobileMenuTreeSelector(BeanUtil.copyToList(originDataList, MobileMenu.class)); + } + @Override public List> loginMobileMenuTree(List menuIdList) { return mobileMenuService.loginMobileMenuTree(menuIdList); diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/MobileMenuService.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/MobileMenuService.java index 6edd3e94..963b4b01 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/MobileMenuService.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/MobileMenuService.java @@ -127,6 +127,14 @@ public interface MobileMenuService extends IService { **/ List mobileMenuTreeSelector(); + /** + * 获取移动端菜单授权树 + * + * @author xuyuxiang + * @date 2023/1/31 10:14 + **/ + List mobileMenuTreeSelector(List originDataList); + /** * 获取移动端登录菜单树 * diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileButtonServiceImpl.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileButtonServiceImpl.java index abcf40a6..df04dce3 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileButtonServiceImpl.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileButtonServiceImpl.java @@ -22,6 +22,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; @@ -102,6 +103,7 @@ public class MobileButtonServiceImpl extends ServiceImpl mobileButtonIdParamList) { List buttonIdList = CollStreamUtil.toList(mobileButtonIdParamList, MobileButtonIdParam::getId); diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileMenuServiceImpl.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileMenuServiceImpl.java index 73fd7204..131f18f8 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileMenuServiceImpl.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileMenuServiceImpl.java @@ -24,6 +24,7 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -61,16 +62,16 @@ public class MobileMenuServiceImpl extends ServiceImpl> tree(MobileMenuTreeParam mobileMenuTreeParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); if(ObjectUtil.isNotEmpty(mobileMenuTreeParam.getModule())) { - lambdaQueryWrapper.eq(MobileMenu::getModule, mobileMenuTreeParam.getModule()); + queryWrapper.lambda().eq(MobileMenu::getModule, mobileMenuTreeParam.getModule()); } if(ObjectUtil.isNotEmpty(mobileMenuTreeParam.getSearchKey())) { - lambdaQueryWrapper.like(MobileMenu::getTitle, mobileMenuTreeParam.getSearchKey()); + queryWrapper.lambda().like(MobileMenu::getTitle, mobileMenuTreeParam.getSearchKey()); } - lambdaQueryWrapper.eq(MobileMenu::getCategory, MobileResourceCategoryEnum.MENU.getValue()); - lambdaQueryWrapper.orderByDesc(MobileMenu::getSortCode); - List mobileMenuList = this.list(lambdaQueryWrapper); + queryWrapper.lambda().eq(MobileMenu::getCategory, MobileResourceCategoryEnum.MENU.getValue()); + queryWrapper.lambda().orderByDesc(MobileMenu::getSortCode); + List mobileMenuList = this.list(queryWrapper.lambda()); List> treeNodeList = mobileMenuList.stream().map(mobileMenu -> new TreeNode<>(mobileMenu.getId(), mobileMenu.getParentId(), mobileMenu.getTitle(), mobileMenu.getSortCode()).setExtra(JSONUtil.parseObj(mobileMenu))) @@ -98,6 +99,7 @@ public class MobileMenuServiceImpl extends ServiceImpl originDataList = this.list(new LambdaQueryWrapper().eq(MobileMenu::getCategory, MobileResourceCategoryEnum.MENU.getValue())); boolean errorLevel = this.getChildListById(originDataList, mobileMenu.getId(), true).stream() - .map(MobileMenu::getId).collect(Collectors.toList()).contains(mobileMenu.getParentId()); + .map(MobileMenu::getId).toList().contains(mobileMenu.getParentId()); if(errorLevel) { throw new CommonException("不可选择上级菜单:{}", this.getById(originDataList, mobileMenu.getParentId()).getTitle()); } @@ -132,6 +134,7 @@ public class MobileMenuServiceImpl extends ServiceImpl toDeleteMenuIdList = CollectionUtil.newArrayList(); mobileMenuIdList.forEach(menuId -> toDeleteMenuIdList.addAll(this.getChildListById(allMenuList, menuId, true).stream() - .map(MobileMenu::getId).collect(Collectors.toList()))); + .map(MobileMenu::getId).toList())); if(ObjectUtil.isNotEmpty(toDeleteMenuIdList)) { // 清除对应的角色与移动端资源信息 sysRelationApi.removeRoleHasMobileMenuRelation(toDeleteMenuIdList); @@ -190,12 +193,12 @@ public class MobileMenuServiceImpl extends ServiceImpl moduleSelector(MobileMenuSelectorModuleParam mobileMenuSelectorModuleParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); if(ObjectUtil.isNotEmpty(mobileMenuSelectorModuleParam.getSearchKey())) { - lambdaQueryWrapper.like(MobileModule::getTitle, mobileMenuSelectorModuleParam.getSearchKey()); + queryWrapper.lambda().like(MobileModule::getTitle, mobileMenuSelectorModuleParam.getSearchKey()); } - lambdaQueryWrapper.eq(MobileModule::getCategory, MobileResourceCategoryEnum.MODULE.getValue()); - return mobileModuleService.list(lambdaQueryWrapper); + queryWrapper.lambda().eq(MobileModule::getCategory, MobileResourceCategoryEnum.MODULE.getValue()); + return mobileModuleService.list(queryWrapper.lambda()); } @Override @@ -216,16 +219,19 @@ public class MobileMenuServiceImpl extends ServiceImpl mobileMenuTreeSelector() { - // 模块、菜单、按钮,应该查所有的,当然这里没有已经删除过的 - List allModuleAndMenuList = this.list(); + return this.mobileMenuTreeSelector(this.list()); + } + + @Override + public List mobileMenuTreeSelector(List originDataList) { List mobileModuleList = CollectionUtil.newArrayList(); List mobileMenuList = CollectionUtil.newArrayList(); List mobileButtonList = CollectionUtil.newArrayList(); - if (ObjectUtil.isEmpty(allModuleAndMenuList)) { + if (ObjectUtil.isEmpty(originDataList)) { // 返回空列表 return CollectionUtil.newArrayList(); } - allModuleAndMenuList.forEach(mobileMenu -> { + originDataList.forEach(mobileMenu -> { if (mobileMenu.getCategory().equals(MobileResourceCategoryEnum.MODULE.getValue())) { mobileModuleList.add(mobileMenu); } @@ -242,7 +248,7 @@ public class MobileMenuServiceImpl extends ServiceImpl> treeList = TreeUtil.build(treeNodeList, "0"); mobileMenuList.forEach(mobileMenu -> { - boolean isLeafMenu = this.getChildListById(mobileMenuList, mobileMenu.getId(), false).size() == 0; + boolean isLeafMenu = this.getChildListById(mobileMenuList, mobileMenu.getId(), false).isEmpty(); if(isLeafMenu) { JSONObject mobileRoleGrantResourceMenuResult = JSONUtil.createObj(); BeanUtil.copyProperties(mobileMenu, mobileRoleGrantResourceMenuResult); @@ -306,7 +312,7 @@ public class MobileMenuServiceImpl extends ServiceImpl menuList = allMenuList.stream().filter(mobileMenu -> - menuIdList.contains(mobileMenu.getId())).collect(Collectors.toList()); + menuIdList.contains(mobileMenu.getId())).toList(); // 对获取到的角色对应的菜单列表进行处理,获取父列表 menuList.forEach(mobileMenu -> execRecursionFindParent(allMenuList, mobileMenu.getId(), resultList)); @@ -355,7 +361,7 @@ public class MobileMenuServiceImpl extends ServiceImpl> treeNodeList = resultJsonObjectList.stream().map(jsonObject -> diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileModuleServiceImpl.java b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileModuleServiceImpl.java index 756b2480..ccc3c384 100644 --- a/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileModuleServiceImpl.java +++ b/snowy-plugin/snowy-plugin-mobile/src/main/java/vip/xiaonuo/mobile/modular/resource/service/impl/MobileModuleServiceImpl.java @@ -26,6 +26,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; @@ -84,6 +85,9 @@ public class MobileModuleServiceImpl extends ServiceImpl mobileModuleIdParamList) { List mobileModuleIdList = CollStreamUtil.toList(mobileModuleIdParamList, MobileModuleIdParam::getId); diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/COMPLETED.png b/snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/COMPLETED.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba0eb11b96320044e6641a9d05916b1fc0c7b9a GIT binary patch literal 15194 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 literal 0 HcmV?d00001 diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/END.png b/snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/END.png new file mode 100644 index 0000000000000000000000000000000000000000..7877da5f2db096a65c01aa791a2f9cbbf8073fe6 GIT binary patch literal 15606 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

v1_T_?kyQt}Ya^yW}rOz8z}B8+m6!_kPW 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 U)2&Jrv& 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

  • qIJtz^ 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 literal 0 HcmV?d00001 diff --git a/snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/SUSPENDED.png b/snowy-plugin/snowy-plugin-mobile/src/main/resources/static/mobile/flw/SUSPENDED.png new file mode 100644 index 0000000000000000000000000000000000000000..5ee4aec4ead8cec9455bcb836fd5101e0e57f336 GIT binary patch literal 15117 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 Os*2(Zg+{rTk^dj8+Y~nd literal 0 HcmV?d00001 diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysBuildInEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysBuildInEnum.java index 383ca2ac..7e226d43 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysBuildInEnum.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysBuildInEnum.java @@ -29,8 +29,17 @@ public enum SysBuildInEnum { /** 超管角色编码 */ BUILD_IN_ROLE_CODE("superAdmin", "超管"), - /** 系统内置模块编码 */ - BUILD_IN_MODULE_CODE("system", "系统内置"); + /** 超管职位编码 */ + BUILD_IN_POSITION_CODE("superAdmin", "超管"), + + /** 系统内置系统模块编码 */ + BUILD_IN_MODULE_CODE("system", "系统内置"), + + /** 系统内置业务模块编码 */ + BUILD_IN_MODULE_CODE_BIZ("biz", "系统内置"), + + /** 系统内置非租户菜单编码 */ + BUILD_IN_NO_TEN_MENU_CODE("noten", "非租户菜单"); private final String value; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysPasswordComplexityEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysPasswordComplexityEnum.java new file mode 100644 index 00000000..15c6197b --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/enums/SysPasswordComplexityEnum.java @@ -0,0 +1,64 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.core.enums; + +import lombok.Getter; + +/** + * 密码复杂度类型枚举 + * + * @author xuyuxiang + * @date 2023/3/3 10:40 + **/ +@Getter +public enum SysPasswordComplexityEnum { + + /** + * 无限制 + */ + REG0("REG0", "无限制"), + + /** + * 必须包含数字和字母 + */ + REG1("REG1", "必须包含数字和字母"), + + /** + * 必须包含数字和大写字母 + */ + REG2("REG2", "必须包含数字和大写字母"), + + /** + * 必须包含数字、大写字母、小写字母和特殊字符 + */ + REG3("REG3", "必须包含数字、大写字母、小写字母和特殊字符"), + + /** + * 至少包含数字、字母和特殊字符中的两种 + */ + REG4("REG4", "至少包含数字、字母和特殊字符中的两种"), + + /** + * 至少包含数字、大写字母、小写字母和特殊字符的三种 + */ + REG5("REG5", "至少包含数字、大写字母、小写字母和特殊字符的三种"); + + private final String value; + + private final String message; + + SysPasswordComplexityEnum(String value, String message) { + this.value = value; + this.message = message; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java index fccd3bfc..1555f24c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/listener/SysDataChangeListener.java @@ -15,15 +15,11 @@ package vip.xiaonuo.sys.core.listener; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; -import jakarta.annotation.Resource; import org.springframework.stereotype.Component; import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; import vip.xiaonuo.auth.core.util.StpLoginUserUtil; -import vip.xiaonuo.common.cache.CommonCacheOperator; import vip.xiaonuo.common.listener.CommonDataChangeListener; import vip.xiaonuo.sys.core.enums.SysDataTypeEnum; -import vip.xiaonuo.sys.modular.org.service.impl.SysOrgServiceImpl; -import vip.xiaonuo.sys.modular.user.service.impl.SysUserServiceImpl; import java.util.List; @@ -36,9 +32,6 @@ import java.util.List; @Component public class SysDataChangeListener implements CommonDataChangeListener { - @Resource - private CommonCacheOperator commonCacheOperator; - @Override public void doAddWithDataId(String dataType, String dataId) { // 此处可做额外处理 @@ -46,20 +39,14 @@ public class SysDataChangeListener implements CommonDataChangeListener { @Override public void doAddWithDataIdList(String dataType, List dataIdList) { - // 如果检测到机构增加,则将机构的数据缓存清除 + // 如果检测到机构增加,则将该机构加入到当前登录用户的数据范围缓存 if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { - commonCacheOperator.remove(SysOrgServiceImpl.ORG_CACHE_ALL_KEY); - // 并将该机构加入到当前登录用户的数据范围缓存 SaBaseLoginUser saBaseLoginUser = StpLoginUserUtil.getLoginUser(); saBaseLoginUser.getDataScopeList().forEach(dataScope -> dataScope.getDataScope().addAll(dataIdList)); saBaseLoginUser.setDataScopeList(saBaseLoginUser.getDataScopeList()); // 重新缓存当前登录用户信息 StpUtil.getTokenSession().set("loginUser", saBaseLoginUser); } - // 如果检测到用户增加,则将用户数据缓存清除 - if(dataType.equals(SysDataTypeEnum.USER.getValue())) { - commonCacheOperator.remove(SysUserServiceImpl.USER_CACHE_ALL_KEY); - } } @Override @@ -79,14 +66,7 @@ public class SysDataChangeListener implements CommonDataChangeListener { @Override public void doUpdateWithDataIdList(String dataType, List dataIdList) { - // 如果检测到机构更新,则将机构的数据缓存清除 - if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { - commonCacheOperator.remove(SysOrgServiceImpl.ORG_CACHE_ALL_KEY); - } - // 如果检测到用户更新,则将用户数据缓存清除 - if(dataType.equals(SysDataTypeEnum.USER.getValue())) { - commonCacheOperator.remove(SysUserServiceImpl.USER_CACHE_ALL_KEY); - } + // 此处可做额外处理 } @Override @@ -106,14 +86,6 @@ public class SysDataChangeListener implements CommonDataChangeListener { @Override public void doDeleteWithDataIdList(String dataType, List dataIdList) { - // 如果检测到机构增加,则将机构的数据缓存清除 - if(dataType.equals(SysDataTypeEnum.ORG.getValue())) { - commonCacheOperator.remove(SysOrgServiceImpl.ORG_CACHE_ALL_KEY); - } - // 如果检测到用户删除,则将用户数据缓存清除,并将这些用户踢下线 - if(dataType.equals(SysDataTypeEnum.USER.getValue())) { - commonCacheOperator.remove(SysUserServiceImpl.USER_CACHE_ALL_KEY); - dataIdList.forEach(StpUtil::kickout); - } + // 此处可做额外处理 } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/timer/SysUserPasswordExpiredNoticeTimerTaskRunner.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/timer/SysUserPasswordExpiredNoticeTimerTaskRunner.java new file mode 100644 index 00000000..0c66d7d1 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/timer/SysUserPasswordExpiredNoticeTimerTaskRunner.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.core.timer; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import vip.xiaonuo.common.timer.CommonTimerTaskRunner; +import vip.xiaonuo.sys.modular.user.service.SysUserService; + +/** + * 通知用户密码即将到期定时类 + * + * @author xuyuxiang + * @date 2022/8/5 15:52 + **/ +@Slf4j +@Component +public class SysUserPasswordExpiredNoticeTimerTaskRunner implements CommonTimerTaskRunner { + + @Resource + private SysUserService sysUserService; + + @Override + public void action(String extJson) { + // 通知用户密码即将到期 + sysUserService.noticeUserPasswordAboutToExpired(); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysEmailFormatUtl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysEmailFormatUtl.java new file mode 100644 index 00000000..f063ad93 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysEmailFormatUtl.java @@ -0,0 +1,48 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.core.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import vip.xiaonuo.dev.api.DevConfigApi; + +/** + * 系统相关邮件格式化工具类 + * + * @author xuyuxiang + * @date 2025/3/21 19:07 + **/ +public class SysEmailFormatUtl { + + /** 系统名称 */ + private static final String SNOWY_SYS_NAME_KEY = "SNOWY_SYS_NAME"; + + /** + * 格式化邮件内容 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static String format(String content, JSONObject paramMap) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取系统名称 + String sysName = devConfigApi.getValueByKey(SNOWY_SYS_NAME_KEY); + // 系统名称 + paramMap.set("sysName", sysName); + // 当前时间 + paramMap.set("sysNowTime", DateUtil.now()); + return StrUtil.format(content, paramMap); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysPasswordUtl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysPasswordUtl.java new file mode 100644 index 00000000..e52632ad --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/core/util/SysPasswordUtl.java @@ -0,0 +1,460 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.core.util; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.pinyin.PinyinUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import vip.xiaonuo.common.exception.CommonException; +import vip.xiaonuo.common.util.CommonCryptogramUtil; +import vip.xiaonuo.dev.api.DevConfigApi; +import vip.xiaonuo.dev.api.DevWeakPasswordApi; +import vip.xiaonuo.sys.core.enums.SysPasswordComplexityEnum; +import vip.xiaonuo.sys.modular.user.entity.SysUser; +import vip.xiaonuo.sys.modular.user.entity.SysUserExt; +import vip.xiaonuo.sys.modular.user.result.SysLoginUser; +import vip.xiaonuo.sys.modular.user.service.SysUserExtService; +import vip.xiaonuo.sys.modular.user.service.SysUserPasswordService; +import vip.xiaonuo.sys.modular.user.service.SysUserService; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统密码工具类 + * + * @author xuyuxiang + * @date 2025/3/21 19:07 + **/ +public class SysPasswordUtl { + + /** B端系统默认密码 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_FOR_B"; + + /** B端系统密码修改验证方式 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_B"; + + /** B端密码最小长度 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_B"; + + /** B端密码最大长度 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_B"; + + /** B端密码复杂度 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_B"; + + /** B端密码不能连续存在相同字符个数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_B_KEY= "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_B"; + + /** B端密码不能包含用户信息开关(开启后,密码中将不能包含账号、手机号、邮箱前缀和姓名拼音) */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_B"; + + /** B端密码不能使用历史密码开关 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_B"; + + /** B端密码不能使用历史密码范围个数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_B"; + + /** B端密码不能使用弱密码库中密码开关 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_B"; + + /** B端密码自定义额外弱密码库 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_B"; + + /** B端密码有效期天数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_B"; + + /** B端密码过期前提醒天数 */ + private static final String SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_B_KEY = "SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_B"; + + /** + * 获取系统默认密码 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static String getDefaultPassword() { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + String defaultPassword = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_FOR_B_KEY); + if(ObjectUtil.isEmpty(defaultPassword)){ + throw new CommonException("请联系管理员配置系统默认密码"); + } + return defaultPassword; + } + + /** + * 获取修改密码验证方式及配置 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static JSONObject getUpdatePasswordValidConfig() { + JSONObject jsonObject = new JSONObject(); + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 修改密码验证方式 + String passwordUpdateValidType = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordUpdateValidType)){ + throw new CommonException("请联系管理员配置系统密码修改验证方式"); + } + jsonObject.set(SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_B_KEY, passwordUpdateValidType); + // 密码最小长度 + String passwordUpdateMinLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordUpdateMinLength)){ + throw new CommonException("请联系管理员配置系统密码修改最小长度"); + } + jsonObject.set(SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_B_KEY, passwordUpdateMinLength); + // 密码最大长度 + String passwordUpdateMaxLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordUpdateMaxLength)){ + throw new CommonException("请联系管理员配置系统密码修改密码最大长度"); + } + jsonObject.set(SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_B_KEY, passwordUpdateMaxLength); + // 密码复杂度 + String passwordUpdateComplexity = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordUpdateValidType)){ + throw new CommonException("请联系管理员配置系统密码修改密码复杂度"); + } + jsonObject.set(SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_B_KEY, passwordUpdateComplexity); + // 不能连续出现相同字符个数 + String passwordUpdateNotAllowContinuousSame = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordUpdateValidType)){ + throw new CommonException("请联系管理员配置系统密码修改联系出现相同字符的个数"); + } + jsonObject.set(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_B_KEY, passwordUpdateNotAllowContinuousSame); + return jsonObject; + } + + /** + * 获取修改密码验证方式 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static String getUpdatePasswordValidType() { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + String passwordUpdateValidType = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordUpdateValidType)){ + throw new CommonException("请联系管理员配置系统密码修改验证方式"); + } + return passwordUpdateValidType; + } + + /** + * 校验修改密码验证方式 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validUpdatePasswordValidType(String type) { + String updatePasswordValidType = getUpdatePasswordValidType(); + if(!updatePasswordValidType.equals(type)){ + throw new CommonException("系统配置不支持此方式修改密码"); + } + } + + /** + * 校验新密码 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(SysLoginUser sysLoginUser, String newPassword) { + String userId = sysLoginUser.getId(); + String account = sysLoginUser.getAccount(); + String name = sysLoginUser.getName(); + String phone = sysLoginUser.getPhone(); + String email = sysLoginUser.getEmail(); + validNewPassword(newPassword); + validNewPassword(userId, account, name, phone, email, newPassword); + } + + /** + * 校验新密码 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(SysUser sysUser, String newPassword) { + String userId = sysUser.getId(); + String account = sysUser.getAccount(); + String name = sysUser.getName(); + String phone = sysUser.getPhone(); + String email = sysUser.getEmail(); + validNewPassword(newPassword); + validNewPassword(userId, account, name, phone, email, newPassword); + } + + /** + * 校验新密码(基本要求) + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(String newPassword) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 密码最小长度 + String passwordMinLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordMinLength)){ + Integer minLengthInt = Convert.toInt(passwordMinLength); + if(newPassword.length() < minLengthInt){ + throw new CommonException("密码最小长度应为:{}", minLengthInt); + } + } + // 密码最大长度 + String passwordMaxLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordMaxLength)){ + Integer maxLengthInt = Convert.toInt(passwordMaxLength); + if(newPassword.length() > maxLengthInt){ + throw new CommonException("密码最大长度应为:{}", maxLengthInt); + } + } + // 密码复杂度 + String passwordComplexity = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordComplexity)){ + // 据复杂度配置判断 + boolean notLimit = SysPasswordComplexityEnum.REG0.getValue().equals(passwordComplexity); + if(!notLimit){ + if(SysPasswordComplexityEnum.REG1.getValue().equals(passwordComplexity)) { + String reg = "^(?=.*[0-9])(?=.*[a-zA-Z]).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", SysPasswordComplexityEnum.REG1.getMessage()); + } + } + if(SysPasswordComplexityEnum.REG2.getValue().equals(passwordComplexity)) { + String reg = "^(?=.*[0-9])(?=.*[A-Z]).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", SysPasswordComplexityEnum.REG2.getMessage()); + } + } + if(SysPasswordComplexityEnum.REG3.getValue().equals(passwordComplexity)) { + String reg = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9]).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", SysPasswordComplexityEnum.REG3.getMessage()); + } + } + if(SysPasswordComplexityEnum.REG4.getValue().equals(passwordComplexity)) { + String reg = "^(?:(?=.*[0-9])(?=.*[a-zA-Z])|(?=.*[0-9])(?=.*[^a-zA-Z0-9])|(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9])).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", SysPasswordComplexityEnum.REG4.getMessage()); + } + } + if(SysPasswordComplexityEnum.REG5.getValue().equals(passwordComplexity)) { + String reg = "^(?:(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])|(?=.*[0-9])(?=.*[a-z])(?=.*[^a-zA-Z0-9])|(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9])).+$"; + if(!newPassword.matches(reg)) { + throw new CommonException("密码{}", SysPasswordComplexityEnum.REG5.getMessage()); + } + } + } + } + // 密码不能连续存在相同字符个数 + String passwordNotAllowContinuousSameCharacterLength = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowContinuousSameCharacterLength)){ + // 密码不能连续存在相同字符个数 + Integer passwordNotAllowContinuousSameCharacterLengthInt = Convert.toInt(passwordNotAllowContinuousSameCharacterLength); + boolean hasConsecutiveChars = hasConsecutiveChars(newPassword, passwordNotAllowContinuousSameCharacterLengthInt); + if(hasConsecutiveChars){ + throw new CommonException("密码不可存在" + passwordNotAllowContinuousSameCharacterLengthInt + "个连续相同的字符"); + } + } + // 密码不能使用弱密码库中密码开关 + String passwordNotAllowUseWeakFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowUseWeakFlag)){ + if(Convert.toBool(passwordNotAllowUseWeakFlag)){ + // 不能包含内置弱密码和自定义额外弱密码库中密码 + DevWeakPasswordApi devWeakPasswordApi = SpringUtil.getBean(DevWeakPasswordApi.class); + List weakPasswordList = devWeakPasswordApi.weakPasswordList(); + // 获取自定义额外弱密码库 + String passwordDefineWeakDatabase = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordDefineWeakDatabase)){ + weakPasswordList.addAll(StrUtil.split(passwordDefineWeakDatabase, StrUtil.COMMA)); + } + if(weakPasswordList.contains(newPassword)){ + throw new CommonException("密码不可使用弱密码"); + } + } + } + } + + /** + * 校验新密码(含用户信息等) + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static void validNewPassword(String userId, String account, String name, String phone, String email, String newPassword) { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 密码不能包含用户信息开关 + String passwordNotAllowContainsUserInfoFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowContainsUserInfoFlag)){ + if(Convert.toBool(passwordNotAllowContainsUserInfoFlag)){ + // 账号,不能包含 + if(ObjectUtil.isNotEmpty(account) && newPassword.contains(account)){ + throw new CommonException("密码不可包含账号"); + } + // 姓名,不能包含拼音 + if(ObjectUtil.isNotEmpty(name) && newPassword.contains(PinyinUtil.getPinyin(name, ""))){ + throw new CommonException("密码不可包含姓名拼音"); + } + // 手机号,不能包含 + if(ObjectUtil.isNotEmpty(phone) && newPassword.contains(phone)){ + throw new CommonException("密码不可包含手机号"); + } + // 邮箱,不能包含前缀,即@字符之前内容 + if(ObjectUtil.isNotEmpty(email) && newPassword.contains(StrUtil.split(email, StrUtil.AT).get(0))){ + throw new CommonException("密码不可包含邮箱前缀"); + } + } + } + // 密码不能使用历史密码开关 + String passwordNotAllowUseHistoryFlag = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowUseHistoryFlag)){ + if(Convert.toBool(passwordNotAllowUseHistoryFlag)){ + // 密码不能使用历史密码范围个数 + String passwordNotAllowContainsHistoryCount = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(passwordNotAllowContainsHistoryCount)){ + Integer passwordNotAllowContainsHistoryCountInt = Convert.toInt(passwordNotAllowContainsHistoryCount); + // 取前N次密码,进行判断 + SysUserPasswordService sysUserPasswordService = SpringUtil.getBean(SysUserPasswordService.class); + List userPasswordHistoryLimit = sysUserPasswordService.getUserPasswordHistoryLimit(userId, passwordNotAllowContainsHistoryCountInt); + if(ObjectUtil.isNotEmpty(userPasswordHistoryLimit)){ + if(userPasswordHistoryLimit.contains(CommonCryptogramUtil.doHashValue(newPassword))) { + throw new CommonException("密码不可包含历史密码"); + } + } + } + } + } + } + + /** + * 判断当前用户密码是否过期 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static boolean isUserPasswordExpired(String userId) { + // 先判断是否系统默认密码 + SysUserService sysUserService = SpringUtil.getBean(SysUserService.class); + SysUser sysUser = sysUserService.queryEntity(userId); + String defaultPassword = getDefaultPassword(); + // 若是,则认为已过期,需要修改 + if(CommonCryptogramUtil.doHashValue(defaultPassword).equals(sysUser.getPassword())){ + return true; + } + SysUserExtService sysUserExtService = SpringUtil.getBean(SysUserExtService.class); + // 获取用户扩展信息 + SysUserExt sysUserExt = sysUserExtService.getOne(new LambdaQueryWrapper().eq(SysUserExt::getUserId, userId)); + if(ObjectUtil.isEmpty(sysUserExt)){ + // 无扩展信息的,直接认定为密码过期 + return true; + } else { + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取密码有效期天数 + String passwordExpiredDays = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_B_KEY); + if(ObjectUtil.isEmpty(passwordExpiredDays)){ + throw new CommonException("请联系管理员配置密码有效期天数"); + } else { + // 判断上次密码修改时间距今天的天数 + long betweenDays = DateUtil.between(sysUserExt.getPasswordUpdateTime(), DateTime.now(), DateUnit.DAY, false); + // 如果距离今天已经超过了系统配置的有效期,则认为已过期 + return betweenDays >= Convert.toInt(passwordExpiredDays); + } + } + } + + /** + * 获取今日需要提醒密码到期的用户集合 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + public static List thisDayPasswordExpiredNeedNoticeUserIdList() { + List resultUserList = new ArrayList<>(); + DevConfigApi devConfigApi = SpringUtil.getBean(DevConfigApi.class); + // 获取密码有效期天数 + String passwordExpiredDays = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_B_KEY); + // 密码有效期配置如果不为空 + if(ObjectUtil.isNotEmpty(passwordExpiredDays)){ + // 获取密码过期前提醒天数 + String passwordExpiredNoticeDays = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_B_KEY); + // 密码过期前提醒天数如果不为空 + if(ObjectUtil.isNotEmpty(passwordExpiredDays)){ + // 获取密码修改日期距离提醒日的天数N + int noticeOffsetDays = Convert.toInt(passwordExpiredDays) - Convert.toInt(passwordExpiredNoticeDays); + // 提前提醒天数必须大于过期天数 + if(noticeOffsetDays > 0) { + // 今日需要提醒的,即密码修改日期为N天前的 + DateTime passWordUpdateTime = DateUtil.offsetDay(DateTime.now(), -noticeOffsetDays); + // 获取当天的开始时间 + DateTime beginDay = DateUtil.beginOfDay(passWordUpdateTime); + // 获取当天的结束时间 + DateTime endDay = DateUtil.endOfDay(passWordUpdateTime); + // 获取SysUserExtService + SysUserExtService sysUserExtService = SpringUtil.getBean(SysUserExtService.class); + // 查询密码修改日期在该范围内的(无修改密码历史(即扩展信息为空)的无需提醒,会强制修改密码) + List userIdList = sysUserExtService.list(new LambdaQueryWrapper() + .between(SysUserExt::getPasswordUpdateTime,beginDay, endDay)).stream() + .map(SysUserExt::getUserId).collect(Collectors.toList()); + if(ObjectUtil.isNotEmpty(userIdList)){ + // 获取SysUserXService + SysUserService sysUserService = SpringUtil.getBean(SysUserService.class); + resultUserList = sysUserService.listByIds(userIdList); + } + } + } + } + return resultUserList; + } + + /** + * 判断字符串是否存在N个连续相同的字符 + * + * @author xuyuxiang + * @date 2025/3/21 19:08 + **/ + private static boolean hasConsecutiveChars(String str, int n) { + // 处理无效输入:字符串为空、n非正、或字符串长度不足 + if (str == null || n <= 0 || str.length() < n) { + return false; + } + // 特殊情况:n=1时只要字符串非空即存在连续1个字符 + if (n == 1) { + return true; + } + + int maxStartIndex = str.length() - n; + for (int i = 0; i <= maxStartIndex; i++) { + char currentChar = str.charAt(i); + boolean isConsecutive = true; + // 检查后续n-1个字符是否相同 + for (int j = 1; j < n; j++) { + if (str.charAt(i + j) != currentChar) { + isConsecutive = false; + break; + } + } + if (isConsecutive) { + return true; + } + } + return false; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/controller/SysGroupController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/controller/SysGroupController.java index ab1411e6..0291948d 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/controller/SysGroupController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/controller/SysGroupController.java @@ -14,8 +14,11 @@ package vip.xiaonuo.sys.modular.group.controller; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -26,9 +29,6 @@ import vip.xiaonuo.common.pojo.CommonResult; import vip.xiaonuo.sys.modular.group.entity.SysGroup; import vip.xiaonuo.sys.modular.group.param.*; import vip.xiaonuo.sys.modular.group.service.SysGroupService; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; import vip.xiaonuo.sys.modular.user.entity.SysUser; import java.util.List; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/entity/SysGroup.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/entity/SysGroup.java index 60bd0a90..87537a5d 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/entity/SysGroup.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/entity/SysGroup.java @@ -12,7 +12,8 @@ */ package vip.xiaonuo.sys.modular.group.entity; -import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/mapper/mapping/SysGroupMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/mapper/mapping/SysGroupMapper.xml index 4534cb42..9d73ad02 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/mapper/mapping/SysGroupMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/mapper/mapping/SysGroupMapper.xml @@ -2,4 +2,4 @@ - \ No newline at end of file + diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupAddParam.java index 354a8ab9..1a2eb1d0 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupAddParam.java @@ -13,10 +13,10 @@ package vip.xiaonuo.sys.modular.group.param; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.Setter; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; /** * 用户组添加参数 diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupEditParam.java index efdc7bdd..95bb1d85 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupEditParam.java @@ -13,10 +13,10 @@ package vip.xiaonuo.sys.modular.group.param; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.Setter; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; /** * 用户组编辑参数 diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupIdParam.java index 1ffbcc69..ac45b94b 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/param/SysGroupIdParam.java @@ -13,9 +13,9 @@ package vip.xiaonuo.sys.modular.group.param; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; import lombok.Setter; -import jakarta.validation.constraints.NotBlank; /** * 用户组Id参数 diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/provider/SysGroupApiProvider.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/provider/SysGroupApiProvider.java index 7cfaed6b..7e4384ea 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/provider/SysGroupApiProvider.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/provider/SysGroupApiProvider.java @@ -22,6 +22,7 @@ import vip.xiaonuo.sys.modular.group.param.SysGroupGrantUserParam; import vip.xiaonuo.sys.modular.group.param.SysGroupIdParam; import vip.xiaonuo.sys.modular.group.param.SysGroupSelectorParam; import vip.xiaonuo.sys.modular.group.service.SysGroupService; + import java.util.List; /** diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/service/impl/SysGroupServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/service/impl/SysGroupServiceImpl.java index 43194d38..cbdb5d8f 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/service/impl/SysGroupServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/group/service/impl/SysGroupServiceImpl.java @@ -39,6 +39,7 @@ import vip.xiaonuo.sys.modular.relation.entity.SysRelation; import vip.xiaonuo.sys.modular.relation.enums.SysRelationCategoryEnum; import vip.xiaonuo.sys.modular.relation.service.SysRelationService; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import vip.xiaonuo.sys.modular.user.enums.SysUserStatusEnum; import vip.xiaonuo.sys.modular.user.service.SysUserService; import java.util.List; @@ -131,9 +132,11 @@ public class SysGroupServiceImpl extends ServiceImpl i @Override public Page userSelector(SysGroupSelectorUserParam sysGroupSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + // 只查询状态为正常的 + queryWrapper.lambda().eq(SysUser::getUserStatus, SysUserStatusEnum.ENABLE.getValue()); // 只查询部分字段 - lambdaQueryWrapper.select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, + queryWrapper.lambda().select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, SysUser::getName, SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate); // 如果查询条件为空,则直接查询 if(ObjectUtil.isAllEmpty(sysGroupSelectorUserParam.getOrgId(), sysGroupSelectorUserParam.getSearchKey())) { @@ -144,16 +147,16 @@ public class SysGroupServiceImpl extends ServiceImpl i List childOrgIdList = CollStreamUtil.toList(sysOrgService.getChildListById(sysOrgService .getAllOrgList(), sysGroupSelectorUserParam.getOrgId(), true), SysOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(SysUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(SysUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if (ObjectUtil.isNotEmpty(sysGroupSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(SysUser::getName, sysGroupSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(SysUser::getName, sysGroupSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysUser::getSortCode); - return sysUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysUser::getSortCode); + return sysUserService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } @@ -174,16 +177,16 @@ public class SysGroupServiceImpl extends ServiceImpl i @Override public Page groupSelector(SysGroupSelectorParam sysGroupSelectorParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 只查询部分字段,排掉extJson - lambdaQueryWrapper.select(SysGroup::getId, SysGroup::getName, SysGroup::getSortCode, SysGroup::getRemark); - lambdaQueryWrapper.orderByAsc(SysGroup::getSortCode); + queryWrapper.lambda().select(SysGroup::getId, SysGroup::getName, SysGroup::getSortCode, SysGroup::getRemark); + queryWrapper.lambda().orderByAsc(SysGroup::getSortCode); // 如果查询条件为空,则直接查询 if (!ObjectUtil.isAllEmpty(sysGroupSelectorParam.getSearchKey())) { if (ObjectUtil.isNotEmpty(sysGroupSelectorParam.getSearchKey())) { - lambdaQueryWrapper.like(SysGroup::getName, sysGroupSelectorParam.getSearchKey()); + queryWrapper.lambda().like(SysGroup::getName, sysGroupSelectorParam.getSearchKey()); } } - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/controller/SysIndexController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/controller/SysIndexController.java index c020405f..530b58ec 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/controller/SysIndexController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/controller/SysIndexController.java @@ -12,11 +12,11 @@ */ package vip.xiaonuo.sys.modular.index.controller; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +30,7 @@ import vip.xiaonuo.sys.modular.index.param.*; import vip.xiaonuo.sys.modular.index.result.*; import vip.xiaonuo.sys.modular.index.service.SysIndexService; +import javax.validation.Valid; import java.util.List; /** @@ -53,6 +54,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 1) @Operation(summary = "添加日程") @CommonLog("添加日程") @PostMapping("/sys/index/schedule/add") @@ -67,6 +69,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "删除日程") @CommonLog("删除日程") @PostMapping("/sys/index/schedule/deleteSchedule") @@ -82,6 +85,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 3) @Operation(summary = "获取日程列表") @GetMapping("/sys/index/schedule/list") public CommonResult> scheduleList(@Valid SysIndexScheduleListParam sysIndexScheduleListParam) { @@ -94,6 +98,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "获取当前用户站内信列表") @GetMapping("/sys/index/message/list") public CommonResult> messageList(SysIndexMessageListParam sysIndexMessageListParam) { @@ -106,6 +111,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取站内信详情") @GetMapping("/sys/index/message/detail") public CommonResult messageDetail(@Valid SysIndexMessageIdParam sysIndexMessageIdParam) { @@ -118,6 +124,7 @@ public class SysIndexController { * @author diantu * @date 2023/7/10 */ + @ApiOperationSupport(order = 6) @Operation(summary = "站内信全部标记已读") @PostMapping("/sys/index/message/allMessageMarkRead") public CommonResult allMessageMarkRead() { @@ -131,6 +138,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取当前用户访问日志列表") @GetMapping("/sys/index/visLog/list") public CommonResult> visLogList() { @@ -143,6 +151,7 @@ public class SysIndexController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 8) @Operation(summary = "获取当前用户操作日志列表") @GetMapping("/sys/index/opLog/list") public CommonResult> opLogList() { @@ -155,6 +164,7 @@ public class SysIndexController { * @author diantu * @date 2023/7/10 **/ + @ApiOperationSupport(order = 9) @Operation(summary = "创建sse连接") @GetMapping("/dev/message/createSseConnect") public SseEmitter createSseConnect(String clientId){ @@ -167,6 +177,7 @@ public class SysIndexController { * @author xuyuxiang、yubaoshan * @date 2024/7/18 17:35 */ + @ApiOperationSupport(order = 10) @Operation(summary = "获取基础系统业务数据") @GetMapping("/sys/index/bizDataCount") public CommonResult getBizDataCount() { @@ -179,6 +190,7 @@ public class SysIndexController { * @author yubaoshan * @date 2024/7/18 17:35 */ + @ApiOperationSupport(order = 11) @Operation(summary = "获取运维一览数据") @GetMapping("/sys/index/opDataCount") public CommonResult getOpDataCount() { @@ -191,6 +203,7 @@ public class SysIndexController { * @author yubaoshan * @date 2024/7/18 17:35 */ + @ApiOperationSupport(order = 12) @Operation(summary = "获取基础工具数据") @GetMapping("/sys/index/toolDataCount") public CommonResult getToolDataCount() { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexMessageIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexMessageIdParam.java index e2f30f47..3e7caaa3 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexMessageIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexMessageIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysIndexMessageIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleAddParam.java index e09f2ae8..5c476ff7 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleAddParam.java @@ -28,17 +28,17 @@ import lombok.Setter; public class SysIndexScheduleAddParam { /** 日程日期 */ - @Schema(description = "日程日期", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "日程日期") @NotBlank(message = "scheduleDate不能为空") private String scheduleDate; /** 日程时间 */ - @Schema(description = "日程时间", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "日程时间") @NotBlank(message = "scheduleTime不能为空") private String scheduleTime; /** 日程内容 */ - @Schema(description = "日程内容", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "日程内容") @NotBlank(message = "scheduleContent不能为空") private String scheduleContent; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleIdParam.java index 90155037..3be14d26 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysIndexScheduleIdParam { /** 日程id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleListParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleListParam.java index bae2da15..02fc2568 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleListParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/param/SysIndexScheduleListParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysIndexScheduleListParam { /** 日程日期 */ - @Schema(description = "日程日期", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "日程日期") @NotBlank(message = "scheduleDate不能为空") private String scheduleDate; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageDetailResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageDetailResult.java index 7f82a14d..50b1f87a 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageDetailResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageDetailResult.java @@ -29,7 +29,7 @@ import java.util.List; public class SysIndexMessageDetailResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 分类 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageListResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageListResult.java index 8da706f8..38f5a4a4 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageListResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexMessageListResult.java @@ -29,7 +29,7 @@ import java.util.Date; public class SysIndexMessageListResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 分类 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexOpLogListResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexOpLogListResult.java index 40609963..da0e37e0 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexOpLogListResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexOpLogListResult.java @@ -31,7 +31,7 @@ import java.util.Date; public class SysIndexOpLogListResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 日志分类 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexScheduleListResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexScheduleListResult.java index 2f92c306..a5fee423 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexScheduleListResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexScheduleListResult.java @@ -27,7 +27,7 @@ import lombok.Setter; public class SysIndexScheduleListResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 用户id */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexVisLogListResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexVisLogListResult.java index 411ecc7c..db6d1537 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexVisLogListResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/index/result/SysIndexVisLogListResult.java @@ -31,7 +31,7 @@ import java.util.Date; public class SysIndexVisLogListResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 日志分类 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java index cf245c53..8e497606 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/controller/SysOrgController.java @@ -14,10 +14,11 @@ package vip.xiaonuo.sys.modular.org.controller; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -27,10 +28,12 @@ import org.springframework.web.bind.annotation.RestController; import vip.xiaonuo.common.annotation.CommonLog; import vip.xiaonuo.common.pojo.CommonResult; import vip.xiaonuo.sys.modular.org.entity.SysOrg; +import vip.xiaonuo.sys.modular.org.enums.SysOrgSourceFromTypeEnum; import vip.xiaonuo.sys.modular.org.param.*; import vip.xiaonuo.sys.modular.org.service.SysOrgService; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import javax.validation.Valid; import java.util.List; /** @@ -40,6 +43,7 @@ import java.util.List; * @date 2022/4/24 19:55 */ @Tag(name = "组织控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 1) @RestController @Validated public class SysOrgController { @@ -53,6 +57,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取组织分页") @GetMapping("/sys/org/page") public CommonResult> page(SysOrgPageParam sysOrgPageParam) { @@ -65,6 +70,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取组织树") @GetMapping("/sys/org/tree") public CommonResult>> tree() { @@ -77,11 +83,12 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "添加组织") @CommonLog("添加组织") @PostMapping("/sys/org/add") public CommonResult add(@RequestBody @Valid SysOrgAddParam sysOrgAddParam) { - sysOrgService.add(sysOrgAddParam); + sysOrgService.add(sysOrgAddParam, SysOrgSourceFromTypeEnum.SYSTEM_ADD.getValue()); return CommonResult.ok(); } @@ -91,6 +98,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "编辑组织") @CommonLog("编辑组织") @PostMapping("/sys/org/edit") @@ -105,6 +113,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "删除组织") @CommonLog("删除组织") @PostMapping("/sys/org/delete") @@ -120,6 +129,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取组织详情") @GetMapping("/sys/org/detail") public CommonResult detail(@Valid SysOrgIdParam sysOrgIdParam) { @@ -134,6 +144,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取组织树选择器") @GetMapping("/sys/org/orgTreeSelector") public CommonResult>> orgTreeSelector() { @@ -146,6 +157,7 @@ public class SysOrgController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 8) @Operation(summary = "获取用户选择器") @GetMapping("/sys/org/userSelector") public CommonResult> userSelector(SysOrgSelectorUserParam sysOrgSelectorUserParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrg.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrg.java index 2e3a43c4..a9e4ae44 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrg.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrg.java @@ -44,7 +44,7 @@ public class SysOrg extends CommonEntity { /** 主管id */ @Schema(description = "主管id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.SIMPLE, target = SysUser.class, fields = "name", alias = "director", ref = "directorName") private String directorId; @@ -66,6 +66,6 @@ public class SysOrg extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrgExt.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrgExt.java new file mode 100644 index 00000000..cc7105b3 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/entity/SysOrgExt.java @@ -0,0 +1,46 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.org.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +/** + * 组织扩展实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("SYS_ORG_EXT") +public class SysOrgExt extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 组织id */ + @Schema(description = "组织id") + private String orgId; + + /** 来源类别 */ + @Schema(description = "来源类别") + private String sourceFromType; + +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/enums/SysOrgSourceFromTypeEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/enums/SysOrgSourceFromTypeEnum.java new file mode 100644 index 00000000..c6cc2ad5 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/enums/SysOrgSourceFromTypeEnum.java @@ -0,0 +1,37 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.org.enums; + +import lombok.Getter; + +/** + * 组织来源类型枚举 + * + * @author xuyuxiang + * @date 2022/4/21 19:56 + **/ +@Getter +public enum SysOrgSourceFromTypeEnum { + + /** 系统自建 */ + SYSTEM_ADD("SYSTEM_ADD"), + + /** 身份源 */ + ID_SOURCE("ID_SOURCE"); + + private final String value; + + SysOrgSourceFromTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgExtMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgExtMapper.java new file mode 100644 index 00000000..063d717c --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgExtMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.org.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.sys.modular.org.entity.SysOrgExt; + +/** + * 组织扩展Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface SysOrgExtMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgMapper.java index d2a67297..e48863f4 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/SysOrgMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.org.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.org.entity.SysOrg; /** @@ -25,13 +22,4 @@ import vip.xiaonuo.sys.modular.org.entity.SysOrg; * @date 2022/4/21 18:37 **/ public interface SysOrgMapper extends BaseMapper { - - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgExtMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgExtMapper.xml new file mode 100644 index 00000000..ae4fc729 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgExtMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgMapper.xml index b76a4280..e9f676e1 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/mapper/mapping/SysOrgMapper.xml @@ -2,7 +2,4 @@ - - DELETE FROM SYS_ORG ${ew.customSqlSegment} - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgAddParam.java index 44b24ec8..28da9195 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgAddParam.java @@ -29,22 +29,22 @@ import lombok.Setter; public class SysOrgAddParam { /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgEditParam.java index e1dba4a9..7fcb6cd1 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgEditParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class SysOrgEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgIdParam.java index cfb908a9..736d0001 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysOrgIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgExtService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgExtService.java new file mode 100644 index 00000000..c50c705f --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgExtService.java @@ -0,0 +1,33 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.org.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.sys.modular.org.entity.SysOrgExt; + +/** + * 组织扩展Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface SysOrgExtService extends IService { + + /** + * 插入扩展信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void createExtInfo(String orgId, String sourceFromType); +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java index 25a2d03c..fb62b65c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/SysOrgService.java @@ -51,7 +51,7 @@ public interface SysOrgService extends IService { * @author xuyuxiang * @date 2022/4/24 20:48 */ - void add(SysOrgAddParam sysOrgAddParam); + void add(SysOrgAddParam sysOrgAddParam, String sourceFromType); /** * 编辑组织 diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgExtServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgExtServiceImpl.java new file mode 100644 index 00000000..71cf8721 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgExtServiceImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.org.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.sys.modular.org.entity.SysOrgExt; +import vip.xiaonuo.sys.modular.org.mapper.SysOrgExtMapper; +import vip.xiaonuo.sys.modular.org.service.SysOrgExtService; + +/** + * 组织扩展Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class SysOrgExtServiceImpl extends ServiceImpl implements SysOrgExtService { + + @Override + public void createExtInfo(String orgId, String sourceFromType) { + SysOrgExt sysOrgExt = new SysOrgExt(); + sysOrgExt.setOrgId(orgId); + sysOrgExt.setSourceFromType(sourceFromType); + this.save(sysOrgExt); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java index 752868d5..58a7eea4 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java @@ -30,7 +30,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import vip.xiaonuo.common.cache.CommonCacheOperator; import vip.xiaonuo.common.enums.CommonSortOrderEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.listener.CommonDataChangeEventCenter; @@ -38,14 +37,17 @@ import vip.xiaonuo.common.page.CommonPageRequest; import vip.xiaonuo.sys.core.enums.SysDataTypeEnum; import vip.xiaonuo.sys.modular.org.entity.SysOrg; import vip.xiaonuo.sys.modular.org.enums.SysOrgCategoryEnum; +import vip.xiaonuo.sys.modular.org.enums.SysOrgSourceFromTypeEnum; import vip.xiaonuo.sys.modular.org.mapper.SysOrgMapper; import vip.xiaonuo.sys.modular.org.param.*; +import vip.xiaonuo.sys.modular.org.service.SysOrgExtService; import vip.xiaonuo.sys.modular.org.service.SysOrgService; import vip.xiaonuo.sys.modular.position.entity.SysPosition; import vip.xiaonuo.sys.modular.position.service.SysPositionService; import vip.xiaonuo.sys.modular.role.entity.SysRole; import vip.xiaonuo.sys.modular.role.service.SysRoleService; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import vip.xiaonuo.sys.modular.user.enums.SysUserStatusEnum; import vip.xiaonuo.sys.modular.user.service.SysUserService; import java.util.Iterator; @@ -61,10 +63,8 @@ import java.util.stream.Collectors; @Service public class SysOrgServiceImpl extends ServiceImpl implements SysOrgService { - public static final String ORG_CACHE_ALL_KEY = "sys-org:all"; - @Resource - private CommonCacheOperator commonCacheOperator; + private SysOrgExtService sysOrgExtService; @Resource private SysRoleService sysRoleService; @@ -109,7 +109,7 @@ public class SysOrgServiceImpl extends ServiceImpl impleme @Transactional(rollbackFor = Exception.class) @Override - public void add(SysOrgAddParam sysOrgAddParam) { + public void add(SysOrgAddParam sysOrgAddParam, String sourceFromType) { SysOrgCategoryEnum.validate(sysOrgAddParam.getCategory()); SysOrg sysOrg = BeanUtil.toBean(sysOrgAddParam, SysOrg.class); // 重复名称 @@ -119,8 +119,10 @@ public class SysOrgServiceImpl extends ServiceImpl impleme throw new CommonException("存在重复的同级组织,名称为:{}", sysOrg.getName()); } sysOrg.setCode(RandomUtil.randomString(10)); + // 保存组织 this.save(sysOrg); - + // 插入扩展信息 + sysOrgExtService.createExtInfo(sysOrg.getId(), sourceFromType); // 发布增加事件 CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(sysOrg)); } @@ -142,8 +144,8 @@ public class SysOrgServiceImpl extends ServiceImpl impleme if(errorLevel) { throw new CommonException("不可选择上级组织:{}", this.getById(originDataList, sysOrg.getParentId()).getName()); } + // 更新组织 this.updateById(sysOrg); - // 发布更新事件 CommonDataChangeEventCenter.doUpdateWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(sysOrg)); } @@ -171,7 +173,7 @@ public class SysOrgServiceImpl extends ServiceImpl impleme List positionOrgIdList = CollectionUtil.newArrayList(); positionJsonList.forEach(positionJson -> JSONUtil.toList(JSONUtil.parseArray(positionJson), JSONObject.class) .forEach(jsonObject -> positionOrgIdList.add(jsonObject.getStr("orgId")))); - boolean hasPositionUser = CollectionUtil.intersectionDistinct(toDeleteOrgIdList, CollectionUtil.removeNull(positionOrgIdList)).size() > 0; + boolean hasPositionUser = !CollectionUtil.intersectionDistinct(toDeleteOrgIdList, CollectionUtil.removeNull(positionOrgIdList)).isEmpty(); if(hasPositionUser) { throw new CommonException("请先删除组织下的用户"); } @@ -210,43 +212,33 @@ public class SysOrgServiceImpl extends ServiceImpl impleme @Override public List getAllOrgList() { - // 从缓存中取 - Object cacheValue = commonCacheOperator.get(ORG_CACHE_ALL_KEY); - if(ObjectUtil.isNotEmpty(cacheValue)) { - return JSONUtil.toList(JSONUtil.parseArray(cacheValue), SysOrg.class); - } - List orgList = this.list(new LambdaQueryWrapper().orderByAsc(SysOrg::getSortCode)); - if(ObjectUtil.isNotEmpty(orgList)) { - // 更新到缓存 - commonCacheOperator.put(ORG_CACHE_ALL_KEY, JSONUtil.toJsonStr(orgList)); - } - return orgList; + return this.list(new LambdaQueryWrapper().orderByAsc(SysOrg::getSortCode)); } @Override public String getOrgIdByOrgFullNameWithCreate(String orgFullName) { - List cachedAllOrgList = this.getAllOrgList(); - List> treeList = TreeUtil.build(cachedAllOrgList.stream().map(sysOrg -> + List allOrgList = this.getAllOrgList(); + List> treeList = TreeUtil.build(allOrgList.stream().map(sysOrg -> new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(), sysOrg.getName(), sysOrg.getSortCode())) .collect(Collectors.toList()), "0"); - return findOrgIdByOrgName("0", StrUtil.split(orgFullName, StrUtil.DASHED).iterator(), cachedAllOrgList, treeList); + return findOrgIdByOrgName("0", StrUtil.split(orgFullName, StrUtil.DASHED).iterator(), allOrgList, treeList); } - public String findOrgIdByOrgName(String parentId, Iterator iterator, List cachedAllOrgList, List> treeList) { + public String findOrgIdByOrgName(String parentId, Iterator iterator, List allOrgList, List> treeList) { String orgName = iterator.next(); if(ObjectUtil.isNotEmpty(treeList)) { List> findList = treeList.stream().filter(tree -> tree.getName().equals(orgName)).collect(Collectors.toList()); if(ObjectUtil.isNotEmpty(findList)) { if(iterator.hasNext()) { - return findOrgIdByOrgName(findList.get(0).getId(), iterator, cachedAllOrgList, findList.get(0).getChildren()); + return findOrgIdByOrgName(findList.get(0).getId(), iterator, allOrgList, findList.get(0).getChildren()); } else { return findList.get(0).getId(); } } } - String orgId = this.doCreateOrg(parentId, orgName, cachedAllOrgList); + String orgId = this.doCreateOrg(parentId, orgName, allOrgList); if(iterator.hasNext()) { - return findOrgIdByOrgName(orgId, iterator, cachedAllOrgList, CollectionUtil.newArrayList()); + return findOrgIdByOrgName(orgId, iterator, allOrgList, CollectionUtil.newArrayList()); } else { return orgId; } @@ -258,7 +250,7 @@ public class SysOrgServiceImpl extends ServiceImpl impleme * @author xuyuxiang * @date 2023/3/8 9:38 **/ - public String doCreateOrg(String parentId, String orgName, List cachedAllOrgList) { + public String doCreateOrg(String parentId, String orgName, List allOrgList) { //创建该组织 SysOrg sysOrg = new SysOrg(); sysOrg.setName(orgName); @@ -266,13 +258,12 @@ public class SysOrgServiceImpl extends ServiceImpl impleme sysOrg.setParentId(parentId); sysOrg.setCategory("0".equals(parentId)?SysOrgCategoryEnum.COMPANY.getValue():SysOrgCategoryEnum.DEPT.getValue()); sysOrg.setSortCode(99); + // 保存组织 this.save(sysOrg); + // 插入扩展信息 + sysOrgExtService.createExtInfo(sysOrg.getId(), SysOrgSourceFromTypeEnum.SYSTEM_ADD.getValue()); // 发布增加事件 CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ORG.getValue(), JSONUtil.createArray().put(sysOrg)); - // 将该组织加入缓存 - cachedAllOrgList.add(sysOrg); - // 更新缓存 - commonCacheOperator.put(ORG_CACHE_ALL_KEY, cachedAllOrgList); return sysOrg.getId(); } @@ -289,25 +280,27 @@ public class SysOrgServiceImpl extends ServiceImpl impleme @Override public Page orgListSelector(SysOrgSelectorOrgListParam sysOrgSelectorOrgListParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - lambdaQueryWrapper.select(SysOrg::getId, SysOrg::getParentId, SysOrg::getName, + queryWrapper.lambda().select(SysOrg::getId, SysOrg::getParentId, SysOrg::getName, SysOrg::getCategory, SysOrg::getSortCode); if(ObjectUtil.isNotEmpty(sysOrgSelectorOrgListParam.getParentId())) { - lambdaQueryWrapper.eq(SysOrg::getParentId, sysOrgSelectorOrgListParam.getParentId()); + queryWrapper.lambda().eq(SysOrg::getParentId, sysOrgSelectorOrgListParam.getParentId()); } if(ObjectUtil.isNotEmpty(sysOrgSelectorOrgListParam.getSearchKey())) { - lambdaQueryWrapper.like(SysOrg::getName, sysOrgSelectorOrgListParam.getSearchKey()); + queryWrapper.lambda().like(SysOrg::getName, sysOrgSelectorOrgListParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysOrg::getSortCode); - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysOrg::getSortCode); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @Override public Page userSelector(SysOrgSelectorUserParam sysOrgSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + // 只查询状态为正常的 + queryWrapper.lambda().eq(SysUser::getUserStatus, SysUserStatusEnum.ENABLE.getValue()); // 只查询部分字段 - lambdaQueryWrapper.select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, + queryWrapper.lambda().select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, SysUser::getName, SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate); // 如果查询条件为空,则直接查询 if(ObjectUtil.isAllEmpty(sysOrgSelectorUserParam.getOrgId(), sysOrgSelectorUserParam.getSearchKey())) { @@ -318,16 +311,16 @@ public class SysOrgServiceImpl extends ServiceImpl impleme List childOrgIdList = CollStreamUtil.toList(this.getChildListById(this .getAllOrgList(), sysOrgSelectorUserParam.getOrgId(), true), SysOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(SysUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(SysUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if(ObjectUtil.isNotEmpty(sysOrgSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(SysUser::getName, sysOrgSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(SysUser::getName, sysOrgSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysUser::getSortCode); - return sysUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysUser::getSortCode); + return sysUserService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/controller/SysPositionController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/controller/SysPositionController.java index 011a8afc..87996e55 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/controller/SysPositionController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/controller/SysPositionController.java @@ -14,10 +14,11 @@ package vip.xiaonuo.sys.modular.position.controller; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +31,7 @@ import vip.xiaonuo.sys.modular.position.entity.SysPosition; import vip.xiaonuo.sys.modular.position.param.*; import vip.xiaonuo.sys.modular.position.service.SysPositionService; +import javax.validation.Valid; import java.util.List; /** @@ -39,6 +41,7 @@ import java.util.List; * @date 2022/4/25 20:40 */ @Tag(name = "职位控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 2) @RestController @Validated public class SysPositionController { @@ -52,6 +55,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取职位分页") @GetMapping("/sys/position/page") public CommonResult> page(SysPositionPageParam sysPositionPageParam) { @@ -64,6 +68,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加职位") @CommonLog("添加职位") @PostMapping("/sys/position/add") @@ -78,6 +83,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑职位") @CommonLog("编辑职位") @PostMapping("/sys/position/edit") @@ -92,6 +98,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除职位") @CommonLog("删除职位") @PostMapping("/sys/position/delete") @@ -107,6 +114,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取职位详情") @GetMapping("/sys/position/detail") public CommonResult detail(@Valid SysPositionIdParam sysPositionIdParam) { @@ -121,6 +129,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取组织树选择器") @GetMapping("/sys/position/orgTreeSelector") public CommonResult>> orgTreeSelector() { @@ -133,6 +142,7 @@ public class SysPositionController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取职位选择器") @GetMapping("/sys/position/positionSelector") public CommonResult> positionSelector(SysPositionSelectorPositionParam sysPositionSelectorPositionParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/entity/SysPosition.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/entity/SysPosition.java index 1ca83e15..712336f8 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/entity/SysPosition.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/entity/SysPosition.java @@ -57,6 +57,6 @@ public class SysPosition extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/enums/SysPositionCategoryEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/enums/SysPositionCategoryEnum.java index e3d40877..78d3c6f0 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/enums/SysPositionCategoryEnum.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/enums/SysPositionCategoryEnum.java @@ -13,7 +13,6 @@ package vip.xiaonuo.sys.modular.position.enums; import lombok.Getter; -import vip.xiaonuo.common.exception.CommonException; /** * 职位分类枚举 @@ -38,11 +37,4 @@ public enum SysPositionCategoryEnum { SysPositionCategoryEnum(String value) { this.value = value; } - - public static void validate(String value) { - boolean flag = HIGH.getValue().equals(value) || MIDDLE.getValue().equals(value) || LOW.getValue().equals(value); - if(!flag) { - throw new CommonException("不支持的职位分类:{}", value); - } - } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/SysPositionMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/SysPositionMapper.java index 68b1b3cc..b186db33 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/SysPositionMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/SysPositionMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.position.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.position.entity.SysPosition; /** @@ -25,13 +22,4 @@ import vip.xiaonuo.sys.modular.position.entity.SysPosition; * @date 2022/4/21 18:37 **/ public interface SysPositionMapper extends BaseMapper { - - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/mapping/SysPositionMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/mapping/SysPositionMapper.xml index 6b68aa65..32780b81 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/mapping/SysPositionMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/mapper/mapping/SysPositionMapper.xml @@ -2,7 +2,4 @@ - - DELETE FROM SYS_POSITION ${ew.customSqlSegment} - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionAddParam.java index 185a7e33..86ec4788 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionAddParam.java @@ -29,22 +29,22 @@ import lombok.Setter; public class SysPositionAddParam { /** 组织id */ - @Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "组织id") @NotBlank(message = "orgId不能为空") private String orgId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionEditParam.java index 3a3901b9..237233a6 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionEditParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class SysPositionEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 组织id */ - @Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "组织id") @NotBlank(message = "orgId不能为空") private String orgId; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionIdParam.java index 8d41825f..9b0673e3 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/param/SysPositionIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysPositionIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/provider/SysPositionApiProvider.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/provider/SysPositionApiProvider.java index d9ac37b7..f1909a53 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/provider/SysPositionApiProvider.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/provider/SysPositionApiProvider.java @@ -40,7 +40,7 @@ public class SysPositionApiProvider implements SysPositionApi { @SuppressWarnings("ALL") @Override - public Page positionSelector(String orgId, String searchKey) { + public Page positionSelector(String orgId, String searchKey, Integer current, Integer size) { SysPositionSelectorPositionParam sysPositionSelectorPositionParam = new SysPositionSelectorPositionParam(); sysPositionSelectorPositionParam.setOrgId(orgId); sysPositionSelectorPositionParam.setSearchKey(searchKey); diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java index 5d73410e..2059b746 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/position/service/impl/SysPositionServiceImpl.java @@ -91,7 +91,6 @@ public class SysPositionServiceImpl extends ServiceImpl().eq(SysPosition::getOrgId, sysPosition.getOrgId()) .eq(SysPosition::getName, sysPosition.getName())) > 0; @@ -108,7 +107,6 @@ public class SysPositionServiceImpl extends ServiceImpl().eq(SysPosition::getOrgId, sysPosition.getOrgId()) @@ -182,7 +180,7 @@ public class SysPositionServiceImpl extends ServiceImpl positionSelector(SysPositionSelectorPositionParam sysPositionSelectorPositionParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - lambdaQueryWrapper.select(SysPosition::getId, SysPosition::getOrgId, SysPosition::getName, + queryWrapper.lambda().select(SysPosition::getId, SysPosition::getOrgId, SysPosition::getName, SysPosition::getCategory, SysPosition::getSortCode); if(ObjectUtil.isNotEmpty(sysPositionSelectorPositionParam.getOrgId())) { - lambdaQueryWrapper.eq(SysPosition::getOrgId, sysPositionSelectorPositionParam.getOrgId()); + queryWrapper.lambda().eq(SysPosition::getOrgId, sysPositionSelectorPositionParam.getOrgId()); } if(ObjectUtil.isNotEmpty(sysPositionSelectorPositionParam.getSearchKey())) { - lambdaQueryWrapper.like(SysPosition::getName, sysPositionSelectorPositionParam.getSearchKey()); + queryWrapper.lambda().like(SysPosition::getName, sysPositionSelectorPositionParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysPosition::getSortCode); - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysPosition::getSortCode); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/entity/SysRelation.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/entity/SysRelation.java index 43549e09..188c1095 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/entity/SysRelation.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/entity/SysRelation.java @@ -48,6 +48,6 @@ public class SysRelation{ /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/mapper/mapping/SysRelationMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/mapper/mapping/SysRelationMapper.xml index 74148f75..5309de89 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/mapper/mapping/SysRelationMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/mapper/mapping/SysRelationMapper.xml @@ -2,5 +2,4 @@ - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/service/impl/SysRelationServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/service/impl/SysRelationServiceImpl.java index 69d77731..105eb488 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/service/impl/SysRelationServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/relation/service/impl/SysRelationServiceImpl.java @@ -72,41 +72,49 @@ public class SysRelationServiceImpl extends ServiceImpl targetIdList, String category) { this.saveRelationBatch(objectId, targetIdList, category, null, false); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithAppend(String objectId, List targetIdList, String category, List extJsonList) { this.saveRelationBatch(objectId, targetIdList, category, extJsonList, false); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationWithClear(String objectId, String targetId, String category) { this.saveRelation(objectId, targetId, category, null, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationWithClear(String objectId, String targetId, String category, String extJson) { this.saveRelation(objectId, targetId, category, extJson, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithClear(String objectId, List targetIdList, String category) { this.saveRelationBatch(objectId, targetIdList, category, null, true); } + @Transactional(rollbackFor = Exception.class) @Override public void saveRelationBatchWithClear(String objectId, List targetIdList, String category, List extJsonList) { this.saveRelationBatch(objectId, targetIdList, category, extJsonList, true); diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysButtonController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysButtonController.java index 46545a6c..b2c3971f 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysButtonController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysButtonController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.sys.modular.resource.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.sys.modular.resource.param.button.SysButtonIdParam; import vip.xiaonuo.sys.modular.resource.param.button.SysButtonPageParam; import vip.xiaonuo.sys.modular.resource.service.SysButtonService; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/6/27 13:56 **/ @Tag(name = "按钮控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 3) @RestController @Validated public class SysButtonController { @@ -54,6 +57,7 @@ public class SysButtonController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取按钮分页") @GetMapping("/sys/button/page") public CommonResult> page(SysButtonPageParam sysButtonPageParam) { @@ -66,6 +70,7 @@ public class SysButtonController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加按钮") @CommonLog("添加按钮") @PostMapping("/sys/button/add") @@ -80,6 +85,7 @@ public class SysButtonController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑按钮") @CommonLog("编辑按钮") @PostMapping("/sys/button/edit") @@ -94,6 +100,7 @@ public class SysButtonController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除按钮") @CommonLog("删除按钮") @PostMapping("/sys/button/delete") @@ -108,6 +115,7 @@ public class SysButtonController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取按钮详情") @GetMapping("/sys/button/detail") public CommonResult detail(@Valid SysButtonIdParam sysButtonIdParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysMenuController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysMenuController.java index 3ccd819f..b9184d84 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysMenuController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysMenuController.java @@ -14,10 +14,11 @@ package vip.xiaonuo.sys.modular.resource.controller; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -31,6 +32,7 @@ import vip.xiaonuo.sys.modular.resource.entity.SysModule; import vip.xiaonuo.sys.modular.resource.param.menu.*; import vip.xiaonuo.sys.modular.resource.service.SysMenuService; +import javax.validation.Valid; import java.util.List; /** @@ -40,6 +42,7 @@ import java.util.List; * @date 2022/6/27 14:09 **/ @Tag(name = "菜单控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 5) @RestController @Validated public class SysMenuController { @@ -53,6 +56,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取菜单分页") @GetMapping("/sys/menu/page") public CommonResult> page(SysMenuPageParam sysMenuPageParam) { @@ -65,6 +69,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 2) @Operation(summary = "获取菜单树") @GetMapping("/sys/menu/tree") public CommonResult>> tree(SysMenuTreeParam sysMenuTreeParam) { @@ -77,6 +82,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "添加菜单") @CommonLog("添加菜单") @PostMapping("/sys/menu/add") @@ -91,6 +97,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 4) @Operation(summary = "编辑菜单") @CommonLog("编辑菜单") @PostMapping("/sys/menu/edit") @@ -105,6 +112,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 5) @Operation(summary = "更改菜单所属模块") @CommonLog("更改菜单所属模块") @PostMapping("/sys/menu/changeModule") @@ -119,6 +127,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "删除菜单") @CommonLog("删除菜单") @PostMapping("/sys/menu/delete") @@ -134,6 +143,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "获取菜单详情") @GetMapping("/sys/menu/detail") public CommonResult detail(@Valid SysMenuIdParam sysMenuIdParam) { @@ -148,6 +158,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 8) @Operation(summary = "获取模块选择器") @GetMapping("/sys/menu/moduleSelector") public CommonResult> moduleSelector(SysMenuSelectorModuleParam sysMenuSelectorModuleParam) { @@ -160,6 +171,7 @@ public class SysMenuController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 9) @Operation(summary = "获取菜单树选择器") @GetMapping("/sys/menu/menuTreeSelector") public CommonResult>> menuTreeSelector(SysMenuSelectorMenuParam sysMenuSelectorMenuParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysModuleController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysModuleController.java index d1205b7a..108165d4 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysModuleController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/controller/SysModuleController.java @@ -13,10 +13,11 @@ package vip.xiaonuo.sys.modular.resource.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.sys.modular.resource.param.module.SysModuleIdParam; import vip.xiaonuo.sys.modular.resource.param.module.SysModulePageParam; import vip.xiaonuo.sys.modular.resource.service.SysModuleService; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/6/27 14:12 **/ @Tag(name = "模块控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 6) @RestController @Validated public class SysModuleController { @@ -54,6 +57,7 @@ public class SysModuleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取模块分页") @GetMapping("/sys/module/page") public CommonResult> page(SysModulePageParam sysModulePageParam) { @@ -66,6 +70,7 @@ public class SysModuleController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加模块") @CommonLog("添加模块") @PostMapping("/sys/module/add") @@ -80,6 +85,7 @@ public class SysModuleController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑模块") @CommonLog("编辑模块") @PostMapping("/sys/module/edit") @@ -94,11 +100,12 @@ public class SysModuleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除模块") @CommonLog("删除模块") @PostMapping("/sys/module/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List sysModuleIdParamList) { + List sysModuleIdParamList) { sysModuleService.delete(sysModuleIdParamList); return CommonResult.ok(); } @@ -109,6 +116,7 @@ public class SysModuleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取模块详情") @GetMapping("/sys/module/detail") public CommonResult detail(@Valid SysModuleIdParam sysModuleIdParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysButton.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysButton.java index 62d57a5c..c64de15b 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysButton.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysButton.java @@ -57,6 +57,6 @@ public class SysButton extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java index a229bb66..bccb9c75 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysMenu.java @@ -45,7 +45,7 @@ public class SysMenu extends CommonEntity { /** 别名 */ @Schema(description = "别名") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String name; /** 编码 */ @@ -70,11 +70,11 @@ public class SysMenu extends CommonEntity { /** 组件 */ @Schema(description = "组件") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String component; /** 图标 */ - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Schema(description = "图标") private String icon; @@ -92,6 +92,6 @@ public class SysMenu extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysModule.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysModule.java index f3009018..6730e815 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysModule.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/entity/SysModule.java @@ -61,6 +61,6 @@ public class SysModule extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysButtonMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysButtonMapper.java index a30c6bff..24ed63d1 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysButtonMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysButtonMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.resource.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.resource.entity.SysButton; /** @@ -25,13 +22,4 @@ import vip.xiaonuo.sys.modular.resource.entity.SysButton; * @date 2022/4/21 18:37 **/ public interface SysButtonMapper extends BaseMapper { - - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysMenuMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysMenuMapper.java index c334b404..0191d82c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysMenuMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysMenuMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.resource.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.resource.entity.SysMenu; /** @@ -25,13 +22,4 @@ import vip.xiaonuo.sys.modular.resource.entity.SysMenu; * @date 2022/4/21 18:37 **/ public interface SysMenuMapper extends BaseMapper { - - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysModuleMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysModuleMapper.java index 0c398baf..e5ad36cd 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysModuleMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/SysModuleMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.resource.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.resource.entity.SysModule; /** @@ -25,14 +22,4 @@ import vip.xiaonuo.sys.modular.resource.entity.SysModule; * @date 2022/4/21 18:37 **/ public interface SysModuleMapper extends BaseMapper { - - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); - } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysButtonMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysButtonMapper.xml index a0864ada..14094f59 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysButtonMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysButtonMapper.xml @@ -2,7 +2,4 @@ - - DELETE FROM SYS_RESOURCE ${ew.customSqlSegment} - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysMenuMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysMenuMapper.xml index 56ebe153..afab2463 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysMenuMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysMenuMapper.xml @@ -2,7 +2,4 @@ - - DELETE FROM SYS_RESOURCE ${ew.customSqlSegment} - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysModuleMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysModuleMapper.xml index 06e5d789..1666db84 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysModuleMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/mapper/mapping/SysModuleMapper.xml @@ -2,7 +2,4 @@ - - DELETE FROM SYS_RESOURCE ${ew.customSqlSegment} - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonAddParam.java index af9be7d3..71891b66 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonAddParam.java @@ -29,22 +29,22 @@ import lombok.Setter; public class SysButtonAddParam { /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 标题 */ - @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "标题") @NotBlank(message = "title不能为空") private String title; /** 编码 */ - @Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "编码") @NotBlank(message = "code不能为空") private String code; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonEditParam.java index 7cde31d4..05838ed9 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonEditParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class SysButtonEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 标题 */ - @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "标题") @NotBlank(message = "title不能为空") private String title; /** 编码 */ - @Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "编码") @NotBlank(message = "code不能为空") private String code; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonIdParam.java index d7d1092f..b10de451 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/button/SysButtonIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysButtonIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java index 178938ba..31d9a8ca 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuAddParam.java @@ -29,32 +29,32 @@ import lombok.Setter; public class SysMenuAddParam { /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 标题 */ - @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "标题") @NotBlank(message = "title不能为空") private String title; /** 菜单类型 */ - @Schema(description = "菜单类型", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "菜单类型") @NotBlank(message = "menuType不能为空") private String menuType; /** 模块 */ - @Schema(description = "模块", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "模块") @NotBlank(message = "module不能为空") private String module; /** 路径 */ - @Schema(description = "路径", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "路径") @NotBlank(message = "path不能为空") private String path; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuChangeModuleParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuChangeModuleParam.java index faf98946..488dea39 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuChangeModuleParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuChangeModuleParam.java @@ -28,12 +28,12 @@ import lombok.Setter; public class SysMenuChangeModuleParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 模块 */ - @Schema(description = "module", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "module") @NotBlank(message = "module不能为空") private String module; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java index 87b8c3e4..60256834 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuEditParam.java @@ -29,37 +29,37 @@ import lombok.Setter; public class SysMenuEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 父id */ - @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "父id") @NotBlank(message = "parentId不能为空") private String parentId; /** 标题 */ - @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "标题") @NotBlank(message = "title不能为空") private String title; /** 菜单类型 */ - @Schema(description = "菜单类型", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "菜单类型") @NotBlank(message = "menuType不能为空") private String menuType; /** 模块 */ - @Schema(description = "模块", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "模块") @NotBlank(message = "module不能为空") private String module; /** 路径 */ - @Schema(description = "路径", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "路径") @NotBlank(message = "path不能为空") private String path; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuIdParam.java index 21870abd..02a49bcb 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/menu/SysMenuIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysMenuIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleAddParam.java index 8b2992e0..e202c884 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleAddParam.java @@ -29,22 +29,22 @@ import lombok.Setter; public class SysModuleAddParam { /** 标题 */ - @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "标题") @NotBlank(message = "title不能为空") private String title; /** 图标 */ - @Schema(description = "图标", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "图标") @NotBlank(message = "icon不能为空") private String icon; /** 颜色 */ - @Schema(description = "颜色", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "颜色") @NotBlank(message = "color不能为空") private String color; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleEditParam.java index c401151b..6b5e27f1 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleEditParam.java @@ -29,27 +29,27 @@ import lombok.Setter; public class SysModuleEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 标题 */ - @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "标题") @NotBlank(message = "title不能为空") private String title; /** 图标 */ - @Schema(description = "图标", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "图标") @NotBlank(message = "icon不能为空") private String icon; /** 颜色 */ - @Schema(description = "颜色", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "颜色") @NotBlank(message = "color不能为空") private String color; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleIdParam.java index 46bfa2fb..e4f44639 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/param/module/SysModuleIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysModuleIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java index dbcd9251..58567add 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysButtonServiceImpl.java @@ -16,6 +16,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollStreamUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; @@ -96,6 +97,7 @@ public class SysButtonServiceImpl extends ServiceImpl sysButtonIdParamList) { List buttonIdList = CollStreamUtil.toList(sysButtonIdParamList, SysButtonIdParam::getId); diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysMenuServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysMenuServiceImpl.java index 1a0f9bc7..35395609 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysMenuServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysMenuServiceImpl.java @@ -92,16 +92,16 @@ public class SysMenuServiceImpl extends ServiceImpl impl @Override public List> tree(SysMenuTreeParam sysMenuTreeParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(SysMenu::getCategory, SysResourceCategoryEnum.MENU.getValue()) + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + queryWrapper.lambda().eq(SysMenu::getCategory, SysResourceCategoryEnum.MENU.getValue()) .orderByAsc(SysMenu::getSortCode); if(ObjectUtil.isNotEmpty(sysMenuTreeParam.getModule())) { - lambdaQueryWrapper.eq(SysMenu::getModule, sysMenuTreeParam.getModule()); + queryWrapper.lambda().eq(SysMenu::getModule, sysMenuTreeParam.getModule()); } if(ObjectUtil.isNotEmpty(sysMenuTreeParam.getSearchKey())) { - lambdaQueryWrapper.like(SysMenu::getTitle, sysMenuTreeParam.getSearchKey()); + queryWrapper.lambda().like(SysMenu::getTitle, sysMenuTreeParam.getSearchKey()); } - List resourceList = this.list(lambdaQueryWrapper); + List resourceList = this.list(queryWrapper.lambda()); // 填充上层的父级菜单 this.fillParentSysMenuInfo(resourceList); @@ -165,6 +165,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl throw new CommonException("module与上级菜单不一致"); } } + sysMenu.setCode(RandomUtil.randomString(10)); sysMenu.setCategory(SysResourceCategoryEnum.MENU.getValue()); this.save(sysMenu); @@ -273,6 +274,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl CommonDataChangeEventCenter.doUpdateWithData(SysDataTypeEnum.RESOURCE.getValue(), JSONUtil.createArray().put(sysMenu)); } + @Transactional(rollbackFor = Exception.class) @Override public void changeModule(SysMenuChangeModuleParam sysMenuChangeModuleParam) { SysMenu sysMenu = this.queryEntity(sysMenuChangeModuleParam.getId()); @@ -319,6 +321,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl } } + @Transactional(rollbackFor = Exception.class) @Override public void delete(List sysMenuIdParamList) { List sysMenuIdList = CollStreamUtil.toList(sysMenuIdParamList, SysMenuIdParam::getId); @@ -359,12 +362,12 @@ public class SysMenuServiceImpl extends ServiceImpl impl @Override public List moduleSelector(SysMenuSelectorModuleParam sysMenuSelectorModuleParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); if(ObjectUtil.isNotEmpty(sysMenuSelectorModuleParam.getSearchKey())) { - lambdaQueryWrapper.like(SysModule::getTitle, sysMenuSelectorModuleParam.getSearchKey()); + queryWrapper.lambda().like(SysModule::getTitle, sysMenuSelectorModuleParam.getSearchKey()); } - lambdaQueryWrapper.eq(SysModule::getCategory, SysResourceCategoryEnum.MODULE.getValue()); - return sysModuleService.list(lambdaQueryWrapper); + queryWrapper.lambda().eq(SysModule::getCategory, SysResourceCategoryEnum.MODULE.getValue()); + return sysModuleService.list(queryWrapper.lambda()); } @Override diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java index 732483d4..ad6b367c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/resource/service/impl/SysModuleServiceImpl.java @@ -95,7 +95,6 @@ public class SysModuleServiceImpl extends ServiceImpl sysModuleIdParamList) { List sysModuleIdList = CollStreamUtil.toList(sysModuleIdParamList, SysModuleIdParam::getId); diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/controller/SysRoleController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/controller/SysRoleController.java index 60919b6c..5913c23e 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/controller/SysRoleController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/controller/SysRoleController.java @@ -14,10 +14,11 @@ package vip.xiaonuo.sys.modular.role.controller; import cn.hutool.core.lang.tree.Tree; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -32,6 +33,7 @@ import vip.xiaonuo.sys.modular.role.result.*; import vip.xiaonuo.sys.modular.role.service.SysRoleService; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import javax.validation.Valid; import java.util.List; /** @@ -41,6 +43,7 @@ import java.util.List; * @date 2022/4/25 20:19 */ @Tag(name = "角色控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 8) @RestController @Validated public class SysRoleController { @@ -54,6 +57,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取角色分页") @GetMapping("/sys/role/page") public CommonResult> page(SysRolePageParam sysRolePageParam) { @@ -66,6 +70,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加角色") @CommonLog("添加角色") @PostMapping("/sys/role/add") @@ -80,6 +85,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑角色") @CommonLog("编辑角色") @PostMapping("/sys/role/edit") @@ -94,6 +100,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除角色") @CommonLog("删除角色") @PostMapping("/sys/role/delete") @@ -109,6 +116,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取角色详情") @GetMapping("/sys/role/detail") public CommonResult detail(@Valid SysRoleIdParam sysRoleIdParam) { @@ -121,6 +129,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 6) @Operation(summary = "获取角色拥有资源") @GetMapping("/sys/role/ownResource") public CommonResult ownResource(@Valid SysRoleIdParam sysRoleIdParam) { @@ -133,6 +142,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 7) @Operation(summary = "给角色授权资源") @CommonLog("给角色授权资源") @PostMapping("/sys/role/grantResource") @@ -147,6 +157,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 8) @Operation(summary = "获取角色拥有移动端菜单") @GetMapping("/sys/role/ownMobileMenu") public CommonResult ownMobileMenu(@Valid SysRoleIdParam sysRoleIdParam) { @@ -159,6 +170,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 9) @Operation(summary = "给角色授权移动端菜单") @CommonLog("给角色授权移动端菜单") @PostMapping("/sys/role/grantMobileMenu") @@ -173,6 +185,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 10) @Operation(summary = "获取角色拥有权限") @GetMapping("/sys/role/ownPermission") public CommonResult ownPermission(@Valid SysRoleIdParam sysRoleIdParam) { @@ -185,6 +198,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 11) @Operation(summary = "给角色授权权限") @CommonLog("给角色授权权限") @PostMapping("/sys/role/grantPermission") @@ -199,6 +213,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 12) @Operation(summary = "获取角色下的用户") @GetMapping("/sys/role/ownUser") public CommonResult> ownUser(@Valid SysRoleIdParam sysRoleIdParam) { @@ -211,6 +226,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 13) @Operation(summary = "给角色授权用户") @CommonLog("给角色授权用户") @PostMapping("/sys/role/grantUser") @@ -227,6 +243,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 14) @Operation(summary = "获取组织树选择器") @GetMapping("/sys/role/orgTreeSelector") public CommonResult>> orgTreeSelector() { @@ -239,10 +256,11 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 15) @Operation(summary = "获取资源授权树") @GetMapping("/sys/role/resourceTreeSelector") public CommonResult> resourceTreeSelector() { - return CommonResult.data(sysRoleService.resourceTreeSelector()); + return CommonResult.data(sysRoleService.resourceTreeSelector(true)); } /** @@ -251,6 +269,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 16) @Operation(summary = "获取移动端菜单授权树") @GetMapping("/sys/role/mobileMenuTreeSelector") public CommonResult> mobileMenuTreeSelector() { @@ -263,6 +282,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 17) @Operation(summary = "获取权限授权树") @GetMapping("/sys/role/permissionTreeSelector") public CommonResult> permissionTreeSelector() { @@ -275,6 +295,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 18) @Operation(summary = "获取角色选择器") @GetMapping("/sys/role/roleSelector") public CommonResult> roleSelector(SysRoleSelectorRoleParam sysRoleSelectorRoleParam) { @@ -287,6 +308,7 @@ public class SysRoleController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 19) @Operation(summary = "获取用户选择器") @GetMapping("/sys/role/userSelector") public CommonResult> userSelector(SysRoleSelectorUserParam sysRoleSelectorUserParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/entity/SysRole.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/entity/SysRole.java index b394b557..8a60c5a0 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/entity/SysRole.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/entity/SysRole.java @@ -37,7 +37,7 @@ public class SysRole extends CommonEntity { /** 组织id */ @Schema(description = "组织id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String orgId; /** 名称 */ @@ -58,6 +58,6 @@ public class SysRole extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/SysRoleMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/SysRoleMapper.java index c79b6237..b98ffb40 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/SysRoleMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/SysRoleMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.role.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.role.entity.SysRole; /** @@ -25,13 +22,4 @@ import vip.xiaonuo.sys.modular.role.entity.SysRole; * @date 2022/4/21 18:37 **/ public interface SysRoleMapper extends BaseMapper { - - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/mapping/SysRoleMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/mapping/SysRoleMapper.xml index de05f4c5..e0b69f04 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/mapping/SysRoleMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/mapper/mapping/SysRoleMapper.xml @@ -2,7 +2,4 @@ - - DELETE FROM SYS_ROLE ${ew.customSqlSegment} - \ No newline at end of file diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleAddParam.java index e126a3e7..ed96e2c8 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleAddParam.java @@ -29,17 +29,22 @@ import lombok.Setter; public class SysRoleAddParam { /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; + /** 编码 */ + @Schema(description = "编码") + @NotBlank(message = "code不能为空") + private String code; + /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleEditParam.java index f69b1c67..a17b3a81 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleEditParam.java @@ -29,22 +29,27 @@ import lombok.Setter; public class SysRoleEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 名称 */ - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "名称") @NotBlank(message = "name不能为空") private String name; + /** 编码 */ + @Schema(description = "编码") + @NotBlank(message = "code不能为空") + private String code; + /** 分类 */ - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "分类") @NotBlank(message = "category不能为空") private String category; /** 排序码 */ - @Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "排序码") @NotNull(message = "sortCode不能为空") private Integer sortCode; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantMobileMenuParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantMobileMenuParam.java index 61abec87..936257c5 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantMobileMenuParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantMobileMenuParam.java @@ -13,12 +13,12 @@ package vip.xiaonuo.sys.modular.role.param; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import javax.validation.Valid; import java.util.List; /** @@ -32,13 +32,13 @@ import java.util.List; public class SysRoleGrantMobileMenuParam { /** 角色id */ - @Schema(description = "角色id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色id") @NotBlank(message = "id不能为空") private String id; /** 授权移动端菜单信息 */ @Valid - @Schema(description = "授权移动端菜单信息", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "授权移动端菜单信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantPermissionParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantPermissionParam.java index d43764d4..c711cd3b 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantPermissionParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantPermissionParam.java @@ -13,12 +13,12 @@ package vip.xiaonuo.sys.modular.role.param; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import javax.validation.Valid; import java.util.List; /** @@ -32,13 +32,13 @@ import java.util.List; public class SysRoleGrantPermissionParam { /** 角色id */ - @Schema(description = "角色id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色id") @NotBlank(message = "id不能为空") private String id; /** 授权权限信息 */ @Valid - @Schema(description = "授权权限信息", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "授权权限信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantResourceParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantResourceParam.java index 64a5832d..2b0ffc42 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantResourceParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantResourceParam.java @@ -13,12 +13,12 @@ package vip.xiaonuo.sys.modular.role.param; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import javax.validation.Valid; import java.util.List; /** @@ -32,13 +32,13 @@ import java.util.List; public class SysRoleGrantResourceParam { /** 角色id */ - @Schema(description = "角色id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色id") @NotBlank(message = "id不能为空") private String id; /** 授权资源信息 */ @Valid - @Schema(description = "授权资源信息", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "授权资源信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java index c3c89058..385823cf 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleGrantUserParam.java @@ -31,12 +31,12 @@ import java.util.List; public class SysRoleGrantUserParam { /** 角色id */ - @Schema(description = "角色id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色id") @NotBlank(message = "id不能为空") private String id; /** 授权用户信息 */ - @Schema(description = "授权用户信息", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "授权用户信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleIdParam.java index 80fb59ce..d8241507 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/param/SysRoleIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysRoleIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/provider/SysRoleApiProvider.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/provider/SysRoleApiProvider.java index c9907375..026f9b38 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/provider/SysRoleApiProvider.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/provider/SysRoleApiProvider.java @@ -107,4 +107,14 @@ public class SysRoleApiProvider implements SysRoleApi { } sysRelationService.saveRelationBatchWithAppend(superAdminRoleId, menuIdList, SysRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue(), extJsonList); } + + @Override + public List resourceTreeSelector() { + return sysRoleService.resourceTreeSelector(false).stream().map(JSONUtil::parseObj).collect(Collectors.toList()); + } + + @Override + public List permissionTreeSelector() { + return sysRoleService.permissionTreeSelector(); + } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/result/SysRoleGrantResourceTreeResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/result/SysRoleGrantResourceTreeResult.java index 2fa1c6c7..6be2fa5c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/result/SysRoleGrantResourceTreeResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/result/SysRoleGrantResourceTreeResult.java @@ -28,8 +28,8 @@ import java.util.List; @Setter public class SysRoleGrantResourceTreeResult { - /** 模块id */ - @Schema(description = "模块id") + /** 模块主键 */ + @Schema(description = "模块主键") private String id; /** 模块名称*/ @@ -54,12 +54,12 @@ public class SysRoleGrantResourceTreeResult { @Setter public static class SysRoleGrantResourceMenuResult { - /** 菜单id */ - @Schema(description = "菜单id") + /** id */ + @Schema(description = "菜单主键") private String id; /** 父id */ - @Schema(description = "父id") + @Schema(description = "菜单id") private String parentId; /** 父名称 */ @@ -88,8 +88,8 @@ public class SysRoleGrantResourceTreeResult { @Setter public static class SysRoleGrantResourceButtonResult { - /** 按钮id */ - @Schema(description = "按钮id") + /** id */ + @Schema(description = "按钮主键") private String id; /** 标题 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/SysRoleService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/SysRoleService.java index 71286ed3..36b5d416 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/SysRoleService.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/SysRoleService.java @@ -13,8 +13,10 @@ package vip.xiaonuo.sys.modular.role.service; import cn.hutool.core.lang.tree.Tree; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.sys.modular.resource.entity.SysMenu; import vip.xiaonuo.sys.modular.role.entity.SysRole; import vip.xiaonuo.sys.modular.role.param.*; import vip.xiaonuo.sys.modular.role.result.*; @@ -158,7 +160,15 @@ public interface SysRoleService extends IService { * @author xuyuxiang * @date 2022/4/24 20:08 */ - List resourceTreeSelector(); + List resourceTreeSelector(boolean containsTen); + + /** + * 获取资源授权树 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + List resourceTreeSelector(List originDataList); /** * 获取移动端菜单授权树 @@ -168,6 +178,14 @@ public interface SysRoleService extends IService { */ List mobileMenuTreeSelector(); + /** + * 获取移动端菜单授权树 + * + * @author xuyuxiang + * @date 2022/4/24 20:08 + */ + List mobileMenuTreeSelector(List originDataList); + /** * 获取权限授权树 * diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java index 1dcbfe74..a73be5a2 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/role/service/impl/SysRoleServiceImpl.java @@ -20,7 +20,6 @@ import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.TreeNode; import cn.hutool.core.lang.tree.TreeUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.json.JSONObject; @@ -61,6 +60,7 @@ import vip.xiaonuo.sys.modular.role.param.*; import vip.xiaonuo.sys.modular.role.result.*; import vip.xiaonuo.sys.modular.role.service.SysRoleService; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import vip.xiaonuo.sys.modular.user.enums.SysUserStatusEnum; import vip.xiaonuo.sys.modular.user.service.SysUserService; import java.util.ArrayList; @@ -100,7 +100,7 @@ public class SysRoleServiceImpl extends ServiceImpl impl public Page page(SysRolePageParam sysRolePageParam) { QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - queryWrapper.lambda().select(SysRole::getId, SysRole::getOrgId, SysRole::getName, + queryWrapper.lambda().select(SysRole::getId, SysRole::getOrgId, SysRole::getName, SysRole::getCode, SysRole::getCategory, SysRole::getSortCode); if(ObjectUtil.isNotEmpty(sysRolePageParam.getOrgId())) { queryWrapper.lambda().eq(SysRole::getOrgId, sysRolePageParam.getOrgId()); @@ -124,6 +124,15 @@ public class SysRoleServiceImpl extends ServiceImpl impl @Transactional(rollbackFor = Exception.class) @Override public void add(SysRoleAddParam sysRoleAddParam) { + checkParam(sysRoleAddParam); + SysRole sysRole = BeanUtil.toBean(sysRoleAddParam, SysRole.class); + this.save(sysRole); + + // 发布增加事件 + CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ROLE.getValue(), JSONUtil.createArray().put(sysRole)); + } + + private void checkParam(SysRoleAddParam sysRoleAddParam) { SysRoleCategoryEnum.validate(sysRoleAddParam.getCategory()); if(SysRoleCategoryEnum.ORG.getValue().equals(sysRoleAddParam.getCategory())) { if(ObjectUtil.isEmpty(sysRoleAddParam.getOrgId())) { @@ -132,47 +141,35 @@ public class SysRoleServiceImpl extends ServiceImpl impl } else { sysRoleAddParam.setOrgId(null); } - SysRole sysRole = BeanUtil.toBean(sysRoleAddParam, SysRole.class); - boolean repeatName = this.count(new LambdaQueryWrapper().eq(SysRole::getOrgId, sysRole.getOrgId()) - .eq(SysRole::getName, sysRole.getName())) > 0; + boolean repeatName = this.count(new LambdaQueryWrapper().eq(SysRole::getOrgId, sysRoleAddParam.getOrgId()) + .eq(SysRole::getName, sysRoleAddParam.getName())) > 0; if(repeatName) { - if(ObjectUtil.isEmpty(sysRole.getOrgId())) { - throw new CommonException("存在重复的全局角色,名称为:{}", sysRole.getName()); + if(ObjectUtil.isEmpty(sysRoleAddParam.getOrgId())) { + throw new CommonException("存在重复的全局角色,名称为:{}", sysRoleAddParam.getName()); } else { - throw new CommonException("同组织下存在重复的角色,名称为:{}", sysRole.getName()); + throw new CommonException("同组织下存在重复的角色,名称为:{}", sysRoleAddParam.getName()); + } + } + boolean repeatCode = this.count(new LambdaQueryWrapper().eq(SysRole::getOrgId, sysRoleAddParam.getOrgId()) + .eq(SysRole::getCode, sysRoleAddParam.getCode())) > 0; + if(repeatCode) { + if(ObjectUtil.isEmpty(sysRoleAddParam.getOrgId())) { + throw new CommonException("存在重复的全局角色,编码为:{}", sysRoleAddParam.getCode()); + } else { + throw new CommonException("同组织下存在重复的角色,编码为:{}", sysRoleAddParam.getCode()); } } - sysRole.setCode(RandomUtil.randomString(10)); - this.save(sysRole); - - // 发布增加事件 - CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.ROLE.getValue(), JSONUtil.createArray().put(sysRole)); } @Transactional(rollbackFor = Exception.class) @Override public void edit(SysRoleEditParam sysRoleEditParam) { SysRole sysRole = this.queryEntity(sysRoleEditParam.getId()); + checkParam(sysRoleEditParam); boolean superRole = sysRole.getCode().equals(SysBuildInEnum.BUILD_IN_ROLE_CODE.getValue()); if(superRole) { throw new CommonException("不可编辑超管角色"); } - if(SysRoleCategoryEnum.ORG.getValue().equals(sysRoleEditParam.getCategory())) { - if (ObjectUtil.isEmpty(sysRoleEditParam.getOrgId())) { - throw new CommonException("orgId不能为空"); - } - } else { - sysRoleEditParam.setOrgId(null); - } - boolean repeatName = this.count(new LambdaQueryWrapper().eq(SysRole::getOrgId, sysRole.getOrgId()) - .eq(SysRole::getName, sysRole.getName()).ne(SysRole::getId, sysRole.getId())) > 0; - if(repeatName) { - if(ObjectUtil.isEmpty(sysRole.getOrgId())) { - throw new CommonException("存在重复的全局角色,名称为:{}", sysRole.getName()); - } else { - throw new CommonException("同组织下存在重复的角色,名称为:{}", sysRole.getName()); - } - } BeanUtil.copyProperties(sysRoleEditParam, sysRole); this.updateById(sysRole); @@ -180,6 +177,36 @@ public class SysRoleServiceImpl extends ServiceImpl impl CommonDataChangeEventCenter.doUpdateWithData(SysDataTypeEnum.ROLE.getValue(), JSONUtil.createArray().put(sysRole)); } + private void checkParam(SysRoleEditParam sysRoleEditParam) { + SysRoleCategoryEnum.validate(sysRoleEditParam.getCategory()); + if(SysRoleCategoryEnum.ORG.getValue().equals(sysRoleEditParam.getCategory())) { + if(ObjectUtil.isEmpty(sysRoleEditParam.getOrgId())) { + throw new CommonException("orgId不能为空"); + } + } else { + sysRoleEditParam.setOrgId(null); + } + boolean repeatName = this.count(new LambdaQueryWrapper().eq(SysRole::getOrgId, sysRoleEditParam.getOrgId()) + .eq(SysRole::getName, sysRoleEditParam.getName()).ne(SysRole::getId, sysRoleEditParam.getId())) > 0; + if(repeatName) { + if(ObjectUtil.isEmpty(sysRoleEditParam.getOrgId())) { + throw new CommonException("存在重复的全局角色,名称为:{}", sysRoleEditParam.getName()); + } else { + throw new CommonException("同组织下存在重复的角色,名称为:{}", sysRoleEditParam.getName()); + } + } + boolean repeatCode = this.count(new LambdaQueryWrapper().eq(SysRole::getOrgId, sysRoleEditParam.getOrgId()) + .eq(SysRole::getCode, sysRoleEditParam.getCode()).ne(SysRole::getId, sysRoleEditParam.getId())) > 0; + if(repeatCode) { + if(ObjectUtil.isEmpty(sysRoleEditParam.getOrgId())) { + throw new CommonException("存在重复的全局角色,编码为:{}", sysRoleEditParam.getCode()); + } else { + throw new CommonException("同组织下存在重复的角色,编码为:{}", sysRoleEditParam.getCode()); + } + } + } + + @Transactional(rollbackFor = Exception.class) @Override public void delete(List sysRoleIdParamList) { @@ -196,6 +223,9 @@ public class SysRoleServiceImpl extends ServiceImpl impl // 级联删除角色与资源关系 sysRelationService.remove(new LambdaUpdateWrapper().in(SysRelation::getObjectId, sysRoleIdList) .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue())); + // 级联删除角色与移动端资源关系 + sysRelationService.remove(new LambdaUpdateWrapper().in(SysRelation::getObjectId, sysRoleIdList) + .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_ROLE_HAS_MOBILE_MENU.getValue())); // 级联删除角色与权限关系 sysRelationService.remove(new LambdaUpdateWrapper().in(SysRelation::getObjectId, sysRoleIdList) .eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_ROLE_HAS_PERMISSION.getValue())); @@ -328,15 +358,22 @@ public class SysRoleServiceImpl extends ServiceImpl impl } @Override - public List resourceTreeSelector() { + public List resourceTreeSelector(boolean containsTen) { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.in(SysMenu::getCategory, SysResourceCategoryEnum.MODULE.getValue(), SysResourceCategoryEnum.MENU.getValue(), SysResourceCategoryEnum.BUTTON.getValue()); - List allMenuAndButtonAndFieldList = sysMenuService.list(lambdaQueryWrapper); + if(!containsTen) { + lambdaQueryWrapper.ne(SysMenu::getCode, SysBuildInEnum.BUILD_IN_NO_TEN_MENU_CODE.getValue()); + } + return this.resourceTreeSelector(sysMenuService.list(lambdaQueryWrapper)); + } + + @Override + public List resourceTreeSelector(List originDataList) { List sysModuleList = CollectionUtil.newArrayList(); List sysMenuList = CollectionUtil.newArrayList(); List sysButtonList = CollectionUtil.newArrayList(); - allMenuAndButtonAndFieldList.forEach(sysMenu -> { + originDataList.forEach(sysMenu -> { if (sysMenu.getCategory().equals(SysResourceCategoryEnum.MODULE.getValue())) { sysModuleList.add(sysMenu); } @@ -408,6 +445,11 @@ public class SysRoleServiceImpl extends ServiceImpl impl return BeanUtil.copyToList(mobileMenuApi.mobileMenuTreeSelector(), SysRoleGrantMobileMenuTreeResult.class); } + @Override + public List mobileMenuTreeSelector(List originDataList) { + return BeanUtil.copyToList(mobileMenuApi.mobileMenuTreeSelector(originDataList), SysRoleGrantMobileMenuTreeResult.class); + } + @Override public List permissionTreeSelector() { List permissionResult = CollectionUtil.newArrayList(); @@ -440,55 +482,57 @@ public class SysRoleServiceImpl extends ServiceImpl impl @Override public Page roleSelector(SysRoleSelectorRoleParam sysRoleSelectorRoleParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - lambdaQueryWrapper.select(SysRole::getId, SysRole::getOrgId, SysRole::getName, + queryWrapper.lambda().select(SysRole::getId, SysRole::getOrgId, SysRole::getName, SysRole::getCode, SysRole::getCategory, SysRole::getSortCode); if(ObjectUtil.isNotEmpty(sysRoleSelectorRoleParam.getOrgId())) { - lambdaQueryWrapper.eq(SysRole::getOrgId, sysRoleSelectorRoleParam.getOrgId()); + queryWrapper.lambda().eq(SysRole::getOrgId, sysRoleSelectorRoleParam.getOrgId()); } if(ObjectUtil.isNotEmpty(sysRoleSelectorRoleParam.getCategory())) { - lambdaQueryWrapper.eq(SysRole::getCategory, sysRoleSelectorRoleParam.getCategory()); + queryWrapper.lambda().eq(SysRole::getCategory, sysRoleSelectorRoleParam.getCategory()); } if(ObjectUtil.isNotEmpty(sysRoleSelectorRoleParam.getSearchKey())) { - lambdaQueryWrapper.like(SysRole::getName, sysRoleSelectorRoleParam.getSearchKey()); + queryWrapper.lambda().like(SysRole::getName, sysRoleSelectorRoleParam.getSearchKey()); } if(ObjectUtil.isNotEmpty(sysRoleSelectorRoleParam.getDataScopeList())) { - lambdaQueryWrapper.in(SysRole::getOrgId, sysRoleSelectorRoleParam.getDataScopeList()); + queryWrapper.lambda().in(SysRole::getOrgId, sysRoleSelectorRoleParam.getDataScopeList()); } // 排除超管角色 if(sysRoleSelectorRoleParam.isExcludeSuperAdmin()) { - lambdaQueryWrapper.ne(SysRole::getCode, SysBuildInEnum.BUILD_IN_ROLE_CODE.getValue()); + queryWrapper.lambda().ne(SysRole::getCode, SysBuildInEnum.BUILD_IN_ROLE_CODE.getValue()); } - lambdaQueryWrapper.orderByAsc(SysRole::getSortCode); - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysRole::getSortCode); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @Override public Page userSelector(SysRoleSelectorUserParam sysRoleSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + // 只查询状态为正常的 + queryWrapper.lambda().eq(SysUser::getUserStatus, SysUserStatusEnum.ENABLE.getValue()); // 只查询部分字段 - lambdaQueryWrapper.select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, + queryWrapper.lambda().select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, SysUser::getName, SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate); // 如果查询条件为空,则直接查询 if(ObjectUtil.isAllEmpty(sysRoleSelectorUserParam.getOrgId(), sysRoleSelectorUserParam.getSearchKey())) { return sysUserService.getAllUserSelectorList(); } else { if (ObjectUtil.isNotEmpty(sysRoleSelectorUserParam.getOrgId())) { - // 如果组织id不为空,则查询该组织及其子极其子下的所有人 + // 如果组织id不为空,则查询该组织及其子组织下的所有人 List childOrgIdList = CollStreamUtil.toList(sysOrgService.getChildListById(sysOrgService .getAllOrgList(), sysRoleSelectorUserParam.getOrgId(), true), SysOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(SysUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(SysUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if (ObjectUtil.isNotEmpty(sysRoleSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(SysUser::getName, sysRoleSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(SysUser::getName, sysRoleSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysUser::getSortCode); - return sysUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysUser::getSortCode); + return sysUserService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/sys/SysApiProvider.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/sys/SysApiProvider.java new file mode 100644 index 00000000..c1cf11a1 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/sys/SysApiProvider.java @@ -0,0 +1,20 @@ +package vip.xiaonuo.sys.modular.sys; + +import org.springframework.stereotype.Service; +import vip.xiaonuo.sys.api.SysApi; +import vip.xiaonuo.sys.core.util.SysPasswordUtl; + +/** + * 系统模块综合API接口实现类 + * + * @author xuyuxiang + * @date 2022/9/26 14:30 + **/ +@Service +public class SysApiProvider implements SysApi { + + @Override + public String getDefaultPassword() { + return SysPasswordUtl.getDefaultPassword(); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserCenterController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserCenterController.java index fab0d88e..d1286ac0 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserCenterController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserCenterController.java @@ -14,11 +14,13 @@ package vip.xiaonuo.sys.modular.user.controller; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.lang.tree.Tree; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -36,15 +38,17 @@ import vip.xiaonuo.sys.modular.user.result.SysUserPicValidCodeResult; import vip.xiaonuo.sys.modular.user.result.SysUserPositionResult; import vip.xiaonuo.sys.modular.user.service.SysUserService; +import javax.validation.Valid; import java.util.List; /** - * 用户个人控制器 + * B端用户个人控制器 * * @author xuyuxiang * @date 2022/4/22 9:34 **/ -@Tag(name = "用户个人控制器") +@Tag(name = "B端用户个人控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 10) @RestController @Validated public class SysUserCenterController { @@ -58,6 +62,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/7/8 9:26 **/ + @ApiOperationSupport(order = 1) @Operation(summary = "获取图片验证码") @GetMapping("/sys/userCenter/getPicCaptcha") public CommonResult getPicCaptcha() { @@ -70,6 +75,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 2) @Operation(summary = "找回密码获取手机验证码") @GetMapping("/sys/userCenter/findPasswordGetPhoneValidCode") public CommonResult findPasswordGetPhoneValidCode(@Valid SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { @@ -82,6 +88,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 3) @Operation(summary = "找回密码获取邮箱验证码") @GetMapping("/sys/userCenter/findPasswordGetEmailValidCode") public CommonResult findPasswordGetEmailValidCode(@Valid SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { @@ -94,6 +101,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 4) @Operation(summary = "通过手机号找回用户密码") @CommonLog("通过手机号找回用户密码") @PostMapping("/sys/userCenter/findPasswordByPhone") @@ -108,6 +116,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 5) @Operation(summary = "通过邮箱找回用户密码") @CommonLog("通过邮箱找回用户密码") @PostMapping("/sys/userCenter/findPasswordByEmail") @@ -117,16 +126,155 @@ public class SysUserCenterController { } /** - * 修改用户密码 + * 修改密码获取手机验证码 * * @author xuyuxiang * @date 2021/10/13 14:01 **/ - @Operation(summary = "修改用户密码") - @CommonLog("修改用户密码") - @PostMapping("/sys/userCenter/updatePassword") - public CommonResult updatePassword(@RequestBody @Valid SysUserUpdatePwdParam sysUserUpdatePwdParam) { - sysUserService.updatePassword(sysUserUpdatePwdParam); + @ApiOperationSupport(order = 6) + @Operation(summary = "修改密码获取手机验证码") + @GetMapping("/sys/userCenter/updatePasswordGetPhoneValidCode") + public CommonResult updatePasswordGetPhoneValidCode(@Valid SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + return CommonResult.data(sysUserService.updatePasswordGetPhoneValidCode(sysUserGetPhoneValidCodeParam)); + } + + /** + * 修改密码获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 7) + @Operation(summary = "修改密码获取邮箱验证码") + @GetMapping("/sys/userCenter/updatePasswordGetEmailValidCode") + public CommonResult updatePasswordGetEmailValidCode(@Valid SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + return CommonResult.data(sysUserService.updatePasswordGetEmailValidCode(sysUserGetEmailValidCodeParam)); + } + + /** + * 通过验证旧密码修改用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 8) + @Operation(summary = "通过验证旧密码修改用户密码") + @CommonLog("通过验证旧密码修改用户密码") + @PostMapping("/sys/userCenter/updatePasswordByOld") + public CommonResult updatePasswordByOld(@RequestBody @Valid SysUserUpdatePwdByOldParam sysUserUpdatePwdByOldParam) { + sysUserService.updatePasswordByOld(sysUserUpdatePwdByOldParam); + return CommonResult.ok(); + } + + /** + * 通过验证手机号修改用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 9) + @Operation(summary = "通过验证手机号修改用户密码") + @CommonLog("通过验证手机号修改用户密码") + @PostMapping("/sys/userCenter/updatePasswordByPhone") + public CommonResult updatePasswordByPhone(@RequestBody @Valid SysUserUpdatePwdByPhoneParam sysUserUpdatePwdByPhoneParam) { + sysUserService.updatePasswordByPhone(sysUserUpdatePwdByPhoneParam); + return CommonResult.ok(); + } + + /** + * 通过验证邮箱修改用户密码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 10) + @Operation(summary = "通过验证邮箱修改用户密码") + @CommonLog("通过验证邮箱修改用户密码") + @PostMapping("/sys/userCenter/updatePasswordByEmail") + public CommonResult updatePasswordByEmail(@RequestBody @Valid SysUserUpdatePwdByEmailParam sysUserUpdatePwdByEmailParam) { + sysUserService.updatePasswordByEmail(sysUserUpdatePwdByEmailParam); + return CommonResult.ok(); + } + + /** + * 绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 11) + @Operation(summary = "绑定手机号获取手机验证码") + @GetMapping("/sys/userCenter/bindPhoneGetPhoneValidCode") + public CommonResult bindPhoneGetPhoneValidCode(@Valid SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + return CommonResult.data(sysUserService.bindPhoneGetPhoneValidCode(sysUserGetPhoneValidCodeParam)); + } + + /** + * 修改绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 12) + @Operation(summary = "修改绑定手机号获取手机验证码") + @GetMapping("/sys/userCenter/updateBindPhoneGetPhoneValidCode") + public CommonResult updateBindPhoneGetPhoneValidCode(@Valid SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + return CommonResult.data(sysUserService.updateBindPhoneGetPhoneValidCode(sysUserGetPhoneValidCodeParam)); + } + + /** + * 绑定手机号 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 13) + @Operation(summary = "绑定手机号") + @CommonLog("绑定手机号") + @PostMapping("/sys/userCenter/bindPhone") + public CommonResult bindPhone(@RequestBody @Valid SysUserBindPhoneParam sysUserBindPhoneParam) { + sysUserService.bindPhone(sysUserBindPhoneParam); + return CommonResult.ok(); + } + + /** + * 绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 14) + @Operation(summary = "绑定邮箱获取邮箱验证码") + @GetMapping("/sys/userCenter/bindEmailGetEmailValidCode") + public CommonResult bindEmailGetEmailValidCode(@Valid SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + return CommonResult.data(sysUserService.bindEmailGetEmailValidCode(sysUserGetEmailValidCodeParam)); + } + + /** + * 修改绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 15) + @Operation(summary = "修改绑定邮箱获取邮箱验证码") + @GetMapping("/sys/userCenter/updateBindEmailGetEmailValidCode") + public CommonResult updateBindEmailGetEmailValidCode(@Valid SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + return CommonResult.data(sysUserService.updateBindEmailGetEmailValidCode(sysUserGetEmailValidCodeParam)); + } + + /** + * 绑定邮箱 + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + @ApiOperationSupport(order = 16) + @Operation(summary = "绑定邮箱") + @CommonLog("绑定邮箱") + @PostMapping("/sys/userCenter/bindEmail") + public CommonResult bindEmail(@RequestBody @Valid SysUserBindEmailParam sysUserBindEmailParam) { + sysUserService.bindEmail(sysUserBindEmailParam); return CommonResult.ok(); } @@ -136,6 +284,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 17) @Operation(summary = "修改用户头像") @CommonLog("修改用户头像") @PostMapping("/sys/userCenter/updateAvatar") @@ -149,6 +298,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 18) @Operation(summary = "修改用户签名图片") @CommonLog("修改用户签名图片") @PostMapping("/sys/userCenter/updateSignature") @@ -157,68 +307,13 @@ public class SysUserCenterController { return CommonResult.ok(); } - /** - * 获取登录用户的菜单(B端、PC端菜单) - * - * @author xuyuxiang - * @date 2022/4/24 20:00 - */ - @Operation(summary = "获取登录用户PC端菜单") - @GetMapping("/sys/userCenter/loginMenu") - public CommonResult>> loginMenu() { - SysUserIdParam sysUserIdParam = new SysUserIdParam(); - sysUserIdParam.setId(StpUtil.getLoginIdAsString()); - return CommonResult.data(sysUserService.ownMenu(sysUserIdParam)); - } - - /** - * 获取登录用户的菜单(B端、移动端菜单) - * - * @author xuyuxiang - * @date 2022/4/24 20:00 - */ - @Operation(summary = "获取登录用户移动端菜单") - @GetMapping("/sys/userCenter/loginMobileMenu") - public CommonResult>> loginMobileMenu() { - SysUserIdParam sysUserIdParam = new SysUserIdParam(); - sysUserIdParam.setId(StpUtil.getLoginIdAsString()); - return CommonResult.data(sysUserService.ownMobileMenu(sysUserIdParam)); - } - - /** - * 获取登录用户组织树 - * - * @author xuyuxiang - * @date 2022/4/24 20:00 - */ - @Operation(summary = "获取登录用户组织树") - @GetMapping("/sys/userCenter/loginOrgTree") - public CommonResult>> loginOrgTree() { - SysUserIdParam sysUserIdParam = new SysUserIdParam(); - sysUserIdParam.setId(StpUtil.getLoginIdAsString()); - return CommonResult.data(sysUserService.loginOrgTree(sysUserIdParam)); - } - - /** - * 获取登录用户的职位信息 - * - * @author xuyuxiang - * @date 2022/4/24 20:00 - */ - @Operation(summary = "获取登录用户的职位信息") - @GetMapping("/sys/userCenter/loginPositionInfo") - public CommonResult> loginPositionInfo() { - SysUserIdParam sysUserIdParam = new SysUserIdParam(); - sysUserIdParam.setId(StpUtil.getLoginIdAsString()); - return CommonResult.data(sysUserService.loginPositionInfo(sysUserIdParam)); - } - /** * 编辑个人信息 * * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 19) @Operation(summary = "编辑个人信息") @CommonLog("编辑个人信息") @PostMapping("/sys/userCenter/updateUserInfo") @@ -233,6 +328,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 20) @Operation(summary = "编辑个人工作台") @CommonLog("编辑个人工作台") @PostMapping("/sys/userCenter/updateUserWorkbench") @@ -241,12 +337,73 @@ public class SysUserCenterController { return CommonResult.ok(); } + /** + * 获取登录用户的菜单(B端、PC端菜单) + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 21) + @Operation(summary = "获取登录用户PC端菜单") + @GetMapping("/sys/userCenter/loginMenu") + public CommonResult>> loginMenu() { + SysUserIdParam sysUserIdParam = new SysUserIdParam(); + sysUserIdParam.setId(StpUtil.getLoginIdAsString()); + return CommonResult.data(sysUserService.ownMenu(sysUserIdParam)); + } + + /** + * 获取登录用户的菜单(B端、移动端菜单) + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 22) + @Operation(summary = "获取登录用户移动端菜单") + @GetMapping("/sys/userCenter/loginMobileMenu") + public CommonResult>> loginMobileMenu() { + SysUserIdParam sysUserIdParam = new SysUserIdParam(); + sysUserIdParam.setId(StpUtil.getLoginIdAsString()); + return CommonResult.data(sysUserService.ownMobileMenu(sysUserIdParam)); + } + + /** + * 获取登录用户组织树 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 23) + @Operation(summary = "获取登录用户组织树") + @GetMapping("/sys/userCenter/loginOrgTree") + public CommonResult>> loginOrgTree() { + SysUserIdParam sysUserIdParam = new SysUserIdParam(); + sysUserIdParam.setId(StpUtil.getLoginIdAsString()); + return CommonResult.data(sysUserService.loginOrgTree(sysUserIdParam)); + } + + /** + * 获取登录用户的职位信息 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 24) + @Operation(summary = "获取登录用户的职位信息") + @GetMapping("/sys/userCenter/loginPositionInfo") + public CommonResult> loginPositionInfo() { + SysUserIdParam sysUserIdParam = new SysUserIdParam(); + sysUserIdParam.setId(StpUtil.getLoginIdAsString()); + return CommonResult.data(sysUserService.loginPositionInfo(sysUserIdParam)); + } + /** * 获取登录用户的工作台 * * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 25) @Operation(summary = "获取登录用户的工作台") @GetMapping("/sys/userCenter/loginWorkbench") public CommonResult loginWorkbench() { @@ -261,6 +418,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 26) @Operation(summary = "获取登录用户的站内信分页") @GetMapping("/sys/userCenter/loginUnreadMessagePage") public CommonResult> loginMessagePage(SysUserMessagePageParam sysUserMessagePageParam) { @@ -273,6 +431,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 27) @Operation(summary = "读取登录用户站内信详情") @GetMapping("/sys/userCenter/loginUnreadMessageDetail") public CommonResult loginMessageDetail(@Valid SysUserMessageIdParam sysUserMessageIdParam) { @@ -285,6 +444,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 28) @Operation(summary = "根据id集合获取组织集合") @PostMapping("/sys/userCenter/getOrgListByIdList") public CommonResult> getOrgListByIdList(@RequestBody @Valid SysUserIdListParam sysUserIdListParam) { @@ -297,6 +457,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 29) @Operation(summary = "根据id集合获取用户集合") @PostMapping("/sys/userCenter/getUserListByIdList") public CommonResult> getUserListByIdList(@RequestBody @Valid SysUserIdListParam sysUserIdListParam) { @@ -309,6 +470,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 30) @Operation(summary = "根据id集合获取职位集合") @PostMapping("/sys/userCenter/getPositionListByIdList") public CommonResult> getPositionListByIdList(@RequestBody @Valid SysUserIdListParam sysUserIdListParam) { @@ -321,6 +483,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 31) @Operation(summary = "根据id集合获取角色集合") @PostMapping("/sys/userCenter/getRoleListByIdList") public CommonResult> getRoleListByIdList(@RequestBody @Valid SysUserIdListParam sysUserIdListParam) { @@ -333,6 +496,7 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 32) @Operation(summary = "根据id集合获取用户组集合") @PostMapping("/sys/userCenter/getGroupListByIdList") public CommonResult> getGroupListByIdList(@RequestBody @Valid SysUserGroupIdListParam sysUserGroupIdListParam) { @@ -345,9 +509,62 @@ public class SysUserCenterController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 33) @Operation(summary = "根据id获取头像") - @PostMapping("/sys/userCenter/getAvatarById") - public CommonResult getAvatarById(@RequestBody @javax.validation.Valid SysUserIdParam sysUserIdParam) { + @GetMapping("/sys/userCenter/getAvatarById") + public CommonResult getAvatarById(@Valid SysUserIdParam sysUserIdParam) { return CommonResult.data(sysUserService.getAvatarById(sysUserIdParam)); } + + /** + * 判断当前用户是否需要绑定手机号 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 34) + @Operation(summary = "判断当前用户是否需要绑定手机号") + @GetMapping("/sys/userCenter/isUserNeedBindPhone") + public CommonResult isUserNeedBindPhone() { + return CommonResult.data(sysUserService.isUserNeedBindPhone()); + } + + /** + * 判断当前用户是否需要绑定邮箱 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 35) + @Operation(summary = "判断当前用户是否需要绑定邮箱") + @GetMapping("/sys/userCenter/isUserNeedBindEmail") + public CommonResult isUserNeedBindEmail() { + return CommonResult.data(sysUserService.isUserNeedBindEmail()); + } + + /** + * 判断当前用户密码是否过期 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 36) + @Operation(summary = "判断当前用户密码是否过期") + @GetMapping("/sys/userCenter/isUserPasswordExpired") + public CommonResult isUserPasswordExpired() { + return CommonResult.data(sysUserService.isUserPasswordExpired()); + } + + /** + * 获取修改密码验证方式及配置 + * + * @author xuyuxiang + * @date 2022/4/24 20:00 + */ + @ApiOperationSupport(order = 37) + @Operation(summary = "获取修改密码验证方式及配置") + @GetMapping("/sys/userCenter/getUpdatePasswordValidConfig") + public CommonResult getUpdatePasswordValidConfig() { + return CommonResult.data(sysUserService.getUpdatePasswordValidConfig()); + } } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserController.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserController.java index 3faccdf2..503f69d1 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserController.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/controller/SysUserController.java @@ -15,11 +15,12 @@ package vip.xiaonuo.sys.modular.user.controller; import cn.hutool.core.lang.tree.Tree; import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; @@ -31,21 +32,24 @@ import vip.xiaonuo.sys.modular.org.entity.SysOrg; import vip.xiaonuo.sys.modular.position.entity.SysPosition; import vip.xiaonuo.sys.modular.role.entity.SysRole; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import vip.xiaonuo.sys.modular.user.enums.SysUserSourceFromTypeEnum; import vip.xiaonuo.sys.modular.user.param.*; import vip.xiaonuo.sys.modular.user.result.SysUserOwnPermissionResult; import vip.xiaonuo.sys.modular.user.result.SysUserOwnResourceResult; import vip.xiaonuo.sys.modular.user.service.SysUserService; +import javax.validation.Valid; import java.io.IOException; import java.util.List; /** - * 用户控制器 + * B端用户控制器 * * @author xuyuxiang * @date 2022/4/22 9:34 **/ -@Tag(name = "用户控制器") +@Tag(name = "B端用户控制器") +@ApiSupport(author = "SNOWY_TEAM", order = 9) @RestController @Validated public class SysUserController { @@ -59,6 +63,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 1) @Operation(summary = "获取用户分页") @GetMapping("/sys/user/page") public CommonResult> page(SysUserPageParam sysUserPageParam) { @@ -71,11 +76,12 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 2) @Operation(summary = "添加用户") @CommonLog("添加用户") @PostMapping("/sys/user/add") public CommonResult add(@RequestBody @Valid SysUserAddParam sysUserAddParam) { - sysUserService.add(sysUserAddParam); + sysUserService.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_ADD.getValue()); return CommonResult.ok(); } @@ -85,6 +91,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:47 */ + @ApiOperationSupport(order = 3) @Operation(summary = "编辑用户") @CommonLog("编辑用户") @PostMapping("/sys/user/edit") @@ -99,11 +106,12 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 4) @Operation(summary = "删除用户") @CommonLog("删除用户") @PostMapping("/sys/user/delete") public CommonResult delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空") - List sysUserIdParamList) { + List sysUserIdParamList) { sysUserService.delete(sysUserIdParamList); return CommonResult.ok(); } @@ -114,6 +122,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 5) @Operation(summary = "获取用户详情") @GetMapping("/sys/user/detail") public CommonResult detail(@Valid SysUserIdParam sysUserIdParam) { @@ -126,6 +135,7 @@ public class SysUserController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 6) @Operation(summary = "禁用用户") @CommonLog("禁用用户") @PostMapping("/sys/user/disableUser") @@ -140,6 +150,7 @@ public class SysUserController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 7) @Operation(summary = "启用用户") @CommonLog("启用用户") @PostMapping("/sys/user/enableUser") @@ -154,6 +165,7 @@ public class SysUserController { * @author xuyuxiang * @date 2021/10/13 14:01 **/ + @ApiOperationSupport(order = 8) @Operation(summary = "重置用户密码") @CommonLog("重置用户密码") @PostMapping("/sys/user/resetPassword") @@ -168,6 +180,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 9) @Operation(summary = "获取用户拥有角色") @GetMapping("/sys/user/ownRole") public CommonResult> ownRole(@Valid SysUserIdParam sysUserIdParam) { @@ -180,6 +193,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 10) @Operation(summary = "给用户授权角色") @CommonLog("给用户授权角色") @PostMapping("/sys/user/grantRole") @@ -194,6 +208,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 11) @Operation(summary = "获取用户拥有资源") @GetMapping("/sys/user/ownResource") public CommonResult ownResource(@Valid SysUserIdParam sysUserIdParam) { @@ -206,6 +221,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 12) @Operation(summary = "给用户授权资源") @CommonLog("给用户授权资源") @PostMapping("/sys/user/grantResource") @@ -220,6 +236,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 13) @Operation(summary = "获取用户拥有权限") @GetMapping("/sys/user/ownPermission") public CommonResult ownPermission(@Valid SysUserIdParam sysUserIdParam) { @@ -232,6 +249,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 14) @Operation(summary = "给用户授权权限") @CommonLog("给用户授权权限") @PostMapping("/sys/user/grantPermission") @@ -246,6 +264,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 15) @Operation(summary = "下载用户导入模板") @CommonLog("下载用户导入模板") @GetMapping(value = "/sys/user/downloadImportUserTemplate", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @@ -259,6 +278,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 16) @Operation(summary = "用户导入") @CommonLog("用户导入") @PostMapping("/sys/user/import") @@ -272,6 +292,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 17) @Operation(summary = "用户导出") @CommonLog("用户导出") @GetMapping(value = "/sys/user/export", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @@ -285,6 +306,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 18) @Operation(summary = "导出用户个人信息") @CommonLog("导出用户个人信息") @GetMapping(value = "/sys/user/exportUserInfo", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @@ -300,6 +322,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 19) @Operation(summary = "获取组织树选择器") @GetMapping("/sys/user/orgTreeSelector") public CommonResult>> orgTreeSelector() { @@ -312,6 +335,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 20) @Operation(summary = "获取组织列表选择器") @GetMapping("/sys/user/orgListSelector") public CommonResult> orgListSelector(SysUserSelectorOrgListParam sysUserSelectorOrgListParam) { @@ -324,6 +348,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 21) @Operation(summary = "获取职位选择器") @GetMapping("/sys/user/positionSelector") public CommonResult> positionSelector(SysUserSelectorPositionParam sysUserSelectorPositionParam) { @@ -336,6 +361,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 22) @Operation(summary = "获取角色选择器") @GetMapping("/sys/user/roleSelector") public CommonResult> roleSelector(SysUserSelectorRoleParam sysUserSelectorRoleParam) { @@ -348,6 +374,7 @@ public class SysUserController { * @author xuyuxiang * @date 2022/4/24 20:00 */ + @ApiOperationSupport(order = 23) @Operation(summary = "获取用户选择器") @GetMapping("/sys/user/userSelector") public CommonResult> userSelector(SysUserSelectorUserParam sysUserSelectorUserParam) { diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUser.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUser.java index 6c0cf78c..b5b373ed 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUser.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUser.java @@ -47,12 +47,12 @@ public class SysUser extends CommonEntity { /** 头像 */ @Schema(description = "头像") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String avatar; /** 签名 */ @Schema(description = "签名") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String signature; /** 账号 */ @@ -70,156 +70,156 @@ public class SysUser extends CommonEntity { /** 昵称 */ @Schema(description = "昵称") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nickname; /** 性别 */ @Schema(description = "性别") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) - @Trans(type = TransType.DICTIONARY, key = "GENDER") + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) + @Trans(type = TransType.DICTIONARY,key = "GENDER") private String gender; /** 年龄 */ @Schema(description = "年龄") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String age; /** 出生日期 */ @Schema(description = "出生日期") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String birthday; /** 民族 */ @Schema(description = "民族") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nation; /** 籍贯 */ @Schema(description = "籍贯") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String nativePlace; /** 家庭住址 */ @Schema(description = "家庭住址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String homeAddress; /** 通信地址 */ @Schema(description = "通信地址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String mailingAddress; /** 证件类型 */ @Schema(description = "证件类型") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String idCardType; /** 证件号码 */ @Schema(description = "证件号码") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String idCardNumber; /** 文化程度 */ @Schema(description = "文化程度") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String cultureLevel; /** 政治面貌 */ @Schema(description = "政治面貌") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String politicalOutlook; /** 毕业院校 */ @Schema(description = "毕业院校") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String college; /** 学历 */ @Schema(description = "学历") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String education; /** 学制 */ @Schema(description = "学制") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String eduLength; /** 学位 */ @Schema(description = "学位") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String degree; /** 手机 */ @Schema(description = "手机") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String phone; /** 邮箱 */ @Schema(description = "邮箱") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String email; /** 家庭电话 */ @Schema(description = "家庭电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String homeTel; /** 办公电话 */ @Schema(description = "办公电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String officeTel; /** 紧急联系人 */ @Schema(description = "紧急联系人") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String emergencyContact; /** 紧急联系人电话 */ @Schema(description = "紧急联系人电话") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED, typeHandler = CommonSm4CbcTypeHandler.class) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS, typeHandler = CommonSm4CbcTypeHandler.class) private String emergencyPhone; /** 紧急联系人地址 */ @Schema(description = "紧急联系人地址") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String emergencyAddress; /** 员工编号 */ @Schema(description = "员工编号") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String empNo; /** 入职日期 */ @Schema(description = "入职日期") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String entryDate; /** 组织id */ @Schema(description = "组织id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.SIMPLE, target = SysOrg.class, fields = "name", alias = "org", ref = "orgName") private String orgId; /** 职位id */ @Schema(description = "职位id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.SIMPLE, target = SysPosition.class, fields = "name", alias = "position", ref = "positionName") private String positionId; /** 职级 */ @Schema(description = "职级") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String positionLevel; /** 主管id */ @Schema(description = "主管id") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) @Trans(type = TransType.SIMPLE, target = SysUser.class, fields = "name", alias = "director", ref = "directorName") private String directorId; /** 兼任信息 */ @Schema(description = "兼任信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String positionJson; /** 上次登录ip */ @@ -264,7 +264,7 @@ public class SysUser extends CommonEntity { /** 扩展信息 */ @Schema(description = "扩展信息") - @TableField(insertStrategy = FieldStrategy.IGNORED, updateStrategy = FieldStrategy.IGNORED) + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private String extJson; /** 组织名称 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserExt.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserExt.java new file mode 100644 index 00000000..667da98e --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserExt.java @@ -0,0 +1,52 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +import java.util.Date; + +/** + * 用户扩展实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("SYS_USER_EXT") +public class SysUserExt extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 用户id */ + @Schema(description = "用户id") + private String userId; + + /** 来源类别 */ + @Schema(description = "来源类别") + private String sourceFromType; + + /** 密码修改日期 */ + @Schema(description = "密码修改日期") + private Date passwordUpdateTime; + +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserPassword.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserPassword.java new file mode 100644 index 00000000..602e3b59 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/entity/SysUserPassword.java @@ -0,0 +1,46 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import vip.xiaonuo.common.pojo.CommonEntity; + +/** + * 用户密码实体 + * + * @author xuyuxiang + * @date 2022/4/21 16:13 + **/ +@Getter +@Setter +@TableName("SYS_USER_PASSWORD") +public class SysUserPassword extends CommonEntity { + + /** id */ + @TableId + @Schema(description = "id") + private String id; + + /** 用户id */ + @Schema(description = "用户id") + private String userId; + + /** 密码 */ + @Schema(description = "密码") + private String password; + +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysEmailEngineTypeEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysEmailEngineTypeEnum.java new file mode 100644 index 00000000..8ad78a75 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysEmailEngineTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.enums; + +import lombok.Getter; + +/** + * 邮件发送引擎类型枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum SysEmailEngineTypeEnum { + + /** 本地 */ + LOCAL("LOCAL"), + + /** 阿里云 */ + ALIYUN("ALIYUN"), + + /** 腾讯云 */ + TENCENT("TENCENT"); + + private final String value; + + SysEmailEngineTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysSmsEngineTypeEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysSmsEngineTypeEnum.java new file mode 100644 index 00000000..34b0cb30 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysSmsEngineTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.enums; + +import lombok.Getter; + +/** + * 短信发送引擎类型枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum SysSmsEngineTypeEnum { + + /** 阿里云 */ + ALIYUN("ALIYUN"), + + /** 腾讯云 */ + TENCENT("TENCENT"), + + /** 小诺短信 */ + XIAONUO("XIAONUO"); + + private final String value; + + SysSmsEngineTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUpdatePasswordValidTypeEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUpdatePasswordValidTypeEnum.java new file mode 100644 index 00000000..a2a307be --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUpdatePasswordValidTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.enums; + +import lombok.Getter; + +/** + * 系统修改密码验证方式枚举 + * + * @author xuyuxiang + * @date 2022/6/16 16:14 + **/ +@Getter +public enum SysUpdatePasswordValidTypeEnum { + + /** 旧密码 */ + OLD("OLD"), + + /** 手机号 */ + PHONE("PHONE"), + + /** 邮箱 */ + EMAIL("EMAIL"); + + private final String value; + + SysUpdatePasswordValidTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUserSourceFromTypeEnum.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUserSourceFromTypeEnum.java new file mode 100644 index 00000000..e5bfda34 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/enums/SysUserSourceFromTypeEnum.java @@ -0,0 +1,40 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.enums; + +import lombok.Getter; + +/** + * 用户来源类型枚举 + * + * @author xuyuxiang + * @date 2022/4/21 19:56 + **/ +@Getter +public enum SysUserSourceFromTypeEnum { + + /** 系统自建 */ + SYSTEM_ADD("SYSTEM_ADD"), + + /** 用户注册 */ + SYSTEM_REGISTER("SYSTEM_REGISTER"), + + /** 身份源 */ + ID_SOURCE("ID_SOURCE"); + + private final String value; + + SysUserSourceFromTypeEnum(String value) { + this.value = value; + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserExtMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserExtMapper.java new file mode 100644 index 00000000..acb4cf03 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserExtMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.sys.modular.user.entity.SysUserExt; + +/** + * 用户扩展Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface SysUserExtMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserMapper.java index 8ba5affb..20d38c1c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserMapper.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserMapper.java @@ -12,10 +12,7 @@ */ package vip.xiaonuo.sys.modular.user.mapper; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import org.apache.ibatis.annotations.Param; import vip.xiaonuo.sys.modular.user.entity.SysUser; /** @@ -26,12 +23,4 @@ import vip.xiaonuo.sys.modular.user.entity.SysUser; **/ public interface SysUserMapper extends BaseMapper { - /** - * 删除数据并忽略插件(逻辑删除、租户拼接) - * - * @author xuyuxiang - * @date 2023/12/25 23:20 - */ - @InterceptorIgnore(tenantLine = "true") - void deleteIgnoreInterceptor(@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserPasswordMapper.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserPasswordMapper.java new file mode 100644 index 00000000..fc8914c0 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/SysUserPasswordMapper.java @@ -0,0 +1,25 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.sys.modular.user.entity.SysUserPassword; + +/** + * 用户密码Mapper接口 + * + * @author xuyuxiang + * @date 2022/4/21 18:37 + **/ +public interface SysUserPasswordMapper extends BaseMapper { +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserExtMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserExtMapper.xml new file mode 100644 index 00000000..3311e0db --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserExtMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserMapper.xml index 417cdb16..7f058c62 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserMapper.xml +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserMapper.xml @@ -2,8 +2,4 @@ - - - DELETE FROM SYS_USER ${ew.customSqlSegment} - - \ No newline at end of file + diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserPasswordMapper.xml b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserPasswordMapper.xml new file mode 100644 index 00000000..7bec95ba --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/mapper/mapping/SysUserPasswordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserAddParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserAddParam.java index 89a11c11..c5319ead 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserAddParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserAddParam.java @@ -28,22 +28,22 @@ import lombok.Setter; public class SysUserAddParam { /** 账号 */ - @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "账号") @NotBlank(message = "account不能为空") private String account; /** 姓名 */ - @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "姓名") @NotBlank(message = "name不能为空") private String name; /** 组织id */ - @Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "组织id") @NotBlank(message = "orgId不能为空") private String orgId; /** 职位id */ - @Schema(description = "职位id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "职位id") @NotBlank(message = "positionId不能为空") private String positionId; @@ -55,6 +55,10 @@ public class SysUserAddParam { @Schema(description = "主管id") private String directorId; + /** 密码 */ + @Schema(description = "密码") + private String password; + /** 头像 */ @Schema(description = "头像,图片base64") private String avatar; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java new file mode 100644 index 00000000..cb67619b --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindEmailParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 绑定邮箱参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class SysUserBindEmailParam { + + /** 邮箱 */ + @Schema(description = "邮箱") + @NotBlank(message = "email不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindPhoneParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindPhoneParam.java new file mode 100644 index 00000000..5584bada --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserBindPhoneParam.java @@ -0,0 +1,44 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 绑定手机号参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class SysUserBindPhoneParam { + + /** 手机号 */ + @Schema(description = "手机号") + @NotBlank(message = "phone不能为空") + private String phone; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserEditParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserEditParam.java index 86bf26b9..c9986267 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserEditParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserEditParam.java @@ -28,27 +28,27 @@ import lombok.Setter; public class SysUserEditParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 账号 */ - @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "账号") @NotBlank(message = "account不能为空") private String account; /** 姓名 */ - @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "姓名") @NotBlank(message = "name不能为空") private String name; /** 组织id */ - @Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "组织id") @NotBlank(message = "orgId不能为空") private String orgId; /** 职位id */ - @Schema(description = "职位id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "职位id") @NotBlank(message = "positionId不能为空") private String positionId; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByEmailParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByEmailParam.java index 279e9220..90887620 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByEmailParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByEmailParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * 用户找回密码参数 + * 用户通过邮箱找回密码参数 * * @author xuyuxiang * @date 2022/7/26 16:04 @@ -28,22 +28,22 @@ import lombok.Setter; public class SysUserFindPwdByEmailParam { /** 邮箱 */ - @Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮箱") @NotBlank(message = "email不能为空") private String email; /** 验证码 */ - @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码") @NotBlank(message = "validCode不能为空") private String validCode; /** 验证码请求号 */ - @Schema(description = "验证码请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码请求号") @NotBlank(message = "validCodeReqNo不能为空") private String validCodeReqNo; /** 新密码 */ - @Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "新密码") @NotBlank(message = "newPassword不能为空") private String newPassword; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByPhoneParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByPhoneParam.java index f4f9f6e9..d41a60f3 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByPhoneParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserFindPwdByPhoneParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * 用户找回密码参数 + * 用户通过手机号找回密码参数 * * @author xuyuxiang * @date 2022/7/26 16:04 @@ -28,22 +28,22 @@ import lombok.Setter; public class SysUserFindPwdByPhoneParam { /** 手机号 */ - @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "手机号") @NotBlank(message = "phone不能为空") private String phone; /** 验证码 */ - @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码") @NotBlank(message = "validCode不能为空") private String validCode; /** 验证码请求号 */ - @Schema(description = "验证码请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码请求号") @NotBlank(message = "validCodeReqNo不能为空") private String validCodeReqNo; /** 新密码 */ - @Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "新密码") @NotBlank(message = "newPassword不能为空") private String newPassword; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetEmailValidCodeParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetEmailValidCodeParam.java index 840afff6..89e22463 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetEmailValidCodeParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetEmailValidCodeParam.java @@ -28,17 +28,17 @@ import lombok.Setter; public class SysUserGetEmailValidCodeParam { /** 邮箱 */ - @Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "邮箱") @NotBlank(message = "邮箱不能为空") private String email; /** 验证码 */ - @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码") @NotBlank(message = "验证码不能为空") private String validCode; /** 验证码请求号 */ - @Schema(description = "验证码请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码请求号") @NotBlank(message = "验证码请求号不能为空") private String validCodeReqNo; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetPhoneValidCodeParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetPhoneValidCodeParam.java index 14f2b9bb..473f0967 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetPhoneValidCodeParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGetPhoneValidCodeParam.java @@ -28,17 +28,17 @@ import lombok.Setter; public class SysUserGetPhoneValidCodeParam { /** 手机号 */ - @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "手机号") @NotBlank(message = "手机号不能为空") private String phone; /** 验证码 */ - @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码") @NotBlank(message = "验证码不能为空") private String validCode; /** 验证码请求号 */ - @Schema(description = "验证码请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "验证码请求号") @NotBlank(message = "验证码请求号不能为空") private String validCodeReqNo; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantPermissionParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantPermissionParam.java index c5fa21ff..8ada201f 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantPermissionParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantPermissionParam.java @@ -13,12 +13,12 @@ package vip.xiaonuo.sys.modular.user.param; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import javax.validation.Valid; import java.util.List; /** @@ -32,13 +32,13 @@ import java.util.List; public class SysUserGrantPermissionParam { /** 用户id */ - @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "用户id") @NotBlank(message = "id不能为空") private String id; /** 授权权限信息 */ @Valid - @Schema(description = "授权权限信息", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "授权权限信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantResourceParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantResourceParam.java index 023d58e8..8f934c4c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantResourceParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantResourceParam.java @@ -13,12 +13,12 @@ package vip.xiaonuo.sys.modular.user.param; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import javax.validation.Valid; import java.util.List; /** @@ -32,13 +32,13 @@ import java.util.List; public class SysUserGrantResourceParam { /** 用户id */ - @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "用户id") @NotBlank(message = "id不能为空") private String id; /** 授权资源信息 */ @Valid - @Schema(description = "授权资源信息", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "授权资源信息") @NotNull(message = "grantInfoList不能为空") private List grantInfoList; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantRoleParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantRoleParam.java index ca6aab17..769f40d7 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantRoleParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserGrantRoleParam.java @@ -31,12 +31,12 @@ import java.util.List; public class SysUserGrantRoleParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 角色id集合 */ - @Schema(description = "角色id集合", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "角色id集合") @NotNull(message = "roleIdList不能为空") private List roleIdList; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdListParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdListParam.java index 734a5b8f..2b72c6c6 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdListParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdListParam.java @@ -30,7 +30,7 @@ import java.util.List; public class SysUserIdListParam { /** id集合 */ - @Schema(description = "id集合", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id集合") @NotNull(message = "idList不能为空") private List idList; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdParam.java index b8d597ac..4fc94274 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysUserIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserMessageIdParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserMessageIdParam.java index cc280ab6..7ca6fb56 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserMessageIdParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserMessageIdParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysUserMessageIdParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserSignatureParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserSignatureParam.java index 0abb6892..7d8a5689 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserSignatureParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserSignatureParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * 用户修改签名图片接口 + * 用户修改签名图片参数 * * @author yubaoshan * @date 2022/9/7 23:12 @@ -28,7 +28,7 @@ import lombok.Setter; public class SysUserSignatureParam { /** 签名图片base64编码 */ - @Schema(description = "signature", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "signature") @NotBlank(message = "signature签名图片不能为空") private String signature; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateInfoParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateInfoParam.java index 6f8ded9d..e33e01d1 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateInfoParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateInfoParam.java @@ -18,7 +18,7 @@ import lombok.Getter; import lombok.Setter; /** - * 编辑个人信息参数 + * 用户编辑个人信息参数 * * @author xuyuxiang * @date 2022/7/27 17:08 @@ -28,19 +28,15 @@ import lombok.Setter; public class SysUserUpdateInfoParam { /** id */ - @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "id") @NotBlank(message = "id不能为空") private String id; /** 姓名 */ - @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "姓名") @NotBlank(message = "name不能为空") private String name; - /** 手机 */ - @Schema(description = "手机") - private String phone; - /** 昵称 */ @Schema(description = "昵称") private String nickname; @@ -53,10 +49,6 @@ public class SysUserUpdateInfoParam { @Schema(description = "出生日期") private String birthday; - /** 邮箱 */ - @Schema(description = "邮箱") - private String email; - /** 签名 */ @Schema(description = "签名,图片base64") private String signature; diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByEmailParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByEmailParam.java new file mode 100644 index 00000000..40cf7b49 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByEmailParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户通过验证邮箱修改密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class SysUserUpdatePwdByEmailParam { + + /** 邮箱 */ + @Schema(description = "邮箱") + @NotBlank(message = "email不能为空") + private String email; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByOldParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByOldParam.java new file mode 100644 index 00000000..5e10b61e --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByOldParam.java @@ -0,0 +1,39 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户通过验证旧密码修改密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class SysUserUpdatePwdByOldParam { + + /** 旧密码 */ + @Schema(description = "旧密码") + @NotBlank(message = "password不能为空") + private String password; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByPhoneParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByPhoneParam.java new file mode 100644 index 00000000..ff04eb76 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdatePwdByPhoneParam.java @@ -0,0 +1,49 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +/** + * 用户通过验证手机号修改密码参数 + * + * @author xuyuxiang + * @date 2022/7/26 16:04 + **/ +@Getter +@Setter +public class SysUserUpdatePwdByPhoneParam { + + /** 手机号 */ + @Schema(description = "手机号") + @NotBlank(message = "phone不能为空") + private String phone; + + /** 验证码 */ + @Schema(description = "验证码") + @NotBlank(message = "validCode不能为空") + private String validCode; + + /** 验证码请求号 */ + @Schema(description = "验证码请求号") + @NotBlank(message = "validCodeReqNo不能为空") + private String validCodeReqNo; + + /** 新密码 */ + @Schema(description = "新密码") + @NotBlank(message = "newPassword不能为空") + private String newPassword; +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateWorkbenchParam.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateWorkbenchParam.java index 7c097633..9c252f2f 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateWorkbenchParam.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/param/SysUserUpdateWorkbenchParam.java @@ -28,7 +28,7 @@ import lombok.Setter; public class SysUserUpdateWorkbenchParam { /** 工作台数据 */ - @Schema(description = "工作台数据", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "工作台数据") @NotBlank(message = "workbenchData不能为空") private String workbenchData; } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/provider/SysLoginUserApiProvider.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/provider/SysLoginUserApiProvider.java index ed15660a..cece921f 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/provider/SysLoginUserApiProvider.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/provider/SysLoginUserApiProvider.java @@ -12,6 +12,7 @@ */ package vip.xiaonuo.sys.modular.user.provider; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import jakarta.annotation.Resource; @@ -19,6 +20,7 @@ import org.springframework.stereotype.Service; import vip.xiaonuo.auth.api.SaBaseLoginUserApi; import vip.xiaonuo.auth.core.pojo.SaBaseClientLoginUser; import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser; +import vip.xiaonuo.sys.modular.user.entity.SysUser; import vip.xiaonuo.sys.modular.user.result.SysLoginUser; import vip.xiaonuo.sys.modular.user.service.SysUserService; @@ -92,6 +94,11 @@ public class SysLoginUserApiProvider implements SaBaseLoginUserApi { return sysUserService.getUserByPhone(phone); } + @Override + public SaBaseLoginUser getUserByEmail(String email) { + return sysUserService.getUserByEmail(email); + } + /** * 不实现C端用户信息 * @@ -103,6 +110,11 @@ public class SysLoginUserApiProvider implements SaBaseLoginUserApi { return null; } + @Override + public SaBaseClientLoginUser getClientUserByEmail(String email) { + return null; + } + /** * 根据用户id获取用户集合 * @@ -168,4 +180,31 @@ public class SysLoginUserApiProvider implements SaBaseLoginUserApi { public void updateUserLoginInfo(String userId, String device) { sysUserService.updateUserLoginInfo(userId, device); } -} \ No newline at end of file + + @Override + public SaBaseLoginUser createUserWithPhone(String phone) { + SysUser sysUser = sysUserService.createUserWithPhone(phone); + return BeanUtil.copyProperties(sysUser, SysLoginUser.class); + } + + @Override + public SaBaseClientLoginUser createClientUserWithPhone(String phone) { + return null; + } + + @Override + public SaBaseLoginUser createUserWithEmail(String email) { + SysUser sysUser = sysUserService.createUserWithEmail(email); + return BeanUtil.copyProperties(sysUser, SysLoginUser.class); + } + + @Override + public SaBaseClientLoginUser createClientUserWithEmail(String email) { + return null; + } + + @Override + public void doRegister(String account, String password) { + sysUserService.doRegister(account, password); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageDetailResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageDetailResult.java index 32f320ff..c8af7d21 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageDetailResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageDetailResult.java @@ -29,7 +29,7 @@ import java.util.List; public class SysUserMessageDetailResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 分类 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageResult.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageResult.java index a4ed0840..e3406989 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageResult.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/result/SysUserMessageResult.java @@ -29,7 +29,7 @@ import java.util.Date; public class SysUserMessageResult { /** id */ - @Schema(description = "id") + @Schema(description = "主键") private String id; /** 分类 */ diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserExtService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserExtService.java new file mode 100644 index 00000000..27ac58aa --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserExtService.java @@ -0,0 +1,41 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.sys.modular.user.entity.SysUserExt; + +/** + * 用户扩展Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface SysUserExtService extends IService { + + /** + * 更新用户最新修改密码时间 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void updatePasswordLastTime(String userId); + + /** + * 插入扩展信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void createExtInfo(String userId, String sourceFromType); +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserPasswordService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserPasswordService.java new file mode 100644 index 00000000..300b0536 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserPasswordService.java @@ -0,0 +1,43 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import vip.xiaonuo.sys.modular.user.entity.SysUserPassword; + +import java.util.List; + +/** + * 用户密码Service接口 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +public interface SysUserPasswordService extends IService { + + /** + * 追加用户历史密码信息 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + void insertUserPasswordHistory(String userId, String newPassword); + + /** + * 获取用户前N个历史密码 + * + * @author xuyuxiang + * @date 2022/4/27 21:38 + */ + List getUserPasswordHistoryLimit(String userId, int limitValue); +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserService.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserService.java index 6738de1d..9ea8a15c 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserService.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/SysUserService.java @@ -83,7 +83,7 @@ public interface SysUserService extends IService { * @author xuyuxiang * @date 2022/4/24 20:48 */ - void add(SysUserAddParam sysUserAddParam); + void add(SysUserAddParam sysUserAddParam, String sourceFromType); /** * 编辑用户 @@ -182,12 +182,92 @@ public interface SysUserService extends IService { void findPasswordByEmail(SysUserFindPwdByEmailParam sysUserFindPwdByEmailParam); /** - * 修改用户密码 + * 修改密码获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updatePasswordGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam); + + /** + * 修改密码获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updatePasswordGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam); + + /** + * 通过验证旧密码修改用户密码 * * @author xuyuxiang * @date 2022/4/22 15:53 **/ - void updatePassword(SysUserUpdatePwdParam sysUserUpdatePwdParam); + void updatePasswordByOld(SysUserUpdatePwdByOldParam sysUserUpdatePwdByOldParam); + + /** + * 通过验证手机号修改用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void updatePasswordByPhone(SysUserUpdatePwdByPhoneParam sysUserUpdatePwdByPhoneParam); + + /** + * 通过验证邮箱修改用户密码 + * + * @author xuyuxiang + * @date 2022/4/22 15:53 + **/ + void updatePasswordByEmail(SysUserUpdatePwdByEmailParam sysUserUpdatePwdByEmailParam); + + /** + * 绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String bindPhoneGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam); + + /** + * 修改绑定手机号获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updateBindPhoneGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam); + + /** + * 绑定手机号 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void bindPhone(SysUserBindPhoneParam sysUserBindPhoneParam); + + /** + * 绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String bindEmailGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam); + + /** + * 修改绑定邮箱获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + String updateBindEmailGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam); + + /** + * 绑定邮箱 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void bindEmail(SysUserBindEmailParam sysUserBindEmailParam); /** * 修改用户头像返回base64 @@ -471,14 +551,6 @@ public interface SysUserService extends IService { **/ List getPositionListByIdList(SysUserIdListParam sysUserIdListParam); - /** - * 根据id集合获取用户组集合 - * - * @author yubaoshan - * @date 2025/1/12 02:36 - */ - List getGroupListByIdList(SysUserGroupIdListParam sysUserGroupIdListParam); - /** * 根据id集合获取角色集合 * @@ -487,6 +559,14 @@ public interface SysUserService extends IService { **/ List getRoleListByIdList(SysUserIdListParam sysUserIdListParam); + /** + * 根据id集合获取用户组集合 + * + * @author yubaoshan + * @date 2025/1/12 02:36 + */ + List getGroupListByIdList(SysUserGroupIdListParam sysUserGroupIdListParam); + /** * 根据id获取头像 * @@ -494,4 +574,76 @@ public interface SysUserService extends IService { * @date 2023/8/28 10:10 **/ String getAvatarById(SysUserIdParam sysUserIdParam); + + /** + * 根据手机号创建用户 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + SysUser createUserWithPhone(String phone); + + /** + * 根据邮箱创建用户 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + SysUser createUserWithEmail(String email); + + /** + * 根据账号密码创建用户 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + SysUser createUserWithAccount(String account, String password); + + /** + * 判断当前用户是否需要绑定手机号 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + Boolean isUserNeedBindPhone(); + + /** + * 判断当前用户是否需要绑定邮箱 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + Boolean isUserNeedBindEmail(); + + /** + * 判断当前用户密码是否过期 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + Boolean isUserPasswordExpired(); + + /** + * 通知用户密码即将到期 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void noticeUserPasswordAboutToExpired(); + + /** + * 执行注册 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + void doRegister(String account, String password); + + /** + * 获取修改密码验证方式及配置 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + JSONObject getUpdatePasswordValidConfig(); } diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserExtServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserExtServiceImpl.java new file mode 100644 index 00000000..1722c8e2 --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserExtServiceImpl.java @@ -0,0 +1,55 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.sys.modular.user.entity.SysUserExt; +import vip.xiaonuo.sys.modular.user.mapper.SysUserExtMapper; +import vip.xiaonuo.sys.modular.user.service.SysUserExtService; + +/** + * 用户扩展Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class SysUserExtServiceImpl extends ServiceImpl implements SysUserExtService { + + @Override + public void updatePasswordLastTime(String userId) { + SysUserExt sysUserExt = this.getOne(new LambdaQueryWrapper().eq(SysUserExt::getUserId, userId)); + if(ObjectUtil.isEmpty(sysUserExt)){ + sysUserExt = new SysUserExt(); + sysUserExt.setUserId(userId); + sysUserExt.setPasswordUpdateTime(DateTime.now()); + this.save(sysUserExt); + } else { + sysUserExt.setPasswordUpdateTime(DateTime.now()); + this.updateById(sysUserExt); + } + } + + @Override + public void createExtInfo(String userId, String sourceFromType) { + SysUserExt sysUserExt = new SysUserExt(); + sysUserExt.setUserId(userId); + sysUserExt.setSourceFromType(sourceFromType); + sysUserExt.setPasswordUpdateTime(DateTime.now()); + this.save(sysUserExt); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserPasswordServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserPasswordServiceImpl.java new file mode 100644 index 00000000..1cbc776c --- /dev/null +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserPasswordServiceImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.sys.modular.user.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import vip.xiaonuo.common.util.CommonCryptogramUtil; +import vip.xiaonuo.sys.modular.user.entity.SysUserPassword; +import vip.xiaonuo.sys.modular.user.mapper.SysUserPasswordMapper; +import vip.xiaonuo.sys.modular.user.service.SysUserPasswordService; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户密码Service接口实现类 + * + * @author yubaoshan + * @date 2024/12/21 01:25 + **/ +@Service +public class SysUserPasswordServiceImpl extends ServiceImpl implements SysUserPasswordService { + + @Override + public void insertUserPasswordHistory(String userId, String newPassword) { + SysUserPassword sysUserPassword = new SysUserPassword(); + sysUserPassword.setUserId(userId); + sysUserPassword.setPassword(CommonCryptogramUtil.doHashValue(newPassword)); + this.save(sysUserPassword); + } + + @Override + public List getUserPasswordHistoryLimit(String userId, int limitValue) { + return this.page(new Page<>(1, limitValue), new LambdaQueryWrapper() + .eq(SysUserPassword::getUserId, userId).orderByDesc(SysUserPassword::getCreateTime)) + .getRecords().stream().map(SysUserPassword::getPassword).collect(Collectors.toList()); + } +} diff --git a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java index a2817d95..1c030601 100644 --- a/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java +++ b/snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/user/service/impl/SysUserServiceImpl.java @@ -79,6 +79,8 @@ import vip.xiaonuo.mobile.api.MobileButtonApi; import vip.xiaonuo.mobile.api.MobileMenuApi; import vip.xiaonuo.sys.core.enums.SysBuildInEnum; import vip.xiaonuo.sys.core.enums.SysDataTypeEnum; +import vip.xiaonuo.sys.core.util.SysEmailFormatUtl; +import vip.xiaonuo.sys.core.util.SysPasswordUtl; import vip.xiaonuo.sys.modular.group.entity.SysGroup; import vip.xiaonuo.sys.modular.group.service.SysGroupService; import vip.xiaonuo.sys.modular.org.entity.SysOrg; @@ -98,12 +100,18 @@ import vip.xiaonuo.sys.modular.resource.service.SysMenuService; import vip.xiaonuo.sys.modular.resource.service.SysModuleService; import vip.xiaonuo.sys.modular.role.entity.SysRole; import vip.xiaonuo.sys.modular.role.enums.SysRoleDataScopeCategoryEnum; +import vip.xiaonuo.sys.modular.role.param.SysRoleGrantUserParam; import vip.xiaonuo.sys.modular.role.service.SysRoleService; import vip.xiaonuo.sys.modular.user.entity.SysUser; +import vip.xiaonuo.sys.modular.user.entity.SysUserExt; +import vip.xiaonuo.sys.modular.user.enums.SysUpdatePasswordValidTypeEnum; +import vip.xiaonuo.sys.modular.user.enums.SysUserSourceFromTypeEnum; import vip.xiaonuo.sys.modular.user.enums.SysUserStatusEnum; import vip.xiaonuo.sys.modular.user.mapper.SysUserMapper; import vip.xiaonuo.sys.modular.user.param.*; import vip.xiaonuo.sys.modular.user.result.*; +import vip.xiaonuo.sys.modular.user.service.SysUserExtService; +import vip.xiaonuo.sys.modular.user.service.SysUserPasswordService; import vip.xiaonuo.sys.modular.user.service.SysUserService; import java.awt.image.BufferedImage; @@ -123,14 +131,72 @@ import java.util.stream.Collectors; @Service public class SysUserServiceImpl extends ServiceImpl implements SysUserService { - private static final String SNOWY_SYS_DEFAULT_PASSWORD_KEY = "SNOWY_SYS_DEFAULT_PASSWORD"; + /** B端验证码失效时间(适用图片验证码和短信验证码,单位:分钟,默认5分钟有效) */ + private static final String SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B_KEY = "SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B"; + /** B端重置密码验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B"; + + /** B端重置密码验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B"; + + /** B端修改密码验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B"; + + /** B端修改密码验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B"; + + /** B端重置密码成功短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B"; + + /** B端重置密码成功邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B"; + + /** B端密码即将到期短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B"; + + /** B端密码即将到期邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B"; + + /** B端绑定手机验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_B"; + + /** B端绑定邮箱验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_B"; + + /** B端修改绑定手机验证码短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_B"; + + /** B端修改绑定邮箱验证码邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_B"; + + /** B端注册账号成功短信消息模板 */ + private static final String SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B_KEY = "SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B"; + + /** B端注册账号成功邮件消息模板 */ + private static final String SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B_KEY = "SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B"; + + /** B端注册后是否需要绑定手机号 */ + private static final String SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_B_KEY = "SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_B"; + + /** B端注册后是否需要绑定邮箱 */ + private static final String SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_B_KEY = "SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_B"; + + /** B端新用户默认机构 */ + private static final String SNOWY_SYS_DEFAULT_NEW_USER_ORG_FOR_B_KEY = "SNOWY_SYS_DEFAULT_NEW_USER_ORG_FOR_B"; + + /** B端新用户默认职位 */ + private static final String SNOWY_SYS_DEFAULT_NEW_USER_POSITION_FOR_B_KEY = "SNOWY_SYS_DEFAULT_NEW_USER_POSITION_FOR_B"; + + /** B端新用户默认角色 */ + private static final String SNOWY_SYS_DEFAULT_NEW_USER_ROLE_FOR_B_KEY = "SNOWY_SYS_DEFAULT_NEW_USER_ROLE_FOR_B"; + + /** 工作台默认快捷方式 */ private static final String SNOWY_SYS_DEFAULT_WORKBENCH_DATA_KEY = "SNOWY_SYS_DEFAULT_WORKBENCH_DATA"; + /** 验证码缓存前缀 */ private static final String USER_VALID_CODE_CACHE_KEY = "user-validCode:"; - public static final String USER_CACHE_ALL_KEY = "sys-user:all"; - @Resource private CommonCacheOperator commonCacheOperator; @@ -179,6 +245,12 @@ public class SysUserServiceImpl extends ServiceImpl impl @Resource private SysGroupService sysGroupService; + @Resource + private SysUserExtService sysUserExtService; + + @Resource + private SysUserPasswordService sysUserPasswordService; + @Override public SysLoginUser getUserById(String id) { SysUser sysUser = this.getById(id); @@ -244,19 +316,26 @@ public class SysUserServiceImpl extends ServiceImpl impl @Transactional(rollbackFor = Exception.class) @Override - public void add(SysUserAddParam sysUserAddParam) { + public void add(SysUserAddParam sysUserAddParam, String sourceFromType) { checkParam(sysUserAddParam); SysUser sysUser = BeanUtil.toBean(sysUserAddParam, SysUser.class); if (ObjectUtil.isEmpty(sysUser.getAvatar())) { // 设置默认头像 sysUser.setAvatar(CommonAvatarUtil.generateImg(sysUser.getName())); } - // 设置默认密码 - sysUser.setPassword(CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_KEY))); + if(ObjectUtil.isEmpty(sysUser.getPassword())) { + // 设置默认密码 + sysUser.setPassword(CommonCryptogramUtil.doHashValue(SysPasswordUtl.getDefaultPassword())); + } else { + // 设置传入的密码 + sysUser.setPassword(CommonCryptogramUtil.doHashValue(sysUser.getPassword())); + } // 设置状态 sysUser.setUserStatus(SysUserStatusEnum.ENABLE.getValue()); + // 保存用户 this.save(sysUser); - + // 插入扩展信息 + sysUserExtService.createExtInfo(sysUser.getId(), sourceFromType); // 发布增加事件 CommonDataChangeEventCenter.doAddWithData(SysDataTypeEnum.USER.getValue(), JSONUtil.createArray().put(sysUser)); } @@ -276,7 +355,7 @@ public class SysUserServiceImpl extends ServiceImpl impl } } if (ObjectUtil.isNotEmpty(sysUserAddParam.getEmail())) { - if (!CommonEmailUtil.isEmail(sysUserAddParam.getEmail())) { + if (CommonEmailUtil.isNotEmail(sysUserAddParam.getEmail())) { throw new CommonException("邮箱:{}格式错误", sysUserAddParam.getEmail()); } if (this.count(new LambdaQueryWrapper() @@ -297,8 +376,8 @@ public class SysUserServiceImpl extends ServiceImpl impl throw new CommonException("不可修改系统内置超管用户账号"); } BeanUtil.copyProperties(sysUserEditParam, sysUser); + // 更新用户 this.updateById(sysUser); - // 发布更新事件 CommonDataChangeEventCenter.doUpdateWithData(SysDataTypeEnum.USER.getValue(), JSONUtil.createArray().put(sysUser)); } @@ -320,7 +399,7 @@ public class SysUserServiceImpl extends ServiceImpl impl } } if (ObjectUtil.isNotEmpty(sysUserEditParam.getEmail())) { - if (!CommonEmailUtil.isEmail(sysUserEditParam.getEmail())) { + if (CommonEmailUtil.isNotEmail(sysUserEditParam.getEmail())) { throw new CommonException("邮箱:{}格式错误", sysUserEditParam.getEmail()); } if (this.count(new LambdaQueryWrapper() @@ -364,6 +443,9 @@ public class SysUserServiceImpl extends ServiceImpl impl // 执行删除 this.removeByIds(sysUserIdList); + // 删除扩展信息 + sysUserExtService.remove(new LambdaQueryWrapper().in(SysUserExt::getUserId, sysUserIdList)); + // 发布删除事件 CommonDataChangeEventCenter.doDeleteWithDataId(SysDataTypeEnum.USER.getValue(), sysUserIdList); } @@ -382,16 +464,69 @@ public class SysUserServiceImpl extends ServiceImpl impl @Override public void enableUser(SysUserIdParam sysUserIdParam) { - this.update(new LambdaUpdateWrapper().eq(SysUser::getId, sysUserIdParam.getId()).set(SysUser::getUserStatus, SysUserStatusEnum.ENABLE.getValue())); } @Override public void resetPassword(SysUserIdParam sysUserIdParam) { + // 获取用户 + SysUser sysUser = this.queryEntity(sysUserIdParam.getId()); + // 获取默认密码 + String defaultPassword = SysPasswordUtl.getDefaultPassword(); + // 修改密码 this.update(new LambdaUpdateWrapper().eq(SysUser::getId, sysUserIdParam.getId()).set(SysUser::getPassword, - CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_KEY)))); + CommonCryptogramUtil.doHashValue(defaultPassword))); + // 获取手机号 + String phone = sysUser.getPhone(); + // 手机号不为空则发送密码重置成功短信 + if(ObjectUtil.isNotEmpty(phone)){ + // 重置密码成功短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("userNewPassword", defaultPassword); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 编码不为空 + if(ObjectUtil.isNotEmpty(codeValue)){ + try { + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } catch (Exception e) { + log.error(">>> 短信发送失败", e); + } + } + } + } + // 获取手机号 + String email = sysUser.getEmail(); + // 密码不为空则发送密码重置成功邮件 + if(ObjectUtil.isNotEmpty(email)){ + // 重置密码成功邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("userNewPassword", defaultPassword); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap); + try { + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } catch (Exception e) { + log.error(">>> 邮件发送失败", e); + } + } + } } @Override @@ -410,8 +545,10 @@ public class SysUserServiceImpl extends ServiceImpl impl sysUserPicValidCodeResult.setValidCodeBase64(validCodeBase64); // 将请求号返回前端 sysUserPicValidCodeResult.setValidCodeReqNo(validCodeReqNo); - // 将请求号作为key,验证码的值作为value放到redis,用于校验,5分钟有效 - commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + validCodeReqNo, validCode, 5 * 60); + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + validCodeReqNo, validCode, validCodeExpiredDuration); return sysUserPicValidCodeResult; } @@ -447,9 +584,19 @@ public class SysUserServiceImpl extends ServiceImpl impl @Override public String findPasswordGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + return this.getPhoneValidCode(sysUserGetPhoneValidCodeParam, "重置密码验证码短信消息模板编码", SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B_KEY); + } + + /** + * 获取手机验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private String getPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam, String templateCodeName, String templateCodeValue) { // 手机号 String phone = sysUserGetPhoneValidCodeParam.getPhone(); - // 验证码正确则校验手机号格式 + // 校验手机号格式 if (!PhoneUtil.isMobile(phone)) { throw new CommonException("手机号码:{}格式错误", phone); } @@ -457,85 +604,484 @@ public class SysUserServiceImpl extends ServiceImpl impl validValidCode(null, sysUserGetPhoneValidCodeParam.getValidCode(), sysUserGetPhoneValidCodeParam.getValidCodeReqNo()); // 根据手机号获取用户信息,判断用户是否存在 if (ObjectUtil.isEmpty(this.getUserByPhone(phone))) { - throw new CommonException("手机码:{}不存在", phone); + throw new CommonException("手机号码:{}不存在对应用户", phone); } // 生成手机验证码的值,随机6为数字 String phoneValidCode = RandomUtil.randomNumbers(6); // 生成手机验证码的请求号 String phoneValidCodeReqNo = IdWorker.getIdStr(); - - // TODO 使用阿里云执行发送验证码,将验证码作为短信内容的参数变量放入, - // TODO 签名不传则使用系统默认配置的签名,支持传入多个参数,示例:{"name":"张三","number":"15038****76"} - //devSmsApi.sendSmsAliyun(phone, null, "验证码模板号", JSONUtil.toJsonStr(JSONUtil.createObj().set("validCode", phoneValidCode))); - - // TODO 使用腾讯云执行发送验证码,将验证码作为短信内容的参数变量放入, - // TODO sdkAppId和签名不传则使用系统默认配置的sdkAppId和签名,支持传入多个参数,逗号拼接,示例:"张三,15038****76,进行中" - //devSmsApi.sendSmsTencent(null, phone, null, "验证码模板号", phoneValidCode); - - // 将请求号作为key,验证码的值作为value放到redis,用于校验,5分钟有效 - commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, 5 * 60); + // 短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(templateCodeValue); + if(ObjectUtil.isEmpty(smsTemplateCode)){ + throw new CommonException("请联系管理员配置{}", templateCodeName); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("validCode", phoneValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, validCodeExpiredDuration); // 返回请求号 return phoneValidCodeReqNo; } @Override public String findPasswordGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + return this.getEmailValidCode(sysUserGetEmailValidCodeParam, "重置密码验证码邮件消息模板内容", SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B_KEY); + } + + /** + * 获取邮箱验证码 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private String getEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam, String templateContentName, String templateContentValue) { // 邮箱 String email = sysUserGetEmailValidCodeParam.getEmail(); - // 验证码正确则校验邮箱格式 - if (!CommonEmailUtil.isEmail(email)) { + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { throw new CommonException("邮箱:{}格式错误", email); } // 执行校验验证码 validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo()); // 根据邮箱获取用户信息,判断用户是否存在 if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { - throw new CommonException("邮箱:{}不存在", email); + throw new CommonException("邮箱:{}不存在对应用户", email); } // 生成邮箱验证码的值,随机6为数字 String emailValidCode = RandomUtil.randomNumbers(6); // 生成邮箱验证码的请求号 String emailValidCodeReqNo = IdWorker.getIdStr(); - - // TODO 使用本地发送邮件 - String content = "您正在找回密码,验证码为:" + emailValidCode + ",5分钟内有效。"; - devEmailApi.sendTextEmailLocal(email, "找回密码邮件", content, CollectionUtil.newArrayList()); - - // 将请求号作为key,验证码的值作为value放到redis,用于校验,5分钟有效 - commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, 5 * 60); + // 邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(templateContentValue); + if(ObjectUtil.isEmpty(emailTemplateContent)){ + throw new CommonException("请联系管理员配置{}", templateContentName); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("validCode", emailValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, validCodeExpiredDuration); // 返回请求号 return emailValidCodeReqNo; } @Override public void findPasswordByPhone(SysUserFindPwdByPhoneParam sysUserFindPwdByPhoneParam) { + // 再次校验手机号是否合法 + String phone = sysUserFindPwdByPhoneParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 根据手机号获取用户信息,判断用户是否存在 + SysLoginUser sysLoginUser = this.getUserByPhone(phone); + if (ObjectUtil.isEmpty(sysLoginUser)) { + throw new CommonException("手机号码:{}不存在对应用户", phone); + } // 执行校验验证码 - validValidCode(sysUserFindPwdByPhoneParam.getPhone(), sysUserFindPwdByPhoneParam.getValidCode(), sysUserFindPwdByPhoneParam.getValidCodeReqNo()); + validValidCode(phone, sysUserFindPwdByPhoneParam.getValidCode(), sysUserFindPwdByPhoneParam.getValidCodeReqNo()); + // 获取新密码 + String newPassword = CommonCryptogramUtil.doSm2Decrypt(sysUserFindPwdByPhoneParam.getNewPassword()).trim(); + // 校验新密码 + SysPasswordUtl.validNewPassword(sysLoginUser, newPassword); + // 修改密码 this.update(new LambdaUpdateWrapper().eq(SysUser::getPhone, - CommonCryptogramUtil.doSm4CbcEncrypt(sysUserFindPwdByPhoneParam.getPhone())).set(SysUser::getPassword, - CommonCryptogramUtil.doHashValue(CommonCryptogramUtil.doSm2Decrypt(sysUserFindPwdByPhoneParam.getNewPassword())))); + CommonCryptogramUtil.doSm4CbcEncrypt(phone)).set(SysUser::getPassword, + CommonCryptogramUtil.doHashValue(newPassword))); + // 更新用户最新修改密码时间 + sysUserExtService.updatePasswordLastTime(sysLoginUser.getId()); + // 追加用户历史密码信息 + sysUserPasswordService.insertUserPasswordHistory(sysLoginUser.getId(), newPassword); + // 重置密码成功短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("userNewPassword", newPassword); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 编码不为空 + if(ObjectUtil.isNotEmpty(codeValue)){ + try { + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } catch (Exception e) { + log.error(">>> 短信发送失败", e); + } + } + } } @Override public void findPasswordByEmail(SysUserFindPwdByEmailParam sysUserFindPwdByEmailParam) { + // 再次校验邮箱是否合法 + String email = sysUserFindPwdByEmailParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 根据邮箱获取用户信息,判断用户是否存在 + SysLoginUser sysLoginUser = this.getUserByEmail(email); + if (ObjectUtil.isEmpty(sysLoginUser)) { + throw new CommonException("邮箱:{}不存在对应用户", email); + } // 执行校验验证码 - validValidCode(sysUserFindPwdByEmailParam.getEmail(), sysUserFindPwdByEmailParam.getValidCode(), sysUserFindPwdByEmailParam.getValidCodeReqNo()); - this.update(new LambdaUpdateWrapper().eq(SysUser::getEmail, - sysUserFindPwdByEmailParam.getEmail()).set(SysUser::getPassword, - CommonCryptogramUtil.doHashValue(CommonCryptogramUtil.doSm2Decrypt(sysUserFindPwdByEmailParam.getNewPassword())))); + validValidCode(email, sysUserFindPwdByEmailParam.getValidCode(), sysUserFindPwdByEmailParam.getValidCodeReqNo()); + // 获取新密码 + String newPassword = CommonCryptogramUtil.doSm2Decrypt(sysUserFindPwdByEmailParam.getNewPassword()).trim(); + // 更新用户最新修改密码时间 + sysUserExtService.updatePasswordLastTime(sysLoginUser.getId()); + // 追加用户历史密码信息 + sysUserPasswordService.insertUserPasswordHistory(sysLoginUser.getId(), newPassword); + SysPasswordUtl.validNewPassword(sysLoginUser, newPassword); + // 修改密码 + this.update(new LambdaUpdateWrapper().eq(SysUser::getEmail, email).set(SysUser::getPassword, + CommonCryptogramUtil.doHashValue(newPassword))); + // 重置密码成功邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("userNewPassword", newPassword); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + try { + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } catch (Exception e) { + log.error(">>> 邮件发送失败", e); + } + } } @Override - public void updatePassword(SysUserUpdatePwdParam sysUserUpdatePwdParam) { + public String updatePasswordGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + // 判断密码验证方式 + SysPasswordUtl.validUpdatePasswordValidType(SysUpdatePasswordValidTypeEnum.PHONE.getValue()); + return this.getPhoneValidCode(sysUserGetPhoneValidCodeParam, "修改密码验证码短信消息模板编码", SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B_KEY); + } + + @Override + public String updatePasswordGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + // 判断密码验证方式 + SysPasswordUtl.validUpdatePasswordValidType(SysUpdatePasswordValidTypeEnum.EMAIL.getValue()); + return this.getEmailValidCode(sysUserGetEmailValidCodeParam, "修改密码验证码邮件消息模板内容", SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B_KEY); + } + + @Override + public void updatePasswordByOld(SysUserUpdatePwdByOldParam sysUserUpdatePwdByOldParam) { + // 判断密码验证方式 + SysPasswordUtl.validUpdatePasswordValidType(SysUpdatePasswordValidTypeEnum.OLD.getValue()); SysUser sysUser = this.queryEntity(StpUtil.getLoginIdAsString()); - String password = sysUserUpdatePwdParam.getPassword(); - String newPassword = sysUserUpdatePwdParam.getNewPassword(); + String password = CommonCryptogramUtil.doSm2Decrypt(sysUserUpdatePwdByOldParam.getPassword()).trim(); + String newPassword = CommonCryptogramUtil.doSm2Decrypt(sysUserUpdatePwdByOldParam.getNewPassword()).trim(); if (!CommonCryptogramUtil.doHashValue(password).equals(sysUser.getPassword())) { throw new CommonException("原密码错误"); } + // 校验新密码 + SysPasswordUtl.validNewPassword(sysUser, newPassword); + // 修改密码 this.update(new LambdaUpdateWrapper().eq(SysUser::getId, sysUser.getId()).set(SysUser::getPassword, CommonCryptogramUtil.doHashValue(newPassword))); + // 更新用户最新修改密码时间 + sysUserExtService.updatePasswordLastTime(sysUser.getId()); + // 追加用户历史密码信息 + sysUserPasswordService.insertUserPasswordHistory(sysUser.getId(), newPassword); + // 获取手机号 + String phone = sysUser.getPhone(); + // 手机号不为空则发送密码重置成功短信 + if(ObjectUtil.isNotEmpty(phone)){ + // 重置密码成功短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("userNewPassword", newPassword); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 编码不为空 + if(ObjectUtil.isNotEmpty(codeValue)){ + try { + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } catch (Exception e) { + log.error(">>> 短信发送失败", e); + } + } + } + } + // 获取手机号 + String email = sysUser.getEmail(); + // 密码不为空则发送密码重置成功邮件 + if(ObjectUtil.isNotEmpty(email)){ + // 重置密码成功邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("userNewPassword", newPassword); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + try { + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } catch (Exception e) { + log.error(">>> 邮件发送失败", e); + } + } + } + } + + @Override + public void updatePasswordByPhone(SysUserUpdatePwdByPhoneParam sysUserUpdatePwdByPhoneParam) { + // 判断密码验证方式 + SysPasswordUtl.validUpdatePasswordValidType(SysUpdatePasswordValidTypeEnum.PHONE.getValue()); + SysUserFindPwdByPhoneParam sysUserFindPwdByPhoneParam = new SysUserFindPwdByPhoneParam(); + BeanUtil.copyProperties(sysUserUpdatePwdByPhoneParam, sysUserFindPwdByPhoneParam); + this.findPasswordByPhone(sysUserFindPwdByPhoneParam); + } + + @Override + public void updatePasswordByEmail(SysUserUpdatePwdByEmailParam sysUserUpdatePwdByEmailParam) { + // 判断密码验证方式 + SysPasswordUtl.validUpdatePasswordValidType(SysUpdatePasswordValidTypeEnum.EMAIL.getValue()); + SysUserFindPwdByEmailParam sysUserFindPwdByEmailParam = new SysUserFindPwdByEmailParam(); + BeanUtil.copyProperties(sysUserUpdatePwdByEmailParam, sysUserFindPwdByEmailParam); + this.findPasswordByEmail(sysUserFindPwdByEmailParam); + } + + @Override + public String bindPhoneGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + // 手机号 + String phone = sysUserGetPhoneValidCodeParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 执行校验验证码 + validValidCode(null, sysUserGetPhoneValidCodeParam.getValidCode(), sysUserGetPhoneValidCodeParam.getValidCodeReqNo()); + // 根据手机号获取用户信息,判断用户是否存在,如果存在则不能绑定该手机号 + if (ObjectUtil.isNotEmpty(this.getUserByPhone(phone))) { + throw new CommonException("手机号码:{}已存在对应用户", phone); + } + // 生成手机验证码的值,随机6为数字 + String phoneValidCode = RandomUtil.randomNumbers(6); + // 生成手机验证码的请求号 + String phoneValidCodeReqNo = IdWorker.getIdStr(); + // 绑定手机验证码短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_B_KEY); + if(ObjectUtil.isEmpty(smsTemplateCode)){ + throw new CommonException("请联系管理员配置绑定手机验证码短信消息模板编码"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("validCode", phoneValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, validCodeExpiredDuration); + // 返回请求号 + return phoneValidCodeReqNo; + } + + @Override + public String updateBindPhoneGetPhoneValidCode(SysUserGetPhoneValidCodeParam sysUserGetPhoneValidCodeParam) { + // 手机号 + String phone = sysUserGetPhoneValidCodeParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 执行校验验证码 + validValidCode(null, sysUserGetPhoneValidCodeParam.getValidCode(), sysUserGetPhoneValidCodeParam.getValidCodeReqNo()); + // 根据手机号获取用户信息,判断用户是否存在,如果存在则不能绑定该手机号 + if (ObjectUtil.isNotEmpty(this.getUserByPhone(phone))) { + throw new CommonException("手机号码:{}已存在对应用户", phone); + } + // 生成手机验证码的值,随机6为数字 + String phoneValidCode = RandomUtil.randomNumbers(6); + // 生成手机验证码的请求号 + String phoneValidCodeReqNo = IdWorker.getIdStr(); + // 修改绑定手机验证码短信消息模板编码 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_B_KEY); + if(ObjectUtil.isEmpty(smsTemplateCode)){ + throw new CommonException("请联系管理员配置修改绑定手机验证码短信消息模板编码"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone).set("validCode", phoneValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + phone + StrUtil.UNDERLINE + phoneValidCodeReqNo, phoneValidCode, validCodeExpiredDuration); + // 返回请求号 + return phoneValidCodeReqNo; + } + + @Override + public void bindPhone(SysUserBindPhoneParam sysUserBindPhoneParam) { + // 再次校验手机号是否合法 + String phone = sysUserBindPhoneParam.getPhone(); + // 校验手机号格式 + if (!PhoneUtil.isMobile(phone)) { + throw new CommonException("手机号码:{}格式错误", phone); + } + // 根据手机号获取用户信息,判断用户是否存在,如果存在则不能绑定该手机号 + if (ObjectUtil.isNotEmpty(this.getUserByPhone(phone))) { + throw new CommonException("手机号码:{}已存在对应用户", phone); + } + // 执行校验验证码 + validValidCode(phone, sysUserBindPhoneParam.getValidCode(), sysUserBindPhoneParam.getValidCodeReqNo()); + // 修改手机号 + this.update(new LambdaUpdateWrapper().eq(SysUser::getId, StpUtil.getLoginIdAsString()) + .set(SysUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(phone))); + } + + @Override + public String bindEmailGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + // 邮箱 + String email = sysUserGetEmailValidCodeParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 执行校验验证码 + validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo()); + // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 + if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + throw new CommonException("邮箱:{}已存在对应用户", email); + } + // 生成邮箱验证码的值,随机6为数字 + String emailValidCode = RandomUtil.randomNumbers(6); + // 生成邮箱验证码的请求号 + String emailValidCodeReqNo = IdWorker.getIdStr(); + // 绑定邮箱验证码邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_B_KEY); + if(ObjectUtil.isEmpty(emailTemplateContent)){ + throw new CommonException("请联系管理员配置绑定邮箱验证码邮件消息模板内容"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("validCode", emailValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, validCodeExpiredDuration); + // 返回请求号 + return emailValidCodeReqNo; + } + + @Override + public String updateBindEmailGetEmailValidCode(SysUserGetEmailValidCodeParam sysUserGetEmailValidCodeParam) { + // 邮箱 + String email = sysUserGetEmailValidCodeParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 执行校验验证码 + validValidCode(null, sysUserGetEmailValidCodeParam.getValidCode(), sysUserGetEmailValidCodeParam.getValidCodeReqNo()); + // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 + if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + throw new CommonException("邮箱:{}已存在对应用户", email); + } + // 生成邮箱验证码的值,随机6为数字 + String emailValidCode = RandomUtil.randomNumbers(6); + // 生成邮箱验证码的请求号 + String emailValidCodeReqNo = IdWorker.getIdStr(); + // 修改绑定邮箱验证码邮件消息模板内容 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_B_KEY); + if(ObjectUtil.isEmpty(emailTemplateContent)){ + throw new CommonException("请联系管理员配置修改绑定邮箱验证码邮件消息模板内容"); + } + // 获取验证码失效时间(单位:秒) + long validCodeExpiredDuration = this.getValidCodeExpiredDuration(); + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email).set("validCode", emailValidCode) + .set("validTime", validCodeExpiredDuration/60); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + // 将请求号作为key,验证码的值作为value放到redis,用于校验 + commonCacheOperator.put(USER_VALID_CODE_CACHE_KEY + email + StrUtil.UNDERLINE + emailValidCodeReqNo, emailValidCode, validCodeExpiredDuration); + // 返回请求号 + return emailValidCodeReqNo; + } + + @Override + public void bindEmail(SysUserBindEmailParam sysUserBindEmailParam) { + // 再次校验邮箱是否合法 + String email = sysUserBindEmailParam.getEmail(); + // 校验邮箱格式 + if (CommonEmailUtil.isNotEmail(email)) { + throw new CommonException("邮箱:{}格式错误", email); + } + // 根据邮箱获取用户信息,判断用户是否存在,如果存在则不能绑定该邮箱 + if (ObjectUtil.isEmpty(this.getUserByEmail(email))) { + throw new CommonException("邮箱:{}已存在对应用户", email); + } + // 执行校验验证码 + validValidCode(email, sysUserBindEmailParam.getValidCode(), sysUserBindEmailParam.getValidCodeReqNo()); + // 修改邮箱 + this.update(new LambdaUpdateWrapper().eq(SysUser::getId, StpUtil.getLoginIdAsString()) + .set(SysUser::getEmail, email)); } @Override @@ -629,7 +1175,7 @@ public class SysUserServiceImpl extends ServiceImpl impl // 获取拥有的菜单列表 List menuList = allMenuList.stream().filter(sysMenu -> - menuIdList.contains(sysMenu.getId())).collect(Collectors.toList()); + menuIdList.contains(sysMenu.getId())).toList(); // 对获取到的角色对应的菜单列表进行处理,获取父列表 menuList.forEach(sysMenu -> execRecursionFindParent(allMenuList, sysMenu.getId(), resultList)); @@ -703,7 +1249,7 @@ public class SysUserServiceImpl extends ServiceImpl impl if (!sysMenu.getMenuType().equals(SysResourceMenuTypeEnum.CATALOG.getValue())) { metaJsonObject.set("type", sysMenu.getMenuType().toLowerCase()); } - if (sysMenu.getId().equals(sysMenus.orElse(null).getId())) { + if (sysMenus.orElse(null) != null && sysMenu.getId().equals(sysMenus.orElse(null).getId())) { // 如果是首页,则设置affix metaJsonObject.set("affix", true); } @@ -714,12 +1260,12 @@ public class SysUserServiceImpl extends ServiceImpl impl } menuJsonObject.set("meta", metaJsonObject); return menuJsonObject; - }).collect(Collectors.toList()); + }).toList(); // 执行构造树 List> treeNodeList = resultJsonObjectList.stream().map(jsonObject -> - new TreeNode<>(jsonObject.getStr("id"), jsonObject.getStr("parentId"), - jsonObject.getStr("title"), jsonObject.getInt("sortCode")).setExtra(JSONUtil.parseObj(jsonObject))) + new TreeNode<>(jsonObject.getStr("id"), jsonObject.getStr("parentId"), + jsonObject.getStr("title"), jsonObject.getInt("sortCode")).setExtra(JSONUtil.parseObj(jsonObject))) .collect(Collectors.toList()); return TreeUtil.build(treeNodeList, "0"); } @@ -801,10 +1347,10 @@ public class SysUserServiceImpl extends ServiceImpl impl } } } + List extJsonList = sysUserGrantResourceParam.getGrantInfoList().stream() + .map(JSONUtil::toJsonStr).collect(Collectors.toList()); + sysRelationService.saveRelationBatchWithClear(sysUserGrantResourceParam.getId(), menuIdList, SysRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue(), extJsonList); } - List extJsonList = sysUserGrantResourceParam.getGrantInfoList().stream() - .map(JSONUtil::toJsonStr).collect(Collectors.toList()); - sysRelationService.saveRelationBatchWithClear(sysUserGrantResourceParam.getId(), menuIdList, SysRelationCategoryEnum.SYS_USER_HAS_RESOURCE.getValue(), extJsonList); } @Override @@ -832,8 +1378,13 @@ public class SysUserServiceImpl extends ServiceImpl impl public List> loginOrgTree(SysUserIdParam sysUserIdParam) { SysUser sysUser = this.queryEntity(sysUserIdParam.getId()); List originDataList = sysOrgService.getAllOrgList(); - List sysOrgList = sysOrgService.getParentListById(originDataList, sysUser.getOrgId(), true); - List> treeNodeList = sysOrgList.stream().map(sysOrg -> { + // 构建一个根组织 + SysOrg rootSysOrg = new SysOrg(); + rootSysOrg.setId("0"); + rootSysOrg.setParentId("-1"); + rootSysOrg.setName("根组织"); + originDataList.add(rootSysOrg); + List> treeNodeList = originDataList.stream().map(sysOrg -> { TreeNode treeNode = new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(), sysOrg.getName(), sysOrg.getSortCode()); if (sysOrg.getId().equals(sysUser.getOrgId())) { treeNode.setExtra(JSONUtil.createObj().set("style", JSONUtil.createObj().set("color", "#FFF") @@ -841,35 +1392,21 @@ public class SysUserServiceImpl extends ServiceImpl impl } return treeNode; }).collect(Collectors.toList()); - return TreeUtil.build(treeNodeList, "0", new TreeNodeConfig().setParentIdKey("pid") + return TreeUtil.build(treeNodeList, "-1", new TreeNodeConfig().setParentIdKey("pid") .setNameKey("label"), new DefaultNodeParser<>()); } @Override public void updateUserInfo(SysUserUpdateInfoParam sysUserUpdateInfoParam) { String id = StpLoginUserUtil.getLoginUser().getId(); - if (!StrUtil.equals(id,sysUserUpdateInfoParam.getId())){ - throw new CommonException("禁止修改他人信息"); + if (!StrUtil.equals(id, sysUserUpdateInfoParam.getId())){ + throw new CommonException("被修改用户与当前登录用户不匹配"); } - SysUser sysUser = this.queryEntity(sysUserUpdateInfoParam.getId()); - - if (ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getPhone())) { - if (!PhoneUtil.isMobile(sysUserUpdateInfoParam.getPhone())) { - throw new CommonException("手机号码:{}格式错误", sysUserUpdateInfoParam.getPhone()); - } - if (this.count(new LambdaQueryWrapper().ne(SysUser::getId, sysUser.getId()) - .eq(SysUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(sysUserUpdateInfoParam.getPhone()))) > 0) { - throw new CommonException("存在重复的手机号,手机号为:{}", sysUserUpdateInfoParam.getPhone()); - } - } LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper().eq(SysUser::getId, sysUser.getId()); if(ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getName())) { lambdaUpdateWrapper.set(SysUser::getName, sysUserUpdateInfoParam.getName()); } - if(ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getPhone())) { - lambdaUpdateWrapper.set(SysUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(sysUserUpdateInfoParam.getPhone())); - } if(ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getNickname())) { lambdaUpdateWrapper.set(SysUser::getNickname, sysUserUpdateInfoParam.getNickname()); } @@ -879,12 +1416,6 @@ public class SysUserServiceImpl extends ServiceImpl impl if(ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getBirthday())) { lambdaUpdateWrapper.set(SysUser::getBirthday, sysUserUpdateInfoParam.getBirthday()); } - if(ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getEmail())) { - lambdaUpdateWrapper.set(SysUser::getEmail, sysUserUpdateInfoParam.getEmail()); - } - if(ObjectUtil.isNotEmpty(sysUserUpdateInfoParam.getSignature())) { - lambdaUpdateWrapper.set(SysUser::getSignature, sysUserUpdateInfoParam.getSignature()); - } // 更新指定字段 this.update(lambdaUpdateWrapper); } @@ -951,7 +1482,7 @@ public class SysUserServiceImpl extends ServiceImpl impl } }); if (ObjectUtil.isNotEmpty(buttonIdList)) { - return mobileButtonApi.listByIds(buttonIdList); + return mobileButtonApi.listButtonCodeListByIdList(buttonIdList); } return CollectionUtil.newArrayList(); } @@ -969,10 +1500,10 @@ public class SysUserServiceImpl extends ServiceImpl impl public List getScopeListByMap(Map> groupMap, String orgId) { List resultList = CollectionUtil.newArrayList(); List sysOrgList = sysOrgService.getAllOrgList(); - List scopeAllList = sysOrgList.stream().map(SysOrg::getId).collect(Collectors.toList()); + List scopeAllList = sysOrgList.stream().map(SysOrg::getId).toList(); List scopeOrgList = CollectionUtil.newArrayList(orgId); List scopeOrgChildList = sysOrgService.getChildListById(sysOrgList, orgId, true) - .stream().map(SysOrg::getId).collect(Collectors.toList()); + .stream().map(SysOrg::getId).toList(); groupMap.forEach((key, value) -> { JSONObject jsonObject = JSONUtil.createObj().set("apiUrl", key); Set scopeSet = CollectionUtil.newHashSet(); @@ -1139,7 +1670,7 @@ public class SysUserServiceImpl extends ServiceImpl impl // 设置默认头像 sysUser.setAvatar(CommonAvatarUtil.generateImg(sysUser.getName())); // 设置默认密码 - sysUser.setPassword(CommonCryptogramUtil.doHashValue(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_PASSWORD_KEY))); + sysUser.setPassword(CommonCryptogramUtil.doHashValue(SysPasswordUtl.getDefaultPassword())); // 设置排序码 sysUser.setSortCode(99); // 设置状态 @@ -1160,6 +1691,10 @@ public class SysUserServiceImpl extends ServiceImpl impl // 保存或更新 this.saveOrUpdate(sysUser); + // 如果是增加,则同时增加用户扩展信息 + if(isAdd) { + sysUserExtService.createExtInfo(sysUser.getId(), SysUserSourceFromTypeEnum.SYSTEM_ADD.getValue()); + } // 返回成功 return JSONUtil.createObj().set("success", true); } catch (Exception e) { @@ -1427,7 +1962,8 @@ public class SysUserServiceImpl extends ServiceImpl impl public Page getAllUserSelectorList() { return this.page(CommonPageRequest.defaultPage(), new LambdaQueryWrapper().select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, SysUser::getName, - SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate).orderByAsc(SysUser::getSortCode)); + SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate) + .eq(SysUser::getUserStatus, SysUserStatusEnum.ENABLE.getValue()).orderByAsc(SysUser::getSortCode)); } /* ====用户部分所需要用到的选择器==== */ @@ -1436,66 +1972,68 @@ public class SysUserServiceImpl extends ServiceImpl impl public List> orgTreeSelector() { List sysOrgList = sysOrgService.getAllOrgList(); List> treeNodeList = sysOrgList.stream().map(sysOrg -> - new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(), sysOrg.getName(), sysOrg.getSortCode())) + new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(), sysOrg.getName(), sysOrg.getSortCode())) .collect(Collectors.toList()); return TreeUtil.build(treeNodeList, "0"); } @Override public Page orgListSelector(SysUserSelectorOrgListParam sysUserSelectorOrgListParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - lambdaQueryWrapper.select(SysOrg::getId, SysOrg::getParentId, SysOrg::getName, + queryWrapper.lambda().select(SysOrg::getId, SysOrg::getParentId, SysOrg::getName, SysOrg::getCategory, SysOrg::getSortCode); if (ObjectUtil.isNotEmpty(sysUserSelectorOrgListParam.getParentId())) { - lambdaQueryWrapper.eq(SysOrg::getParentId, sysUserSelectorOrgListParam.getParentId()); + queryWrapper.lambda().eq(SysOrg::getParentId, sysUserSelectorOrgListParam.getParentId()); } if (ObjectUtil.isNotEmpty(sysUserSelectorOrgListParam.getSearchKey())) { - lambdaQueryWrapper.like(SysOrg::getName, sysUserSelectorOrgListParam.getSearchKey()); + queryWrapper.lambda().like(SysOrg::getName, sysUserSelectorOrgListParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysOrg::getSortCode); - return sysOrgService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysOrg::getSortCode); + return sysOrgService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @Override public Page positionSelector(SysUserSelectorPositionParam sysUserSelectorPositionParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); // 查询部分字段 - lambdaQueryWrapper.select(SysPosition::getId, SysPosition::getOrgId, SysPosition::getName, + queryWrapper.lambda().select(SysPosition::getId, SysPosition::getOrgId, SysPosition::getName, SysPosition::getCategory, SysPosition::getSortCode); if (ObjectUtil.isNotEmpty(sysUserSelectorPositionParam.getOrgId())) { - lambdaQueryWrapper.eq(SysPosition::getOrgId, sysUserSelectorPositionParam.getOrgId()); + queryWrapper.lambda().eq(SysPosition::getOrgId, sysUserSelectorPositionParam.getOrgId()); } if (ObjectUtil.isNotEmpty(sysUserSelectorPositionParam.getSearchKey())) { - lambdaQueryWrapper.like(SysPosition::getName, sysUserSelectorPositionParam.getSearchKey()); + queryWrapper.lambda().like(SysPosition::getName, sysUserSelectorPositionParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysPosition::getSortCode); - return sysPositionService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysPosition::getSortCode); + return sysPositionService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @Override public Page roleSelector(SysUserSelectorRoleParam sysUserSelectorRoleParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.select(SysRole::getId, SysRole::getOrgId, SysRole::getName, + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + queryWrapper.lambda().select(SysRole::getId, SysRole::getOrgId, SysRole::getName, SysRole::getCode, SysRole::getCategory, SysRole::getSortCode); if (ObjectUtil.isNotEmpty(sysUserSelectorRoleParam.getOrgId())) { - lambdaQueryWrapper.eq(SysRole::getOrgId, sysUserSelectorRoleParam.getOrgId()); + queryWrapper.lambda().eq(SysRole::getOrgId, sysUserSelectorRoleParam.getOrgId()); } if (ObjectUtil.isNotEmpty(sysUserSelectorRoleParam.getCategory())) { - lambdaQueryWrapper.eq(SysRole::getCategory, sysUserSelectorRoleParam.getCategory()); + queryWrapper.lambda().eq(SysRole::getCategory, sysUserSelectorRoleParam.getCategory()); } if (ObjectUtil.isNotEmpty(sysUserSelectorRoleParam.getSearchKey())) { - lambdaQueryWrapper.like(SysRole::getName, sysUserSelectorRoleParam.getSearchKey()); + queryWrapper.lambda().like(SysRole::getName, sysUserSelectorRoleParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysRole::getSortCode); - return sysRoleService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysRole::getSortCode); + return sysRoleService.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } @Override public Page userSelector(SysUserSelectorUserParam sysUserSelectorUserParam) { - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + QueryWrapper queryWrapper = new QueryWrapper().checkSqlInjection(); + // 只查询状态为正常的 + queryWrapper.lambda().eq(SysUser::getUserStatus, SysUserStatusEnum.ENABLE.getValue()); // 只查询部分字段 - lambdaQueryWrapper.select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, + queryWrapper.lambda().select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount, SysUser::getName, SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate); // 如果查询条件为空,则直接查询 if(ObjectUtil.isAllEmpty(sysUserSelectorUserParam.getOrgId(), sysUserSelectorUserParam.getSearchKey())) { @@ -1504,18 +2042,18 @@ public class SysUserServiceImpl extends ServiceImpl impl if (ObjectUtil.isNotEmpty(sysUserSelectorUserParam.getOrgId())) { // 如果组织id不为空,则查询该组织及其子组织下的所有人 List childOrgIdList = CollStreamUtil.toList(sysOrgService.getChildListById(sysOrgService - .getAllOrgList(), sysUserSelectorUserParam.getOrgId(), true), SysOrg::getId); + .getAllOrgList(), sysUserSelectorUserParam.getOrgId(), true), SysOrg::getId); if (ObjectUtil.isNotEmpty(childOrgIdList)) { - lambdaQueryWrapper.in(SysUser::getOrgId, childOrgIdList); + queryWrapper.lambda().in(SysUser::getOrgId, childOrgIdList); } else { return new Page<>(); } } if (ObjectUtil.isNotEmpty(sysUserSelectorUserParam.getSearchKey())) { - lambdaQueryWrapper.like(SysUser::getName, sysUserSelectorUserParam.getSearchKey()); + queryWrapper.lambda().like(SysUser::getName, sysUserSelectorUserParam.getSearchKey()); } - lambdaQueryWrapper.orderByAsc(SysUser::getSortCode); - return this.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper); + queryWrapper.lambda().orderByAsc(SysUser::getSortCode); + return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda()); } } @@ -1570,18 +2108,6 @@ public class SysUserServiceImpl extends ServiceImpl impl return sysPositionService.list(lambdaQueryWrapper); } - @Override - public List getGroupListByIdList(SysUserGroupIdListParam sysUserGroupIdListParam) { - if (ObjectUtil.isEmpty(sysUserGroupIdListParam.getIdList())) { - return CollectionUtil.newArrayList(); - } - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - // 查询部分字段 - lambdaQueryWrapper.select(SysGroup::getId, SysGroup::getName, SysGroup::getRemark, SysGroup::getSortCode) - .in(SysGroup::getId, sysUserGroupIdListParam.getIdList()).orderByAsc(SysGroup::getSortCode); - return sysGroupService.list(lambdaQueryWrapper); - } - @Override public List getRoleListByIdList(SysUserIdListParam sysUserIdListParam) { if (ObjectUtil.isEmpty(sysUserIdListParam.getIdList())) { @@ -1595,8 +2121,300 @@ public class SysUserServiceImpl extends ServiceImpl impl return sysRoleService.list(lambdaQueryWrapper); } + @Override + public List getGroupListByIdList(SysUserGroupIdListParam sysUserGroupIdListParam) { + if (ObjectUtil.isEmpty(sysUserGroupIdListParam.getIdList())) { + return CollectionUtil.newArrayList(); + } + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + // 查询部分字段 + lambdaQueryWrapper.select(SysGroup::getId, SysGroup::getName, SysGroup::getRemark, SysGroup::getSortCode) + .in(SysGroup::getId, sysUserGroupIdListParam.getIdList()).orderByAsc(SysGroup::getSortCode); + return sysGroupService.list(lambdaQueryWrapper); + } + @Override public String getAvatarById(SysUserIdParam sysUserIdParam) { return this.detail(sysUserIdParam).getAvatar(); } + + @Transactional(rollbackFor = Exception.class) + @Override + public SysUser createUserWithPhone(String phone) { + SysUserAddParam sysUserAddParam = new SysUserAddParam(); + sysUserAddParam.setAccount(phone); + sysUserAddParam.setName(phone); + sysUserAddParam.setPhone(phone); + sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId()); + sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId()); + // 保存用户 + this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); + // 获取用户信息 + SysUser sysUser = this.getOne(new LambdaQueryWrapper().eq(SysUser::getPhone, CommonCryptogramUtil.doSm4CbcEncrypt(phone))); + // 授权默认角色 + SysRoleGrantUserParam sysRoleGrantUserParam = new SysRoleGrantUserParam(); + sysRoleGrantUserParam.setId(this.getDefaultNewUserRoleId()); + sysRoleGrantUserParam.setGrantInfoList(CollectionUtil.newArrayList(sysUser.getId())); + sysRoleService.grantUser(sysRoleGrantUserParam); + // 发送注册成功短信 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } + // 返回用户 + return sysUser; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public SysUser createUserWithEmail(String email) { + SysUserAddParam sysUserAddParam = new SysUserAddParam(); + sysUserAddParam.setAccount(email); + sysUserAddParam.setName(email); + sysUserAddParam.setEmail(email); + sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId()); + sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId()); + // 保存用户 + this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); + // 获取用户信息 + SysUser sysUser = this.getOne(new LambdaQueryWrapper().eq(SysUser::getEmail, email)); + // 授权默认角色 + SysRoleGrantUserParam sysRoleGrantUserParam = new SysRoleGrantUserParam(); + sysRoleGrantUserParam.setId(this.getDefaultNewUserRoleId()); + sysRoleGrantUserParam.setGrantInfoList(CollectionUtil.newArrayList(sysUser.getId())); + sysRoleService.grantUser(sysRoleGrantUserParam); + // 发送注册成功邮件 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B_KEY); + // 不为空才发送 + if(ObjectUtil.isNotEmpty(emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } + // 返回用户 + return sysUser; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public SysUser createUserWithAccount(String account, String password) { + SysUserAddParam sysUserAddParam = new SysUserAddParam(); + sysUserAddParam.setAccount(account); + sysUserAddParam.setName(account); + sysUserAddParam.setPassword(password); + sysUserAddParam.setOrgId(this.getDefaultNewUserOrgId()); + sysUserAddParam.setPositionId(this.getDefaultNewUserPositionId()); + // 保存用户 + this.add(sysUserAddParam, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue()); + // 获取用户信息 + SysUser sysUser = this.getOne(new LambdaQueryWrapper().eq(SysUser::getAccount, account)); + // 授权默认角色 + SysRoleGrantUserParam sysRoleGrantUserParam = new SysRoleGrantUserParam(); + sysRoleGrantUserParam.setId(this.getDefaultNewUserRoleId()); + sysRoleGrantUserParam.setGrantInfoList(CollectionUtil.newArrayList(sysUser.getId())); + sysRoleService.grantUser(sysRoleGrantUserParam); + // 返回用户 + return sysUser; + } + + @Override + public Boolean isUserNeedBindPhone() { + // 获取当前用户 + SysUser sysUser = this.queryEntity(StpUtil.getLoginIdAsString()); + // 查询当前用户是否注册的 + SysUserExt sysUserExt = sysUserExtService.getOne(new LambdaQueryWrapper().eq(SysUserExt::getUserId, StpUtil.getLoginIdAsString()) + .eq(SysUserExt::getSourceFromType, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue())); + // 不为空,则判断手机号是否为空 + if(ObjectUtil.isNotEmpty(sysUserExt)){ + // 手机号为空,判断系统注册后是否需要绑定手机号 + if(ObjectUtil.isEmpty(sysUser.getPhone())) { + String registerNeedBindPhone = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(registerNeedBindPhone)){ + return Convert.toBool(registerNeedBindPhone); + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + @Override + public Boolean isUserNeedBindEmail() { + // 获取当前用户 + SysUser sysUser = this.queryEntity(StpUtil.getLoginIdAsString()); + // 查询当前用户是否注册的 + SysUserExt sysUserExt = sysUserExtService.getOne(new LambdaQueryWrapper().eq(SysUserExt::getUserId, StpUtil.getLoginIdAsString()) + .eq(SysUserExt::getSourceFromType, SysUserSourceFromTypeEnum.SYSTEM_REGISTER.getValue())); + // 不为空,则判断邮箱是否为空 + if(ObjectUtil.isNotEmpty(sysUserExt)){ + // 邮箱为空,判断系统注册后是否需要绑定邮箱 + if(ObjectUtil.isEmpty(sysUser.getEmail())) { + String registerNeedBindEmail = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_B_KEY); + if(ObjectUtil.isNotEmpty(registerNeedBindEmail)){ + return Convert.toBool(registerNeedBindEmail); + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + /** + * 获取新用户默认机构配置 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private String getDefaultNewUserOrgId() { + String defaultNewUserOrgId = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_NEW_USER_ORG_FOR_B_KEY); + if(ObjectUtil.isEmpty(defaultNewUserOrgId)){ + throw new CommonException("请联系管理员配置新用户默认机构"); + } + return defaultNewUserOrgId; + } + + /** + * 获取新用户默认职位配置 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private String getDefaultNewUserPositionId() { + String defaultNewUserPositionId = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_NEW_USER_POSITION_FOR_B_KEY); + if(ObjectUtil.isEmpty(defaultNewUserPositionId)){ + throw new CommonException("请联系管理员配置新用户默认职位"); + } + return defaultNewUserPositionId; + } + + /** + * 获取新用户默认角色配置 + * + * @author xuyuxiang + * @date 2022/8/25 15:16 + **/ + private String getDefaultNewUserRoleId() { + String defaultNewUserRoleId = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_NEW_USER_ROLE_FOR_B_KEY); + if(ObjectUtil.isEmpty(defaultNewUserRoleId)){ + throw new CommonException("请联系管理员配置新用户默认角色"); + } + return defaultNewUserRoleId; + } + + @Override + public Boolean isUserPasswordExpired() { + return SysPasswordUtl.isUserPasswordExpired(StpUtil.getLoginIdAsString()); + } + + @Override + public void noticeUserPasswordAboutToExpired() { + // 密码即将到期短信消息模板 + String smsTemplateCode = devConfigApi.getValueByKey(SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B_KEY); + // 密码即将到期邮件消息模板 + String emailTemplateContent = devConfigApi.getValueByKey(SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B_KEY); + // 获取今日需要提醒密码到期的用户集合 + SysPasswordUtl.thisDayPasswordExpiredNeedNoticeUserIdList().forEach(sysUser -> { + // 获取手机号 + String phone = sysUser.getPhone(); + // 不为空才发送 + if(ObjectUtil.isAllNotEmpty(phone, smsTemplateCode)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(smsTemplateCode); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userPhone", phone); + // 获取编码 + String codeValue = contentJSONObject.getStr("code"); + // 编码不为空 + if(ObjectUtil.isNotEmpty(codeValue)){ + try { + // 发送短信 + devSmsApi.sendDynamicSms(phone, codeValue, paramMap); + } catch (Exception e) { + log.error(">>> 短信发送失败", e); + } + } + } + // 获取邮箱 + String email = sysUser.getEmail(); + // 不为空才发送 + if(ObjectUtil.isAllNotEmpty(email, emailTemplateContent)){ + // 模板内容转为JSONObject + JSONObject contentJSONObject = JSONUtil.parseObj(emailTemplateContent); + // 定义变量参数 + JSONObject paramMap = JSONUtil.createObj().set("userEmail", email); + // 获取格式化后的主题 + String subject = SysEmailFormatUtl.format(contentJSONObject.getStr("subject"), paramMap);; + // 获取格式化后的内容 + String content = SysEmailFormatUtl.format(contentJSONObject.getStr("content"), paramMap);; + try { + // 发送邮件 + devEmailApi.sendDynamicHtmlEmail(email, subject, content); + } catch (Exception e) { + log.error(">>> 邮件发送失败", e); + } + } + }); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void doRegister(String account, String password) { + // 校验账号 + SysLoginUser sysLoginUser = this.getUserByAccount(account); + if(ObjectUtil.isNotEmpty(sysLoginUser)) { + throw new CommonException("账号已存在"); + } + // 校验密码 + SysPasswordUtl.validNewPassword(password); + // 根据账号密码创建用户 + this.createUserWithAccount(account, password); + } + + @Override + public JSONObject getUpdatePasswordValidConfig() { + return SysPasswordUtl.getUpdatePasswordValidConfig(); + } + + /** + * 获取验证码失效时间(单位:秒) + * + * @author xuyuxiang + * @date 2025/3/21 20:25 + **/ + private long getValidCodeExpiredDuration() { + // 默认5分钟 + int defaultExpiredTime = 5; + // 获取配置验证码失效时间 + String configCaptchaExpiredDuration = devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B_KEY); + // 判断是否为空 + if(ObjectUtil.isNotEmpty(configCaptchaExpiredDuration)){ + // 配置了则使用配置的失效时间 + defaultExpiredTime = Convert.toInt(configCaptchaExpiredDuration); + } + // 转为秒 + return defaultExpiredTime * 60L; + } } diff --git a/snowy-web-app/pom.xml b/snowy-web-app/pom.xml index 713a3f22..3f7aa18b 100644 --- a/snowy-web-app/pom.xml +++ b/snowy-web-app/pom.xml @@ -16,6 +16,7 @@ + junit @@ -37,9 +38,9 @@ - - com.mysql - mysql-connector-j + + com.mysql + mysql-connector-j @@ -52,8 +53,8 @@ - diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java index 4199eef4..c7b8fada 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java @@ -147,9 +147,6 @@ public class GlobalConfigure implements WebMvcConfigurer { /* 系统字典树 */ "/dev/dict/tree", - /* 文件下载 */ - "/dev/file/download", - /* 用户个人中心相关 */ "/sys/userCenter/getPicCaptcha", "/sys/userCenter/findPasswordGetPhoneValidCode", @@ -576,29 +573,19 @@ public class GlobalConfigure implements WebMvcConfigurer { @Component public static class CustomMetaObjectHandler implements MetaObjectHandler { - /** - * 删除标志 - */ + /** 删除标志 */ private static final String DELETE_FLAG = "deleteFlag"; - /** - * 创建人 - */ + /** 创建人 */ private static final String CREATE_USER = "createUser"; - /** - * 创建时间 - */ + /** 创建时间 */ private static final String CREATE_TIME = "createTime"; - /** - * 更新人 - */ + /** 更新人 */ private static final String UPDATE_USER = "updateUser"; - /** - * 更新时间 - */ + /** 更新时间 */ private static final String UPDATE_TIME = "updateTime"; @Override @@ -609,24 +596,21 @@ public class GlobalConfigure implements WebMvcConfigurer { if (ObjectUtil.isNull(deleteFlag)) { setFieldValByName(DELETE_FLAG, EnumUtil.toString(CommonDeleteFlagEnum.NOT_DELETE), metaObject); } - } catch (ReflectionException ignored) { - } + } catch (ReflectionException ignored) { } try { //为空则设置createUser Object createUser = metaObject.getValue(CREATE_USER); if (ObjectUtil.isNull(createUser)) { setFieldValByName(CREATE_USER, this.getUserId(), metaObject); } - } catch (ReflectionException ignored) { - } + } catch (ReflectionException ignored) { } try { //为空则设置createTime Object createTime = metaObject.getValue(CREATE_TIME); if (ObjectUtil.isNull(createTime)) { setFieldValByName(CREATE_TIME, DateTime.now(), metaObject); } - } catch (ReflectionException ignored) { - } + } catch (ReflectionException ignored) { } } @Override diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorAttributesHandler.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorAttributesHandler.java index 0320a17a..8177cf4d 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorAttributesHandler.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorAttributesHandler.java @@ -60,8 +60,7 @@ public class GlobalErrorAttributesHandler extends DefaultErrorAttributes { // 如果返回的异常是CommonException,则按CommonException响应的内容进行返回 Throwable throwable = this.getError(webRequest); if (ObjectUtil.isNotEmpty(throwable)) { - if (throwable instanceof CommonException) { - CommonException commonException = (CommonException) throwable; + if (throwable instanceof CommonException commonException) { return BeanUtil.beanToMap(CommonResult.error(commonException.getMsg())); } else { return BeanUtil.beanToMap(CommonResult.get(HttpStatus.HTTP_INTERNAL_ERROR, "服务器异常,请求地址:" + diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewController.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewController.java index 1eb623b9..540cecdd 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewController.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewController.java @@ -14,12 +14,15 @@ package vip.xiaonuo.core.handler; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.pojo.CommonResult; +import java.io.IOException; + /** * 全局异常页面处理器,覆盖默认的Whitelabel Error Page * @@ -37,7 +40,7 @@ public class GlobalErrorViewController { * @date 2022/2/11 16:11 **/ @RequestMapping("/errorView") - public CommonResult globalError(HttpServletRequest request) { + public CommonResult globalError(HttpServletRequest request, HttpServletResponse response) throws IOException { CommonResult commonResult = new CommonResult<>(404, "路径不存在", null); Object model = request.getAttribute("model"); if(ObjectUtil.isNotEmpty(model)) { diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewHandler.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewHandler.java index 29fe8cd5..c1eeb10d 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewHandler.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalErrorViewHandler.java @@ -16,7 +16,6 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; import org.springframework.http.HttpStatus; @@ -38,7 +37,7 @@ import java.util.Map; @RestController public class GlobalErrorViewHandler extends BasicErrorController { - public GlobalErrorViewHandler(@Autowired(required = false) ServerProperties serverProperties) { + public GlobalErrorViewHandler(ServerProperties serverProperties) { super(new GlobalErrorAttributesHandler(), serverProperties.getError()); } diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalExceptionUtil.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalExceptionUtil.java index 8b00d16d..fba33e8f 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalExceptionUtil.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/handler/GlobalExceptionUtil.java @@ -16,8 +16,6 @@ import cn.dev33.satoken.exception.SaTokenException; import cn.hutool.core.text.StrPool; import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.HttpStatus; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -39,6 +37,8 @@ import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.pojo.CommonResult; import vip.xiaonuo.common.util.CommonServletUtil; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; import java.util.Set; import java.util.stream.Collectors; @@ -127,7 +127,7 @@ public class GlobalExceptionUtil { log.error(">>> 数据操作异常:", e); commonResult = CommonResult.error("数据操作异常"); } - } else { + }else { log.error(">>> 数据操作异常:", e); commonResult = CommonResult.error("数据操作异常"); } diff --git a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql index 40a12dab..f9533061 100644 --- a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql +++ b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql @@ -21,12 +21,40 @@ CREATE TABLE `AUTH_THIRD_USER` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '三方用户' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '三方用户' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of AUTH_THIRD_USER -- ---------------------------- +-- ---------------------------- +-- Table structure for BIZ_NOTICE +-- ---------------------------- +DROP TABLE IF EXISTS `BIZ_NOTICE`; +CREATE TABLE `BIZ_NOTICE` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `TITLE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', + `IMAGE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面图', + `CONTENT` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '内容', + `DIGEST` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '摘要', + `TYPE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型', + `PLACE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发布位置', + `STATUS` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态', + `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序', + `REMARK` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '更新时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '通知公告' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of BIZ_NOTICE +-- ---------------------------- + -- ---------------------------- -- Table structure for CLIENT_RELATION -- ---------------------------- @@ -38,7 +66,7 @@ CREATE TABLE `CLIENT_RELATION` ( `CATEGORY` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类', `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关系' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关系' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of CLIENT_RELATION @@ -95,12 +123,53 @@ CREATE TABLE `CLIENT_USER` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'C端用户' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'C端用户' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of CLIENT_USER -- ---------------------------- +-- ---------------------------- +-- Table structure for CLIENT_USER_EXT +-- ---------------------------- +DROP TABLE IF EXISTS `CLIENT_USER_EXT`; +CREATE TABLE `CLIENT_USER_EXT` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `USER_ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户id', + `SOURCE_FROM_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '来源类别', + `PASSWORD_UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '密码修改日期', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'C端用户扩展' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of CLIENT_USER_EXT +-- ---------------------------- + +-- ---------------------------- +-- Table structure for CLIENT_USER_PASSWORD +-- ---------------------------- +DROP TABLE IF EXISTS `CLIENT_USER_PASSWORD`; +CREATE TABLE `CLIENT_USER_PASSWORD` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `USER_ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户id', + `PASSWORD` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'C端用户密码' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of CLIENT_USER_PASSWORD +-- ---------------------------- + -- ---------------------------- -- Table structure for DEV_CONFIG -- ---------------------------- @@ -119,19 +188,19 @@ CREATE TABLE `DEV_CONFIG` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '配置' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '配置' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_CONFIG -- ---------------------------- INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967455', 'SNOWY_SYS_LOGO', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAC4jAAAuIwF4pT92AAAE5UlEQVR42nVVfWxTVRS/b93QbcA6GF8SYGAChDjFGI1B/jBRpjLEoHEamSSIEkSY8rFu3fruve+rr+1rWTvW176yxWBgGoxGR8AEJNEgxiAxxoiiQREYCOI+GGMIrO95zisFlfjHTU/vved3fufcc36PcM5JfjFcjMGv5AnxZkJzNuHub+6cMu7RmZ8wSfLg3X/647ptg1FKqKyVPtt2ICAzkXAqQpBcIAggBGkTeS6xv6lRjU2VaIsb5F+A+cics5sMFYkSrzX058LEYdOgm4nIeIHIJI8hbiKLY/t8JR22Iyqhci4GCP0fQIG7DJChCyxUtJ//nmxznGWxPetU2kxw1Rm7XiQZxynPDPdRNVTOxBz7GyUREItgWhIsyiXBrR+jaBdUtP/xA0lnR4SMbb+hJas2aonZRZmRqyRlZysyQxcAcFyuHMy9jxgITDYo8coGNTZNFf1EBFCOgJAiMDxK0raNjF4Nvf3oqui7zyBjALQnWv2/MUUrRUD0Uamf+ACjhat3kNWyWTUtefbbzcG2uZrYBPViRFLUYi+wQGcCDNeGOxfWhQEQbAwyLjVwWpIkqCsXgqKP1IesByuTp7+SRH8B2ShFpxSYV4cmWH0nRDk4URJbiMxZ4WNtXyaQHa63jM5HarUdi/P/H098YciMCvjKLUpoijd96dzY1KVzUclPyHo5PmtscuAUsRyn0uw5zGW1nFFR0KE9no91rxE6HedNo3NhbeTDFYUd9shy4/06HVLEO0xWvTPMM0fQd7LV+0tIgRrWy62VJeal3yGVLB5Utf+0W2GBghYmFxmBjZjOw7PMnq+rzOOf+rTWOXqggQSYVAiPWThv68970Qd9x6UHTmkyE0i9Ep9Zkhw8e/Mgc7mXqnqZEmjC1Ec92XqACnBWnB7ur4u8V4vMFWghnxTyFplXBlwiaccZDzUPamoJWQ+vXOoyREDHmbRt6LyiKMUN6pY5d5unDpEOx3kh1r363uSx3fjKC9qOdFBJGe/nWin4ncsRcZyy9NAFKFcxpjxjdPJiD7HgBVNQi8zFnkYd6poaPIOXBSt7fa2eeag6cShGrOwI7s02Tx6kSrBsNAK6RGy7zBruV0PGJNIY61xwp3XtCjYsHky2+k9uCKXv96SuDQspAABWr2/Z+fQT8c9VbBvcm5QZOE316NSy1MUzOSLZkVEZ22GRxCyi6JHp88wTn+WpT073nWiMpO4rSf816EaHlNfEupY8Fd3nc9sG9ipSvccDmjGlIg2Z4R3wnW6e/YbLipfggCtc9CyNfbJpFIzWGCh+wEjeMzYDgFACZPhadGdNdXjPOndS8AFSMCl69C4vzDQGWRQ/GJYkXgyTI7gzjLoXFhtIvZ56YEHyu64GfevcMamhC5DedbLNtlcZXUuWte6tRxv3yq3Lvf5gfOb85I8fvxLaXh0B3xsaQG6KJ8xkAbaDxpoJTEz5BAsfCifDzq6M7KhZHvtoJdpuE6f7fg3AHYVTokEboa8rgSgOOfm5JUEgDDBSImmAJq5qP9aNNXw53LX0pciuWrTnbz36QbNqzJBoIK/uAmppXvFvSf8NkeU5mXebN0wbSc2W/Y2rwtsXrdDfqa6JHxDD1Edk2pzTTp4nwnLE/vsJyEl97hLUwxPgclFE3ExUSE0FFUc7ACOJ+ucCMX7bJ+Rv+yglcdlNWbUAAAAASUVORK5CYII=', 'SYS_BASE', '系统LOGO', 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967456', 'SNOWY_SYS_NAME', 'Snowy', 'SYS_BASE', '系统名称', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967457', 'SNOWY_SYS_VERSION', 'V2.0.0', 'SYS_BASE', '系统版本', 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967457', 'SNOWY_SYS_VERSION', 'V3.0.0', 'SYS_BASE', '系统版本', 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967458', 'SNOWY_SYS_COPYRIGHT', 'Snowy ©2022 Created by 小诺开源技术', 'SYS_BASE', '系统版权', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967459', 'SNOWY_SYS_COPYRIGHT_URL', 'https://www.xiaonuo.vip', 'SYS_BASE', '系统版权链接地址', 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967462', 'SNOWY_SYS_DEFAULT_CAPTCHA_OPEN', 'false', 'SYS_BASE', '登录验证码开关', 8, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967462', 'SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_B', 'B端全局验证码开关', 'SYS_BASE', 'B端全局验证码开关', 8, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967463', 'SNOWY_SYS_DEFAULT_FILE_ENGINE', 'LOCAL', 'SYS_BASE', '默认文件存储引擎', 9, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967464', 'SNOWY_SYS_DEFAULT_PASSWORD', '123456', 'SYS_BASE', '默认用户密码', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967464', 'SNOWY_SYS_DEFAULT_PASSWORD_FOR_B', '123456', 'PASSWORD_STRATEGY_FOR_B', 'B端默认用户密码', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967465', 'SNOWY_SYS_DEFAULT_DESCRRIPTION', 'Snowy是一款国内首例国产密码算法加密框架,采用Vue3.0+AntDesignVue3.0+SpringBoot2.8前后分离技术打造,技术框架与密码的结合,让前后分离‘密’不可分!', 'SYS_BASE', '系统描述', 11, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967466', 'SNOWY_SYS_DEFAULT_WORKBENCH_DATA', '{\"shortcut\":[{\"id\":\"1548901111999770526\",\"title\":\"系统首页\",\"icon\":\"home-outlined\",\"path\":\"/index\"}]}', 'SYS_BASE', '系统默认工作台数据', 12, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967558', 'SNOWY_THIRD_GITEE_CLIENT_ID', 'GiteeClientId', 'THIRD_GITEE', 'GiteeClientId', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); @@ -158,18 +227,16 @@ INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967578', 'SNOWY_EMAIL_LOCAL_FROM' INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967579', 'SNOWY_EMAIL_LOCAL_PASSWORD', '本地邮件发件密码', 'EMAIL_LOCAL', '本地邮件发件密码', 34, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967580', 'SNOWY_EMAIL_TENCENT_SECRET_ID', '腾讯云邮件SecretId', 'EMAIL_TENCENT', '腾讯云邮件SecretId', 35, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967581', 'SNOWY_EMAIL_TENCENT_SECRET_KEY', '腾讯云邮件SecretKey', 'EMAIL_TENCENT', '腾讯云邮件SecretKey', 36, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967582', 'SNOWY_EMAIL_TENCENT_REGION_ID', '腾讯云邮件RegionId', 'EMAIL_TENCENT', '腾讯云邮件RegionId', 37, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967582', 'SNOWY_EMAIL_TENCENT_FROM', '默认发送账号', 'EMAIL_TENCENT', '默认发送账号', 37, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967583', 'SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID', '阿里云邮件AccessKeyId', 'EMAIL_ALIYUN', '阿里云邮件AccessKeyId', 38, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967584', 'SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET', '阿里云邮件AccessKeySecret', 'EMAIL_ALIYUN', '阿里云邮件AccessKeySecret', 39, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967585', 'SNOWY_EMAIL_ALIYUN_REGION_ID', '阿里云邮件RegionId', 'EMAIL_ALIYUN', '阿里云邮件RegionId', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967585', 'SNOWY_EMAIL_ALIYUN_FROM', '默认发送账号', 'EMAIL_ALIYUN', '默认发送账号', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967586', 'SNOWY_SMS_TENCENT_SECRET_ID', '腾讯云短信SecretId', 'SMS_TENCENT', '腾讯云短信SecretId', 41, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967587', 'SNOWY_SMS_TENCENT_SECRET_KEY', '腾讯云短信SecretKey', 'SMS_TENCENT', '腾讯云短信SecretKey', 42, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967588', 'SNOWY_SMS_TENCENT_REGION_ID', '腾讯云短信RegionId', 'SMS_TENCENT', '腾讯云短信RegionId', 43, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967589', 'SNOWY_SMS_TENCENT_DEFAULT_SDK_APP_ID', '腾讯云短信默认SdkAppId', 'SMS_TENCENT', '腾讯云短信默认SdkAppId', 44, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967590', 'SNOWY_SMS_TENCENT_DEFAULT_SIGN_NAME', '腾讯云短信默认签名', 'SMS_TENCENT', '腾讯云短信默认签名', 45, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967591', 'SNOWY_SMS_ALIYUN_ACCESS_KEY_ID', '阿里云短信AccessKeyId', 'SMS_ALIYUN', '阿里云短信AccessKeyId', 46, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967592', 'SNOWY_SMS_ALIYUN_ACCESS_KEY_SECRET', '阿里云短信AccessKeySecret', 'SMS_ALIYUN', '阿里云短信AccessKeySecret', 47, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967593', 'SNOWY_SMS_ALIYUN_END_POINT', '阿里云短信EndPoint', 'SMS_ALIYUN', '阿里云短信EndPoint', 48, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967594', 'SNOWY_SMS_ALIYUN_DEFAULT_SIGN_NAME', '阿里云短信默认签名', 'SMS_ALIYUN', '阿里云短信默认签名', 49, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967595', 'SNOWY_SMS_XIAONUO_ACCESS_KEY_ID', '小诺短信账号Id', 'SMS_XIAONUO', '小诺短信账号Id', 50, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362967596', 'SNOWY_SMS_XIAONUO_ACCESS_KEY_SECRET', '小诺短信账号Secret', 'SMS_XIAONUO', '小诺短信账号', 51, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); @@ -180,6 +247,96 @@ INSERT INTO `DEV_CONFIG` VALUES ('1554740179362968001', 'SNOWY_EMAIL_LOCAL_SMTP_ INSERT INTO `DEV_CONFIG` VALUES ('1554740179362968002', 'SNOWY_EMAIL_LOCAL_AUTH', 'true', 'EMAIL_LOCAL', '本地邮件是否需要用户名密码验证', 82, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362968003', 'SNOWY_EMAIL_LOCAL_SSL_ENABLE', 'true', 'EMAIL_LOCAL', '本地邮件是否使用SSL安全连接', 83, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `DEV_CONFIG` VALUES ('1554740179362968004', 'SNOWY_EMAIL_LOCAL_STARTTLS_ENABLE', 'true', 'EMAIL_LOCAL', '本地邮件是否使用STARTTLS安全连接', 84, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755202', 'SNOWY_SYS_DEFAULT_PUSH_ENGINE', 'DINGTALK', 'SYS_BASE', '默认消息推送引擎', 85, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755203', 'SNOWY_SYS_DEFAULT_SMS_ENGINE', 'XIAONUO', 'SYS_BASE', '默认短信发送引擎', 86, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755204', 'SNOWY_SYS_DEFAULT_EMAIL_ENGINE', 'LOCAL', 'SYS_BASE', '默认邮件发送引擎', 87, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755205', 'SNOWY_SYS_DEFAULT_CAPTCHA_OPEN_FLAG_FOR_C', 'true', 'SYS_BASE', 'C端全局验证码开关', 88, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755206', 'SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_B', '5', 'SYS_BASE', 'B端验证码失效时间', 89, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755207', 'SNOWY_SYS_DEFAULT_CAPTCHA_EXPIRED_DURATION_FOR_C', '5', 'SYS_BASE', 'C端验证码失效时间', 90, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755208', 'SNOWY_PUSH_DINGTALK_SIGN', '钉钉消息推送签名', 'PUSH_DINGTALK', '钉钉消息推送签名', 91, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755209', 'SNOWY_PUSH_DINGTALK_TOKEN_ID', '钉钉消息推送TOKENID', 'PUSH_DINGTALK', '钉钉消息推送TOKENID', 92, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755210', 'SNOWY_PUSH_FEISHU_TOKEN_ID', '飞书消息推送TOKENID', 'PUSH_FEISHU', '飞书消息推送TOKENID', 93, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755211', 'SNOWY_PUSH_WORKWECHAT_TOKEN_ID', '企业微信消息推送TOKENID', 'PUSH_WORKWECHAT', '企业微信消息推送TOKENID', 94, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755212', 'SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B', '{\"subject\":\"注册账号成功提醒\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您的账号注册成功,感谢您加入{sysName}。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端注册账号成功邮件消息模板内容', 95, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755213', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_B', '{\"subject\":\"登录系统验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在登录系统, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端登录系统验证码邮件消息模板内容', 96, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755214', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B', '{\"subject\":\"修改密码验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在修改密码, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端修改密码验证码邮件消息模板内容', 97, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755215', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B', '{\"subject\":\"重置密码验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在重置密码, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端重置密码验证码邮件消息模板内容', 98, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755216', 'SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B', '{\"subject\":\"重置密码成功提醒\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您的密码已经重置,重置后的密码为:{userNewPassword},如非本人操作请立即修账户密码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端重置密码成功邮件消息模板内容', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755217', 'SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B', '{\"subject\":\"密码即将到期提醒\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您的密码即将过期,请尽快修改密码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端密码即将到期邮件消息模板内容', 100, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755218', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_B', '{\"subject\":\"绑定邮箱验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在绑定邮箱, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端绑定邮箱验证码邮件消息模板内容', 101, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755219', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_B', '{\"subject\":\"修改绑定邮箱验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在修改绑定邮箱, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_B', 'B端修改绑定邮箱验证码邮件消息模板内容', 102, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755220', 'SNOWY_EMAIL_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C', '{\"subject\":\"注册账号成功提醒\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您的账号注册成功,感谢您加入{sysName}。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端注册账号成功邮件消息模板内容', 103, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755221', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_LOGIN_FOR_C', '{\"subject\":\"登录系统验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在登录系统, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端登录系统验证码邮件消息模板内容', 104, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755222', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C', '{\"subject\":\"修改密码验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在修改密码, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端修改密码验证码邮件消息模板内容', 105, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755223', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_C', '{\"subject\":\"重置密码验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在重置密码, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端重置密码验证码邮件消息模板内容', 106, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755224', 'SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C', '{\"subject\":\"重置密码成功提醒\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您的密码已经重置,重置后的密码为:{userNewPassword},如非本人操作请立即修账户密码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端重置密码成功邮件消息模板内容', 107, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755225', 'SNOWY_EMAIL_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C', '{\"subject\":\"密码即将到期提醒\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您的密码即将过期,请尽快修改密码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端密码即将到期邮件消息模板内容', 108, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755226', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_BINDING_EMAIL_FOR_C', '{\"subject\":\"绑定邮箱验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在绑定邮箱, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端绑定邮箱验证码邮件消息模板内容', 109, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755227', 'SNOWY_EMAIL_TEMPLATE_VALID_CODE_UPDATE_BINDING_EMAIL_FOR_C', '{\"subject\":\"修改绑定邮箱验证码\",\"content\":\"
    \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
    \\n {sysName}\\n
    \\n
    \\n

    \\n \\n 亲爱的用户:{userEmail}\\n \\n

    \\n

    您正在修改绑定邮箱, 您的验证码为:{validCode},该验证码{validTime}分钟内有效,请尽快验证并保管好验证码。

    \\n

    {sysName}

    \\n

    {sysNowTime}

    \\n
    \\n
    \\n
    \"}', 'EMAIL_TEMPLATE_FOR_C', 'C端修改绑定邮箱验证码邮件消息模板内容', 110, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755228', 'SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_B', '{\"code\":\"\",\"content\":\"您的账号注册成功,感谢您加入${sysName}。\"}', 'SMS_TEMPLATE_FOR_B', 'B端注册账号成功短信消息模板编码', 111, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755229', 'SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_B', '{\"code\":\"\",\"content\":\"您正在登录系统, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端登录系统验证码短信消息模板编码', 112, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755230', 'SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_B', '{\"code\":\"\",\"content\":\"您正在修改密码, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端修改密码验证码短信消息模板编码', 113, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755231', 'SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_B', '{\"code\":\"\",\"content\":\"您正在重置密码, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端重置密码验证码短信消息模板编码', 114, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755232', 'SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_B', '{\"code\":\"\",\"content\":\"您的密码已经重置,重置后的密码为:${userNewPassword},如非本人操作请立即修账户密码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端重置密码成功短信消息模板编码', 115, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755233', 'SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_B', '{\"code\":\"\",\"content\":\"您的密码即将过期,请尽快修改密码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端密码即将到期短信消息模板编码', 116, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755234', 'SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_B', '{\"code\":\"\",\"content\":\"您正在绑定手机, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端绑定手机验证码短信消息模板编码', 117, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755235', 'SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_B', '{\"code\":\"\",\"content\":\"您正在修改绑定手机, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_B', 'B端修改绑定手机验证码短信消息模板编码', 118, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755236', 'SNOWY_SMS_TEMPLATE_NOTICE_REGISTER_SUCCESS_FOR_C', '{\"code\":\"\",\"content\":\"您的账号注册成功,感谢您加入${sysName}。\"}', 'SMS_TEMPLATE_FOR_C', 'C端注册账号成功短信消息模板编码', 119, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755237', 'SNOWY_SMS_TEMPLATE_VALID_CODE_LOGIN_FOR_C', '{\"code\":\"\",\"content\":\"您正在登录系统, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端登录系统验证码短信消息模板编码', 120, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755238', 'SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_PASSWORD_FOR_C', '{\"code\":\"\",\"content\":\"您正在修改密码, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端修改密码验证码短信消息模板编码', 121, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755239', 'SNOWY_SMS_TEMPLATE_VALID_CODE_RESET_PASSWORD_FOR_C', '{\"code\":\"\",\"content\":\"您正在重置密码, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端重置密码验证码短信消息模板编码', 122, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755240', 'SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_RESET_SUCCESS_FOR_C', '{\"code\":\"\",\"content\":\"您的密码已经重置,重置后的密码为:${userNewPassword},如非本人操作请立即修账户密码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端重置密码成功短信消息模板编码', 123, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755241', 'SNOWY_SMS_TEMPLATE_NOTICE_PASSWORD_EXPIRED_FOR_C', '{\"code\":\"\",\"content\":\"您的密码即将过期,请尽快修改密码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端密码即将到期短信消息模板编码', 124, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755242', 'SNOWY_SMS_TEMPLATE_VALID_CODE_BINDING_PHONE_FOR_C', '{\"code\":\"\",\"content\":\"您正在绑定手机, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端绑定手机验证码短信消息模板编码', 125, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755243', 'SNOWY_SMS_TEMPLATE_VALID_CODE_UPDATE_BINDING_PHONE_FOR_C', '{\"code\":\"\",\"content\":\"您正在修改绑定手机, 您的验证码为:${validCode},该验证码${validTime}分钟内有效,请尽快验证并保管好验证码。\"}', 'SMS_TEMPLATE_FOR_C', 'C端修改绑定手机验证码短信消息模板编码', 126, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755244', 'SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_B', '5', 'LOGIN_STRATEGY_FOR_B', 'B端连续登录失败持续时间', 127, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755245', 'SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_B', '5', 'LOGIN_STRATEGY_FOR_B', 'B端连续登录失败次数', 128, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755246', 'SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_B', '5', 'LOGIN_STRATEGY_FOR_B', 'B端连续登录失败锁定时间', 129, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755247', 'SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_B', 'true', 'LOGIN_STRATEGY_FOR_B', 'B端是否允许手机号登录', 130, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755248', 'SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_B', 'NOT_ALLOW_LOGIN', 'LOGIN_STRATEGY_FOR_B', 'B端手机号无对应用户时策略', 131, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755249', 'SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_B', 'true', 'LOGIN_STRATEGY_FOR_B', 'B端是否允许邮箱登录', 132, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755250', 'SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_B', 'NOT_ALLOW_LOGIN', 'LOGIN_STRATEGY_FOR_B', 'B端邮箱无对应用户时策略', 133, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755251', 'SNOWY_SYS_DEFAULT_NEW_USER_ORG_FOR_B', '1543842934270394368', 'REGISTER_STRATEGY_FOR_B', 'B端新用户默认机构', 144, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755252', 'SNOWY_SYS_DEFAULT_NEW_USER_POSITION_FOR_B', '1543899639134019583', 'REGISTER_STRATEGY_FOR_B', 'B端新用户默认职位', 145, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755253', 'SNOWY_SYS_DEFAULT_NEW_USER_ROLE_FOR_B', '1570687866138206208', 'REGISTER_STRATEGY_FOR_B', 'B端新用户默认角色', 146, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755254', 'SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_DURATION_FOR_C', '5', 'LOGIN_STRATEGY_FOR_C', 'C端连续登录失败持续时间', 134, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755255', 'SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_TIMES_FOR_C', '5', 'LOGIN_STRATEGY_FOR_C', 'C端连续登录失败次数', 135, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755256', 'SNOWY_SYS_DEFAULT_CONTINUOUS_LOGIN_FAIL_LOCK_DURATION_FOR_C', '5', 'LOGIN_STRATEGY_FOR_C', 'C端连续登录失败锁定时间', 136, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755257', 'SNOWY_SYS_DEFAULT_ALLOW_PHONE_LOGIN_FLAG_FOR_C', 'true', 'LOGIN_STRATEGY_FOR_C', 'C端是否允许手机号登录', 137, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755258', 'SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_PHONE_FOR_C', 'NOT_ALLOW_LOGIN', 'LOGIN_STRATEGY_FOR_C', 'C端手机号无对应用户时策略', 138, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755259', 'SNOWY_SYS_DEFAULT_ALLOW_EMAIL_LOGIN_FLAG_FOR_C', 'true', 'LOGIN_STRATEGY_FOR_C', 'C端是否允许邮箱登录', 139, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755260', 'SNOWY_SYS_DEFAULT_STRATEGY_WHEN_NO_USER_WITH_EMAIL_FOR_C', 'NOT_ALLOW_LOGIN', 'LOGIN_STRATEGY_FOR_C', 'C端邮箱无对应用户时策略', 140, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755261', 'SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_B', 'true', 'REGISTER_STRATEGY_FOR_B', 'B端是否允许注册', 141, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755262', 'SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_B', 'false', 'REGISTER_STRATEGY_FOR_B', 'B端注册后是否需要绑定手机号', 142, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755263', 'SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_B', 'false', 'REGISTER_STRATEGY_FOR_B', 'B端注册后是否需要绑定邮箱', 143, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755264', 'SNOWY_SYS_DEFAULT_ALLOW_REGISTER_FLAG_FOR_C', 'true', 'REGISTER_STRATEGY_FOR_C', 'C端是否允许注册', 147, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755265', 'SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_PHONE_FOR_C', 'false', 'REGISTER_STRATEGY_FOR_C', 'C端注册后是否需要绑定手机号', 148, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755266', 'SNOWY_SYS_DEFAULT_REGISTER_NEED_BIND_EMAIL_FOR_C', 'false', 'REGISTER_STRATEGY_FOR_C', 'C端注册后是否需要绑定邮箱', 149, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755267', 'SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_B', 'OLD', 'PASSWORD_STRATEGY_FOR_B', 'B端密码修改验证方式', 150, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755268', 'SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_B', '6', 'PASSWORD_STRATEGY_FOR_B', 'B端密码最小长度', 151, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755269', 'SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_B', '20', 'PASSWORD_STRATEGY_FOR_B', 'B端密码最大长度', 152, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755270', 'SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_B', 'REG0', 'PASSWORD_STRATEGY_FOR_B', 'B端密码复杂度', 153, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755271', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_B', '3', 'PASSWORD_STRATEGY_FOR_B', 'B端密码不能连续存在相同字符个数', 154, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755272', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_B', 'true', 'PASSWORD_STRATEGY_FOR_B', 'B端密码不能包含用户信息开关', 155, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755273', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_B', 'true', 'PASSWORD_STRATEGY_FOR_B', 'B端密码不能使用历史密码开关', 156, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755274', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_B', '3', 'PASSWORD_STRATEGY_FOR_B', 'B端密码不能使用历史密码范围个数', 157, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755275', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_B', 'true', 'PASSWORD_STRATEGY_FOR_B', 'B端密码不能使用弱密码库中密码开关', 158, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755276', 'SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_B', 'xiaonuo,xiaonuoark', 'PASSWORD_STRATEGY_FOR_B', 'B端密码自定义额外弱密码库', 159, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755277', 'SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_B', '30', 'PASSWORD_STRATEGY_FOR_B', 'B端密码有效期天数', 160, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755278', 'SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_B', '3', 'PASSWORD_STRATEGY_FOR_B', 'B端密码过期前提醒天数', 161, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755279', 'SNOWY_SYS_DEFAULT_PASSWORD_FOR_C', '123456', 'PASSWORD_STRATEGY_FOR_C', 'C端密码默认密码', 162, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755280', 'SNOWY_SYS_DEFAULT_PASSWORD_UPDATE_VALID_TYPE_FOR_C', 'OLD', 'PASSWORD_STRATEGY_FOR_C', 'C端密码修改验证方式', 163, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755281', 'SNOWY_SYS_DEFAULT_PASSWORD_MIN_LENGTH_FOR_C', '6', 'PASSWORD_STRATEGY_FOR_C', 'C端密码最小长度', 164, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755282', 'SNOWY_SYS_DEFAULT_PASSWORD_MAX_LENGTH_FOR_C', '20', 'PASSWORD_STRATEGY_FOR_C', 'C端密码最大长度', 165, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755283', 'SNOWY_SYS_DEFAULT_PASSWORD_COMPLEXITY_FOR_C', 'REG0', 'PASSWORD_STRATEGY_FOR_C', 'C端密码复杂度', 166, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755284', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTINUOUS_SAME_CHARACTER_LENGTH_FOR_C', '3', 'PASSWORD_STRATEGY_FOR_C', 'C端密码不能连续存在相同字符个数', 167, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755285', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_CONTAINS_USER_INFO_FLAG_FOR_C', 'true', 'PASSWORD_STRATEGY_FOR_C', 'C端密码不能包含用户信息开关', 168, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755286', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_FLAG_FOR_C', 'true', 'PASSWORD_STRATEGY_FOR_C', 'C端密码不能使用历史密码开关', 169, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755287', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_HISTORY_COUNT_FOR_C', '3', 'PASSWORD_STRATEGY_FOR_C', 'C端密码不能使用历史密码范围个数', 170, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755288', 'SNOWY_SYS_DEFAULT_PASSWORD_NOT_ALLOW_USE_WEAK_FLAG_FOR_C', 'true', 'PASSWORD_STRATEGY_FOR_C', 'C端密码不能使用弱密码库中密码开关', 171, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755289', 'SNOWY_SYS_DEFAULT_PASSWORD_DEFINE_WEAK_DATABASE_FOR_C', 'xiaonuo,xiaonuoark', 'PASSWORD_STRATEGY_FOR_C', 'C端密码自定义额外弱密码库', 172, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755290', 'SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_DAYS_FOR_C', '30', 'PASSWORD_STRATEGY_FOR_C', 'C端密码有效期天数', 173, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_CONFIG` VALUES ('1908870094824755291', 'SNOWY_SYS_DEFAULT_PASSWORD_EXPIRED_NOTICE_DAYS_FOR_C', '3', 'PASSWORD_STRATEGY_FOR_C', 'C端密码过期前提醒天数', 174, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -- ---------------------------- -- Table structure for DEV_DICT @@ -190,6 +347,7 @@ CREATE TABLE `DEV_DICT` ( `PARENT_ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父id', `DICT_LABEL` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字典文字', `DICT_VALUE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字典值', + `CODE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '编码', `CATEGORY` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类', `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序码', `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', @@ -199,172 +357,190 @@ CREATE TABLE `DEV_DICT` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_DICT -- ---------------------------- -INSERT INTO `DEV_DICT` VALUES ('1543839774776291330', '0', '用户性别类型', 'GENDER', 'FRM', 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543839901037424642', '1543839774776291330', '男', '男', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543840033980084226', '1543839774776291330', '女', '女', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543860103661809666', '0', '系统菜单类型', 'MENU_TYPE', 'FRM', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543860239020388354', '1543860103661809666', '目录', 'CATALOG', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543860305508495361', '1543860103661809666', '菜单', 'MENU', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543860423485878274', '1543860103661809666', '内链', 'IFRAME', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1543860477512708098', '1543860103661809666', '外链', 'LINK', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1544329873407946753', '0', '系统通用状态', 'COMMON_STATUS', 'FRM', 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1545397556652027906', '1544329873407946753', '启用', 'ENABLE', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1545397556652027907', '1544329873407946753', '停用', 'DISABLED', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547207669861064706', '0', '系统角色分类', 'ROLE_CATEGORY', 'FRM', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547207891009937409', '1547207669861064706', '全局', 'GLOBAL', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547207990075203585', '1547207669861064706', '机构', 'ORG', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547227094995705858', '0', '系统机构分类', 'ORG_CATEGORY', 'FRM', 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547227670693289985', '1547227094995705858', '部门', 'DEPT', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547228161267474434', '1547227094995705858', '公司', 'COMPANY', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547409689434742786', '0', '系统职位分类', 'POSITION_CATEGORY', 'FRM', 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547409794837602305', '1547409689434742786', '高层', 'HIGH', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547409844779180033', '1547409689434742786', '中层', 'MIDDLE', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547409906406088706', '1547409689434742786', '基层', 'LOW', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658113', '0', '用户民族类型', 'NATION', 'FRM', 7, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658114', '1547641470701658113', '汉族', '汉族', 'FRM', 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658115', '1547641470701658113', '壮族', '壮族', 'FRM', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658116', '1547641470701658113', '回族', '回族', 'FRM', 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658117', '1547641470701658113', '满族', '满族', 'FRM', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658118', '1547641470701658113', '维吾尔族', '维吾尔族', 'FRM', 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658119', '1547641470701658113', '苗族', '苗族', 'FRM', 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658120', '1547641470701658113', '彝族', '彝族', 'FRM', 7, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658121', '1547641470701658113', '土家族', '土家族', 'FRM', 8, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658122', '1547641470701658113', '藏族', '藏族', 'FRM', 9, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658123', '1547641470701658113', '蒙古族', '蒙古族', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658124', '1547641470701658113', '侗族', '侗族', 'FRM', 11, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658125', '1547641470701658113', '布依族', '布依族', 'FRM', 12, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658126', '1547641470701658113', '瑶族', '瑶族', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658127', '1547641470701658113', '白族', '白族', 'FRM', 14, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658128', '1547641470701658113', '朝鲜族', '朝鲜族', 'FRM', 15, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658129', '1547641470701658113', '哈尼族', '哈尼族', 'FRM', 16, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658130', '1547641470701658113', '黎族', '黎族', 'FRM', 17, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658131', '1547641470701658113', '哈萨克族', '哈萨克族', 'FRM', 18, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658132', '1547641470701658113', '傣族', '傣族', 'FRM', 19, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658133', '1547641470701658113', '畲族', '畲族', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658134', '1547641470701658113', '傈僳族', '傈僳族', 'FRM', 21, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658135', '1547641470701658113', '东乡族', '东乡族', 'FRM', 22, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658136', '1547641470701658113', '仡佬族', '仡佬族', 'FRM', 23, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658137', '1547641470701658113', '拉祜族', '拉祜族', 'FRM', 24, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658138', '1547641470701658113', '佤族', '佤族', 'FRM', 25, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658139', '1547641470701658113', '水族', '水族', 'FRM', 26, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658140', '1547641470701658113', '纳西族', '纳西族', 'FRM', 27, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658141', '1547641470701658113', '羌族', '羌族', 'FRM', 28, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658142', '1547641470701658113', '土族', '土族', 'FRM', 29, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658143', '1547641470701658113', '仫佬族', '仫佬族', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658144', '1547641470701658113', '锡伯族', '锡伯族', 'FRM', 31, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658145', '1547641470701658113', '柯尔克孜族', '柯尔克孜族', 'FRM', 32, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658146', '1547641470701658113', '景颇族', '景颇族', 'FRM', 33, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658147', '1547641470701658113', '达斡尔族', '达斡尔族', 'FRM', 34, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658148', '1547641470701658113', '撒拉族', '撒拉族', 'FRM', 35, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658149', '1547641470701658113', '布朗族', '布朗族', 'FRM', 36, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658150', '1547641470701658113', '毛南族', '毛南族', 'FRM', 37, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658151', '1547641470701658113', '塔吉克族', '塔吉克族', 'FRM', 38, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658152', '1547641470701658113', '普米族', '普米族', 'FRM', 39, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658153', '1547641470701658113', '阿昌族', '阿昌族', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658154', '1547641470701658113', '怒族', '怒族', 'FRM', 41, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658155', '1547641470701658113', '鄂温克族', '鄂温克族', 'FRM', 42, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658156', '1547641470701658113', '京族', '京族', 'FRM', 43, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658157', '1547641470701658113', '基诺族', '基诺族', 'FRM', 44, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658158', '1547641470701658113', '德昂族', '德昂族', 'FRM', 45, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658159', '1547641470701658113', '保安族', '保安族', 'FRM', 46, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658160', '1547641470701658113', '俄罗斯族', '俄罗斯族', 'FRM', 47, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658161', '1547641470701658113', '裕固族', '裕固族', 'FRM', 48, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658162', '1547641470701658113', '乌孜别克族', '乌孜别克族', 'FRM', 49, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658163', '1547641470701658113', '门巴族', '门巴族', 'FRM', 50, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658164', '1547641470701658113', '鄂伦春族', '鄂伦春族', 'FRM', 51, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658165', '1547641470701658113', '独龙族', '独龙族', 'FRM', 52, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658166', '1547641470701658113', '赫哲族', '赫哲族', 'FRM', 53, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658167', '1547641470701658113', '高山族', '高山族', 'FRM', 54, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658168', '1547641470701658113', '珞巴族', '珞巴族', 'FRM', 55, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1547641470701658169', '1547641470701658113', '塔塔尔族 ', '塔塔尔族 ', 'FRM', 56, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1549019269252104194', '0', '登录设备类型', 'AUTH_DEVICE_TYPE', 'FRM', 8, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1549019748883349506', '1549019269252104194', 'PC端', 'PC', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1549019813924421634', '1549019269252104194', '移动端', 'APP', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1549019864537088002', '1549019269252104194', '小程序', 'MINI', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554678566166323202', '0', '系统字典分类', 'DICT_CATEGORY', 'FRM', 9, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554678761742524417', '1554678566166323202', '框架', 'FRM', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554678863617974273', '1554678566166323202', '业务', 'BIZ', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554679788378120194', '0', '短信发送引擎', 'SMS_ENGINE', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554679872054484993', '1554679788378120194', '阿里云', 'ALIYUN', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554679958398427138', '1554679788378120194', '腾讯云', 'TENCENT', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554679958398427139', '1554679788378120194', '小诺方舟', 'XIAONUO', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554726376265744386', '0', '文件上传引擎', 'FILE_ENGINE', 'FRM', 11, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554726639571566593', '1554726376265744386', '本地', 'LOCAL', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554726696068841474', '1554726376265744386', '阿里云', 'ALIYUN', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554726762338844674', '1554726376265744386', '腾讯云', 'TENCENT', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1554726830844411905', '1554726376265744386', 'MINIO', 'MINIO', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1556317797993218049', '0', '邮件发送引擎', 'EMAIL_ENGINE', 'FRM', 12, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1556319651447767041', '1556317797993218049', '本地', 'LOCAL', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1556319726962016258', '1556317797993218049', '阿里云', 'ALIYUN', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1556319786349166593', '1556317797993218049', '腾讯云', 'TENCENT', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1559942543251079169', '0', '系统通用开关', 'COMMON_SWITCH', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1559942706694717442', '1559942543251079169', '开', 'true', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1559942777674924034', '1559942543251079169', '关', 'false', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560306347516461058', '0', '用户证件类型', 'IDCARD_TYPE', 'FRM', 14, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560306502135283714', '1560306347516461058', '身份证', '身份证', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560306768913989633', '1560306347516461058', '出生证', '出生证', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560307009365049346', '1560306347516461058', '军官证', '军官证', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560307180937248769', '1560306347516461058', '护照', '护照', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309358598914050', '0', '通用文化程度', 'CULTURE_LEVEL', 'FRM', 15, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309494892822530', '1560309358598914050', '小学', '小学', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309602136981505', '1560309358598914050', '中学', '中学', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309700136894465', '1560309358598914050', '高中', '高中', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309744118366209', '1560309358598914050', '中专', '中专', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309783037313026', '1560309358598914050', '大专', '大专', 'FRM', 50, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309816423972866', '1560309358598914050', '本科', '本科', 'FRM', 60, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560309855661686785', '1560309358598914050', '硕士研究生', '硕士研究生', 'FRM', 70, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560310085471797250', '1560309358598914050', '博士研究生', '博士研究生', 'FRM', 80, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560338934867791874', '0', '定时任务分类', 'JOB_CATEGORY', 'FRM', 16, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560339092900777985', '1560338934867791874', '框架', 'FRM', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560339156134105089', '1560338934867791874', '业务', 'BIZ', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560342111344234497', '0', '定时任务状态', 'JOB_STATUS', 'FRM', 17, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560342186812346370', '1560342111344234497', '运行', 'RUNNING', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1560342250096005121', '1560342111344234497', '停止', 'STOPPED', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1561595062998102017', '0', '三方用户分类', 'THIRD_CATEGORY', 'FRM', 18, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1561595252714860545', '1561595062998102017', '码云GITEE', 'GITEE', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1561595322336112641', '1561595062998102017', '微信WECHAT', 'WECHAT', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1567580351742619650', '0', '系统消息类型', 'MESSAGE_CATEGORY', 'FRM', 19, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1567580424270524418', '1567580351742619650', '系统', 'SYS', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1567580487684206594', '1567580351742619650', '业务', 'BIZ', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1619343323218432002', '0', '移动菜单状态', 'MOBILE_STATUS', 'FRM', 93, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1619343680636047362', '1619343323218432002', '可用', 'ENABLE', 'FRM', 94, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1619343846382358529', '1619343323218432002', '不可用', 'DISABLED', 'FRM', 96, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1619344256295882753', '0', '移动菜单规则', 'MOBILE_REG_TYPE', 'FRM', 97, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1619344428111351809', '1619344256295882753', '正规则', 'YES', 'FRM', 98, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1619344504456073218', '1619344256295882753', '反规则', 'NO', 'FRM', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1728459107437219842', '0', '系统菜单可见', 'MENU_VISIBLE', 'FRM', 100, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1728459178341928962', '1728459107437219842', '显示', 'TRUE', 'FRM', 101, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1728459493170581505', '1728459107437219842', '隐藏', 'FALSE', 'FRM', 102, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811285429576929282', '0', '轮播图位置', 'DEV_SLIDESHOW_PLACE', 'FRM', 114, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811285517497929730', '1811285429576929282', '后台移动端首页', 'BACK_MOBILE', 'FRM', 115, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811285597999206402', '1811285429576929282', '后台业务首页', 'BACK_INDEX', 'FRM', 116, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811285669692444674', '1811285429576929282', '用户移动端首页', 'CLIENT_MOBILE', 'FRM', 117, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811285778270392321', '1811285429576929282', '后台系统首页', 'BACK_SYS_INDEX', 'FRM', 118, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811286076128890881', '0', '轮播图状态', 'DEV_SLIDESHOW_STATUS', 'FRM', 119, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811286168449716226', '1811286076128890881', '启用', 'ENABLE', 'FRM', 120, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811286273949044737', '1811286076128890881', '禁用', 'DISABLE', 'FRM', 121, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811286542808125441', '0', '轮播图跳转', 'WHETHER_TO_CLICK', 'FRM', 122, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811286611254972418', '1811286542808125441', '启用', 'ENABLE', 'FRM', 123, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811286765760548866', '1811286542808125441', '禁用', 'DISABLE', 'FRM', 124, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811287001631428610', '0', '轮播图跳转方式', 'SKIP_MODE', 'FRM', 125, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811287257836294146', '1811287001631428610', '跳转至URL', 'URL', 'FRM', 126, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811287406557925378', '1811287001631428610', '跳转至路由', 'ROUTER', 'FRM', 127, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811257769085767682', '0', '通知公告类型', 'BIZ_NOTICE_TYPE', 'FRM', 128, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811258110468558849', '1811257769085767682', '通知', 'NOTICE', 'FRM', 129, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811258351498432514', '1811257769085767682', '公告', 'ANNOUNCEMENT', 'FRM', 130, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811258502975721474', '1811257769085767682', '警告', 'WARNING', 'FRM', 131, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811258687793532929', '0', '通知公告状态', 'BIZ_NOTICE_STATUS', 'FRM', 132, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811259114710765570', '1811258687793532929', '已关闭', 'DISABLE', 'FRM', 133, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811259393917194242', '1811258687793532929', '正常', 'ENABLE', 'FRM', 134, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811259821748785154', '0', '通知公告位置', 'BIZ_NOTICE_PLACE', 'FRM', 135, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811260041488371714', '1811259821748785154', '后台移动端首页', 'BACK_MOBILE', 'FRM', 136, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811260212410454018', '1811259821748785154', '后台业务首页', 'BACK_INDEX', 'FRM', 137, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `DEV_DICT` VALUES ('1811260660487950338', '1811259821748785154', '用户移动端首页', 'CLIENT_MOBILE', 'FRM', 138, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543839774776291330', '0', '用户性别类型', 'GENDER', 'nx2UbxB6z6', 'FRM', 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543839901037424642', '1543839774776291330', '男', '男', 'WRrdMORE3c', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543840033980084226', '1543839774776291330', '女', '女', '4MbEORlvBJ', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543860103661809666', '0', '系统菜单类型', 'MENU_TYPE', 'pEnxBN7E2o', 'FRM', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543860239020388354', '1543860103661809666', '目录', 'CATALOG', 'kMKSJSFZgt', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543860305508495361', '1543860103661809666', '菜单', 'MENU', 'FOHDkzOjxa', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543860423485878274', '1543860103661809666', '内链', 'IFRAME', 'u6rH9LmTvz', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1543860477512708098', '1543860103661809666', '外链', 'LINK', 'vOmYaKkhrK', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1544329873407946753', '0', '系统通用状态', 'COMMON_STATUS', 'SpdguT1MTy', 'FRM', 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1545397556652027906', '1544329873407946753', '启用', 'ENABLE', '4fPYJApbLH', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1545397556652027907', '1544329873407946753', '停用', 'DISABLED', 'DreeA3e26Y', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547207669861064706', '0', '系统角色分类', 'ROLE_CATEGORY', 'rMCKoVuOoF', 'FRM', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547207891009937409', '1547207669861064706', '全局', 'GLOBAL', 'gaLjy7wwCw', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547207990075203585', '1547207669861064706', '机构', 'ORG', 'f1B0Zt9PPM', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547227094995705858', '0', '系统机构分类', 'ORG_CATEGORY', '2ATB1ySwLN', 'FRM', 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547227670693289985', '1547227094995705858', '部门', 'DEPT', 'XUUCvprRXw', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547228161267474434', '1547227094995705858', '公司', 'COMPANY', '6ntdgLkMOi', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547409689434742786', '0', '系统职位分类', 'POSITION_CATEGORY', 'hPvAP5dxiW', 'FRM', 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547409794837602305', '1547409689434742786', '高层', 'HIGH', '7QQxWyMMB0', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547409844779180033', '1547409689434742786', '中层', 'MIDDLE', 'WneMc7T6IT', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547409906406088706', '1547409689434742786', '基层', 'LOW', 'aQhuK5cZ1B', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658113', '0', '用户民族类型', 'NATION', 'OfM9Yo627Z', 'FRM', 7, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658114', '1547641470701658113', '汉族', '汉族', 'IldDHFWUJu', 'FRM', 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658115', '1547641470701658113', '壮族', '壮族', 'BcWVpbu1xR', 'FRM', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658116', '1547641470701658113', '回族', '回族', 'yjVUonNG7d', 'FRM', 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658117', '1547641470701658113', '满族', '满族', 'eJi56S3voF', 'FRM', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658118', '1547641470701658113', '维吾尔族', '维吾尔族', 'EQaAIa8CM3', 'FRM', 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658119', '1547641470701658113', '苗族', '苗族', 'jey27sIjJh', 'FRM', 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658120', '1547641470701658113', '彝族', '彝族', 'NLeKPrUqmD', 'FRM', 7, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658121', '1547641470701658113', '土家族', '土家族', 'jT8d1Ik5pg', 'FRM', 8, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658122', '1547641470701658113', '藏族', '藏族', 'Hn7hhRzZkK', 'FRM', 9, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658123', '1547641470701658113', '蒙古族', '蒙古族', 'nXOl2haSmn', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658124', '1547641470701658113', '侗族', '侗族', 'sjtNWihEAP', 'FRM', 11, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658125', '1547641470701658113', '布依族', '布依族', 'BUJNxSLxaG', 'FRM', 12, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658126', '1547641470701658113', '瑶族', '瑶族', 'XO7sLv3shh', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658127', '1547641470701658113', '白族', '白族', 'kLKZ70OwP1', 'FRM', 14, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658128', '1547641470701658113', '朝鲜族', '朝鲜族', 'nMRLtjAPfu', 'FRM', 15, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658129', '1547641470701658113', '哈尼族', '哈尼族', 'rAD1IjUe8L', 'FRM', 16, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658130', '1547641470701658113', '黎族', '黎族', 'pgrMlPbuhg', 'FRM', 17, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658131', '1547641470701658113', '哈萨克族', '哈萨克族', 'ZCMR77KXLM', 'FRM', 18, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658132', '1547641470701658113', '傣族', '傣族', 'w7FEqD6b9b', 'FRM', 19, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658133', '1547641470701658113', '畲族', '畲族', 'II3pYCP3gy', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658134', '1547641470701658113', '傈僳族', '傈僳族', 'P4cZRdzfkD', 'FRM', 21, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658135', '1547641470701658113', '东乡族', '东乡族', 'LsDVhLz5aK', 'FRM', 22, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658136', '1547641470701658113', '仡佬族', '仡佬族', 'cRW15z07Wf', 'FRM', 23, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658137', '1547641470701658113', '拉祜族', '拉祜族', 'Rxxpkdtuyi', 'FRM', 24, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658138', '1547641470701658113', '佤族', '佤族', 'BTFWGDBADw', 'FRM', 25, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658139', '1547641470701658113', '水族', '水族', 'rrXze6vNX9', 'FRM', 26, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658140', '1547641470701658113', '纳西族', '纳西族', 'E78hSFKAko', 'FRM', 27, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658141', '1547641470701658113', '羌族', '羌族', 'VoNs4A5D5o', 'FRM', 28, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658142', '1547641470701658113', '土族', '土族', 'UxDL9BKnUm', 'FRM', 29, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658143', '1547641470701658113', '仫佬族', '仫佬族', 'Qn03GasUeA', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658144', '1547641470701658113', '锡伯族', '锡伯族', 'yf4RZRyGzK', 'FRM', 31, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658145', '1547641470701658113', '柯尔克孜族', '柯尔克孜族', 'mCACEtEHGz', 'FRM', 32, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658146', '1547641470701658113', '景颇族', '景颇族', 'XVGhmOIr1v', 'FRM', 33, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658147', '1547641470701658113', '达斡尔族', '达斡尔族', 'pB7plgu56s', 'FRM', 34, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658148', '1547641470701658113', '撒拉族', '撒拉族', '6z5gsbJYwa', 'FRM', 35, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658149', '1547641470701658113', '布朗族', '布朗族', 'qFV4FirD9p', 'FRM', 36, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658150', '1547641470701658113', '毛南族', '毛南族', 'rsNRdCZSMn', 'FRM', 37, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658151', '1547641470701658113', '塔吉克族', '塔吉克族', 'Snn1gGO0Mo', 'FRM', 38, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658152', '1547641470701658113', '普米族', '普米族', 'OfJpLT9wnU', 'FRM', 39, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658153', '1547641470701658113', '阿昌族', '阿昌族', 'GB03mwF8Ou', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658154', '1547641470701658113', '怒族', '怒族', 'kIUgNs9ESr', 'FRM', 41, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658155', '1547641470701658113', '鄂温克族', '鄂温克族', 'TMlFI08Nyp', 'FRM', 42, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658156', '1547641470701658113', '京族', '京族', 'QNeQWqhYjB', 'FRM', 43, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658157', '1547641470701658113', '基诺族', '基诺族', 'LW4sPUhztO', 'FRM', 44, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658158', '1547641470701658113', '德昂族', '德昂族', 'au5pfugMm1', 'FRM', 45, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658159', '1547641470701658113', '保安族', '保安族', 'xAkxr6cORb', 'FRM', 46, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658160', '1547641470701658113', '俄罗斯族', '俄罗斯族', 'XVDaOjSCRC', 'FRM', 47, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658161', '1547641470701658113', '裕固族', '裕固族', 'aDgjM4JVJ4', 'FRM', 48, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658162', '1547641470701658113', '乌孜别克族', '乌孜别克族', 'IPtwpYl2GX', 'FRM', 49, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658163', '1547641470701658113', '门巴族', '门巴族', 'lP5Vim88tt', 'FRM', 50, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658164', '1547641470701658113', '鄂伦春族', '鄂伦春族', 'NQYDgg0vzB', 'FRM', 51, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658165', '1547641470701658113', '独龙族', '独龙族', 'a37PtONVYo', 'FRM', 52, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658166', '1547641470701658113', '赫哲族', '赫哲族', 'JJ97lOiA4D', 'FRM', 53, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658167', '1547641470701658113', '高山族', '高山族', 'zc52WRi5ro', 'FRM', 54, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658168', '1547641470701658113', '珞巴族', '珞巴族', 'v4ZkItC09c', 'FRM', 55, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1547641470701658169', '1547641470701658113', '塔塔尔族 ', '塔塔尔族 ', 'c4AMDTdh2c', 'FRM', 56, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1549019269252104194', '0', '登录设备类型', 'AUTH_DEVICE_TYPE', '29o4YioH2v', 'FRM', 8, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1549019748883349506', '1549019269252104194', 'PC端', 'PC', 'kf2lvOCEcJ', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1549019813924421634', '1549019269252104194', '移动端', 'APP', 'QGygBhRmjE', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1549019864537088002', '1549019269252104194', '小程序', 'MINI', 'uTYA8duLr3', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554678566166323202', '0', '系统字典分类', 'DICT_CATEGORY', 'f4vCzVKlh5', 'FRM', 9, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554678761742524417', '1554678566166323202', '框架', 'FRM', 'ydzbkvUTj4', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554678863617974273', '1554678566166323202', '业务', 'BIZ', 'xI3z1fXU5z', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554679788378120194', '0', '短信发送引擎', 'SMS_ENGINE', 'kPEEms6spU', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554679872054484993', '1554679788378120194', '阿里云', 'ALIYUN', 'GGSVo47jJ0', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554679958398427138', '1554679788378120194', '腾讯云', 'TENCENT', 'jQ4boYgQCK', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554679958398427139', '1554679788378120194', '小诺方舟', 'XIAONUO', 'M3Oie6gy5Z', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554726376265744386', '0', '文件上传引擎', 'FILE_ENGINE', 'Vo3kYSoWu4', 'FRM', 11, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554726639571566593', '1554726376265744386', '本地', 'LOCAL', 'qw9Tr2Dzox', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554726696068841474', '1554726376265744386', '阿里云', 'ALIYUN', 'DdvFFdIFJA', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554726762338844674', '1554726376265744386', '腾讯云', 'TENCENT', 'Ikys8NAfP4', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1554726830844411905', '1554726376265744386', 'MINIO', 'MINIO', 'KXhgDXlijP', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556317797993218049', '0', '邮件发送引擎', 'EMAIL_ENGINE', 'NfnLwwpxlj', 'FRM', 12, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319651447767041', '1556317797993218049', '本地', 'LOCAL', '61rvXPdT9X', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319726962016258', '1556317797993218049', '阿里云', 'ALIYUN', 'DfXhM5Gwau', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166593', '1556317797993218049', '腾讯云', 'TENCENT', 'NRjywm25dm', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166594', '0', '消息推送引擎', 'PUSH_ENGINE', 'qRPg7zAJdP', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166595', '1556319786349166594', '钉钉', 'DINGTALK', 'KDLmGWwMkJ', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166596', '1556319786349166594', '飞书', 'FEISHU', 'Vewyfq4W15', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166597', '1556319786349166594', '企业微信', 'WORKWECHAT', 'JMkb4b45Xd', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166598', '0', '改密验证方式', 'UPDATE_PASSWORD_VALID_TYPE', '9Mqw6ShkbD', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166599', '1556319786349166598', '旧密码', 'OLD', 'pObj0Dl4Xe', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166600', '1556319786349166598', '手机号', 'PHONE', 'WfOLuw9YmO', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166601', '1556319786349166598', '邮箱', 'EMAIL', 'nsGz3lTCqX', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166602', '0', '密码复杂策略', 'PASSWORD_COMPLEXITY_TYPE', 'dCk4dqC6IY', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166603', '1556319786349166602', '无限制', 'REG0', '7SWkXJllso', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166604', '1556319786349166602', '必须包含数字和字母', 'REG1', 'MZm9NDOMlf', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166605', '1556319786349166602', '必须包含数字和大写字母', 'REG2', 'RnOoCgVDv6', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166606', '1556319786349166602', '必须包含数字、大写字母、小写字母和特殊字符', 'REG3', 'q8abKxE74G', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166607', '1556319786349166602', '至少包含数字、字母和特殊字符中的两种', 'REG4', 'SW7iBXX4oY', 'FRM', 50, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166608', '1556319786349166602', '至少包含数字、大写字母、小写字母和特殊字符的三种', 'REG5', 'Fztg672Cva', 'FRM', 60, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166609', '0', '无用户时策略', 'NO_USER_STRATEGY', '49p2f52gYw', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166610', '1556319786349166609', '不允许登录', 'NOT_ALLOW_LOGIN', '5G50YsKslb', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1556319786349166611', '1556319786349166609', '自动创建用户', 'AUTO_CREATE_USER', '7uCMN8LbRL', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1559942543251079169', '0', '系统通用开关', 'COMMON_SWITCH', 'MFJCVVdJgk', 'FRM', 13, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1559942706694717442', '1559942543251079169', '开', 'true', 'kNPE0kSKBO', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1559942777674924034', '1559942543251079169', '关', 'false', 'NNzkxA5SNS', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560306347516461058', '0', '用户证件类型', 'IDCARD_TYPE', '2J7klwyzPJ', 'FRM', 14, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560306502135283714', '1560306347516461058', '身份证', '身份证', 'REJIJwygYr', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560306768913989633', '1560306347516461058', '出生证', '出生证', 'eXyBSq6xwR', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560307009365049346', '1560306347516461058', '军官证', '军官证', 'L4pbqvDHsG', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560307180937248769', '1560306347516461058', '护照', '护照', 's8RAk6LIO3', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309358598914050', '0', '通用文化程度', 'CULTURE_LEVEL', 'pwP5ee8waN', 'FRM', 15, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309494892822530', '1560309358598914050', '小学', '小学', 'oE5AicWtWP', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309602136981505', '1560309358598914050', '中学', '中学', 'DPuwboHfx2', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309700136894465', '1560309358598914050', '高中', '高中', 'u8M3iyacaz', 'FRM', 30, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309744118366209', '1560309358598914050', '中专', '中专', 'CswfpaCuEy', 'FRM', 40, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309783037313026', '1560309358598914050', '大专', '大专', 'hrJGWys2Wj', 'FRM', 50, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309816423972866', '1560309358598914050', '本科', '本科', 'LkR8xvh9tY', 'FRM', 60, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560309855661686785', '1560309358598914050', '硕士研究生', '硕士研究生', '75Vt847ADj', 'FRM', 70, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560310085471797250', '1560309358598914050', '博士研究生', '博士研究生', 'dgOJaPhHzh', 'FRM', 80, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560338934867791874', '0', '定时任务分类', 'JOB_CATEGORY', 'Hodol7eYnE', 'FRM', 16, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560339092900777985', '1560338934867791874', '框架', 'FRM', 'AIBvupunuc', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560339156134105089', '1560338934867791874', '业务', 'BIZ', 'L0kgu7bNYN', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560342111344234497', '0', '定时任务状态', 'JOB_STATUS', 'jlfpcMEVVK', 'FRM', 17, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560342186812346370', '1560342111344234497', '运行', 'RUNNING', 'DHhBaibuBk', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1560342250096005121', '1560342111344234497', '停止', 'STOPPED', 'O6KfK7Cobx', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1561595062998102017', '0', '三方用户分类', 'THIRD_CATEGORY', 'OqMe62ViBY', 'FRM', 18, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1561595252714860545', '1561595062998102017', '码云GITEE', 'GITEE', 'lZq8s2ehA5', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1561595322336112641', '1561595062998102017', '微信WECHAT', 'WECHAT', 'pGhKCHQ7hF', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1567580351742619650', '0', '系统消息类型', 'MESSAGE_CATEGORY', 'UPIN4KJqvT', 'FRM', 19, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1567580424270524418', '1567580351742619650', '系统', 'SYS', 'l7Mc5zE5ib', 'FRM', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1567580487684206594', '1567580351742619650', '业务', 'BIZ', 'nYhpV3ep7j', 'FRM', 20, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1619343323218432002', '0', '移动菜单状态', 'MOBILE_STATUS', 'zhK8QL6NOu', 'FRM', 93, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1619343680636047362', '1619343323218432002', '可用', 'ENABLE', 'pCdVlpHewf', 'FRM', 94, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1619343846382358529', '1619343323218432002', '不可用', 'DISABLED', 'K3FADjJN7G', 'FRM', 96, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1619344256295882753', '0', '移动菜单规则', 'MOBILE_REG_TYPE', '4Lz21CUUTV', 'FRM', 97, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1619344428111351809', '1619344256295882753', '正规则', 'YES', 'Tb4OsxMVgN', 'FRM', 98, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1619344504456073218', '1619344256295882753', '反规则', 'NO', '0ibifiB9mB', 'FRM', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1728459107437219842', '0', '系统菜单可见', 'MENU_VISIBLE', 'SCF7DIoiOw', 'FRM', 100, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1728459178341928962', '1728459107437219842', '显示', 'TRUE', 'JpeQ3wzeTY', 'FRM', 101, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1728459493170581505', '1728459107437219842', '隐藏', 'FALSE', 's5RGksqfjr', 'FRM', 102, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811257769085767682', '0', '通知公告类型', 'BIZ_NOTICE_TYPE', 'iXHgzfK7W5', 'FRM', 128, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811258110468558849', '1811257769085767682', '通知', 'NOTICE', 'rNtBUWLnag', 'FRM', 129, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811258351498432514', '1811257769085767682', '公告', 'ANNOUNCEMENT', '578Xq2zTkK', 'FRM', 130, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811258502975721474', '1811257769085767682', '警告', 'WARNING', 'cVjlhwLiE0', 'FRM', 131, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811258687793532929', '0', '通知公告状态', 'BIZ_NOTICE_STATUS', '1OcT1FGyRU', 'FRM', 132, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811259114710765570', '1811258687793532929', '已关闭', 'DISABLE', 'SB07WaNLrC', 'FRM', 133, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811259393917194242', '1811258687793532929', '正常', 'ENABLE', 'O27ZBLXOF5', 'FRM', 134, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811259821748785154', '0', '通知公告位置', 'BIZ_NOTICE_PLACE', '0gnQn6GnJs', 'FRM', 135, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811260041488371714', '1811259821748785154', '后台移动端首页', 'BACK_MOBILE', 'g7E1fXh3l8', 'FRM', 136, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811260212410454018', '1811259821748785154', '后台业务首页', 'BACK_INDEX', 'GP4eqroglk', 'FRM', 137, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811260660487950338', '1811259821748785154', '用户移动端首页', 'CLIENT_MOBILE', 'gnDATqoDpO', 'FRM', 138, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811285429576929282', '0', '轮播图位置', 'DEV_SLIDESHOW_PLACE', '1HQeP9ZwrY', 'FRM', 114, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811285517497929730', '1811285429576929282', '后台移动端首页', 'BACK_MOBILE', 'Lcd7Oc3SMD', 'FRM', 115, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811285597999206402', '1811285429576929282', '后台业务首页', 'BACK_INDEX', 'J1utDwWvGZ', 'FRM', 116, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811285669692444674', '1811285429576929282', '用户移动端首页', 'CLIENT_MOBILE', 'QOA6Gh75nr', 'FRM', 117, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811285778270392321', '1811285429576929282', '后台系统首页', 'BACK_SYS_INDEX', 'vdeOwzBXBr', 'FRM', 118, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811286076128890881', '0', '轮播图状态', 'DEV_SLIDESHOW_STATUS', 'T5lIZkVfTj', 'FRM', 119, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811286168449716226', '1811286076128890881', '启用', 'ENABLE', 'MuZagpmxPv', 'FRM', 120, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811286273949044737', '1811286076128890881', '禁用', 'DISABLE', '5gpxaee739', 'FRM', 121, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811286542808125441', '0', '轮播图跳转', 'WHETHER_TO_CLICK', 'yBB2WcLn2V', 'FRM', 122, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811286611254972418', '1811286542808125441', '启用', 'ENABLE', 'ac87rrN9WF', 'FRM', 123, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811286765760548866', '1811286542808125441', '禁用', 'DISABLE', 'la3FazhpXJ', 'FRM', 124, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811287001631428610', '0', '轮播图跳转方式', 'SKIP_MODE', 'PGtlHTRTEA', 'FRM', 125, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811287257836294146', '1811287001631428610', '跳转至URL', 'URL', 'xmKzrPyyrM', 'FRM', 126, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `DEV_DICT` VALUES ('1811287406557925378', '1811287001631428610', '跳转至路由', 'ROUTER', 'lrtd0Zt0Di', 'FRM', 127, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -- ---------------------------- -- Table structure for DEV_EMAIL @@ -389,7 +565,7 @@ CREATE TABLE `DEV_EMAIL` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '邮件' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '邮件' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_EMAIL @@ -419,7 +595,7 @@ CREATE TABLE `DEV_FILE` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文件' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文件' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_FILE @@ -445,7 +621,7 @@ CREATE TABLE `DEV_JOB` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '定时任务' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '定时任务' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_JOB @@ -480,7 +656,7 @@ CREATE TABLE `DEV_LOG` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '日志' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '日志' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_LOG @@ -502,12 +678,36 @@ CREATE TABLE `DEV_MESSAGE` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '站内信' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '站内信' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_MESSAGE -- ---------------------------- +-- ---------------------------- +-- Table structure for DEV_PUSH +-- ---------------------------- +DROP TABLE IF EXISTS `DEV_PUSH`; +CREATE TABLE `DEV_PUSH` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ENGINE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息引擎', + `TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息类别', + `TITLE` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息标题', + `CONTENT` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', + `RECEIPT_INFO` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '回执信息', + `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '消息推送' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of DEV_PUSH +-- ---------------------------- + -- ---------------------------- -- Table structure for DEV_RELATION -- ---------------------------- @@ -519,12 +719,37 @@ CREATE TABLE `DEV_RELATION` ( `CATEGORY` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类', `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关系' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关系' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_RELATION -- ---------------------------- +-- ---------------------------- +-- Table structure for DEV_SLIDESHOW +-- ---------------------------- +DROP TABLE IF EXISTS `DEV_SLIDESHOW`; +CREATE TABLE `DEV_SLIDESHOW` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `TITLE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', + `PLACE` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '展示位置', + `IMAGE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片', + `PATH_DETAILS` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径详情', + `STATUS` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态', + `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序', + `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '更新时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '轮播图' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of DEV_SLIDESHOW +-- ---------------------------- + -- ---------------------------- -- Table structure for DEV_SMS -- ---------------------------- @@ -544,12 +769,31 @@ CREATE TABLE `DEV_SMS` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '短信' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '短信' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of DEV_SMS -- ---------------------------- +-- ---------------------------- +-- Table structure for DEV_WEAK_PASSWORD +-- ---------------------------- +DROP TABLE IF EXISTS `DEV_WEAK_PASSWORD`; +CREATE TABLE `DEV_WEAK_PASSWORD` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `PASSWORD` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '弱密码', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '弱密码库' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of DEV_WEAK_PASSWORD +-- ---------------------------- + -- ---------------------------- -- Table structure for GEN_BASIC -- ---------------------------- @@ -579,7 +823,7 @@ CREATE TABLE `GEN_BASIC` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '生成基础' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '生成基础' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of GEN_BASIC @@ -612,7 +856,7 @@ CREATE TABLE `GEN_CONFIG` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '生成配置' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '生成配置' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of GEN_CONFIG @@ -643,16 +887,16 @@ CREATE TABLE `MOBILE_RESOURCE` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '移动资源' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '移动资源' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of MOBILE_RESOURCE -- ---------------------------- INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380023993298945', NULL, '业务', '217gcp9ifi', 'MODULE', NULL, NULL, NULL, 'container-outlined', '#1890ff', NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380258656219138', '0', '机构管理', NULL, 'MENU', '1623380023993298945', 'MENU', '/pages/biz/org/index', 'apartment-outlined', '#1890ff', 'YES', 'ENABLE', 0, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380614295449601', '0', '岗位管理', NULL, 'MENU', '1623380023993298945', 'MENU', '/pages/biz/position/index', 'robot-outlined', '#9c28b1', 'YES', 'ENABLE', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380765202313218', '0', '人员管理', NULL, 'MENU', '1623380023993298945', 'MENU', '/pages/biz/user/index', 'team-outlined', '#fed835', 'YES', 'ENABLE', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `MOBILE_RESOURCE` VALUES ('1623381127095250946', '0', '更多', NULL, 'MENU', '1623380023993298945', 'CATALOG', '7029146815941316608', 'small-dash-outlined', '#f1627e', 'YES', 'ENABLE', 7, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380258656219138', '0', '机构管理', 'UJ3Iwy3jsW', 'MENU', '1623380023993298945', 'MENU', '/pages/biz/org/index', 'apartment-outlined', '#1890ff', 'YES', 'ENABLE', 0, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380614295449601', '0', '岗位管理', 'sjIY9oGYir', 'MENU', '1623380023993298945', 'MENU', '/pages/biz/position/index', 'robot-outlined', '#9c28b1', 'YES', 'ENABLE', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `MOBILE_RESOURCE` VALUES ('1623380765202313218', '0', '人员管理', 'sjIY9oGYir', 'MENU', '1623380023993298945', 'MENU', '/pages/biz/user/index', 'team-outlined', '#fed835', 'YES', 'ENABLE', 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `MOBILE_RESOURCE` VALUES ('1623381127095250946', '0', '更多', 'mFVJNzE7gx', 'MENU', '1623380023993298945', 'CATALOG', '7029146815941316608', 'small-dash-outlined', '#f1627e', 'YES', 'ENABLE', 7, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `MOBILE_RESOURCE` VALUES ('1623381298801668098', '1623380258656219138', '新增机构', 'mobileBizOrgAdd', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `MOBILE_RESOURCE` VALUES ('1623381632131395586', '1623380258656219138', '编辑机构', 'mobileBizOrgEdit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `MOBILE_RESOURCE` VALUES ('1623381698837606401', '1623380258656219138', '删除机构', 'mobileBizOrgDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); @@ -668,17 +912,17 @@ INSERT INTO `MOBILE_RESOURCE` VALUES ('1623696346547859458', '162338076520231321 -- ---------------------------- DROP TABLE IF EXISTS `SYS_GROUP`; CREATE TABLE `SYS_GROUP` ( - `ID` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', - `REMARK` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', - `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序码', - `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', - `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', - `CREATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', - `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `UPDATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', - `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', - PRIMARY KEY (`ID`) USING BTREE + `ID` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `REMARK` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序码', + `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户组' ROW_FORMAT = Dynamic; -- ---------------------------- @@ -704,7 +948,7 @@ CREATE TABLE `SYS_ORG` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '组织' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '组织' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of SYS_ORG @@ -720,6 +964,26 @@ INSERT INTO `SYS_ORG` VALUES ('1543842934270394376', '1543842934270394368', '154 INSERT INTO `SYS_ORG` VALUES ('1543842934270394377', '1543842934270394368', '1543837863788879912', '计划营销部', 'w742mipwer', 'DEPT', 10, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_ORG` VALUES ('1543842934270394378', '1543842934270394368', '1543837863788879917', '后勤保卫部', 'b71pvf46do', 'DEPT', 11, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +-- ---------------------------- +-- Table structure for SYS_ORG_EXT +-- ---------------------------- +DROP TABLE IF EXISTS `SYS_ORG_EXT`; +CREATE TABLE `SYS_ORG_EXT` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ORG_ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '组织id', + `SOURCE_FROM_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '来源类别', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '组织扩展' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of SYS_ORG_EXT +-- ---------------------------- + -- ---------------------------- -- Table structure for SYS_POSITION -- ---------------------------- @@ -738,7 +1002,7 @@ CREATE TABLE `SYS_POSITION` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '职位' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '职位' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of SYS_POSITION @@ -760,7 +1024,7 @@ CREATE TABLE `SYS_RELATION` ( `CATEGORY` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类', `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关系' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '关系' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of SYS_RELATION @@ -900,9 +1164,9 @@ INSERT INTO `SYS_RELATION` VALUES ('1728455598297944066', '1570687866138206208', INSERT INTO `SYS_RELATION` VALUES ('1728455598297944067', '1570687866138206208', '1548901111999773978', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1548901111999773978\",\"buttonInfo\":[\"1571129529564758017\",\"1571129929961406466\",\"1571130756155408386\",\"1571130811058847745\"]}'); INSERT INTO `SYS_RELATION` VALUES ('1728455598297944068', '1570687866138206208', '1548901111999773979', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1548901111999773979\",\"buttonInfo\":[\"1571130973294526465\",\"1571131043532341249\",\"1571131137006600193\",\"1571131427361488898\",\"1571131544973967361\",\"1571131727656878081\",\"1571132076853657601\",\"1635110416263262209\",\"1635110536451043329\"]}'); INSERT INTO `SYS_RELATION` VALUES ('1728455598297944069', '1570687866138206208', '1548901111999773980', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1548901111999773980\",\"buttonInfo\":[\"1571132393993371649\",\"1571132468178026497\",\"1571132576143605761\",\"1571132658851086338\"]}'); - -INSERT INTO `SYS_RELATION` VALUES ('1812126273234231297', '1570687866138206208', '1811290937444667393', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1811290937444667393\",\"buttonInfo\":[\"1811290937469833217\",\"1811290937486610434\",\"1811290937494999042\",\"1811290937503387650\",\"1811328402989662210\",\"1811330359695400961\"]}'); INSERT INTO `SYS_RELATION` VALUES ('1728521685882490892', '1570687866138206208', '1811800584425500674', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1811800584425500674\",\"buttonInfo\":[]}'); +INSERT INTO `SYS_RELATION` VALUES ('1812126273234231297', '1570687866138206208', '1811290937444667393', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1811290937444667393\",\"buttonInfo\":[\"1811290937469833217\",\"1811290937486610434\",\"1811290937494999042\",\"1811290937503387650\",\"1811328402989662210\",\"1811330359695400961\"]}'); +INSERT INTO `SYS_RELATION` VALUES ('1813959903803842580', '1570687866138206208', '1813959658013433858', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1813959658013433858\",\"buttonInfo\":[]}'); INSERT INTO `SYS_RELATION` VALUES ('1813960110876631044', '1570687866138206208', '/biz/notice/add', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/add\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}'); INSERT INTO `SYS_RELATION` VALUES ('1813960110876631045', '1570687866138206208', '/biz/notice/delete', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/delete\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}'); INSERT INTO `SYS_RELATION` VALUES ('1813960110876631046', '1570687866138206208', '/biz/notice/detail', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/detail\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}'); @@ -910,10 +1174,9 @@ INSERT INTO `SYS_RELATION` VALUES ('1813960110876631047', '1570687866138206208', INSERT INTO `SYS_RELATION` VALUES ('1813960110876631048', '1570687866138206208', '/biz/notice/edit', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/edit\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}'); INSERT INTO `SYS_RELATION` VALUES ('1813960110876631049', '1570687866138206208', '/biz/notice/enableStatus', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/enableStatus\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}'); INSERT INTO `SYS_RELATION` VALUES ('1813960110876631050', '1570687866138206208', '/biz/notice/page', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/page\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}'); -INSERT INTO `SYS_RELATION` VALUES ('1813959903803842580', '1570687866138206208', '1813959658013433858', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1813959658013433858\",\"buttonInfo\":[]}'); - INSERT INTO `SYS_RELATION` VALUES ('1871280434097565701', '1570687866138206208', '1870158678418993154', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1870158678418993154\",\"buttonInfo\":[\"1870158678481907713\",\"1870158678481907714\",\"1870158678481907715\",\"1870158678481907716\"]}'); INSERT INTO `SYS_RELATION` VALUES ('1871280434097565751', '1570687866138206208', '1871278073018986498', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1871278073018986498\",\"buttonInfo\":[\"1871278073086095361\",\"1871278073086095362\",\"1871278073086095363\",\"1871278073086095364\",\"1871280381043814402\"]}'); +INSERT INTO `SYS_RELATION` VALUES ('1909233948956041233', '1570687866138206208', '1548901111999771927', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1548901111999771927\",\"buttonInfo\":[]}'); -- ---------------------------- -- Table structure for SYS_RESOURCE @@ -941,7 +1204,7 @@ CREATE TABLE `SYS_RESOURCE` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '资源' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '资源' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of SYS_RESOURCE @@ -960,6 +1223,7 @@ INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999771626', '0', '基础工具', N INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999771726', '1548901111999771626', '文件管理', 'devFile', 'n25k83x4sy', 'MENU', '1548901111999770525', 'MENU', '/dev/file/index', 'dev/file/index', 'copy-outlined', NULL, NULL, 14, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999771826', '1548901111999771626', '邮件推送', 'devEmail', 'x4fx2a91tq', 'MENU', '1548901111999770525', 'MENU', '/dev/email/index', 'dev/email/index', 'send-outlined', NULL, NULL, 15, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999771926', '1548901111999771626', '短信发送', 'devSms', 'nnjsr7tkrs', 'MENU', '1548901111999770525', 'MENU', '/dev/sms/index', 'dev/sms/index', 'mail-outlined', NULL, NULL, 16, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999771927', '1548901111999771626', '消息推送', 'devPush', 'ECKjtnzE9A', 'MENU', '1548901111999770525', 'MENU', '/dev/push/index', 'dev/push/index', 'appstore-outlined', NULL, NULL, 16, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999772026', '1548901111999771626', '站内信息', 'devMessage', '0yitzu8786', 'MENU', '1548901111999770525', 'MENU', '/dev/message/index', 'dev/message/index', 'message-outlined', NULL, NULL, 17, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999772126', '0', '系统运维', NULL, '3poiqgf7zx', 'MENU', '1548901111999770525', 'CATALOG', '/a0l7fxfq3m', NULL, 'hdd-outlined', NULL, NULL, 18, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1548901111999772226', '1548901111999772126', '三方用户', 'authThird', 'xf89fmzrtz', 'MENU', '1548901111999770525', 'MENU', '/auth/third', 'auth/third/index', 'team-outlined', NULL, NULL, 19, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); @@ -1022,11 +1286,8 @@ INSERT INTO `SYS_RESOURCE` VALUES ('1635110416263262209', '1548901111999773979', INSERT INTO `SYS_RESOURCE` VALUES ('1635110536451043329', '1548901111999773979', '批量导出', NULL, 'bizUserBatchExport', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 9, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1689891405367353346', '0', '业务字典', 'bizDict', NULL, 'MENU', '1548901111999773976', 'MENU', '/biz/dict/index', 'biz/dict/index', 'read-outlined', NULL, NULL, 12, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1689892202679377921', '1689891405367353346', '编辑字典', NULL, 'bizDictEdit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('1689894316554067969', '1548901111999773426', '高德地图', 'gaodeMap', NULL, 'MENU', '1548901111999770525', 'MENU', '/exm/map/gaodeMap', 'exm/map/gaodeMap', 'environment-outlined', NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('1689894577238450177', '1548901111999773426', '百度地图', 'baiduMap', NULL, 'MENU', '1548901111999770525', 'MENU', '/exm/map/baiduMap', 'exm/map/baiduMap', 'compass-outlined', NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); - -INSERT INTO `SYS_RESOURCE` VALUES ('1811800584425500674', '1548901111999772126', '轮播图', 'slideshow', 'XPLrleqZof', 'MENU', '1548901111999770525', 'MENU', '/dev/slideshow', 'dev/slideshow/index', 'file-image-outlined', NULL, 'TRUE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -INSERT INTO `SYS_RESOURCE` VALUES ('1813959658013433858', '0', '业务首页', 'bizIndex', NULL, 'MENU', '1548901111999773976', 'MENU', '/biz/index', 'biz/index/index', 'home-outlined', NULL, 'TRUE', 0, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('1689894316554067969', '1548901111999773426', '高德地图', 'gaodeMap', 'noten', 'MENU', '1548901111999770525', 'MENU', '/exm/map/gaodeMap', 'exm/map/gaodeMap', 'environment-outlined', NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('1689894577238450177', '1548901111999773426', '百度地图', 'baiduMap', 'noten', 'MENU', '1548901111999770525', 'MENU', '/exm/map/baiduMap', 'exm/map/baiduMap', 'compass-outlined', NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1811290937444667393', '0', '通知公告', 'notice', 'oFordpxYEi', 'MENU', '1548901111999773976', 'MENU', '/biz/notice', 'biz/notice/index', 'appstore-outlined', NULL, NULL, 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1811290937469833217', '1811290937444667393', '新增通知公告', NULL, 'bizNoticeAdd', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1811290937486610434', '1811290937444667393', '编辑通知公告', NULL, 'bizNoticeEdit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); @@ -1034,7 +1295,8 @@ INSERT INTO `SYS_RESOURCE` VALUES ('1811290937494999042', '1811290937444667393', INSERT INTO `SYS_RESOURCE` VALUES ('1811290937503387650', '1811290937444667393', '批量删除', NULL, 'bizNoticeBatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1811328402989662210', '1811290937444667393', '更新状态', NULL, 'bizNoticerUpdateStatus', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1811330359695400961', '1811290937444667393', '通知公告详情', NULL, 'bizNoticeDetail', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); - +INSERT INTO `SYS_RESOURCE` VALUES ('1811800584425500674', '1548901111999772126', '轮播图', 'slideshow', 'XPLrleqZof', 'MENU', '1548901111999770525', 'MENU', '/dev/slideshow', 'dev/slideshow/index', 'file-image-outlined', NULL, 'TRUE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); +INSERT INTO `SYS_RESOURCE` VALUES ('1813959658013433858', '0', '业务首页', 'bizIndex', 'vY0Qc3fkcR', 'MENU', '1548901111999773976', 'MENU', '/biz/index', 'biz/index/index', 'home-outlined', NULL, 'TRUE', 0, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1870158678418993154', '1548901111999770726', '用户组管理', 'groupIndex', 'd4KUq2ZnK7', 'MENU', '1548901111999770525', 'MENU', '/sys/group', 'sys/group/index', 'team-outlined', NULL, 'TRUE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1871278073018986498', '1548901111999773977', '用户组', 'bizGroupIndex', 'HQVofyRf7Z', 'MENU', '1548901111999773976', 'MENU', '/biz/group', 'biz/group/index', 'team-outlined', NULL, 'TRUE', 55, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_RESOURCE` VALUES ('1871278073086095361', '1871278073018986498', '新增用户组', NULL, 'bizGroupAdd', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); @@ -1061,7 +1323,7 @@ CREATE TABLE `SYS_ROLE` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of SYS_ROLE @@ -1127,7 +1389,7 @@ CREATE TABLE `SYS_USER` ( `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户' ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of SYS_USER @@ -1135,43 +1397,45 @@ CREATE TABLE `SYS_USER` ( INSERT INTO `SYS_USER` VALUES ('1543837863788879871', 'data:image/jpg;base64,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', NULL, 'superAdmin', '207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb', '超管', NULL, '男', NULL, '1990-01-01', '汉', '', '', '', '身份证', '', NULL, NULL, NULL, NULL, NULL, NULL, 'eb77186abe605f8de5958df60ef4a279', 'superAdmin@foxmail.com', NULL, NULL, '', '', '', '0000', '2022-07-04', '1543842934270394368', '1543899639134019584', 'C1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'ENABLE', 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); INSERT INTO `SYS_USER` VALUES ('1543837863788879873', 'data:image/jpg;base64,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', NULL, 'bizAdmin', '207cf410532f92a47dee245ce9b11ff71f578ebd763eb3bbea44ebd043d018fb', '业管', NULL, '男', NULL, '1995-01-01', '汉', '', '', '', '身份证', '', NULL, NULL, NULL, NULL, NULL, NULL, '9c8f683ccff14071f90f1f51ba83f069', 'bizAdmin@foxmail.com', NULL, NULL, '', '', '', '0001', '2022-07-04', '1543842934270394368', '1543899639134019584', 'C1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'ENABLE', 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL); -DROP TABLE IF EXISTS `BIZ_NOTICE`; -CREATE TABLE `BIZ_NOTICE` ( - `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `TITLE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', - `IMAGE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面图', - `CONTENT` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '内容', - `DIGEST` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '摘要', - `TYPE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型', - `PLACE` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发布位置', - `STATUS` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态', - `SORT_CODE` int(10) NULL DEFAULT NULL COMMENT '排序', - `REMARK` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', - `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', - `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', - `CREATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', - `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `UPDATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', - `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '通知公告' ROW_FORMAT = Dynamic; +-- ---------------------------- +-- Table structure for SYS_USER_EXT +-- ---------------------------- +DROP TABLE IF EXISTS `SYS_USER_EXT`; +CREATE TABLE `SYS_USER_EXT` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `USER_ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户id', + `SOURCE_FROM_TYPE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '来源类别', + `PASSWORD_UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '密码修改日期', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户扩展' ROW_FORMAT = Dynamic; -DROP TABLE IF EXISTS `DEV_SLIDESHOW`; -CREATE TABLE `DEV_SLIDESHOW` ( - `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', - `TITLE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', - `PLACE` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '展示位置', - `IMAGE` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片', - `PATH_DETAILS` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径详情', - `STATUS` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '状态', - `SORT_CODE` int(255) NULL DEFAULT NULL COMMENT '排序', - `EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息', - `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', - `CREATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', - `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', - `UPDATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', - `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新用户', - PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '轮播图' ROW_FORMAT = Dynamic; +-- ---------------------------- +-- Records of SYS_USER_EXT +-- ---------------------------- + +-- ---------------------------- +-- Table structure for SYS_USER_PASSWORD +-- ---------------------------- +DROP TABLE IF EXISTS `SYS_USER_PASSWORD`; +CREATE TABLE `SYS_USER_PASSWORD` ( + `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `USER_ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户id', + `PASSWORD` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', + `DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志', + `CREATE_TIME` datetime NULL DEFAULT NULL COMMENT '创建时间', + `CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户', + `UPDATE_TIME` datetime NULL DEFAULT NULL COMMENT '修改时间', + `UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户', + PRIMARY KEY (`ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户密码' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of SYS_USER_PASSWORD +-- ---------------------------- SET FOREIGN_KEY_CHECKS = 1; diff --git a/snowy-web-app/src/main/resources/_sql/数据库说明.md b/snowy-web-app/src/main/resources/_sql/数据库说明.md deleted file mode 100644 index fd1afec8..00000000 --- a/snowy-web-app/src/main/resources/_sql/数据库说明.md +++ /dev/null @@ -1,6 +0,0 @@ -# 数据库说明 -注意:sql文件为mysql数据库的文件,如需其他数据库文件,可通过Navicat数据传输等工具传输到目标数据库。 - -文档地址:https://xiaonuo.vip/doc - -如果有其他问题请在群内提出。 \ No newline at end of file diff --git a/snowy-web-app/src/main/resources/application.properties b/snowy-web-app/src/main/resources/application.properties new file mode 100644 index 00000000..7341fe54 --- /dev/null +++ b/snowy-web-app/src/main/resources/application.properties @@ -0,0 +1,209 @@ +######################################### +# server configuration +######################################### +server.port=82 + +######################################### +# spring allow-circular-references +######################################### +spring.main.allow-circular-references=true + +######################################### +# spring profiles configuration +######################################### +spring.profiles.active=local +#spring.profiles.active=test +#spring.profiles.active=prod + +######################################### +# multipart configuration +######################################### +spring.servlet.multipart.max-request-size=100MB +spring.servlet.multipart.max-file-size=100MB + +######################################### +# datasource configuration +######################################### + +# mysql +spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/snowy?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&useInformationSchema=true&rewriteBatchedStatements=true +spring.datasource.dynamic.datasource.master.username=root +spring.datasource.dynamic.datasource.master.password=12345678 +spring.datasource.dynamic.strict=true + +# postgres +#spring.datasource.dynamic.datasource.master.driver-class-name=org.postgresql.Driver +#spring.datasource.dynamic.datasource.master.url=jdbc:postgresql://localhost:5432/snowy +#spring.datasource.dynamic.datasource.master.username=postgres +#spring.datasource.dynamic.datasource.master.password=123456 +#spring.datasource.dynamic.strict=true + +# oracle +#spring.datasource.dynamic.datasource.master.driver-class-name=oracle.jdbc.OracleDriver +#spring.datasource.dynamic.datasource.master.url=jdbc:oracle:thin:@//127.0.0.1:1521/ORCL?remarksReporting=true +#spring.datasource.dynamic.datasource.master.username=SNOWY +#spring.datasource.dynamic.datasource.master.password=12345678 +#spring.datasource.dynamic.strict=true + +# mssql +#spring.datasource.dynamic.datasource.master.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver +#spring.datasource.dynamic.datasource.master.url=jdbc:sqlserver://localhost:1433;DatabaseName=SNOWY +#spring.datasource.dynamic.datasource.master.username=sa +#spring.datasource.dynamic.datasource.master.password=123456 +#spring.datasource.dynamic.strict=true + +# dm database +#spring.datasource.dynamic.datasource.master.driver-class-name=dm.jdbc.driver.DmDriver +#spring.datasource.dynamic.datasource.master.url=jdbc:dm://localhost:5236/SNOWY +#spring.datasource.dynamic.datasource.master.username=SYSDBA +#spring.datasource.dynamic.datasource.master.password=SYSDBA +#spring.datasource.dynamic.strict=true + +# kingbase database +#spring.datasource.dynamic.datasource.master.driver-class-name=com.kingbase8.Driver +#spring.datasource.dynamic.datasource.master.url=jdbc:kingbase8://localhost:54321/snowy +#spring.datasource.dynamic.datasource.master.username=SYSTEM +#spring.datasource.dynamic.datasource.master.password=123456 +#spring.datasource.dynamic.strict=true + +# druid monitor configuration +spring.datasource.druid.stat-view-servlet.enabled=true +spring.datasource.druid.stat-view-servlet.login-username=admin +spring.datasource.druid.stat-view-servlet.login-password=123456 + +# druid global configuration +spring.datasource.dynamic.public-key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMWiTVtdXFVrgFHDDKELZM0SywkWY3KjugN90eY5Sogon1j8Y0ClPF7nx3FuE7pAeBKiv7ChIS0vvx/59WUpKmUCAwEAAQ== +spring.datasource.dynamic.druid.initial-size=5 +spring.datasource.dynamic.druid.max-active=20 +spring.datasource.dynamic.druid.min-idle=5 +spring.datasource.dynamic.druid.max-wait=60000 +spring.datasource.dynamic.druid.pool-prepared-statements=true +spring.datasource.dynamic.druid.max-pool-prepared-statement-per-connection-size=20 +spring.datasource.dynamic.druid.validation-query-timeout=2000 +spring.datasource.dynamic.druid.test-on-borrow=false +spring.datasource.dynamic.druid.test-on-return=false +spring.datasource.dynamic.druid.test-while-idle=true +spring.datasource.dynamic.druid.time-between-eviction-runs-millis=6000 +spring.datasource.dynamic.druid.min-evictable-idle-time-millis=300000 +spring.datasource.dynamic.druid.filters=stat +spring.datasource.dynamic.druid.break-after-acquire-failure=false + +######################################### +# jackson configuration +######################################### +spring.jackson.time-zone=GMT+8 +spring.jackson.date-format=yyyy-MM-dd HH:mm:ss +spring.jackson.locale=zh_CN +spring.jackson.serialization.write-dates-as-timestamps=false +######################################### +# redis configuration +######################################### +spring.data.redis.database=1 +spring.data.redis.host=127.0.0.1 +spring.data.redis.port=6379 +spring.data.redis.password= +spring.data.redis.timeout=10s + +spring.data.redis.lettuce.pool.max-active=200 +spring.data.redis.lettuce.pool.max-wait=-1ms +spring.data.redis.lettuce.pool.max-idle=10 +spring.data.redis.lettuce.pool.min-idle=0 + +######################################### +# mybatis-plus configuration +######################################### +mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl +mybatis-plus.configuration.jdbc-type-for-null=null +mybatis-plus.global-config.banner=false +mybatis-plus.global-config.enable-sql-runner=true +mybatis-plus.global-config.db-config.id-type=ASSIGN_ID +mybatis-plus.global-config.db-config.logic-delete-field=DELETE_FLAG +mybatis-plus.global-config.db-config.logic-delete-value=DELETED +mybatis-plus.global-config.db-config.logic-not-delete-value=NOT_DELETE +mybatis-plus.mapper-locations=classpath*:vip/xiaonuo/**/mapping/*.xml,com/bstek/**/mapping/*.xml +mybatis-plus.type-handlers-package=vip.xiaonuo.common.handler + +######################################### +# easy-trans configuration +######################################### +easy-trans.is-enable-redis=true +easy-trans.is-enable-global=true +easy-trans.is-enable-tile=true +easy-trans.is-enable-cloud=false + +######################################### +# sa-token configuration +######################################### +sa-token.token-name=token +sa-token.timeout=2592000 +sa-token.active-timeout=-1 +sa-token.is-concurrent=true +sa-token.is-share=false +sa-token.max-login-count=-1 +sa-token.token-style=random-32 +sa-token.is-log=false +sa-token.is-print=false + +# sa-token alone-redis configuration +sa-token.alone-redis.database=2 +sa-token.alone-redis.host=${spring.data.redis.host} +sa-token.alone-redis.port=${spring.data.redis.port} +sa-token.alone-redis.password=${spring.data.redis.password} +sa-token.alone-redis.timeout=${spring.data.redis.timeout} +sa-token.alone-redis.lettuce.pool.max-active=${spring.data.redis.lettuce.pool.max-active} +sa-token.alone-redis.lettuce.pool.max-wait=${spring.data.redis.lettuce.pool.max-wait} +sa-token.alone-redis.lettuce.pool.max-idle=${spring.data.redis.lettuce.pool.max-idle} +sa-token.alone-redis.lettuce.pool.min-idle=${spring.data.redis.lettuce.pool.min-idle} + +######################################### +# knife4j configuration +######################################### +knife4j.enable=true +knife4j.production=false +knife4j.basic.enable=true +knife4j.basic.username=admin +knife4j.basic.password=123456 +knife4j.setting.enableOpenApi=false +knife4j.setting.enableSwaggerModels=false +knife4j.setting.enableFooter=false +knife4j.setting.enableFooterCustom=true +knife4j.setting.footerCustomContent=Apache License 2.0 | Copyright 2020-2024[SNOWY](https://www.xiaonuo.vip) +springdoc.default-flat-param-object=true + +# knife4j doc groups +springdoc.group-configs[0].group=SNOWY-PLUGIN-AUTH +springdoc.group-configs[0].display-name=${springdoc.group-configs[0].group} +springdoc.group-configs[0].packages-to-scan=vip.xiaonuo.auth +springdoc.group-configs[1].group=SNOWY-PLUGIN-BIZ +springdoc.group-configs[1].display-name=${springdoc.group-configs[1].group} +springdoc.group-configs[1].packages-to-scan=vip.xiaonuo.biz +springdoc.group-configs[2].group=SNOWY-PLUGIN-CLIENT +springdoc.group-configs[2].display-name=${springdoc.group-configs[2].group} +springdoc.group-configs[2].packages-to-scan=vip.xiaonuo.client +springdoc.group-configs[3].group=SNOWY-PLUGIN-DEV +springdoc.group-configs[3].display-name=${springdoc.group-configs[3].group} +springdoc.group-configs[3].packages-to-scan=vip.xiaonuo.dev +springdoc.group-configs[4].group=SNOWY-PLUGIN-GEN +springdoc.group-configs[4].display-name=${springdoc.group-configs[4].group} +springdoc.group-configs[4].packages-to-scan=vip.xiaonuo.gen +springdoc.group-configs[5].group=SNOWY-PLUGIN-MOBILE +springdoc.group-configs[5].display-name=${springdoc.group-configs[5].group} +springdoc.group-configs[5].packages-to-scan=vip.xiaonuo.mobile +springdoc.group-configs[6].group=SNOWY-PLUGIN-SYS +springdoc.group-configs[6].display-name=${springdoc.group-configs[6].group} +springdoc.group-configs[6].packages-to-scan=vip.xiaonuo.sys + +######################################### +# snowy configuration +######################################### + +# common configuration +snowy.config.common.backend-url=http://localhost:82 + +# plugin dev-sms configuration +sms-oa.config-type=yaml +sms-oa.core-pool-size=20 +sms-oa.queue-capacity=20 +sms-oa.max-pool-size=20 + diff --git a/snowy-web-app/src/main/resources/application.yaml b/snowy-web-app/src/main/resources/application.yaml deleted file mode 100644 index b0e464bf..00000000 --- a/snowy-web-app/src/main/resources/application.yaml +++ /dev/null @@ -1,163 +0,0 @@ -server: - port: 82 # 服务端口 - -spring: - profiles: - active: local # 本地环境 - # active: test # 测试环境 - # active: prod # 生产环境 - servlet: - multipart: - max-request-size: 100MB # 定义单个HTTP请求的最大体积 - max-file-size: 100MB # 定义单个上传文件的最大体积限制 - main: - allow-circular-references: true # 允许循环引用 - # jackson 配置 - jackson: - time-zone: GMT+8 - date-format: yyyy-MM-dd HH:mm:ss - locale: zh_CN - serialization: - write-dates-as-timestamps: false - # 数据源相关配置 - datasource: - dynamic: - datasource: - master: # 主数据源配置 - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/snowy?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&useInformationSchema=true&rewriteBatchedStatements=true - username: root - password: 123456 - strict: true - public-key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMWiTVtdXFVrgFHDDKELZM0SywkWY3KjugN90eY5Sogon1j8Y0ClPF7nx3FuE7pAeBKiv7ChIS0vvx/59WUpKmUCAwEAAQ== - # Druid连接池参数(针对动态数据源) - druid: - initial-size: 5 - max-active: 20 - min-idle: 5 - max-wait: 60000 - pool-prepared-statements: true - max-pool-prepared-statement-per-connection-size: 20 - validation-query-timeout: 2000 - test-on-borrow: false - test-on-return: false - test-while-idle: true - time-between-eviction-runs-millis: 60000 - min-evictable-idle-time-millis: 300000 - filters: stat - break-after-acquire-failure: false - # Druid全局配置(监控界面) - druid: - stat-view-servlet: - enabled: true - login-username: admin - login-password: 123456 - - # redis 配置 - data: - redis: - database: 1 - host: 127.0.0.1 - port: 6379 - password: - timeout: 10s - lettuce: - pool: - max-active: 200 - max-wait: -1ms - max-idle: 10 - min-idle: 0 - -# mybatis-plus 配置 -mybatis-plus: - configuration: - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - jdbc-type-for-null: null - global-config: - banner: false - enable-sql-runner: true - db-config: - id-type: ASSIGN_ID - logic-delete-field: DELETE_FLAG - logic-delete-value: DELETED - logic-not-delete-value: NOT_DELETE - mapper-locations: classpath*:vip/xiaonuo/**/mapping/*.xml - type-handlers-package: vip.xiaonuo.common.handler - -# easy-trans 配置 -easy-trans: - is-enable-redis: true - is-enable-global: true - is-enable-tile: true - is-enable-cloud: false - -# sa-token 配置 -sa-token: - token-name: token - timeout: 2592000 - active-timeout: -1 - is-concurrent: true - is-share: false - max-login-count: -1 - token-style: random-32 - is-log: false - is-print: false - alone-redis: - database: 2 - host: ${spring.data.redis.host} - port: ${spring.data.redis.port} - password: ${spring.data.redis.password} - timeout: ${spring.data.redis.timeout} - lettuce: - pool: - max-active: ${spring.data.redis.lettuce.pool.max-active} - max-wait: ${spring.data.redis.lettuce.pool.max-wait} - max-idle: ${spring.data.redis.lettuce.pool.max-idle} - min-idle: ${spring.data.redis.lettuce.pool.min-idle} - -# knife4j 配置 -knife4j: - enable: true - production: false - basic: - enable: true - username: admin - password: 123456 - setting: - enableOpenApi: false - enableSwaggerModels: false - enableFooter: false - enableFooterCustom: true - footerCustomContent: Apache License 2.0 | Copyright 2020-2024[SNOWY](https://www.xiaonuo.vip) - -springdoc: - default-flat-param-object: true - group-configs: - - group: SNOWY-PLUGIN-AUTH - display-name: SNOWY-PLUGIN-AUTH - packages-to-scan: vip.xiaonuo.auth - - group: SNOWY-PLUGIN-BIZ - display-name: SNOWY-PLUGIN-BIZ - packages-to-scan: vip.xiaonuo.biz - - group: SNOWY-PLUGIN-CLIENT - display-name: SNOWY-PLUGIN-CLIENT - packages-to-scan: vip.xiaonuo.client - - group: SNOWY-PLUGIN-DEV - display-name: SNOWY-PLUGIN-DEV - packages-to-scan: vip.xiaonuo.dev - - group: SNOWY-PLUGIN-GEN - display-name: SNOWY-PLUGIN-GEN - packages-to-scan: vip.xiaonuo.gen - - group: SNOWY-PLUGIN-MOBILE - display-name: SNOWY-PLUGIN-MOBILE - packages-to-scan: vip.xiaonuo.mobile - - group: SNOWY-PLUGIN-SYS - display-name: SNOWY-PLUGIN-SYS - packages-to-scan: vip.xiaonuo.sys - -# snowy 配置 -snowy: - config: - common: - front-url: http://localhost:${server.port} - backend-url: http://localhost:${server.port} \ No newline at end of file diff --git a/snowy-web-app/src/main/resources/favicon.ico b/snowy-web-app/src/main/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9e3ed92f2842c0c91d9a72a689ed576ce3e88e82 GIT binary patch literal 4286 zcmbuD3s6*57{|}u1(rp5g|3PSDw>b%fuubY(NT*u$0mD>(|e{#s_8LgWmAn?HaRtA zIoTCzqXhg+HT53;A2rqzGXXLQG_1mzd2a`?ZH-7xQ5MD+2#?nNU3{7oOqku=)CQxGzaZ zMOrDE^5z0C;q%oOgNP~%&oF^a*QUTTvw?KBv;J-v_hz@_$gX(CN-A1zNI=`o z13?Syd_-W+3LCuR?AW$&rKZC(+{mvS5x}P}q@!b59^9#a8~AmX`MCdBl*Zl17%fB7 ztTDKizWix>#C1?!(5EKUOqjuV-p&{U<4uLX(E?X;IKP{38m5lb#tu3JKDfh-x+!zG_wCfv z8?vM1H|48nzuN+bV&r?X0|>OFGyn1^W8{|z6-&r(noT}+1>?qHI>R*|V2s{^j>35C zdh%-8ThE{19Br+X**Zt%`Ye<+@@ppq7#rv3-$VYU>EZk!qkM1|_0Ps9i8tmt9Xd~x+#(Qu9V}fRRxTPsf>*yVeBBkWxk3XcNzI| z+?)LsjvY)zea>PyWAvKTfBj{HR1}iGVXPWfH{=|-*NP#>vFEu0a>ugyjeN#z%Z(~_ z7sXM&%`omx_2G~^2HS2f)N-XiTl%|l#2OTl?-^#~%efUp{>0wr=bo3}TA<?4btOgSJIsesHEP27`3qDnPxd^^ zIL;r5%JgF9rylFB-sNY9DKfvr zfAbi2+zN2+Wt@0v|kuwML6(gLjSrdWl){P_#6Hp z<3smZe;>G#{H%?U`3_SL+0Roxj`dQ*WA{_crO^V7)21?ZcQO{f<2_>@W9>f1e;4an zCF&++;udlbyspc%EfU!EL>zU!NFRmgsK@5#`Dx_K7_Ufs2b-@=K@}+&t6OW)~+%m@MAiPIo@L?^G zcC&HqUds1s^`|=PTh@;(zRNYR{xE-BNsT;DhtQ^)oF>c9%(=(e{tdAuXXE8MzdSLM zwhcc&N-d}8i{OVs&Ffd2fHb{fMoKg8DfG$ZF2W4Lyr z&fh#EQ@e}yk1e^Es*x&q{sbS^D#3hb9?#2#JLPNYlxJE3+c@sGk@=mAH5@;4CMcr) z<#=TNhS5I!+-|`q&t%fR;ro|-cdCk~!c++y-7heX`aHIowAnh^VK8l;Ncl{>&HlQ{ z;R1Y%%C8*Z!~Rtkd|x*bHRHe6eA?dz&X{7XpnUJiFrBEsO7QGbxP}qr#)b_>c!|od zNNdN=hvUglKy_vZ=OL`sO>Si##NlLj1g!(_Vt&yE=hiUgG;?7ECUK0aP?i2D?Rg@M z-;gWg!-{`?A2=++OuS0{rPhA&#~gOXI(Yx&cOiZ!YFjLLM~h=V+j&nsTVwS6wBoNo z1g!(_!o%cyY~(YhWb+JbMq{px^&q5#--B4^o=jvOtmPd24q1PtzW?q+p?Ux30~V6+ z&DQTw&e)GwAF{c3gDTbof!awatT7w3b;|m1`lJ;{zc9?bkPhwsQGexn=82!NJ44nq z8IzG7-c065S3X$Isg?TXK0S2~mJN_UoB>B(n